LCOV - code coverage report
Current view: top level - physics/clubb/src/CLUBB_core - new_pdf_main.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 100 0.0 %
Date: 2025-03-13 18:42:46 Functions: 0 4 0.0 %

          Line data    Source code
       1             : ! $Id$
       2             : !===============================================================================
       3             : module new_pdf_main
       4             : 
       5             :   ! Description:
       6             :   ! The portion of CLUBB's multivariate, two-component PDF that is the
       7             :   ! trivariate, two-component normal PDF of vertical velocity (w), total water
       8             :   ! mixing ratio (rt), and liquid water potential temperature (thl).
       9             : 
      10             :   ! References:
      11             :   !-------------------------------------------------------------------------
      12             : 
      13             :   implicit none
      14             : 
      15             :   public :: new_pdf_driver    ! Procedure(s)
      16             : 
      17             :   private :: calc_responder_var,     & ! Procedure(s)
      18             :              calc_F_x_zeta_x_setter, &
      19             :              calc_F_x_responder
      20             : 
      21             :   private
      22             : 
      23             :   contains
      24             : 
      25             :   !=============================================================================
      26           0 :   subroutine new_pdf_driver( nz, ngrdcol, wm, rtm, thlm, wp2, rtp2, thlp2, Skw,  & ! In
      27           0 :                              wprtp, wpthlp, rtpthlp,                    & ! In
      28             :                              slope_coef_spread_DG_means_w,              & ! In
      29             :                              pdf_component_stdev_factor_w,              & ! In
      30             :                              coef_spread_DG_means_rt,                   & ! In
      31             :                              coef_spread_DG_means_thl,                  & ! In
      32           0 :                              Skrt, Skthl,                               & ! I/O
      33           0 :                              mu_w_1, mu_w_2,                            & ! Out
      34           0 :                              mu_rt_1, mu_rt_2,                          & ! Out
      35           0 :                              mu_thl_1, mu_thl_2,                        & ! Out
      36           0 :                              sigma_w_1_sqd, sigma_w_2_sqd,              & ! Out
      37           0 :                              sigma_rt_1_sqd, sigma_rt_2_sqd,            & ! Out
      38           0 :                              sigma_thl_1_sqd, sigma_thl_2_sqd,          & ! Out
      39           0 :                              mixt_frac,                                 & ! Out
      40             :                              pdf_implicit_coefs_terms,                  & ! Out
      41           0 :                              F_w, F_rt, F_thl, min_F_w, max_F_w,        & ! Out
      42           0 :                              min_F_rt, max_F_rt, min_F_thl, max_F_thl )   ! Out
      43             :                              
      44             : 
      45             :     ! Description:
      46             :     ! Selects which variable is used to set the mixture fraction for the PDF
      47             :     ! ("the setter") and which variables are handled after that mixture fraction
      48             :     ! has been set ("the responders").  Traditionally, w has been used to set
      49             :     ! the PDF.
      50             : 
      51             :     ! References:
      52             :     !-----------------------------------------------------------------------
      53             : 
      54             :     use constants_clubb, only: &
      55             :         four,                & ! Variable(s)
      56             :         two,                 &
      57             :         one,                 &
      58             :         zero,                &
      59             :         rt_tol,              &
      60             :         thl_tol,             &
      61             :         max_mag_correlation
      62             : 
      63             :     use new_pdf, only: &
      64             :         calc_setter_var_params,     & ! Procedure(s)
      65             :         calc_coef_wp4_implicit,     &
      66             :         calc_coef_wpxp2_implicit,   &
      67             :         calc_coefs_wp2xp_semiimpl,  &
      68             :         calc_coefs_wpxpyp_semiimpl
      69             : 
      70             :     use pdf_parameter_module, only: &
      71             :         implicit_coefs_terms    ! Variable Type
      72             : 
      73             :     use model_flags, only: &
      74             :         l_explicit_turbulent_adv_wp3,  & ! Variable(s)
      75             :         l_explicit_turbulent_adv_wpxp, &
      76             :         l_explicit_turbulent_adv_xpyp
      77             : 
      78             :     use clubb_precision, only: &
      79             :         core_rknd    ! Variable(s)
      80             : 
      81             :     implicit none
      82             : 
      83             :     integer, intent(in) :: &
      84             :       nz, &
      85             :       ngrdcol
      86             : 
      87             :     ! Input Variables
      88             :     real( kind = core_rknd ), dimension(ngrdcol,nz), intent(in) :: &
      89             :       wm,      & ! Mean of w (overall)                 [m/s]
      90             :       rtm,     & ! Mean of rt (overall)                [kg/kg]
      91             :       thlm,    & ! Mean of thl (overall)               [K]
      92             :       wp2,     & ! Variance of w (overall)             [m^2/s^2]
      93             :       rtp2,    & ! Variance of rt (overall)            [kg^2/kg^2]
      94             :       thlp2,   & ! Variance of thl (overall)           [K^2]
      95             :       Skw,     & ! Skewness of w (overall)             [-]
      96             :       wprtp,   & ! Covariance of w and rt (overall)    [(m/s)kg/kg]
      97             :       wpthlp,  & ! Covariance of w and thl (overall)   [(m/s)K]
      98             :       rtpthlp    ! Covariance of rt and thl (overall)  [(kg/kg)K]
      99             : 
     100             :     real( kind = core_rknd ), intent(in) :: &
     101             :       ! Slope coefficient for the spread between the PDF component means of w.
     102             :       slope_coef_spread_DG_means_w, &
     103             :       ! Parameter to adjust the PDF component standard deviations of w.
     104             :       pdf_component_stdev_factor_w, &
     105             :       ! Coefficient for the spread between the PDF component means of rt.
     106             :       coef_spread_DG_means_rt, &
     107             :       ! Coefficient for the spread between the PDF component means of thl.
     108             :       coef_spread_DG_means_thl
     109             : 
     110             :     ! Input/Output Variables
     111             :     ! These variables are input/output because their values may be clipped.
     112             :     ! Otherwise, as long as it is not necessary to clip them, their values
     113             :     ! will stay the same.
     114             :     real( kind = core_rknd ), dimension(ngrdcol,nz), intent(inout) :: &
     115             :       Skrt,  & ! Skewness of rt (overall)            [-]
     116             :       Skthl    ! Skewness of thl (overall)           [-]
     117             : 
     118             :     ! Output Variables
     119             :     real( kind = core_rknd ), dimension(ngrdcol,nz), intent(out) :: &
     120             :       mu_w_1,          & ! Mean of w (1st PDF component)        [m/s]
     121             :       mu_w_2,          & ! Mean of w (2nd PDF component)        [m/s]
     122             :       mu_rt_1,         & ! Mean of rt (1st PDF component)       [kg/kg]
     123             :       mu_rt_2,         & ! Mean of rt (2nd PDF component)       [kg/kg]
     124             :       mu_thl_1,        & ! Mean of thl (1st PDF component)      [K]
     125             :       mu_thl_2,        & ! Mean of thl (2nd PDF component)      [K]
     126             :       sigma_w_1_sqd,   & ! Variance of w (1st PDF component)    [m^2/s^2]
     127             :       sigma_w_2_sqd,   & ! Variance of w (2nd PDF component)    [m^2/s^2]
     128             :       sigma_rt_1_sqd,  & ! Variance of rt (1st PDF component)   [kg^2/kg^2]
     129             :       sigma_rt_2_sqd,  & ! Variance of rt (2nd PDF component)   [kg^2/kg^2]
     130             :       sigma_thl_1_sqd, & ! Variance of thl (1st PDF component)  [K^2]
     131             :       sigma_thl_2_sqd, & ! Variance of thl (2nd PDF component)  [K^2]
     132             :       mixt_frac          ! Mixture fraction                     [-]
     133             : 
     134             :     type(implicit_coefs_terms), intent(inout) :: &
     135             :       pdf_implicit_coefs_terms    ! Implicit coefs / explicit terms [units vary]
     136             : 
     137             :     ! Output only for recording statistics.
     138             :     real( kind = core_rknd ), dimension(ngrdcol,nz), intent(out) :: &
     139             :       F_w,   & ! Parameter for the spread of the PDF component means of w    [-]
     140             :       F_rt,  & ! Parameter for the spread of the PDF component means of rt   [-]
     141             :       F_thl    ! Parameter for the spread of the PDF component means of thl  [-]
     142             : 
     143             :     real( kind = core_rknd ), dimension(ngrdcol,nz), intent(out) :: &
     144             :       min_F_w,   & ! Minimum allowable value of parameter F_w      [-]
     145             :       max_F_w,   & ! Maximum allowable value of parameter F_w      [-]
     146             :       min_F_rt,  & ! Minimum allowable value of parameter F_rt     [-]
     147             :       max_F_rt,  & ! Maximum allowable value of parameter F_rt     [-]
     148             :       min_F_thl, & ! Minimum allowable value of parameter F_thl    [-]
     149             :       max_F_thl    ! Maximum allowable value of parameter F_thl    [-]
     150             : 
     151             :     ! Local Variables
     152             :     real( kind = core_rknd ), dimension(nz) :: &
     153           0 :       sigma_w_1,   & ! Standard deviation of w (1st PDF component)      [m/s]
     154           0 :       sigma_w_2,   & ! Standard deviation of w (2nd PDF component)      [m/s]
     155           0 :       sgn_wprtp,   & ! Sign of the covariance of w and rt (overall)     [-]
     156           0 :       sgn_wpthlp,  & ! Sign of the covariance of w and thl (overall)    [-]
     157           0 :       sgn_wp2        ! Sign of the variance of w (overall); always pos. [-]
     158             : 
     159             :     real( kind = core_rknd ), dimension(nz) :: &
     160           0 :       coef_sigma_w_1_sqd,   & ! sigma_w_1^2 = coef_sigma_w_1_sqd * <w'^2>    [-]
     161           0 :       coef_sigma_w_2_sqd,   & ! sigma_w_2^2 = coef_sigma_w_2_sqd * <w'^2>    [-]
     162           0 :       coef_sigma_rt_1_sqd,  & ! sigma_rt_1^2 = coef_sigma_rt_1_sqd * <rt'^2> [-]
     163           0 :       coef_sigma_rt_2_sqd,  & ! sigma_rt_2^2 = coef_sigma_rt_2_sqd * <rt'^2> [-]
     164           0 :       coef_sigma_thl_1_sqd, & ! sigma_thl_1^2=coef_sigma_thl_1_sqd*<thl'^2>  [-]
     165           0 :       coef_sigma_thl_2_sqd    ! sigma_thl_2^2=coef_sigma_thl_2_sqd*<thl'^2>  [-]
     166             : 
     167             :     real( kind = core_rknd ), dimension(nz) :: &
     168           0 :       max_Skx2_pos_Skx_sgn_wpxp, & ! Maximum Skx^2 when Skx*sgn(<w'x'>) >= 0 [-]
     169           0 :       max_Skx2_neg_Skx_sgn_wpxp    ! Maximum Skx^2 when Skx*sgn(<w'x'>) < 0  [-]
     170             : 
     171             :     real( kind = core_rknd ), dimension(nz) :: &
     172           0 :       zeta_w    ! Parameter for the PDF component variances of w           [-]
     173             : 
     174             :     real ( kind = core_rknd ) :: &
     175             :       lambda_w    ! Param. that increases or decreases Skw dependence  [-]
     176             : 
     177             :     real ( kind = core_rknd ), dimension(nz) :: &
     178           0 :       exp_factor_rt,   & ! Factor of the form 1 - exp{} that reduces F_rt   [-]
     179           0 :       exp_factor_thl,  & ! Don't reduce F_thl by exp_factor_thl        [-]
     180           0 :       adj_corr_rt_thl    ! Adjusted (overall) correlation of rt and theta-l [-]
     181             : 
     182             :     real ( kind = core_rknd ), dimension(nz) :: &
     183           0 :       coef_wp4_implicit,     & ! <w'^4> = coef_wp4_implicit * <w'^2>^2       [-]
     184           0 :       coef_wprtp2_implicit,  & ! <w'rt'^2> = coef_wprtp2_implicit*<rt'^2>  [m/s]
     185           0 :       coef_wpthlp2_implicit    ! <w'thl'^2>=coef_wpthlp2_implicit*<thl'^2> [m/s]
     186             : 
     187             :     ! <w'^2 rt'> = coef_wp2rtp_implicit * <w'rt'> + term_wp2rtp_explicit
     188             :     real ( kind = core_rknd ), dimension(nz) :: &
     189           0 :       coef_wp2rtp_implicit, & ! Coefficient that is multiplied by <w'rt'>  [m/s]
     190           0 :       term_wp2rtp_explicit    ! Term that is on the RHS          [m^2/s^2 kg/kg]
     191             : 
     192             :     ! <w'^2 thl'> = coef_wp2thlp_implicit * <w'thl'> + term_wp2thlp_explicit
     193             :     real ( kind = core_rknd ), dimension(nz) :: &
     194           0 :       coef_wp2thlp_implicit, & ! Coef. that is multiplied by <w'thl'>      [m/s]
     195           0 :       term_wp2thlp_explicit    ! Term that is on the RHS             [m^2/s^2 K]
     196             : 
     197             :     ! <w'rt'thl'> = coef_wprtpthlp_implicit*<rt'thl'> + term_wprtpthlp_explicit
     198             :     real ( kind = core_rknd ), dimension(nz) :: &
     199           0 :       coef_wprtpthlp_implicit, & ! Coef. that is multiplied by <rt'thl'>   [m/s]
     200           0 :       term_wprtpthlp_explicit    ! Term that is on the RHS         [m/s(kg/kg)K]
     201             :       
     202             :     integer :: &
     203             :       i
     204             :       
     205             :     ! ------------------------- Begin Code -------------------------
     206             :       
     207           0 :     do  i = 1, ngrdcol
     208             : 
     209             :       ! Calculate sgn( <w'rt'> ).
     210           0 :       where ( wprtp(i,:) >= zero )
     211             :          sgn_wprtp = one
     212             :       elsewhere ! wprtp < 0
     213             :          sgn_wprtp = -one
     214             :       endwhere ! wprtp >= 0
     215             : 
     216             :       ! Calculate sgn( <w'thl'> ).
     217           0 :       where ( wpthlp(i,:) >= zero )
     218             :          sgn_wpthlp = one
     219             :       elsewhere ! wpthlp < 0
     220             :          sgn_wpthlp = -one
     221             :       endwhere ! wpthlp >= 0
     222             : 
     223             :       ! Sign of the variance of w (overall), which is always positive.
     224           0 :       sgn_wp2 = one
     225             : 
     226           0 :       lambda_w = 0.5_core_rknd
     227             : 
     228             :       ! Calculate the adjusted (overall) correlation of rt and theta-l, and the
     229             :       ! value of exp_factor_rt.
     230           0 :       where ( rtp2(i,:) >= rt_tol**2 .and. thlp2(i,:) >= thl_tol**2 )
     231             :          adj_corr_rt_thl = rtpthlp(i,:) / sqrt( rtp2(i,:) * thlp2(i,:) ) * sgn_wprtp * sgn_wpthlp
     232             :          adj_corr_rt_thl = min( max( adj_corr_rt_thl, -max_mag_correlation ), &
     233             :                                 max_mag_correlation )
     234             :          exp_factor_rt = one &
     235             :                          - exp( -0.2_core_rknd * ( adj_corr_rt_thl + one )**5 )
     236             :       elsewhere ! <rt'^2> < rt_tol^2 or <thl'^2> < thl_tol^2
     237             :          adj_corr_rt_thl = zero  ! adj_corr_rt_thl is undefined in this scenario.
     238             :          exp_factor_rt = one     ! Set exp_factor_rt to 1.
     239             :       endwhere ! <rt'^2> >= rt_tol^2 and <thl'^2> >= thl_tol^2
     240             : 
     241             :       ! The value of F_thl is not reduced by exp_factor_thl.
     242           0 :       exp_factor_thl = one
     243             : 
     244             : 
     245             :       ! Vertical velocity, w, will always be the setter variable.
     246             :       call calc_F_x_zeta_x_setter( nz, Skw(i,:),                      & ! In
     247             :                                    slope_coef_spread_DG_means_w, & ! In
     248             :                                    pdf_component_stdev_factor_w, & ! In
     249             :                                    lambda_w,                     & ! In
     250             :                                    F_w(i,:), zeta_w,                  & ! Out
     251           0 :                                    min_F_w(i,:), max_F_w(i,:)              ) ! Out
     252             : 
     253             :       ! Calculate the PDF parameters, including mixture fraction, for the
     254             :       ! setter variable, w.
     255             :       call calc_setter_var_params( nz, wm(i,:), wp2(i,:), Skw(i,:), sgn_wp2, & ! In
     256             :                                    F_w(i,:), zeta_w,               & ! In
     257             :                                    mu_w_1(i,:), mu_w_2(i,:), sigma_w_1, & ! Out
     258             :                                    sigma_w_2, mixt_frac(i,:),      & ! Out
     259             :                                    coef_sigma_w_1_sqd,        & ! Out
     260           0 :                                    coef_sigma_w_2_sqd         ) ! Out
     261             : 
     262           0 :       sigma_w_1_sqd(i,:) = sigma_w_1**2
     263           0 :       sigma_w_2_sqd(i,:) = sigma_w_2**2
     264             : 
     265             :       ! Calculate the upper limit on the magnitude of skewness for responding
     266             :       ! variables.
     267             :       max_Skx2_pos_Skx_sgn_wpxp = four * ( one - mixt_frac(i,:) )**2 &
     268           0 :                                   / ( mixt_frac(i,:) * ( two - mixt_frac(i,:) ) )
     269             : 
     270           0 :       max_Skx2_neg_Skx_sgn_wpxp = four * mixt_frac(i,:)**2 / ( one - mixt_frac(i,:)**2 )
     271             : 
     272             :       ! Calculate the PDF parameters for responder variable rt.
     273             :       call calc_responder_var( nz, rtm(i,:), rtp2(i,:), sgn_wprtp, mixt_frac(i,:), & ! In
     274             :                                coef_spread_DG_means_rt,         & ! In
     275             :                                exp_factor_rt,                   & ! In
     276             :                                max_Skx2_pos_Skx_sgn_wpxp,       & ! In
     277             :                                max_Skx2_neg_Skx_sgn_wpxp,       & ! In
     278             :                                Skrt(i,:),                            & ! In/Out
     279             :                                mu_rt_1(i,:), mu_rt_2(i,:),                & ! Out
     280             :                                sigma_rt_1_sqd(i,:), sigma_rt_2_sqd(i,:),  & ! Out
     281             :                                coef_sigma_rt_1_sqd,             & ! Out
     282             :                                coef_sigma_rt_2_sqd,             & ! Out
     283           0 :                                F_rt(i,:), min_F_rt(i,:), max_F_rt(i,:)         ) ! Out
     284             : 
     285             :       ! Calculate the PDF parameters for responder variable thl.
     286             :       call calc_responder_var( nz, thlm(i,:), thlp2(i,:), sgn_wpthlp, mixt_frac(i,:), & ! In
     287             :                                coef_spread_DG_means_thl,           & ! In
     288             :                                exp_factor_thl,                     & ! In
     289             :                                max_Skx2_pos_Skx_sgn_wpxp,          & ! In
     290             :                                max_Skx2_neg_Skx_sgn_wpxp,          & ! In
     291             :                                Skthl(i,:),                              & ! In/Out
     292             :                                mu_thl_1(i,:), mu_thl_2(i,:),                 & ! Out
     293             :                                sigma_thl_1_sqd(i,:), sigma_thl_2_sqd(i,:),   & ! Out
     294             :                                coef_sigma_thl_1_sqd,               & ! Out
     295             :                                coef_sigma_thl_2_sqd,               & ! Out
     296           0 :                                F_thl(i,:), min_F_thl(i,:), max_F_thl(i,:)         ) ! Out
     297             : 
     298             : 
     299             :       if ( .not. l_explicit_turbulent_adv_wp3 ) then
     300             : 
     301             :          ! Turbulent advection of <w'^3> is being handled implicitly.
     302             : 
     303             :          ! <w'^4> = coef_wp4_implicit * <w'^2>^2.
     304             :          coef_wp4_implicit &
     305             :          = calc_coef_wp4_implicit( nz, mixt_frac(i,:), F_w(i,:), &
     306             :                                    coef_sigma_w_1_sqd, &
     307           0 :                                    coef_sigma_w_2_sqd )
     308             : 
     309             :       else ! l_explicit_turbulent_adv_wp3
     310             : 
     311             :          ! Turbulent advection of <w'^3> is being handled explicitly.
     312             :          coef_wp4_implicit = zero
     313             : 
     314             :       endif ! .not. l_explicit_turbulent_adv_wp3
     315             : 
     316             :       if ( .not. l_explicit_turbulent_adv_xpyp ) then
     317             : 
     318             :          ! Turbulent advection of <rt'^2> and <thl'^2> is being handled
     319             :          ! implicitly.  Turbulent advection of <rt'thl'> is being handled
     320             :          ! semi-implicitly.
     321             : 
     322             :          ! <w'rt'^2> = coef_wprtp2_implicit * <rt'^2>
     323             :          coef_wprtp2_implicit &
     324             :          = calc_coef_wpxp2_implicit( nz, wp2(i,:), rtp2(i,:), wprtp(i,:), sgn_wprtp, &
     325             :                                      mixt_frac(i,:), F_w(i,:), F_rt(i,:), &
     326             :                                      coef_sigma_w_1_sqd, &
     327             :                                      coef_sigma_w_2_sqd, &
     328             :                                      coef_sigma_rt_1_sqd, &
     329           0 :                                      coef_sigma_rt_2_sqd  )
     330             : 
     331             :          ! <w'thl'^2> = coef_wpthlp2_implicit * <thl'^2>
     332             :          coef_wpthlp2_implicit &
     333             :          = calc_coef_wpxp2_implicit( nz, wp2(i,:), thlp2(i,:), wpthlp(i,:), sgn_wpthlp, &
     334             :                                      mixt_frac(i,:), F_w(i,:), F_thl(i,:), &
     335             :                                      coef_sigma_w_1_sqd, &
     336             :                                      coef_sigma_w_2_sqd, &
     337             :                                      coef_sigma_thl_1_sqd, &
     338           0 :                                      coef_sigma_thl_2_sqd  )
     339             : 
     340             :          ! <w'rt'thl'> = coef_wprtpthlp_implicit * <rt'thl'>
     341             :          !               + term_wprtpthlp_explicit
     342             :          call calc_coefs_wpxpyp_semiimpl( nz, wp2(i,:), rtp2(i,:), thlp2(i,:), wprtp(i,:),       & ! In
     343             :                                           wpthlp(i,:), sgn_wprtp, sgn_wpthlp, & ! In
     344             :                                           mixt_frac(i,:), F_w(i,:), F_rt(i,:), F_thl(i,:),   & ! In
     345             :                                           coef_sigma_w_1_sqd  ,          & ! In
     346             :                                           coef_sigma_w_2_sqd,            & ! In
     347             :                                           coef_sigma_rt_1_sqd,           & ! In
     348             :                                           coef_sigma_rt_2_sqd,           & ! In
     349             :                                           coef_sigma_thl_1_sqd,          & ! In
     350             :                                           coef_sigma_thl_2_sqd,          & ! In
     351             :                                           coef_wprtpthlp_implicit,       & ! Out
     352           0 :                                           term_wprtpthlp_explicit        ) ! Out
     353             : 
     354             :       else ! l_explicit_turbulent_adv_xpyp
     355             : 
     356             :          ! Turbulent advection of <rt'^2>, <thl'^2>, and <rt'thl'> is being
     357             :          ! handled explicitly.
     358             :          coef_wprtp2_implicit = zero
     359             :          coef_wpthlp2_implicit = zero
     360             :          coef_wprtpthlp_implicit = zero
     361             :          term_wprtpthlp_explicit = zero
     362             : 
     363             :       endif ! .not. l_explicit_turbulent_adv_xpyp
     364             : 
     365             :       if ( .not. l_explicit_turbulent_adv_wpxp ) then
     366             : 
     367             :          ! Turbulent advection of <w'rt'> and <w'thl'> is being handled
     368             :          ! semi-implicitly.
     369             : 
     370             :          ! <w'^2 rt'> = coef_wp2rtp_implicit * <w'rt'> + term_wp2rtp_explicit
     371             :          call calc_coefs_wp2xp_semiimpl( nz, wp2(i,:), rtp2(i,:), sgn_wprtp, & ! In
     372             :                                          mixt_frac(i,:), F_w(i,:), F_rt(i,:), & ! In
     373             :                                          coef_sigma_w_1_sqd,   & ! In
     374             :                                          coef_sigma_w_2_sqd,   & ! In
     375             :                                          coef_sigma_rt_1_sqd,  & ! In
     376             :                                          coef_sigma_rt_2_sqd,  & ! In
     377             :                                          coef_wp2rtp_implicit, & ! Out
     378           0 :                                          term_wp2rtp_explicit  ) ! Out
     379             : 
     380             :          ! <w'^2 thl'> = coef_wp2thlp_implicit * <w'thl'> + term_wp2thlp_explicit
     381             :          call calc_coefs_wp2xp_semiimpl( nz, wp2(i,:), thlp2(i,:), sgn_wpthlp, & ! In
     382             :                                          mixt_frac(i,:), F_w(i,:), F_thl(i,:),  & ! In
     383             :                                          coef_sigma_w_1_sqd,     & ! In
     384             :                                          coef_sigma_w_2_sqd,     & ! In
     385             :                                          coef_sigma_thl_1_sqd,   & ! In
     386             :                                          coef_sigma_thl_2_sqd,   & ! In
     387             :                                          coef_wp2thlp_implicit,  & ! Out
     388           0 :                                          term_wp2thlp_explicit   ) ! Out
     389             : 
     390             :       else ! l_explicit_turbulent_adv_wpxp
     391             : 
     392             :          ! Turbulent advection of <w'rt'> and <w'thl'> is being handled
     393             :          ! explicitly.
     394             :          coef_wp2rtp_implicit = zero
     395             :          term_wp2rtp_explicit = zero
     396             :          coef_wp2thlp_implicit = zero
     397             :          term_wp2thlp_explicit = zero
     398             : 
     399             :       endif ! .not. l_explicit_turbulent_adv_wpxp
     400             : 
     401             :       ! Pack the implicit coefficients and explicit terms into a single type
     402             :       ! variable for output.
     403           0 :       pdf_implicit_coefs_terms%coef_wp4_implicit(i,:) = coef_wp4_implicit
     404           0 :       pdf_implicit_coefs_terms%coef_wprtp2_implicit(i,:) = coef_wprtp2_implicit
     405           0 :       pdf_implicit_coefs_terms%coef_wpthlp2_implicit(i,:) = coef_wpthlp2_implicit
     406           0 :       pdf_implicit_coefs_terms%coef_wp2rtp_implicit(i,:) = coef_wp2rtp_implicit
     407           0 :       pdf_implicit_coefs_terms%term_wp2rtp_explicit(i,:) = term_wp2rtp_explicit
     408           0 :       pdf_implicit_coefs_terms%coef_wp2thlp_implicit(i,:) = coef_wp2thlp_implicit
     409           0 :       pdf_implicit_coefs_terms%term_wp2thlp_explicit(i,:) = term_wp2thlp_explicit
     410           0 :       pdf_implicit_coefs_terms%coef_wprtpthlp_implicit(i,:) = coef_wprtpthlp_implicit
     411           0 :       pdf_implicit_coefs_terms%term_wprtpthlp_explicit(i,:) = term_wprtpthlp_explicit
     412             : 
     413             :     end do
     414             : 
     415           0 :     return
     416             : 
     417             :   end subroutine new_pdf_driver
     418             : 
     419             :   !=============================================================================
     420           0 :   subroutine calc_responder_var( nz, xm, xp2, sgn_wpxp, mixt_frac, & ! In
     421             :                                  coef_spread_DG_means_x,       & ! In
     422           0 :                                  exp_factor_x,                 & ! In
     423           0 :                                  max_Skx2_pos_Skx_sgn_wpxp,    & ! In
     424           0 :                                  max_Skx2_neg_Skx_sgn_wpxp,    & ! In
     425           0 :                                  Skx,                          & ! In/Out
     426           0 :                                  mu_x_1, mu_x_2,               & ! Out
     427           0 :                                  sigma_x_1_sqd, sigma_x_2_sqd, & ! Out
     428           0 :                                  coef_sigma_x_1_sqd,           & ! Out
     429           0 :                                  coef_sigma_x_2_sqd,           & ! Out
     430           0 :                                  F_x, min_F_x, max_F_x         ) ! Out
     431             : 
     432             :     ! Description:
     433             :     ! This is the sub-driver for a responder variable.  The upper limits of the
     434             :     ! magnitude of Skx are calculated, and Skx is clipped when its magnitude
     435             :     ! exceeds the upper limits.  The limits of the F_x parameter are calculated,
     436             :     ! and the value of F_x is set within those limits.  Then, the PDF parameters
     437             :     ! for responder variable x are calculated.
     438             : 
     439             :     ! References:
     440             :     !-----------------------------------------------------------------------
     441             : 
     442             :     use constants_clubb, only: &
     443             :         zero    ! Variable(s)
     444             : 
     445             :     use new_pdf, only: &
     446             :         calc_limits_F_x_responder, & ! Procedure(s)
     447             :         calc_responder_params
     448             : 
     449             :     use clubb_precision, only: &
     450             :         core_rknd    ! Variable(s)
     451             : 
     452             :     implicit none
     453             : 
     454             :     integer, intent(in) :: &
     455             :       nz
     456             : 
     457             :     ! Input Variables
     458             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
     459             :       xm,           & ! Mean of x (overall)                       [units vary]
     460             :       xp2,          & ! Variance of x (overall)               [(units vary)^2]
     461             :       sgn_wpxp,     & ! Sign of the covariance of w and x                  [-]
     462             :       mixt_frac,    & ! Mixture fraction                                   [-]
     463             :       exp_factor_x    ! Factor of the form 1 - exp{}; reduces F_x          [-]
     464             : 
     465             :     real( kind = core_rknd ), intent(in) :: &
     466             :       coef_spread_DG_means_x    ! Coef.: spread betw. PDF comp. means of x   [-]
     467             : 
     468             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
     469             :       max_Skx2_pos_Skx_sgn_wpxp, & ! Maximum Skx^2 when Skx*sgn(<w'x'>) >= 0 [-]
     470             :       max_Skx2_neg_Skx_sgn_wpxp    ! Maximum Skx^2 when Skx*sgn(<w'x'>) < 0  [-]
     471             : 
     472             :     ! Input/Output Variable
     473             :     real( kind = core_rknd ), dimension(nz), intent(inout) :: &
     474             :       Skx    ! Skewness of x (overall)              [-]
     475             : 
     476             :     ! Output Variables
     477             :     real( kind = core_rknd ), dimension(nz), intent(out) :: &
     478             :       mu_x_1,        & ! Mean of x (1st PDF component)        [units vary]
     479             :       mu_x_2,        & ! Mean of x (2nd PDF component)        [units vary]
     480             :       sigma_x_1_sqd, & ! Variance of x (1st PDF component)    [(units vary)^2]
     481             :       sigma_x_2_sqd    ! Variance of x (2nd PDF component)    [(units vary)^2]
     482             : 
     483             :     real( kind = core_rknd ), dimension(nz), intent(out) :: &
     484             :       coef_sigma_x_1_sqd, & ! sigma_x_1^2 = coef_sigma_x_1_sqd * <x'^2>    [-]
     485             :       coef_sigma_x_2_sqd    ! sigma_x_2^2 = coef_sigma_x_2_sqd * <x'^2>    [-]
     486             : 
     487             :     ! Output only for recording statistics.
     488             :     real( kind = core_rknd ), dimension(nz), intent(out) :: &
     489             :       F_x,     & ! Param. for the spread betw. the PDF component means of x  [-]
     490             :       min_F_x, & ! Minimum allowable value of parameter F_x                  [-]
     491             :       max_F_x    ! Maximum allowable value of parameter F_x                  [-]
     492             : 
     493             : 
     494             :     ! Calculate the upper limit of the magnitude of Skx.
     495           0 :     where ( Skx * sgn_wpxp >= zero )
     496             :        where ( Skx**2 >= max_Skx2_pos_Skx_sgn_wpxp )
     497             :           where ( Skx >= zero )
     498             :              Skx = sqrt( 0.99_core_rknd * max_Skx2_pos_Skx_sgn_wpxp )
     499             :           elsewhere
     500             :              Skx = -sqrt( 0.99_core_rknd * max_Skx2_pos_Skx_sgn_wpxp )
     501             :           endwhere
     502             :        endwhere ! Skx^2 >= max_Skx2_pos_Skx_sgn_wpxp
     503             :     elsewhere ! Skx * sgn( <w'x'> ) < 0
     504             :        where ( Skx**2 >= max_Skx2_neg_Skx_sgn_wpxp )
     505             :           where ( Skx >= zero )
     506             :              Skx = sqrt( 0.99_core_rknd * max_Skx2_neg_Skx_sgn_wpxp )
     507             :           elsewhere
     508             :              Skx = -sqrt( 0.99_core_rknd * max_Skx2_neg_Skx_sgn_wpxp )
     509             :           endwhere
     510             :        endwhere ! Skx^2 >= max_Skx2_neg_Skx_sgn_wpxp
     511             :     endwhere ! Skx * sgn( <w'x'> ) >= 0
     512             : 
     513             :     call calc_limits_F_x_responder( nz, mixt_frac, Skx, sgn_wpxp,  & ! In
     514             :                                     max_Skx2_pos_Skx_sgn_wpxp, & ! In
     515             :                                     max_Skx2_neg_Skx_sgn_wpxp, & ! In
     516           0 :                                     min_F_x, max_F_x )           ! Out
     517             : 
     518             :     ! F_x must have a value between min_F_x and max_F_x.
     519             :     F_x = calc_F_x_responder( nz, coef_spread_DG_means_x, exp_factor_x, &
     520           0 :                               min_F_x, max_F_x )
     521             : 
     522             :     call calc_responder_params( nz, xm, xp2, Skx, sgn_wpxp,       & ! In
     523             :                                 F_x, mixt_frac,               & ! In
     524             :                                 mu_x_1, mu_x_2,               & ! Out
     525             :                                 sigma_x_1_sqd, sigma_x_2_sqd, & ! Out
     526             :                                 coef_sigma_x_1_sqd,           & ! Out
     527           0 :                                 coef_sigma_x_2_sqd            ) ! Out
     528             : 
     529             : 
     530           0 :     return
     531             : 
     532             :   end subroutine calc_responder_var
     533             : 
     534             :   !=============================================================================
     535           0 :   subroutine calc_F_x_zeta_x_setter( nz, Skx,                          & ! In
     536             :                                      slope_coef_spread_DG_means_x, & ! In
     537             :                                      pdf_component_stdev_factor_x, & ! In
     538             :                                      lambda,                       & ! In
     539           0 :                                      F_x, zeta_x,                  & ! Out
     540           0 :                                      min_F_x, max_F_x              ) ! Out
     541             : 
     542             :     ! Description:
     543             :     ! Calculates the values of F_x and zeta_x for the setter variable (which is
     544             :     ! the variable that sets the mixture fraction).
     545             :     !
     546             :     ! The value of F_x is calculated between 0 (min_F_x) and 1 (max_F_x).  The
     547             :     ! equation is:
     548             :     !
     549             :     ! F_x = max_F_x + ( min_F_x - max_F_x )
     550             :     !                 * exp{ -|Skx|^lambda / slope_coef_spread_DG_means_x };
     551             :     !
     552             :     ! which reduces to:
     553             :     !
     554             :     ! F_x = 1 - exp{ -|Skx|^lambda / slope_coef_spread_DG_means_x };
     555             :     !
     556             :     ! where lambda > 0 and slope_coef_spread_DG_means_x > 0.  As |Skx| goes
     557             :     ! toward 0, the value of F_x goes toward 0, and as |Skx| becomes large, the
     558             :     ! value of F_x goes toward 1.  When slope_coef_spread_DG_means_x is small,
     559             :     ! the value of F_x tends toward 1, and when slope_coef_spread_DG_means_x is
     560             :     ! large, the value of F_x tends toward 0.  When lambda is small, the value
     561             :     ! of F_x is less dependent on Skx, and when lambda is large, the value of
     562             :     ! F_x is more dependent on Skx.
     563             :     !
     564             :     ! Mathematically, this equation will always produce a value of F_x that
     565             :     ! falls between min_F_x and max_F_x.  However, in order to prevent a value
     566             :     ! of F_x from being calculated outside the bounds of min_F_x and max_F_x
     567             :     ! owing to numerical underflow or loss of precision, this equation can be
     568             :     ! rewritten as:
     569             :     !
     570             :     ! F_x
     571             :     ! = min_F_x * exp{ -|Skx|^lambda / slope_coef_spread_DG_means_x }
     572             :     !   + max_F_x * ( 1 - exp{ -|Skx|^lambda / slope_coef_spread_DG_means_x } ).
     573             :     !
     574             :     ! The value of zeta_x used to adjust the PDF component standard devations:
     575             :     !
     576             :     ! 1 + zeta_x = ( mixt_frac * sigma_x_1^2 )
     577             :     !              / ( ( 1 - mixt_frac ) * sigma_x_2^2 );
     578             :     !
     579             :     ! where zeta_x > -1.  The sign of zeta_x is used to easily determine if
     580             :     ! mixt_frac * sigma_x_1^2 is greater than ( 1 - mixt_frac ) * sigma_x_2^2
     581             :     ! (when zeta_x is positive), mixt_frac * sigma_x_1^2 is less than
     582             :     ! ( 1 - mixt_frac ) * sigma_x_2^2 (when zeta_x is negative), or
     583             :     ! mixt_frac * sigma_x_1^2 is equal to ( 1 - mixt_frac ) * sigma_x_2^2 (when
     584             :     ! zeta_x is 0).
     585             :     !
     586             :     ! In order to allow for a tunable parameter that is the pure ratio of
     587             :     ! mixt_frac * sigma_x_1^2 to ( 1 - mixt_frac ) * sigma_x_2^2, zeta_x is
     588             :     ! related to the parameter pdf_component_stdev_factor_x, where:
     589             :     !
     590             :     ! 1 + zeta_x = pdf_component_stdev_factor_x.
     591             : 
     592             :     ! References:
     593             :     !-----------------------------------------------------------------------
     594             : 
     595             :     use constants_clubb, only: &
     596             :         one,  & ! Variable(s)
     597             :         zero
     598             : 
     599             :     use clubb_precision, only: &
     600             :         core_rknd    ! Variable(s)
     601             : 
     602             :     implicit none
     603             : 
     604             :     integer, intent(in) :: &
     605             :       nz
     606             : 
     607             :     ! Input Variables
     608             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
     609             :       Skx    ! Skewness of x (overall)              [-]
     610             : 
     611             :     real( kind = core_rknd ), intent(in) :: &
     612             :       slope_coef_spread_DG_means_x, & ! Slope coef: spread PDF comp. means x [-]
     613             :       pdf_component_stdev_factor_x, & ! Param.: PDF comp. standard devs.; x  [-]
     614             :       lambda                          ! Param. for Skx dependence            [-]
     615             : 
     616             :     ! Output Variables
     617             :     real( kind = core_rknd ), dimension(nz), intent(out) :: &
     618             :       F_x,     & ! Parameter for the spread of the PDF component means of x  [-]
     619             :       zeta_x,  & ! Parameter for the PDF component variances of x            [-]
     620             :       min_F_x, & ! Minimum allowable value of parameter F_x                  [-]
     621             :       max_F_x    ! Maximum allowable value of parameter F_x                  [-]
     622             : 
     623             :     ! Local Variable
     624             :     real( kind = core_rknd ), dimension(nz) :: &
     625           0 :       exp_Skx_interp_factor    ! Function to interp. between min. and max.   [-]
     626             : 
     627             : 
     628             :     ! Set min_F_x to 0 and max_F_x to 1 for the setter variable.
     629           0 :     where ( abs( Skx ) > zero )
     630             :        min_F_x = 1.0e-3_core_rknd
     631             :     elsewhere
     632             :        min_F_x = zero
     633             :     endwhere
     634           0 :     max_F_x = one
     635             : 
     636             :     ! F_x must have a value between min_F_x and max_F_x.
     637             :     exp_Skx_interp_factor &
     638           0 :     = exp( -abs(Skx)**lambda / slope_coef_spread_DG_means_x )
     639             : 
     640             :     F_x = min_F_x * exp_Skx_interp_factor &
     641           0 :           + max_F_x * ( one - exp_Skx_interp_factor )
     642             : 
     643             :     ! The value of zeta_x must be greater than -1.
     644           0 :     zeta_x = pdf_component_stdev_factor_x - one
     645             : 
     646             : 
     647           0 :     return
     648             : 
     649             :   end subroutine calc_F_x_zeta_x_setter
     650             : 
     651             :   !=============================================================================
     652           0 :   function calc_F_x_responder( nz, coef_spread_DG_means_x, exp_factor_x, &
     653           0 :                                min_F_x, max_F_x ) &
     654           0 :   result( F_x )
     655             : 
     656             :     ! Description:
     657             :     ! Calculates the value of F_x as a tunable function between min_F_x and
     658             :     ! max_F_x.
     659             :     !
     660             :     ! The value of F_x is calculated between min_F_x and max_F_x.  The equation
     661             :     ! is:
     662             :     !
     663             :     ! F_x = min_F_x + ( max_F_x - min_F_x )
     664             :     !                 * coef_spread_DG_means_x * exp_factor_x;
     665             :     !
     666             :     ! where 0 <= coef_spread_DG_means_x <= 1.  As coef_spread_DG_means_x
     667             :     ! goes toward 0, the value of F_x goes toward min_F_x, and as
     668             :     ! coef_spread_DG_means_x goes toward 1, the value of F_x goes toward
     669             :     ! max_F_x.  The exp_factor_x is a factor of the form 1 - exp{ }.  The range
     670             :     ! of values of exp_factor_x is 0 <= exp_factor_x <= 1.  Here, exp_factor_x
     671             :     ! is used to reduce the value of F_x under special conditions.
     672             :     !
     673             :     ! The equation for exp_factor_x depends on which responder variable is being
     674             :     ! solved for.  For rt, the F_rt equation is:
     675             :     !
     676             :     ! F_rt = min_F_rt + ( max_F_rt - min_F_rt )
     677             :     !                   * coef_spread_DG_means_rt * exp_factor_rt;
     678             :     !
     679             :     ! where exp_factor_rt is given by:
     680             :     !
     681             :     ! exp_factor_rt = 1 - exp{ -0.2 * ( adj_corr_rt_thl + 1 )^5 };
     682             :     !
     683             :     ! and where the adjusted (overall) correlation of rt and theta-l, denoted
     684             :     ! adj_corr_rt_thl, is given by:
     685             :     !
     686             :     ! adj_corr_rt_thl = <rt'thl'> / ( sqrt( <rt'^2> ) * sqrt( <thl'^2> ) )
     687             :     !                   * sgn( <w'rt'> ) * sgn( <w'thl'> ).
     688             :     !
     689             :     ! The range of values of the adjusted (overall) correlation of rt and
     690             :     ! theta-l is -1 <= adj_corr_rt_thl <= 1.  The adjusted (overall) correlation
     691             :     ! of rt and theta-l has the same absolute magnitude as the (overall)
     692             :     ! correlation of rt and theta-l, but the sign of the adjusted correlation is
     693             :     ! dependent on the agreement between the signs of <w'rt'> and <w'thl'>.
     694             :     ! When all three covariances are in sign agreement, which is when:
     695             :     !
     696             :     ! sgn( <w'rt'> ) * sgn( <w'thl'> ) * sgn( <rt'thl'> ) = 1,
     697             :     !
     698             :     ! the value of adj_corr_rt_thl is positive.  However, when the three
     699             :     ! covariances aren't consistent in sign, which is when:
     700             :     !
     701             :     ! sgn( <w'rt'> ) * sgn( <w'thl'> ) * sgn( <rt'thl'> ) = -1,
     702             :     !
     703             :     ! the value of adj_corr_rt_thl is negative.
     704             :     !
     705             :     ! For theta-l, the F_thl equation is:
     706             :     !
     707             :     ! F_thl = min_F_thl + ( max_F_thl - min_F_thl ) * coef_spread_DG_means_thl;
     708             :     !
     709             :     ! where exp_factor_thl is set to 1 (1 - exp{-inf} = 1) because reducing
     710             :     ! F_thl through the use of exp_factor_thl is not desired for theta-l.
     711             :     !
     712             :     ! The direction of the two PDF component means of x (mu_x_1 and mu_x_2) with
     713             :     ! respect to each other and the overall mean of x (<x>) is given by
     714             :     ! sgn( <w'x'> ).  When sgn( <w'x'> ) = 1, ( mu_x_1 - <x> ) >= 0 and
     715             :     ! ( mu_x_2 - <x> ) <= 0.  When sgn( <w'x'> ) = -1, ( mu_x_1 - <x> ) <= 0 and
     716             :     ! ( mu_x_2 - <x> ) >= 0.  This helps to promote realizability of the PDF
     717             :     ! component correlations (corr_w_x_1 and corr_w_x_2).
     718             :     !
     719             :     ! The realizability of the PDF component correlations corr_w_rt_1,
     720             :     ! corr_w_rt_2, corr_w_thl_1, and corr_w_thl_2 is promoted by using
     721             :     ! sgn( <w'rt'> ) and sgn( <w'thl'> ), respectively to choose the direction
     722             :     ! of the PDF component means of rt and theta-l.  However, when the three
     723             :     ! covariances (<w'rt'>, <w'thl'>, and <rt'thl'>) aren't consistent in sign
     724             :     ! (as shown above), it becomes difficult to keep the PDF component
     725             :     ! correlations corr_rt_thl_1 and corr_rt_thl_2 in the realizable range.
     726             :     ! However, in this situation, the above equation for exp_factor_rt brings
     727             :     ! F_rt closer to min_F_rt, which promotes realizability for corr_rt_thl_1
     728             :     ! and corr_rt_thl_2.
     729             :     !
     730             :     ! Mathematically, this equation will always produce a value of F_x that
     731             :     ! falls between min_F_x and max_F_x.  However, in order to prevent a value
     732             :     ! of F_x from being calculated outside the bounds of min_F_x and max_F_x
     733             :     ! owing to numerical underflow or loss of precision, this equation can be
     734             :     ! rewritten as:
     735             :     !
     736             :     ! F_x = min_F_x * ( 1 - coef_spread_DG_means_x * exp_factor_x )
     737             :     !       + max_F_x * coef_spread_DG_means_x * exp_factor_x.
     738             : 
     739             :     ! References:
     740             :     !-----------------------------------------------------------------------
     741             : 
     742             :     use constants_clubb, only: &
     743             :         one    ! Variable(s)
     744             : 
     745             :     use clubb_precision, only: &
     746             :         core_rknd    ! Variable(s)
     747             : 
     748             :     implicit none
     749             : 
     750             :     integer, intent(in) :: &
     751             :       nz
     752             : 
     753             :     ! Input Variables
     754             :     real( kind = core_rknd ), intent(in) :: &
     755             :       coef_spread_DG_means_x    ! Coef.: spread betw. PDF comp. means of x   [-]
     756             : 
     757             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
     758             :       exp_factor_x, & ! Factor of the form 1 - exp{}; reduces F_x  [-]
     759             :       min_F_x,      & ! Minimum allowable value of parameter F_x   [-]
     760             :       max_F_x         ! Maximum allowable value of parameter F_x   [-]
     761             : 
     762             :     ! Return Variable
     763             :     real( kind = core_rknd ), dimension(nz) :: &
     764             :       F_x    ! Parameter for the spread between the PDF component means of x [-]
     765             : 
     766             : 
     767             :     ! F_x must have a value between min_F_x and max_F_x.
     768             :     F_x = min_F_x * ( one - coef_spread_DG_means_x * exp_factor_x ) &
     769           0 :           + max_F_x * coef_spread_DG_means_x * exp_factor_x
     770             : 
     771             : 
     772           0 :     return
     773             : 
     774           0 :   end function calc_F_x_responder
     775             : 
     776             :   !=============================================================================
     777             : 
     778             : end module new_pdf_main

Generated by: LCOV version 1.14