Example #1
0
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
Example #2
0
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


#==============================================================================