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
|