def internal_coeffs(m, x, n_max): ''' Calculate internal Mie coefficients c_n and d_n given relative index, size parameter, and maximum order of expansion. Follow Bohren & Huffman's convention. Note that van de Hulst and Kerker have different conventions (labeling of c_n and d_n and factors of m) for their internal coefficients. ''' ratio = mie_specfuncs.R_psi(x, m * x, n_max) D1x, D3x = mie_specfuncs.log_der_13(x, n_max) D1mx = mie_specfuncs.log_der_1(m * x, n_max + 15, n_max) cl = m * ratio * (D3x - D1x) / (D3x - m * D1mx) dl = m * ratio * (D3x - D1x) / (m * D3x - D1mx) return array([cl[1:], dl[1:]]) # start from l = 1
def scatcoeffs_multi(marray, xarray): ''' Calculate scattered field expansion coefficients (in the Mie formalism) for a particle with an arbitrary number of layers. Inputs: marray: numpy array of layer indices, innermost first xarray: numpy array of layer size parameters (k * radius), innermost first ''' # ensure correct data types marray = np.array(marray, dtype = 'complex128') xarray = np.array(xarray, dtype = 'float64') # sanity check: marray and xarray must be same size if marray.size != xarray.size: raise ModelInputError('Arrays of layer indices and size parameters must be the same length!') # need number of layers L nlayers = marray.size # calculate nstop based on outermost radius nstop = miescatlib.nstop(xarray.max()) # initialize H_n^a and H_n^b in the core, see eqns. 12a and 13a intl = log_der_13(marray[0]*xarray[0], nstop)[0] hans = intl hbns = intl for lay in np.arange(1, nlayers): # lay is l-1 (index on layers used by Yang) z1 = marray[lay]*xarray[lay-1] # m_l x_{l-1} z2 = marray[lay]*xarray[lay] # m_l x_l # calculate logarithmic derivatives D_n^1 and D_n^3 derz1s = log_der_13(z1, nstop) derz2s = log_der_13(z2, nstop) # calculate G1, G2, Gtilde1, Gtilde2 according to # eqns 26-29 # using H^a_n and H^b_n from previous layer G1 = marray[lay]*hans - marray[lay-1]*derz1s[0] G2 = marray[lay]*hans - marray[lay-1]*derz1s[1] Gt1 = marray[lay-1]*hbns - marray[lay]*derz1s[0] Gt2 = marray[lay-1]*hbns - marray[lay]*derz1s[1] # calculate ratio Q_n^l for this layer Qnl = Qratio(z1, z2, nstop, dns1 = derz1s, dns2 = derz2s) # now calculate H^a_n and H^b_n in current layer # see eqns 24 and 25 hans = (G2*derz2s[0] - Qnl*G1*derz2s[1]) / (G2 - Qnl*G1) hbns = (Gt2*derz2s[0] - Qnl*Gt1*derz2s[1]) / (Gt2 - Qnl*Gt1) # repeat for next layer # Relate H^a and H^b in the outer layer to the Mie scat coeffs # see Yang eqns 14 and 15 psiandxi = riccati_psi_xi(xarray.max(), nstop) # n = 0 to nstop n = np.arange(nstop+1) psi = psiandxi[0] xi = psiandxi[1] # this doesn't bother to calculate psi/xi_{-1} correctly, # but OK since we're throwing out a_0, b_0 where it appears psishift = np.concatenate((np.zeros(1), psi))[0:nstop+1] xishift = np.concatenate((np.zeros(1), xi))[0:nstop+1] an = ((hans/marray[nlayers-1] + n/xarray[nlayers-1])*psi - psishift) / ( (hans/marray[nlayers-1] + n/xarray[nlayers-1])*xi - xishift) bn = ((hbns*marray[nlayers-1] + n/xarray[nlayers-1])*psi - psishift) / ( (hbns*marray[nlayers-1] + n/xarray[nlayers-1])*xi - xishift) return np.array([an[1:nstop+1], bn[1:nstop+1]]) # output begins at n=1
def scatcoeffs_multi(marray, xarray, eps1 = 1e-3, eps2 = 1e-16): ''' Calculate scattered field expansion coefficients (in the Mie formalism) for a particle with an arbitrary number of layers. Inputs: marray: numpy array of layer indices, innermost first xarray: numpy array of layer size parameters (k * radius), innermost first ''' # ensure correct data types marray = np.array(marray, dtype = 'complex128') xarray = np.array(xarray, dtype = 'float64') # sanity check: marray and xarray must be same size if marray.size != xarray.size: raise ModelInputError('Arrays of layer indices and size parameters must be the same length!') # need number of layers L nlayers = marray.size # calculate nstop based on outermost radius nstop = miescatlib.nstop(xarray.max()) # initialize H_n^a and H_n^b in the core, see eqns. 12a and 13a intl = log_der_13(marray[0]*xarray[0], nstop, eps1, eps2)[0] hans = intl hbns = intl for lay in np.arange(1, nlayers): # lay is l-1 (index on layers used by Yang) z1 = marray[lay]*xarray[lay-1] # m_l x_{l-1} z2 = marray[lay]*xarray[lay] # m_l x_l # calculate logarithmic derivatives D_n^1 and D_n^3 derz1s = log_der_13(z1, nstop, eps1, eps2) derz2s = log_der_13(z2, nstop, eps1, eps2) # calculate G1, G2, Gtilde1, Gtilde2 according to # eqns 26-29 # using H^a_n and H^b_n from previous layer G1 = marray[lay]*hans - marray[lay-1]*derz1s[0] G2 = marray[lay]*hans - marray[lay-1]*derz1s[1] Gt1 = marray[lay-1]*hbns - marray[lay]*derz1s[0] Gt2 = marray[lay-1]*hbns - marray[lay]*derz1s[1] # calculate ratio Q_n^l for this layer Qnl = Qratio(z1, z2, nstop, dns1 = derz1s, dns2 = derz2s, eps1 = eps1, eps2 = eps2) # now calculate H^a_n and H^b_n in current layer # see eqns 24 and 25 hans = (G2*derz2s[0] - Qnl*G1*derz2s[1]) / (G2 - Qnl*G1) hbns = (Gt2*derz2s[0] - Qnl*Gt1*derz2s[1]) / (Gt2 - Qnl*Gt1) # repeat for next layer # Relate H^a and H^b in the outer layer to the Mie scat coeffs # see Yang eqns 14 and 15 psiandxi = riccati_psi_xi(xarray.max(), nstop) # n = 0 to nstop n = np.arange(nstop+1) psi = psiandxi[0] xi = psiandxi[1] # this doesn't bother to calculate psi/xi_{-1} correctly, # but OK since we're throwing out a_0, b_0 where it appears psishift = np.concatenate((np.zeros(1), psi))[0:nstop+1] xishift = np.concatenate((np.zeros(1), xi))[0:nstop+1] an = ((hans/marray[nlayers-1] + n/xarray[nlayers-1])*psi - psishift) / ( (hans/marray[nlayers-1] + n/xarray[nlayers-1])*xi - xishift) bn = ((hbns*marray[nlayers-1] + n/xarray[nlayers-1])*psi - psishift) / ( (hbns*marray[nlayers-1] + n/xarray[nlayers-1])*xi - xishift) return np.array([an[1:nstop+1], bn[1:nstop+1]]) # output begins at n=1