exo_k.two_stream.two_stream_toon ================================ .. py:module:: exo_k.two_stream.two_stream_toon .. autoapi-nested-parse:: Created in Jan 2021. @author: jeremy leconte Module Contents --------------- .. py:function:: solve_2stream_nu_xsec(source_nu, tau_nu, dtau_nu, omega0_nu, g_asym_nu, flux_top_dw_nu, alb_surf_nu, mu0 = 0.5, flux_at_level = False, mu_star = None, stellar_mode = 'diffusive', planck_correction_factor = None) Deals with the spectral axis. :param source_nu: $\pi B(T)$ (Planck function) at each of the Nlay+1 level interfaces. Shape: **(Nlev+1, Nw)**. :param tau_nu: Cumulative optical depth of the previous levels, start at 0. The last value tau[-1] is equals to the optical depth of the column. Shape: **(Nlev+1, Nw)**. :param dtau_nu: Optical depth of each level, for each band. Shape: **(Nlev, Nw)**. :param omega0_nu: Single scattering albedo of each level for each band. Shape: **(Nlev, Nw)**. :param g_asym_nu: Asymmetry factor. Shape: **(Nlev, Nw)**. :param flux_top_dw_nu: Top down flux, either diffusive or collimated. Shape: **(Nw,)**. :param alb_surf_nu: Surface albedo. Emissivity is assumed to be 1.-alb_surf. Shape: **(Nw,)**. :param mu0: $\mu_0$ is the incident direction of the observer. It is used as an effective angle. - $\frac{1}{2}$ yields the hemispheric mean approximation. - $\frac{1}{\sqrt(3)}$ yields the quadrature approximation :param flux_at_level: - If ``flux_at_level`` is ``True``, fluxes are calculated at the **level surfaces**. - If ``False``, fluxes are computed at the **middle of the layers**. The top of atmosphere flux is always computed at the top of the uppermost layer (1st level). :param mu_star: $\mu_*$ is the incident direction of the solar beam. Used when the incoming diffuse flux is treated as a source term. :param stellar_mode: When `flux_top_dw_nu` is provided, set the method to be used to take it into account. - ``diffusive``: Incoming diffuse flux at the upper boundary. - ``collimated``: Incoming diffuse flux is treated as a source term. :param planck_correction_factor: Allow setting the epsilon used to rewrite the equations , from Chaverot et al. (2022). :returns: * **flux_up** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw)**. * **flux_dw** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw)**. * **flux_net** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw)**. * **J4pi** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw, Ng)**. .. py:function:: solve_2stream_nu_corrk(source_nu, tau_nu, dtau_nu, omega0_nu, g_asym_nu, flux_top_dw_nu, alb_surf_nu, mu0 = 0.5, flux_at_level = False, mu_star = None, stellar_mode = 'diffusive', planck_correction_factor = None) Deals with the spectral axis. :param source_nu: $\pi B(T)$ (Planck function) at each of the Nlay+1 level interfaces. Shape: **(Nlev+1, Nw)**. :param tau_nu: Cumulative optical depth of the previous levels, start at 0. The last value tau[-1] is equals to the optical depth of the column. Shape: **(Nlev+1, Nw, Ng)**. :param dtau_nu: Optical depth of each level, for each band. Shape: **(Nlev, Nw, Ng)**. :param omega0_nu: Single scattering albedo of each level, for each band. Shape: **(Nlev, Nw, Ng)**. :param g_asym_nu: Asymmetry factor. Shape: **(Nlev, Nw, Ng)**. :param flux_top_dw_nu: Top down flux, either diffusive or collimated. Shape: **(Nw,)**. :param alb_surf_nu: Surface albedo. Emissivity is assumed to be 1.-alb_surf. Shape: **(Nw,)**. :param mu0: $\mu_0$ is the incident direction of the observer. It is used as an effective angle. - $\frac{1}{2}$ yields the hemispheric mean approximation. - $\frac{1}{\sqrt(3)}$ yields the quadrature approximation :param flux_at_level: - If ``flux_at_level`` is ``True``, fluxes are calculated at the **level surfaces**. - If ``False``, fluxes are computed at the **middle of the layers**. The top of atmosphere flux is always computed at the top of the uppermost layer (1st level). :param mu_star: $\mu_*$ is the incident direction of the solar beam. Used when the incoming diffuse flux is treated as a source term. :param stellar_mode: Dictate how `flux_top_dw_nu` is taken it into account. - ``diffusive``: Incoming diffuse flux at the upper boundary. - ``collimated``: Incoming diffuse flux is treated as a source term. :param planck_correction_factor: Allow setting the epsilon used to rewrite the equations , from Chaverot et al. (2022). :returns: * **flux_up** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw, Ng)**. * **flux_dw** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw, Ng)**. * **flux_net** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw, Ng)**. * **J4pi** (:class:`np.ndarray`) -- Shape: **(Nlev, Nw, Ng)**. .. py:function:: solve_2stream(source, tau, dtau, omega0, g_asym, flux_top_dw, alb_surf, mu0, flux_at_level, mu_star, stellar_mode, planck_correction_factor) Solve the 2-stream equations over a bin. After Toon et al. (JGR, 1989). Equation numbers refer to this article. ``alb_surf`` = $R_{sfc}$, ``emis_surf`` = $\varepsilon$ = ``1 - alb_surf`` = $1 - R_{sfc}$, :param source: Shape: **(Nlev+1,)**. :param tau: Shape: **(Nlev+1,)**. :param dtau: Shape: **(Nlev,)**. :param omega0: Shape: **(Nlev,)**. :param g_asym: Shape: **(Nlev,)**. :param mu0: :param flux_top_dw: :param alb_surf: :param flux_at_level: :param mu_star: :param stellar_mode: :param planck_correction_factor: Allow setting the epsilon used to rewrite the equations , from Chaverot et al. (2022). :returns: * **flux_up** (:class:`np.ndarray`) -- Shape: **(Nlev+1,)**. * **flux_dw** (:class:`np.ndarray`) -- Shape: **(Nlev+1,)**. * **flux_net** (:class:`np.ndarray`) -- Shape: **(Nlev+1,)**. * **J4pi** (:class:`np.ndarray`) -- Shape: **(Nlev+1,)**. .. py:function:: c_planck(source, dtau, gamma_1, gamma_2) c_up/dw is for c+/- without direct beam scattering. _top is for tau equal 0 (top of the layer) _bot is for tau=dtau (bottom of the layer) removed a pi factor because source is pi*B :param source: Shape: **(Nlev+1,)** :param dtau: Shape: **(Nlev,)** :param gamma_1: Shape: **(Nlev,)** :param gamma_2: Shape: **(Nlev,)** :returns: * **c_up_top** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **c_dw_top** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **c_up_bot** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **c_dw_bot** (:class:`np.ndarray`) -- Shape: **(Nlev,)** .. py:function:: _c_star_denominator(l, mu_star, eps_frac = 1e-12) Compute the denominator for equations (23) and (24). We use the following reference: https://github.com/NCAR/iCESM1.2/blob/355f7b2c77f1b49004145f6b975617c0917d18ce/models/atm/cam/src/chemistry/mozart/mo_ps2str.F90#L236C1-L238C47 This allow to properly implement "In practice, if the equality happens to occur, this problem can be eliminated by simply choosing a slightly different value of mu0" (Toon & al 1989) :param l: lambda_toon value :param mu_star: $\mu_{*}$ :param eps_frac: .. py:function:: c_star(flux_collimated_top_down, taucum, dtau, gamma_1, gamma_2, gamma_3, gamma_4, omega_0, mu_star) Compute the values of $C^{+}(0), C^{-}(0),C^{+}(\tau)$ and $C^{-}(\tau)$ for the solar radiation part. Follow the equations (23) and (24). :param flux_collimated_top_down: :param taucum: Shape: **(Nlev+1,)**. :param dtau: Shape: **(Nlev,)**. :param gamma_1: $\gamma_{1}$ Shape: **(Nlev,)**. :param gamma_2: $\gamma_{2}$ Shape: **(Nlev,)**. :param gamma_3: $\gamma_{3}$ Shape: **(Nlev,)**. :param gamma_4: $\gamma_{3}$ Shape: **(Nlev,)**. :param omega_0: $\omega_{0}$ Shape: **(Nlev,)**. :param mu_star: $\mu_{*}$ :returns: * :class:`$C^```{+}``:class:`(0)$` -- Shape: **(Nlev,)**. * :class:`$C^```{-}``:class:`(0)$` -- Shape: **(Nlev,)**. * :class:`$C^```{+}``:class:`(\tau)$` -- Shape: **(Nlev,)**. * :class:`$C^```{-}``:class:`(\tau)$` -- Shape: **(Nlev,)**. .. py:function:: c_planck_mid(source, dtau, gamma_1, gamma_2) Compute $C^\pm$ at the middle of the layer, i.e. at tau=dtau/2, ie $C^\pm(\frac{\tau}{2})$. c_up/dw is for c+/- without direct beam scattering. :param source: Shape: **(Nlev+1,)**. :param dtau: Shape: **(Nlev,)**. :param gamma_1: $\gamma_1$ Shape: **(Nlev,)**. :param gamma_2: $\gamma_2$ Shape: **(Nlev,)**. :returns: * :class:`$C^```{+}``:class:`(\frac```{\tau}````{2}``:class:`)$` -- Shape: **(Nlev,)**. * :class:`$C^```{-}``:class:`(\frac```{\tau}````{2}``:class:`)$` -- Shape: **(Nlev,)**. .. py:function:: c_star_mid(flux_collimated_top_down, taucum, dtau, gamma_1, gamma_2, gamma_3, gamma_4, omega_0, mu_star) Compute $C^\pm$ at the middle of the layer, i.e. at tau=dtau/2, ie $C^\pm(\frac{\tau}{2})$. :param flux_collimated_top_down: :param taucum: Shape: **(Nlev+1,)**. :param dtau: Shape: **(Nlev,)**. :param gamma_1: $\gamma_1$ Shape: **(Nlev,)**. :param gamma_2: $\gamma_2$ Shape: **(Nlev,)**. :param gamma_3: $\gamma_3$ Shape: **(Nlev,)**. :param gamma_4: $\gamma_{3}$ Shape: **(Nlev,)**. :param omega_0: $\omega_0$ Shape: **(Nlev,)**. :param mu_star: $\mu_*$ :returns: * :class:`$C^```{+}``:class:`(\frac```{\tau}````{2}``:class:`)$` -- Shape: **(Nlev,)**. * :class:`$C^```{-}``:class:`(\frac```{\tau}````{2}``:class:`)$` -- Shape: **(Nlev,)**. .. py:function:: mid_factor_toon(dtau, gamma_1, gamma_2) Factors to recover the flux at mid layer. :param dtau: Shape: **(Nlev,)**. :param gamma_1: $\gamma_1$ Shape: **(Nlev,)**. :param gamma_2: $\gamma_2$ Shape: **(Nlev,)**. :returns: * **$\text{factor}_{1,\frac{1}{2}}$** (:class:`np.ndarray`) * **$\text{factor}_{2,\frac{1}{2}}$** (:class:`np.ndarray`) .. py:function:: s_planck(omega0, bb_source, planck_correction_factor) Implement equation (15). :param omega0: Shape: **(Nlev,)**. :param bb_source: Shape: **(Nlev,)**. :param planck_correction_factor: :returns: * **$S^+$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. * **$S^-$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. .. py:function:: s_star(omega0, gamma_3, gamma_4, taucum, flux_collimated_top_down, mu_star) Implement equations (13) and (14). :param omega0: Shape: **(Nlev,)**. :param gamma_3: Shape: **(Nlev,)**. :param gamma_4: Shape: **(Nlev,)**. :param taucum: Shape: **(Nlev+1,)**. :param flux_collimated_top_down: :param mu_star: :returns: * **$S^+$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. * **$S^-$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. .. py:function:: _gamma_planck(omega0, g_asym, mu0, planck_correction_factor) Compute the value for $\gamma_1$ and $\gamma_2$ using Table 1. :param omega0: Shape: **(Nlev,)** :param g_asym: Shape: **(Nlev,)** :param mu0: :param planck_correction_factor: :returns: $\gamma_1$ : np.ndarray Shape: **(Nlev,)** $\gamma_2$ : np.ndarray Shape: **(Nlev,)** .. py:function:: _gamma_star(g_asym, mu0, mu_star) Compute the value of $\gamma_{3,4}$, following Toon et al. At this moment, we made the choice to use the value for the quadrature method and identifying the factor $\sqrt{3}$ to $\frac{1}{mu0}$ in our code. Moreover, these factor are not subject to the `planck_correction_factor`. .. rubric:: Notes For this function, $\mu_0$ should have the same meaning as $\mu_1$ in the article. :param g_asym: Shape: **(Nlev,)**. :param mu0: :param mu_star: :returns: * **$\gamma_3$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. * **$\gamma_4$** (:class:`np.ndarray`) -- Shape: **(Nlev,)**. .. py:function:: _gammas_toon(omega0, g_asym, mu0, mu_star, planck_correction_factor, stellar_mode) Compute the value for $\gamma_1$, $\gamma_2$, $\gamma_3$ and $\gamma_4$. :param omega0: Shape: **(Nlev,)** :param g_asym: Shape: **(Nlev,)** :param mu0: :param mu_star: :param planck_correction_factor: :param stellar_mode: :returns: $\gamma_1$ : np.ndarray Shape: **(Nlev,)** $\gamma_2$ : np.ndarray Shape: **(Nlev,)** $\gamma_3$ : np.ndarray Shape: **(Nlev,)** $\gamma_4$ : np.ndarray Shape: **(Nlev,)** .. py:function:: lambda_toon2(gamma_1, gamma_2) Compute $\lambda^2$ from eq 21 of Toon et al. :param gamma_1: $\gamma_1$, Shape: **(Nlev,)**. :param gamma_2: $\gamma_2$, Shape: **(Nlev,)**. :returns: **$\left( \gamma_1^2 - \gamma_2^2 \right)$** -- Shape: **(Nlev,)**. :rtype: :class:`np.ndarray` .. py:function:: lambda_toon(gamma_1, gamma_2) Compute $\lambda$ from eq 21 of Toon et al. :param gamma_1: $\gamma_1$ Shape: **(Nlev,)**. :param gamma_2: $\gamma_2$ Shape: **(Nlev,)**. :returns: **$\left( \gamma_1^2 - \gamma_2^2 \right)^\frac{1}{2}$** -- Shape: **(Nlev,)**. :rtype: :class:`np.ndarray` .. py:function:: lambda_GAMMA(gamma_1, gamma_2) Compute $\lambda$ and $\Gamma$ from eq 21 and 22 of Toon et al. .. rubric:: Notes Toon and al. provide two formulas for $\Gamma$ at equation (22): - $\frac{\gamma_2}{\gamma_1 + \lambda}$ - $\frac{\gamma_1 - \lambda}{\gamma_2}$ We choose two use the first one. :param gamma_1: $\gamma_1$ Shape: **(Nlev,)** :param gamma_2: $\gamma_2$ Shape: **(Nlev,)** :returns: * **$\lambda$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **$\Gamma$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** .. py:function:: e_i_toon(dtau, gamma_1, gamma_2) $e_i$ factors defined in eq 44. :param dtau: Shape: **(Nlev,)** :param gamma_1: $\gamma_1$ Shape: **(Nlev,)** :param gamma_2: $\gamma_2$ Shape: **(Nlev,)** :returns: * **$e_{1}$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **$e_{2}$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **$e_{3}$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** * **$e_{4}$** (:class:`np.ndarray`) -- Shape: **(Nlev,)** .. py:function:: matrix_toon_tridiag(Nlev, taucum, dtau, omega_0, gamma_1, gamma_2, gamma_3, gamma_4, source, mu0, mu_star, flux_diffuse_top_dw, flux_collimated_top_dw, alb_surf, flux_at_level) Compute the up/dw/net fluxes and J4pi. :param Nlev: Number of levels. :param taucum: Shape: **(Nlev+1,)=(Nlay,)**. :param dtau: Shape: **(Nlev,)**. :param omega_0: Shape: **(Nlev,)**. :param source: Shape: **(Nlev,)**. :param gamma_1: Shape: **(Nlev,)**. :param gamma_2: Shape: **(Nlev,)**. :param gamma_3: Shape: **(Nlev,)**. Required in `collimated` mode. :param gamma_4: Shape: **(Nlev,)**. Required in `collimated` mode. :param mu0: :param mu_star: :param flux_diffuse_top_dw: Top downward flux to be treated as a diffusive flux (ie, boundary condition). :param flux_collimated_top_dw: Top downward flux to be treated as a collimated flux. Can be seen as $\mu_0\pi Fs$ in toon. :param alb_surf: Shape: **(Nlev,)**. :param flux_at_level: :returns: $F_{up}$: np.ndarray Upper flux at the bottom of the Nlay layers. Shape: **(Nlev+1,)=(Nlay,)**. $F_{dw}$: np.ndarray Down flux at the bottom of the Nlay layers. Shape: **(Nlev+1,)=(Nlay,)**. $F_{net}$: np.ndarray Net flux at the bottom of the Nlay layers. Shape: **(Nlev+1,)=(Nlay,)**. $4\pi J_n$: np.ndarray J4pi at the bottom of the Nlay layers. Take into account the contribution from the incident flux. Shape: **(Nlev+1,)=(Nlay,)**. .. py:function:: DTRIDGL(L, AF, BF, CF, DF) DIMENSION AF(L),BF(L),CF(L),DF(L),XK(L). DIMENSION AS(2*L),DS(2*L) !* THIS SUBROUTINE SOLVES A SYSTEM OF TRIDIAGIONAL MATRIX !* EQUATIONS. THE FORM OF THE EQUATIONS ARE: !* A(I)*X(I-1) + B(I)*X(I) + C(I)*X(I+1) = D(I) !======================================================================! :param L: :param AF: Shape: **(L,)**. :param BF: Shape: **(L,)**. :param CF: Shape: **(L,)**. :param DF: Shape: **(L,)**. :returns: Y: np.ndarray