Skip to content

Commit afd7825

Browse files
committed
generalized _scatcoeffs_multi() to work with multidimensional m, x
1 parent b3afd67 commit afd7825

File tree

1 file changed

+25
-23
lines changed

1 file changed

+25
-23
lines changed

pymie/mie.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ def _pis_and_taus(nstop, thetas):
519519
Returns
520520
-------
521521
pis, taus (order 1 to n): ndarray
522-
angular functions, each has shape (thetas.shape, nstop)
522+
angular functions, each has shape (..., num_thetas, nstop)
523523
524524
Notes
525525
-----
@@ -553,13 +553,11 @@ def _pis_and_taus(nstop, thetas):
553553
ang_shape = thetas.shape + (nstop+1,)
554554
pis = np.reshape(pis, ang_shape)
555555
taus = np.reshape(taus, ang_shape)
556-
return pis[...,1:nstop+1], taus[...,1:nstop+1]
556+
return pis[..., 1:nstop+1], taus[..., 1:nstop+1]
557557

558558

559559
def _scatcoeffs(m, x, nstop, eps1 = DEFAULT_EPS1, eps2 = DEFAULT_EPS2):
560-
# index ratio should be specified as a 2D array with shape
561-
# [num_values, num_layers] to calculate over a set of different values,
562-
# such as wavelengths. If specified as a 1D array, shape is [num_layers].
560+
# test for multilayer particle
563561
if m.shape[-1] > 1:
564562
return _scatcoeffs_multi(m, x)
565563

@@ -578,9 +576,9 @@ def _scatcoeffs(m, x, nstop, eps1 = DEFAULT_EPS1, eps2 = DEFAULT_EPS2):
578576
n = np.arange(nstop+1)
579577
psi, xi = mie_specfuncs.riccati_psi_xi(x, nstop)
580578

581-
# insert zeroes at the beginning of second axis (order axis)
582-
psishift = np.pad(psi, ((0,), (1,)))[:, 0:nstop+1]
583-
xishift = np.pad(xi, ((0,), (1,)))[:, 0:nstop+1]
579+
# insert zeroes at the beginning of last axis (order axis)
580+
psishift = np.pad(psi, ((0,), (1,)))[..., 0:nstop+1]
581+
xishift = np.pad(xi, ((0,), (1,)))[..., 0:nstop+1]
584582
an = ( (Dnmx/m + n/x)*psi - psishift ) / ( (Dnmx/m + n/x)*xi - xishift )
585583
bn = ( (Dnmx*m + n/x)*psi - psishift ) / ( (Dnmx*m + n/x)*xi - xishift )
586584

@@ -644,32 +642,35 @@ def _scatcoeffs_multi(marray, xarray, nstop=None, eps1 = 1e-3, eps2 = 1e-16):
644642
z2 = marray[..., 1:] * xarray[..., 1:]
645643

646644
# pre-calculate logarithmic derivatives for all layers
645+
# log_der_13 returns 2-tuple, each element w/ shape (..., nlayers-1, nstop)
647646
derz1s = mie_specfuncs.log_der_13(z1, nstop, eps1, eps2)
648647
derz2s = mie_specfuncs.log_der_13(z2, nstop, eps1, eps2)
649648

650649
# pre-calculate ratio Q_n^l for all layers
650+
# Qratio returns array with shape (..., nlayers-1, nstop)
651651
Qnl_arr = mie_specfuncs.Qratio(z1, z2, nstop, dns1 = derz1s,
652652
dns2 = derz2s, eps1 = eps1, eps2 = eps2)
653653

654654
# lay is l-1 (index on layers used by Yang)
655655
for lay in np.arange(1, nlayers):
656-
m = marray[..., lay]
657-
mm1 = marray[..., lay-1]
656+
# add axis for order; resulting shape is (..., 1, 1)
657+
m = marray[..., lay, np.newaxis]
658+
mm1 = marray[..., lay-1, np.newaxis]
658659

659660
# calculate logarithmic derivatives D_n^1 and D_n^3
660-
dz1s0, dz1s1 = derz1s[0][:, lay-1], derz1s[1][:, lay-1]
661-
dz2s0, dz2s1 = derz2s[0][:, lay-1], derz2s[1][:, lay-1]
661+
dz1s0, dz1s1 = derz1s[0][..., lay-1, :], derz1s[1][..., lay-1, :]
662+
dz2s0, dz2s1 = derz2s[0][..., lay-1, :], derz2s[1][..., lay-1, :]
662663

663664
# calculate G1, G2, Gtilde1, Gtilde2 according to
664665
# eqns 26-29
665666
# using H^a_n and H^b_n from previous layer
666-
G1 = m[:, np.newaxis]*hans - mm1[:, np.newaxis]*dz1s0
667-
G2 = m[:, np.newaxis]*hans - mm1[:, np.newaxis]*dz1s1
668-
Gt1 = mm1[:, np.newaxis]*hbns - m[:, np.newaxis]*dz1s0
669-
Gt2 = mm1[:, np.newaxis]*hbns - m[:, np.newaxis]*dz1s1
667+
G1 = m * hans - mm1 * dz1s0
668+
G2 = m * hans - mm1 * dz1s1
669+
Gt1 = mm1 * hbns - m * dz1s0
670+
Gt2 = mm1 * hbns - m * dz1s1
670671

671672
# calculate ratio Q_n^l for this layer
672-
Qnl = Qnl_arr[:, lay-1]
673+
Qnl = Qnl_arr[..., lay-1, :]
673674

674675
# now calculate H^a_n and H^b_n in current layer
675676
# see eqns 24 and 25
@@ -681,10 +682,11 @@ def _scatcoeffs_multi(marray, xarray, nstop=None, eps1 = 1e-3, eps2 = 1e-16):
681682
# see Yang eqns 14 and 15
682683
#
683684
# n = 0 to nstop
684-
# (below we vectorize over the first dimension of xarray; we calculate the
685-
# max x over layers for each value of the first dimension)
686-
psiandxi = mie_specfuncs.riccati_psi_xi(xarray.max(axis=1)[:, np.newaxis],
687-
nstop)
685+
# (below we vectorize over the leading dimensions of x; we calculate the
686+
# max x over layers for each value specified in leading dims)
687+
xmax = xarray.max(axis=-1)
688+
psiandxi = mie_specfuncs.riccati_psi_xi(xmax[..., np.newaxis], nstop)
689+
688690
n = np.arange(nstop+1)
689691
psi = psiandxi[0]
690692
xi = psiandxi[1]
@@ -694,8 +696,8 @@ def _scatcoeffs_multi(marray, xarray, nstop=None, eps1 = 1e-3, eps2 = 1e-16):
694696
np.zeros(psi.shape[:-1]), axis=-1)[..., 0:nstop+1]
695697
xishift = np.insert(xi, 0,
696698
np.zeros(xi.shape[:-1]), axis=-1)[..., 0:nstop+1]
697-
mlast = marray[..., nlayers-1][:, np.newaxis]
698-
xlast = xarray[..., nlayers-1][:, np.newaxis]
699+
mlast = marray[..., nlayers-1][..., np.newaxis]
700+
xlast = xarray[..., nlayers-1][..., np.newaxis]
699701
an = (((hans/mlast + n/xlast)*psi - psishift)
700702
/ ((hans/mlast + n/xlast)*xi - xishift))
701703
bn = (((hbns*mlast + n/xlast)*psi- psishift)

0 commit comments

Comments
 (0)