def single_scattering_up(mu, mu0, azr, tau0, xk): ''' Task: To compute single scattering at top of a homogeneous atmosphere. In: mu d cos(vza_up) < 0 mu0 d cos(sza) > 0 azr d[naz] relative azimuths in radians; naz = len(azr) tau0 d total atmosphere optical thickness xk d[nk] expansion moments * ssa/2, (2k+1) included, nk=len(xk) Out: I11up d Itoa=f(mu, mu0, azr) Tree: - Note: TOA scaling factor = 2pi; Refs: 1. - ''' # # Parameters: nk = len(xk) # smu = np.sqrt(1.0 - mu * mu) smu0 = np.sqrt(1.0 - mu0 * mu0) nu = mu * mu0 + smu * smu0 * np.cos(azr) p = np.zeros_like(nu) for inu, nui in enumerate(nu): pk = legendre_polynomial(nui, nk - 1) p[inu] = np.dot(xk, pk) # mup = -mu I11up = p * mu0 / (mu0 + mup) * (1.0 - np.exp(-tau0 / mup - tau0 / mu0)) # return I11up
def source_function_integrate_up(m, mu, mu0, srfa, nlr, dtau, xk, mug, wg, Ig05, Igboa): ''' Task: Source function integration: up. In: m i Fourier moment: m = 0, 1, 2, .... mu d upward LOS cos(VZA) < 0 mu0 d cos(SZA) > 0 srfa d Lambertian surface albedo nlr i number of layer elements dtau, tau0 = dtau*nlr dtau d thickness of element layer (integration step over tau) ssa d single scattering albedo xk d[nk] expansion moments*ssa/2, (2k+1) included, nk=len(xk) mug d[ng2] Gauss nodes wg d[ng2] Gauss weights Ig05 d[nlr, ng2] RTE solution at Gauss nodes & at midpoint of every layer dtau Igboa d[ng1] Same as Ig05, except for downward at BOA Out: Itoa d Itoa=f(mu) Tree: - Note: TOA scaling factor = 2pi; Refs: 1. - Revision History: 2020-06-29: New input parameter: m; Removed input paramter: ssa; Pk(x) or Qkm(x) is now called depending on m; 2020-06-18: Changes similar to gsitm() 2020-06-14: First created and tested vs IPOL for R&A ''' # # parameters: ng2 = len(wg) ng1 = ng2 // 2 nk = len(xk) mup = -mu nb = nlr + 1 tau0 = nlr * dtau tau = np.linspace(0.0, tau0, nb) # pk = np.zeros((ng2, nk)) if m == 0: pk0 = legendre_polynomial(mu0, nk - 1) pku = legendre_polynomial(mu, nk - 1) for ig in range(ng2): pk[ig, :] = legendre_polynomial(mug[ig], nk - 1) else: pk0 = schmidt_polynomial(m, mu0, nk - 1) pku = schmidt_polynomial(m, mu, nk - 1) for ig in range(ng2): pk[ig, :] = schmidt_polynomial(m, mug[ig], nk - 1) p = np.dot(xk, pku * pk0) # I11up = p * mu0 / (mu0 + mup) * (1.0 - np.exp(-dtau / mup - dtau / mu0)) # I1up = np.zeros(nb) if m == 0 and srfa > 0.0: I1up[nb - 1] = 2.0 * srfa * mu0 * np.exp(-tau0 / mu0) I1up[nb - 2] = I1up[nb - 1] * np.exp(-dtau / mup) + I11up * np.exp( -tau[nb - 2] / mu0) else: I1up[nb - 2] = I11up * np.exp(-tau[nb - 2] / mu0) for ib in range(nb - 3, -1, -1): I1up[ib] = I1up[ib + 1] * np.exp(-dtau / mup) + I11up * np.exp( -tau[ib] / mu0) # wpij = np.zeros(ng2) # sum{xk*pk(mu)*pk(muj)*wj, k=0:nk} for jg in range(ng2): wpij[jg] = wg[jg] * np.dot(xk, pku[:] * pk[jg, :]) # Iup = np.copy(I1up) if m == 0 and srfa > 0.0: Iup[nb-1] = 2.0*srfa*np.dot(Igboa, mug[ng1:ng2]*wg[ng1:ng2]) + \ 2.0*srfa*mu0*np.exp(-tau0/mu0) J = np.dot(wpij, Ig05[nb - 2, :]) Iup[nb-2] = Iup[nb-1]*np.exp(-dtau/mup) + \ I11up*np.exp(-tau[nb-2]/mu0) + \ (1.0 - np.exp(-dtau/mup))*J for ib in range(nb - 3, -1, -1): J = np.dot(wpij, Ig05[ib, :]) Iup[ib] = Iup[ib+1]*np.exp(-dtau/mup) + \ I11up*np.exp(-tau[ib]/mu0) + \ (1.0 - np.exp(-dtau/mup))*J # # Subtract SS (including surface) & extract TOA value Ims = Iup - I1up Itoa = Ims[0] return Itoa #==============================================================================
def gauss_seidel_iterations_m(m, mu0, srfa, nit, ng1, nlr, dtau, xk): ''' Task: Solve RTE in a basic scenario using Gauss-Seidel (GS) iterations. In: m i Fourier moment: m = 0, 1, 2, ... len(xk)-1 mu0 d cos(SZA) > 0 srfa d Lambertian surface albedo nit i number of iterations, nit > 0 ng1 i number of gauss nodes per hemisphere nlr i number of layer elements dtau, tau0 = dtau*nlr dtau d thickness of element layer (integration step over tau) xk d[nk] expansion moments*ssa/2, (2k+1) included, nk=len(xk) Out: mug, wg d[ng1*2] Gauss nodes & weights Iup, Idn d[nlr+1, ng1] intensity, I = f(tau), at Gauss nodes Tree: gsit() > gauszw() - computes Gauss zeros and weights > polleg() - computes ordinary Legendre polynomilas Pk(x) > polqkm() - computes *renormalized* associated Legendre polynomilas Qkm(x) Note: TOA scaling factor = 2pi; Refs: 1. - ''' # # Parameters: tiny = 1.0e-8 nb = nlr+1 nk = len(xk) ng2 = ng1*2 tau0 = nlr*dtau tau = np.linspace(0.0, tau0, nb) # # Gauss nodes and weights: mup - positive Gauss nodes; mug - all Gauss nodes: mup, w = gauss_zeroes_weights(0.0, 1.0, ng1) mug = np.concatenate((-mup, mup)) wg = np.concatenate((w, w)) # pk = np.zeros((ng2, nk)) p = np.zeros(ng2) if m == 0: pk0 = legendre_polynomial(mu0, nk-1) for ig in range(ng2): pk[ig, :] = legendre_polynomial(mug[ig], nk-1) p[ig] = np.dot(xk, pk[ig, :]*pk0) else: pk0 = schmidt_polynomial(m, mu0, nk-1) for ig in range(ng2): pk[ig, :] = schmidt_polynomial(m, mug[ig], nk-1) p[ig] = np.dot(xk, pk[ig, :]*pk0) # # SS down: I11dn = np.zeros(ng1) for ig in range(ng1): mu = mup[ig] if (np.abs(mu0 - mu) < tiny): I11dn[ig] = p[ng1+ig]*dtau*np.exp(-dtau/mu0)/mu0 else: I11dn[ig] = p[ng1+ig]*mu0/(mu0 - mu)*(np.exp(-dtau/mu0) - np.exp(-dtau/mu)) I1dn = np.zeros((nb, ng1)) I1dn[1, :] = I11dn for ib in range(2, nb): I1dn[ib, :] = I1dn[ib-1, :]*np.exp(-dtau/mup) + I11dn*np.exp(-tau[ib-1]/mu0) # # SS up: I11up = p[0:ng1]*mu0/(mu0 + mup)*(1.0 - np.exp(-dtau/mup - dtau/mu0)) I1up = np.zeros_like(I1dn) if m == 0 and srfa > tiny: I1up[nb-1, :] = 2.0*srfa*mu0*np.exp(-tau0/mu0) I1up[nb-2, :] = I1up[nb-1, :]*np.exp(-dtau/mup) + I11up*np.exp(-tau[nb-2]/mu0) else: I1up[nb-2, :] = I11up*np.exp(-tau[nb-2]/mu0) for ib in range(nb-3, -1, -1): I1up[ib, :] = I1up[ib+1, :]*np.exp(-dtau/mup) + I11up*np.exp(-tau[ib]/mu0) # # MS: only odd/even k are needed for up/down - not yet applied wpij = np.zeros((ng2, ng2)) # sum{xk*pk(mui)*pk(muj)*wj, k=0:nk} for ig in range(ng2): for jg in range(ng2): wpij[ig, jg] = wg[jg]*np.dot(xk, pk[ig, :]*pk[jg, :]) # thinkme: use matrix formalism? # # MOM: [Jup; Jdn] = [[Tup Rup]; [Rdn Tdn]]*[Iup Idn]; Tup = Tdn = T; Rup = Rdn = R T = wpij[0:ng1, 0:ng1].copy() # T.flags.c_contiguous = True R = wpij[0:ng1, ng1:ng2].copy() # R.flags.c_contiguous = True # Iup = np.copy(I1up) Idn = np.copy(I1dn) for itr in range(nit): # Down: Iup05 = 0.5*(Iup[0, :] + Iup[1, :]) Idn05 = 0.5*(Idn[0, :] + Idn[1, :]) # Idn[0, :] = 0.0 J = np.dot(R, Iup05) + np.dot(T, Idn05) Idn[1, :] = I11dn + (1.0 - np.exp(-dtau/mup))*J for ib in range(2, nb): Iup05 = 0.5*(Iup[ib-1, :] + Iup[ib, :]) Idn05 = 0.5*(Idn[ib-1, :] + Idn[ib, :]) J = np.dot(R, Iup05) + np.dot(T, Idn05) Idn[ib, :] = Idn[ib-1, :]*np.exp(-dtau/mup) + \ I11dn*np.exp(-tau[ib-1]/mu0) + \ (1.0 - np.exp(-dtau/mup))*J # Up: # Lambertian surface if m == 0 and srfa > tiny: Iup[nb-1, :] = 2.0*srfa*np.dot(Idn[nb-1, :], mup*w) + 2.0*srfa*mu0*np.exp(-tau0/mu0) Iup05 = 0.5*(Iup[nb-2, :] + Iup[nb-1, :]) # Iup[nb-1, :] = 0.0 Idn05 = 0.5*(Idn[nb-2, :] + Idn[nb-1, :]) J = np.dot(T, Iup05) + np.dot(R, Idn05) Iup[nb-2, :] = Iup[nb-1, :]*np.exp(-dtau/mup) + \ I11up*np.exp(-tau[nb-2]/mu0) + \ (1.0 - np.exp(-dtau/mup))*J for ib in range(nb-3, -1, -1): # going up, ib = 0 (TOA) must be included Iup05 = 0.5*(Iup[ib, :] + Iup[ib+1, :]) Idn05 = 0.5*(Idn[ib, :] + Idn[ib+1, :]) J = np.dot(T, Iup05) + np.dot(R, Idn05) Iup[ib, :] = Iup[ib+1, :]*np.exp(-dtau/mup) + \ I11up*np.exp(-tau[ib]/mu0) + \ (1.0 - np.exp(-dtau/mup))*J # print("iter=%i"%itr) return mug, wg, Iup[:, :], Idn[:, :]
def source_function_integrate_down(m, mu, mu0, nlr, dtau, xk, mug, wg, Ig05): ''' Task: Source function integration: down. In: m i Fourier moment: m = 0, 1, 2, .... mu d upward LOS cos(VZA) < 0 nlr i number of layer elements dtau, tau0 = dtau*nlr dtau d thickness of element layer (integration step over tau) xk d[nk] expansion moments*ssa/2, (2k+1) included, nk=len(xk) mug d[ng2] Gauss nodes wg d[ng2] Gauss weights Ig05 d[nlr, ng2] RTE solution at Gauss nodes & at midpoint of every layer dtau Out: Iboa d Itoa=f(mu) Tree: - Note: TOA scaling factor = 2pi; Refs: 1. - ''' # # Parameters: tiny = 1.0e-8 ng2 = len(wg) nk = len(xk) nb = nlr + 1 tau0 = nlr * dtau tau = np.linspace(0.0, tau0, nb) # pk = np.zeros((ng2, nk)) if m == 0: pk0 = legendre_polynomial(mu0, nk - 1) pku = legendre_polynomial(mu, nk - 1) for ig in range(ng2): pk[ig, :] = legendre_polynomial(mug[ig], nk - 1) else: pk0 = schmidt_polynomial(m, mu0, nk - 1) pku = schmidt_polynomial(m, mu, nk - 1) for ig in range(ng2): pk[ig, :] = schmidt_polynomial(m, mug[ig], nk - 1) p = np.dot(xk, pku * pk0) # if np.abs(mu - mu0) < tiny: I11dn = p * dtau * np.exp(-dtau / mu0) / mu0 else: I11dn = p * mu0 / (mu0 - mu) * (np.exp(-dtau / mu0) - np.exp(-dtau / mu)) # I1dn = np.zeros(nb) I1dn[1] = I11dn for ib in range(2, nb): I1dn[ib] = I1dn[ib - 1] * np.exp(-dtau / mu) + I11dn * np.exp( -tau[ib - 1] / mu0) # wpij = np.zeros(ng2) # sum{xk*pk(mu)*pk(muj)*wj, k=0:nk} for jg in range(ng2): wpij[jg] = wg[jg] * np.dot(xk, pku[:] * pk[jg, :]) # Idn = np.copy(I1dn) # boundary condition: Idn[0, :] = 0.0 J = np.dot(wpij, Ig05[0, :]) Idn[1] = I11dn + (1.0 - np.exp(-dtau / mu)) * J for ib in range(2, nb): J = np.dot(wpij, Ig05[ib - 1, :]) Idn[ib] = Idn[ib-1]*np.exp(-dtau/mu) + \ I11dn*np.exp(-tau[ib-1]/mu0) + \ (1.0 - np.exp(-dtau/mu))*J # # Subtract SS & extract BOA value Ims = Idn - I1dn Iboa = Ims[nb - 1] return Iboa #==============================================================================