CCPP SciDoc v7.0.0  v7.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
module_mp_tempo_main.F90
2 !! main tempo microphysics code
4 use module_mp_tempo_params, only : wp, sp, dp, &
5 min_qv, roverrv, rdry, r1, r2, nt_c_max, t0, nrhg, rho_g, &
6 meters3_to_liters, eps, aero_max, nwfa_default, nifa_default, nt_c_l, nt_c_o
7 use module_mp_tempo_utils, only : get_nuc, get_constant_cloud_number, snow_moments, calc_rslf, calc_rsif
8 use module_mp_tempo_diags, only : reflectivity_10cm, effective_radius, max_hail_diam, &
9 freezing_rain
10 use module_mp_tempo_aerosols, only : init_ice_friendly_aerosols, init_water_friendly_aerosols, &
11 aerosol_collection_efficiency
12 use module_mp_tempo_ml, only : tempo_ml_predict_cloud_number
13 implicit none
14 private
15
16 public :: tempo_main, ty_tempo_main_diags
17
18 !! needed for effective radius calculations when using FV3 since advection
19 !! happens between the effective radius calcuation and call to radiation
20 public :: cloud_check_and_update, ice_check_and_update, snow_check_and_update
21
22
23#ifdef unit_testing
24 public :: get_cloud_table_index, get_snow_table_index, &
25 get_temperature_table_index, get_rain_table_index, &
26 get_graupel_table_index, get_ice_table_index
27#endif
28
30 real(wp) :: rain_precip
31 real(wp) :: cloud_precip
32 real(wp) :: ice_liquid_equiv_precip
33 real(wp) :: snow_liquid_equiv_precip
34 real(wp) :: graupel_liquid_equiv_precip
35 real(wp) :: frozen_fraction
36 real(wp) :: frz_rain_precip
37 real(wp), dimension(:), allocatable :: rain_med_vol_diam
38 real(wp), dimension(:), allocatable :: graupel_med_vol_diam
39 real(wp), dimension(:), allocatable :: refl10cm
40 real(wp), dimension(:), allocatable :: re_cloud
41 real(wp), dimension(:), allocatable :: re_ice
42 real(wp), dimension(:), allocatable :: re_snow
43 real(wp), dimension(:), allocatable :: max_hail_diameter
44 real(wp), dimension(:), allocatable :: cloud_number_mixing_ratio
45 end type
46
47 type :: ty_tend
48 real(dp), pointer, contiguous, dimension(:) :: &
49 prr_wau, pnr_wau, pnc_wau, prr_rcw, pnc_rcw, pnr_rcr, & ! warm rain
50 prs_scw, pnc_scw, png_scw, pbg_scw, prg_gcw, pnc_gcw, pbg_gcw, & ! riming
51 pri_ihm, pni_ihm, prs_ihm, prg_ihm, prg_scw, & ! riming
52 prr_rcs, pnr_rcs, prg_rcs, png_rcs, prs_rcs, pbg_rcs, & ! rain-snow
53 prr_rcg, pnr_rcg, prg_rcg, png_rcg, pbg_rcg, & ! rain-graupel
54 pri_inu, pni_inu, pri_iha, pni_iha, & ! ice nucleation
55 pri_wfz, pni_wfz, & ! water freezing
56 prg_rfz, png_rfz, pnr_rfz, pri_rfz, pni_rfz, pbg_rfz, & ! rain freezing
57 prs_sde, pri_ide, pni_ide, prs_ide, prg_gde, png_gde, & ! depositional growth
58 pni_iau, prs_iau, & ! ice-snow conversion
59 prr_sml, prr_gml, pbg_sml, pbg_gml, pnr_sml, pnr_gml, & ! melting
60 prr_rci, pnr_rci, pri_rci, pni_rci, prg_rci, png_rci, pbg_rci, & ! rain-ice
61 pni_sci, prs_sci, & ! snow-ice
62 prw_vcd, pnc_wcd, prv_rev, pnr_rev, & ! condensation/evaporation
63 pna_rca, pna_sca, pna_gca, pnd_rcd, pnd_scd, pnd_gcd ! aerosol
64 end type
65
66 interface get_cloud_number
67 module procedure tempo_ml_predict_cloud_number
68 module procedure get_constant_cloud_number
69 end interface
70
71 contains
72
73 subroutine tempo_main(tempo_cfgs, &
74 qv1d, qc1d, qi1d, qr1d, qs1d, qg1d, qb1d, ni1d, nr1d, nc1d, ng1d, &
75 nwfa1d, nifa1d, t1d, p1d, w1d, dz1d, land1d, &
76 qcfrac1d, qifrac1d, qc_bl1d, qcfrac_bl1d, &
77 thten_bl1d, qvten_bl1d, qcten_bl1d, qiten_bl1d, &
78 thten_lwrad1d, thten_swrad1d, &
79 kts, kte, dt, ii, jj, tempo_main_diags)
80 !! tempo main
81
82 type(ty_tend) :: tend
83 type(ty_tempo_main_diags), intent(out) :: tempo_main_diags
84
85 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
86 integer, intent(in) :: kts, kte, ii, jj
87 real(wp), intent(in) :: dt
88 real(wp), dimension(kts:kte), intent(inout) :: t1d !! 1D temperature \‍([K]\‍)
89 real(wp), dimension(kts:kte), intent(in) :: p1d !! 1D pressure \‍([Pa]\‍)
90 real(wp), dimension(kts:kte), intent(inout) :: qv1d !! 1D water vapor mixing ratio \‍([kg\; kg^{-1}]\‍)
91 real(wp), dimension(kts:kte), intent(inout) :: qc1d !! 1D cloud water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
92 real(wp), dimension(kts:kte), intent(inout) :: qr1d !! 1D rain water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
93 real(wp), dimension(kts:kte), intent(inout) :: qi1d !! 1D cloud ice mass mixing ratio \‍([kg\; kg^{-1}]\‍)
94 real(wp), dimension(kts:kte), intent(inout) :: qs1d !! 1D snow mass mixing ratio \‍([kg\; kg^{-1}]\‍)
95 real(wp), dimension(kts:kte), intent(inout) :: qg1d !! 1D graupel mass mixing ratio \‍([kg\; kg^{-1}]\‍)
96 real(wp), dimension(kts:kte), intent(inout) :: ni1d !! 1D cloud ice number mixing ratio \‍([kg^{-1}]\‍)
97 real(wp), dimension(kts:kte), intent(inout) :: nr1d !! 1D rain water number mixing ratio \‍([kg^{-1}]\‍)
98 real(wp), dimension(:), intent(inout), optional :: nc1d !! 1D cloud water number mixing ratio \‍([kg^{-1}]\‍)
99 real(wp), dimension(:), intent(inout), optional :: nwfa1d !! 1D water-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍)
100 real(wp), dimension(:), intent(inout), optional :: nifa1d !! 1D ice-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍)
101 real(wp), dimension(:), intent(inout), optional :: qb1d !! 1D graupel volume mixing ratio \‍([m^{-3}\; kg^{-1}]\‍)
102 real(wp), dimension(:), intent(inout), optional :: ng1d !! 1D graupel number mixing ratio \‍([kg^{-1}]\‍)
103 real(wp), dimension(kts:kte), intent(in) :: w1d !! 1D vertical velocity \‍(m\; s^{-1}]\‍)
104 real(wp), dimension(kts:kte), intent(in) :: dz1d !! 1D vertical grid spacing \‍([m]\‍)
105 integer, intent(in), optional :: land1d !! grid-point land type
106
107 ! additional optional arrays
108 real(wp), dimension(:), intent(inout), optional :: qcfrac1d !! cloud fraction
109 real(wp), dimension(:), intent(inout), optional :: qifrac1d !! cloud ice fraction
110 real(wp), dimension(:), intent(in), optional :: qc_bl1d !! cloud water mixing ratio from boundary layer scheme
111 real(wp), dimension(:), intent(in), optional :: qcfrac_bl1d !! cloud fraction from boundary layer scheme
112 real(wp), dimension(:), intent(in), optional :: thten_bl1d !! potential temperature tendency from boundary layer scheme
113 real(wp), dimension(:), intent(in), optional :: qvten_bl1d !! water vapor mixing ratio tendency from boundary layer scheme
114 real(wp), dimension(:), intent(in), optional :: qcten_bl1d !! cloud water mixing ratio tendency from boundary layer scheme
115 real(wp), dimension(:), intent(in), optional :: qiten_bl1d !! cloud ice mixing ratio from boundary layer scheme
116 real(wp), dimension(:), intent(in), optional :: thten_lwrad1d !! potential temperature tendency from longwave radiation scheme
117 real(wp), dimension(:), intent(in), optional :: thten_swrad1d !! potential temperature tendency from shortwave radiation scheme
118
119 real(wp), dimension(kts:kte) :: tten, qvten, qcten, qiten, qrten, qsten, &
120 qgten, qbten, niten, nrten, ncten, ngten, nwfaten, nifaten !! tendencies
121
122 logical, dimension(kts:kte) :: l_qc, l_qi, l_qr, l_qs, l_qg !! hydrometeor existence logicals
123 integer, dimension(kts:kte) :: idx_bg !! graupel density index
124
125 ! thermodynamic variables
126 real(wp), dimension(kts:kte) :: temp, pres, qv !! thermodynamic variables
127 real(wp), dimension(kts:kte) :: rho, rhof, rhof2 !! thermodynamic variables
128 real(wp), dimension(kts:kte) :: qvs, qvsi, delqvs !! thermodynamic variables
129 real(wp), dimension(kts:kte) :: satw, sati, ssatw, ssati !! thermodynamic variables
130 real(wp), dimension(kts:kte) :: diffu, visco, vsc2, tcond, lvap, ocp, lvt2 !! thermodynamic variables
131
132 real(wp), dimension(kts:kte) :: rc, ri, rr, rs, rg, rb !! local microphysical variables
133 real(wp), dimension(kts:kte) :: ni, nr, nc, ng, nwfa, nifa !! local microphysics variables
134
135 real(dp), dimension(kts:kte) :: ilamc, ilami, ilamr, ilamg !! inverse lambda
136 real(wp), dimension(kts:kte) :: mvd_r, mvd_c, mvd_g !! median volume diameter
137 real(dp), dimension(kts:kte) :: smob, smo2, smo1, smo0, smoc, smoe, smof, smog, ns, smoz !! snow moments
138
139 real(wp), dimension(kts:kte) :: xrx, xnx !! temporary arrays
140 real(wp), dimension(:), allocatable :: xncx, xngx, xqbx, ncsave !! temporary arrays
141
142 real(wp), dimension(kts:kte+1) :: vtrr, vtnr, vtrs, vtri, vtni, vtrg, vtng, vtrc, vtnc !! fallspeeds
143 real(wp), dimension(kts:kte) :: vtboost !! snow fallspeed boost factor
144 integer :: substeps_sedi, ktop_sedi, n !! sedimentation substepping variables
145 real(wp) :: semi_sedi_factor !! semi-lagrangian sedimentation factor
146
147 real(dp), target, dimension(kts:kte, 74) :: tend_work !! array to store tendencies
148
149 ! local variables
150 real(wp) :: tempc, tc0, odt
151 logical :: do_micro, supersaturated
152 logical, save :: first_call_main = .true.
153 integer :: k, nz
154
155 ! --------------------------------------------------------------------------------------------
156 do_micro = .false.
157 supersaturated = .false.
158 odt = 1._wp / dt
159
160 nz = size(qv1d)
161
162 ! map pointers to the contiguous stack workspace
163 ! warm rain
164 tend%prr_wau => tend_work(:, 1)
165 tend%pnr_wau => tend_work(:, 2)
166 tend%pnc_wau => tend_work(:, 3)
167 tend%prr_rcw => tend_work(:, 4)
168 tend%pnc_rcw => tend_work(:, 5)
169 tend%pnr_rcr => tend_work(:, 6)
170
171 ! riming
172 tend%prs_scw => tend_work(:, 7)
173 tend%pnc_scw => tend_work(:, 8)
174 tend%png_scw => tend_work(:, 9)
175 tend%pbg_scw => tend_work(:, 10)
176 tend%prg_gcw => tend_work(:, 11)
177 tend%pnc_gcw => tend_work(:, 12)
178 tend%pbg_gcw => tend_work(:, 13)
179 tend%pri_ihm => tend_work(:, 14)
180 tend%pni_ihm => tend_work(:, 15)
181 tend%prs_ihm => tend_work(:, 16)
182 tend%prg_ihm => tend_work(:, 17)
183 tend%prg_scw => tend_work(:, 18)
184
185 ! rain-snow
186 tend%prr_rcs => tend_work(:, 19)
187 tend%pnr_rcs => tend_work(:, 20)
188 tend%prg_rcs => tend_work(:, 21)
189 tend%png_rcs => tend_work(:, 22)
190 tend%prs_rcs => tend_work(:, 23)
191 tend%pbg_rcs => tend_work(:, 24)
192
193 ! rain-graupel
194 tend%prr_rcg => tend_work(:, 25)
195 tend%pnr_rcg => tend_work(:, 26)
196 tend%prg_rcg => tend_work(:, 27)
197 tend%png_rcg => tend_work(:, 28)
198 tend%pbg_rcg => tend_work(:, 29)
199
200 ! ice nucleation
201 tend%pri_inu => tend_work(:, 30)
202 tend%pni_inu => tend_work(:, 31)
203 tend%pri_iha => tend_work(:, 32)
204 tend%pni_iha => tend_work(:, 33)
205
206 ! water freezing
207 tend%pri_wfz => tend_work(:, 34)
208 tend%pni_wfz => tend_work(:, 35)
209
210 ! rain freezing
211 tend%prg_rfz => tend_work(:, 36)
212 tend%png_rfz => tend_work(:, 37)
213 tend%pnr_rfz => tend_work(:, 38)
214 tend%pri_rfz => tend_work(:, 39)
215 tend%pni_rfz => tend_work(:, 40)
216 tend%pbg_rfz => tend_work(:, 41)
217
218 ! depositional growth
219 tend%prs_sde => tend_work(:, 42)
220 tend%pri_ide => tend_work(:, 43)
221 tend%pni_ide => tend_work(:, 44)
222 tend%prs_ide => tend_work(:, 45)
223 tend%prg_gde => tend_work(:, 46)
224 tend%png_gde => tend_work(:, 47)
225
226 ! ice-snow conversion
227 tend%pni_iau => tend_work(:, 48)
228 tend%prs_iau => tend_work(:, 49)
229
230 ! melting
231 tend%prr_sml => tend_work(:, 50)
232 tend%prr_gml => tend_work(:, 51)
233 tend%pbg_sml => tend_work(:, 52)
234 tend%pbg_gml => tend_work(:, 53)
235 tend%pnr_sml => tend_work(:, 54)
236 tend%pnr_gml => tend_work(:, 55)
237
238 ! rain-ice
239 tend%prr_rci => tend_work(:, 56)
240 tend%pnr_rci => tend_work(:, 57)
241 tend%pri_rci => tend_work(:, 58)
242 tend%pni_rci => tend_work(:, 59)
243 tend%prg_rci => tend_work(:, 60)
244 tend%png_rci => tend_work(:, 61)
245 tend%pbg_rci => tend_work(:, 62)
246
247 ! snow-ice
248 tend%pni_sci => tend_work(:, 63)
249 tend%prs_sci => tend_work(:, 64)
250
251 ! condensation/evaporation
252 tend%prw_vcd => tend_work(:, 65)
253 tend%pnc_wcd => tend_work(:, 66)
254 tend%prv_rev => tend_work(:, 67)
255 tend%pnr_rev => tend_work(:, 68)
256
257 ! aerosol
258 tend%pna_rca => tend_work(:, 69)
259 tend%pna_sca => tend_work(:, 70)
260 tend%pna_gca => tend_work(:, 71)
261 tend%pnd_rcd => tend_work(:, 72)
262 tend%pnd_scd => tend_work(:, 73)
263 tend%pnd_gcd => tend_work(:, 74)
264
265 ! zero out all mp tendencies
266 tend_work = 0._dp
267
268 ! zero tendencies
269 do k = 1, nz
270 tten(k) = 0._wp
271 qvten(k) = 0._wp
272 qcten(k) = 0._wp
273 qiten(k) = 0._wp
274 qrten(k) = 0._wp
275 qsten(k) = 0._wp
276 qgten(k) = 0._wp
277 ngten(k) = 0._wp
278 qbten(k) = 0._wp
279 niten(k) = 0._wp
280 nrten(k) = 0._wp
281 ncten(k) = 0._wp
282 nwfaten(k) = 0._wp
283 nifaten(k) = 0._wp
284 smo0(k) = 0._dp
285 smo1(k) = 0._dp
286 smo2(k) = 0._dp
287 smob(k) = 0._dp
288 smoc(k) = 0._dp
289 smoe(k) = 0._dp
290 smof(k) = 0._dp
291 smog(k) = 0._dp
292 smoz(k) = 0._dp
293 ns(k) = 0._dp
294 vtboost(k) = 1._wp
295 enddo
296
297 ! fallspeeds and sedimentation
298 do k = 1, nz+1
299 vtrr(k) = 0._wp
300 vtnr(k) = 0._wp
301 vtrs(k) = 0._wp
302 vtri(k) = 0._wp
303 vtni(k) = 0._wp
304 vtrc(k) = 0._wp
305 vtnc(k) = 0._wp
306 vtrg(k) = 0._wp
307 vtng(k) = 0._wp
308 enddo
309
310 tempo_main_diags%rain_precip = 0._wp
311 tempo_main_diags%cloud_precip = 0._wp
312 tempo_main_diags%ice_liquid_equiv_precip = 0._wp
313 tempo_main_diags%snow_liquid_equiv_precip = 0._wp
314 tempo_main_diags%graupel_liquid_equiv_precip = 0._wp
315 tempo_main_diags%frz_rain_precip = 0._wp
316
317 ! initialization -----------------------------------------------------------------------------
318 do k = 1, nz
319 temp(k) = t1d(k)
320 qv(k) = max(min_qv, qv1d(k))
321 pres(k) = p1d(k)
322 rho(k) = roverrv*pres(k)/(rdry*temp(k)*(qv(k)+roverrv))
323 enddo
324
325 if (present(nwfa1d)) then
326 if (first_call_main) then
327 if (sum(nwfa1d) < eps) call init_water_friendly_aerosols(dz1d, nwfa)
328 endif
329 else
330 call init_water_friendly_aerosols(dz1d, nwfa)
331 endif
332
333 if (present(nifa1d)) then
334 if (first_call_main) then
335 if (sum(nifa1d) < eps) call init_ice_friendly_aerosols(dz1d, nifa)
336 endif
337 else
338 call init_ice_friendly_aerosols(dz1d, nifa)
339 endif
340
341 call aerosol_check_and_update(rho=rho, nwfa1d=nwfa1d, nifa1d=nifa1d, &
342 nwfa=nwfa, nifa=nifa, nwfaten=nwfaten, nifaten=nifaten, dt=dt)
343
344 call rain_check_and_update(rho, l_qr, qr1d, nr1d, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
345
346 call ice_check_and_update(rho, l_qi, qi1d, ni1d, ri, ni, qiten, niten, ilami, dt, odt)
347
348 call snow_check_and_update(rho, l_qs, qs1d, rs, qsten, dt, odt)
349 ! snow moments
350 do k = 1, nz
351 if (l_qs(k)) then
352 tc0 = min(-0.1, temp(k)-t0)
353 call snow_moments(rs=rs(k), tc=tc0, &
354 smob=smob(k), smoc=smoc(k), ns=ns(k), &
355 smo0=smo0(k), smo1=smo1(k), smo2=smo2(k), &
356 smoe=smoe(k), smof=smof(k), smog=smog(k))
357 endif
358 enddo
359
360 ! set one-moment cloud number concentration
361 if (.not. present(nc1d)) then
362 if (tempo_cfgs%ml_for_nc_flag) then
363 xrx = qc1d
364 where(xrx <= 1.e-12_wp) xrx = 0._wp
365 ! ml prediction
366 call get_cloud_number(xrx, qr1d, qi1d, qs1d, pres, temp, w1d, xnx)
367 nc = xnx * rho
368 else
369 ! single moment constant value
370 if (present(land1d)) then
371 call get_cloud_number(land=land1d, nc=nc)
372 else
373 nc = tempo_cfgs%get_nc_val(val_land=nt_c_l, val_ocean=nt_c_o)
374 endif
375 endif
376 allocate(ncsave(nz), source=nc)
377 endif
378
379 call cloud_check_and_update(rho=rho, l_qc=l_qc, qc1d=qc1d, nc1d=nc1d, &
380 ncsave=ncsave, rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c, &
381 dt=dt, odt=odt)
382
383 ! init ng and qb
384 if (first_call_main) then
385 if (present(ng1d) .and. present(qb1d)) then
386 if (sum(qg1d) > r1 .and. sum(ng1d) < eps .and. sum(qb1d) < eps) then
387 call graupel_init(rho, qg1d, ng1d, qb1d)
388 endif
389 endif
390 endif
391 call graupel_check_and_update(rho=rho, l_qg=l_qg, qg1d=qg1d, ng1d=ng1d, &
392 qb1d=qb1d, rg=rg, ng=ng, rb=rb, idx=idx_bg, qgten=qgten, ngten=ngten, &
393 qbten=qbten, ilamg=ilamg, mvd_g=mvd_g, dt=dt, odt=odt)
394
395 ! re-zero tendencies after initial check zero tendencies
396 do k = 1, nz
397 qcten(k) = 0._wp
398 qiten(k) = 0._wp
399 qrten(k) = 0._wp
400 qsten(k) = 0._wp
401 qgten(k) = 0._wp
402 ngten(k) = 0._wp
403 qbten(k) = 0._wp
404 niten(k) = 0._wp
405 nrten(k) = 0._wp
406 ncten(k) = 0._wp
407 enddo
408
409 call thermo_vars(qv, temp, pres, rho, rhof, rhof2, qvs, delqvs, qvsi, &
410 satw, sati, ssatw, ssati, diffu, visco, vsc2, ocp, lvap, tcond, lvt2, &
411 supersaturated)
412
413 if (first_call_main) first_call_main = .false.
414
415 ! check for hydrometeors or supersaturation --------------------------------------------------
416 do_micro = any(l_qc) .or. any(l_qr) .or. any(l_qi) .or. any(l_qs) .or. any(l_qg)
417 if (.not. do_micro .and. .not. supersaturated) return
418
419 ! main microphysical processes ---------------------------------------------------------------
420 if (.not. tempo_cfgs%turn_off_micro_flag) then
421 call warm_rain(rhof, l_qc, rc, nc, ilamc, mvd_c, l_qr, rr, nr, mvd_r, tend, odt)
422 endif
423 if (.not. tempo_cfgs%turn_off_micro_flag) then
424 call rain_snow_rain_graupel(temp, l_qr, rr, nr, ilamr, l_qs, rs, &
425 l_qg, rg, ng, ilamg, idx_bg, tend, odt)
426 endif
427 if (.not. tempo_cfgs%turn_off_micro_flag) then
428 call ice_nucleation(temp, rho, w1d, qv, qvsi, ssati, ssatw, &
429 nwfa1d, nifa1d, nwfa, nifa, ni, smo0, rc, nc, rr, nr, ilamr, tend, dt, odt)
430 endif
431 if (.not. tempo_cfgs%turn_off_micro_flag) then
432 call ice_processes(rhof, rhof2, rho, w1d, temp, qv, qvsi, tcond, diffu, &
433 vsc2, ssati, l_qi, ri, ni, ilami, l_qs, rs, smoe, smof, smo1, rr, nr, &
434 ilamr, mvd_r, l_qg, rg, ng, ilamg, idx_bg, tend, odt)
435 endif
436 if (.not. tempo_cfgs%turn_off_micro_flag) then
437 call riming(temp, rhof, visco, l_qc, rc, nc, ilamc, mvd_c, l_qs, rs, &
438 smo0, smob, smoc, smoe, vtboost, l_qg, rg, ng, ilamg, idx_bg, tend, odt)
439 endif
440 if (.not. tempo_cfgs%turn_off_micro_flag) then
441 call melting(rhof2, rho, temp, qvsi, tcond, diffu, vsc2, ssati, delqvs, &
442 l_qs, rs, smof, smo0, smo1, l_qg, rg, ng, ilamg, idx_bg, tend, dt, odt)
443 endif
444 if (.not. tempo_cfgs%turn_off_micro_flag) then
445 if (present(nwfa1d) .or. present(nifa1d)) then
446 call aerosol_scavenging(temp, rho, rhof, visco, nwfa, nifa, l_qr, nr, ilamr, &
447 mvd_r, l_qs, rs, smob, smoc, smoe, l_qg, rg, ng, ilamg, idx_bg, tend, odt)
448 endif
449 endif
450
451 ! check and sum tendencies -------------------------------------------------------------------
452 call check_over_depletion(rho, temp, qvsi, qv, l_qc, rc, l_qi, ri, &
453 l_qr, rr, l_qs, rs, l_qg, rg, tend, odt)
454
455 call sum_tendencies(rho, temp, idx_bg, lvap, ocp, tend, tten, qvten, qcten, &
456 ncten, qiten, niten, qsten, qrten, nrten, qgten, ngten, qbten)
457
458 ! update after tendencies applied ------------------------------------------------------------
459 do k = 1, nz
460 temp(k) = t1d(k) + tten(k)*dt
461 tempc = temp(k) - t0
462 qv(k) = max(min_qv, qv1d(k) + qvten(k)*dt)
463 rho(k) = roverrv*pres(k)/(rdry*temp(k)*(qv(k)+roverrv))
464 nwfaten(k) = nwfaten(k) - (tend%pna_rca(k) + tend%pna_sca(k) + tend%pna_gca(k) + &
465 tend%pni_iha(k)) / rho(k)
466 nifaten(k) = nifaten(k) - (tend%pnd_rcd(k) + tend%pnd_scd(k) + tend%pnd_gcd(k)) / rho(k)
467 enddo
468
469 ! only updates nwfa, nifa
470 call aerosol_check_and_update(rho=rho, nwfa1d=nwfa1d, nifa1d=nifa1d, &
471 nwfa=nwfa, nifa=nifa, nwfaten=nwfaten, nifaten=nifaten, dt=dt)
472
473 ! send temporary arrays to avoid updates to 1d variables at this point
474 xrx = qc1d
475 if (present(nc1d)) then
476 if (.not. allocated(xncx)) allocate(xncx(nz), source=0._wp)
477 xncx = nc1d
478 endif
479 call cloud_check_and_update(rho=rho, l_qc=l_qc, qc1d=xrx, nc1d=xncx, &
480 ncsave=ncsave, rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c, &
481 dt=dt, odt=odt)
482
483 xrx = qr1d
484 xnx = nr1d
485 call rain_check_and_update(rho, l_qr, xrx, xnx, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
486
487 xrx = qi1d
488 xnx = ni1d
489 call ice_check_and_update(rho, l_qi, xrx, xnx, ri, ni, qiten, niten, ilami, dt, odt)
490
491 xrx = qs1d
492 call snow_check_and_update(rho, l_qs, xrx, rs, qsten, dt, odt)
493 ! snow moments
494 do k = 1, nz
495 smo0(k) = 0._dp
496 smo1(k) = 0._dp
497 smo2(k) = 0._dp
498 smob(k) = 0._dp
499 smoc(k) = 0._dp
500 smoe(k) = 0._dp
501 smof(k) = 0._dp
502 smog(k) = 0._dp
503 ns(k) = 0._dp
504 if (l_qs(k)) then
505 tc0 = min(-0.1, temp(k)-t0)
506 call snow_moments(rs=rs(k), tc=tc0, &
507 smob=smob(k), smoc=smoc(k), &
508 smo2=smo2(k))
509 endif
510 enddo
511
512 xrx = qg1d
513 if (present(ng1d) .and. present(qb1d)) then
514 if (.not. allocated(xngx)) allocate(xngx(nz), source=0._wp)
515 if (.not. allocated(xqbx)) allocate(xqbx(nz), source=0._wp)
516 xngx = ng1d
517 xqbx = qb1d
518 endif
519 call graupel_check_and_update(rho=rho, l_qg=l_qg, qg1d=xrx, ng1d=xngx, &
520 qb1d=xqbx, rg=rg, ng=ng, rb=rb, idx=idx_bg, qgten=qgten, ngten=ngten, &
521 qbten=qbten, ilamg=ilamg, mvd_g=mvd_g, dt=dt, odt=odt)
522
523 call thermo_vars(qv, temp, pres, rho, rhof, rhof2, qvs, delqvs, qvsi, &
524 satw, sati, ssatw, ssati, diffu, visco, vsc2, ocp, lvap, tcond, lvt2, &
525 supersaturated)
526
527 ! after update do cloud condensation / rain evaporation --------------------------------------
528 ! cloud condensation
529 if (.not. tempo_cfgs%turn_off_micro_flag .and. tempo_cfgs%cloud_condensation_flag) then
530 call cloud_condensation(rho, temp, w1d, ssatw, lvap, tcond, diffu, lvt2, &
531 nwfa1d, nwfa, ncsave, qv, qvs, l_qc, rc, nc, tend, dt, odt)
532
533 do k = 1, nz
534 qvten(k) = qvten(k) - tend%prw_vcd(k)
535 qcten(k) = qcten(k) + tend%prw_vcd(k)
536 ncten(k) = ncten(k) + tend%pnc_wcd(k)
537 nwfaten(k) = nwfaten(k) - tend%pnc_wcd(k)
538 tten(k) = tten(k) + lvap(k)*ocp(k)*tend%prw_vcd(k)
539 enddo
540
541 xrx = qc1d
542 if (present(nc1d)) then
543 if (.not. allocated(xncx)) allocate(xncx(nz), source=0._wp)
544 xncx = nc1d
545 endif
546 call cloud_check_and_update(rho=rho, l_qc=l_qc, qc1d=xrx, nc1d=xncx, &
547 ncsave=ncsave, rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c, &
548 dt=dt, odt=odt)
549
550 do k = 1, nz
551 qv(k) = max(min_qv, qv1d(k) + qvten(k)*dt)
552 temp(k) = t1d(k) + tten(k)*dt
553 rho(k) = roverrv*pres(k)/(rdry*temp(k)*(qv(k)+roverrv))
554 enddo
555
556 call thermo_vars(qv, temp, pres, rho, rhof, rhof2, qvs, delqvs, qvsi, &
557 satw, sati, ssatw, ssati, diffu, visco, vsc2, ocp, lvap, tcond, lvt2, &
558 supersaturated)
559 endif
560
561 ! rain evaporation
562 if (.not. tempo_cfgs%turn_off_micro_flag) then
563 call rain_evaporation(rho, temp, ssatw, lvap, tcond, diffu, vsc2, rhof2, &
564 qv, qvs, l_qr, rr, nr, ilamr, tend, odt)
565
566 do k = 1, nz
567 qrten(k) = qrten(k) - tend%prv_rev(k)
568 qvten(k) = qvten(k) + tend%prv_rev(k)
569 nrten(k) = nrten(k) - tend%pnr_rev(k)
570 nwfaten(k) = nwfaten(k) + tend%pnr_rev(k)
571 tten(k) = tten(k) - lvap(k)*ocp(k)*tend%prv_rev(k)
572 enddo
573
574 xrx = qr1d
575 xnx = nr1d
576 call rain_check_and_update(rho, l_qr, xrx, xnx, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
577
578 do k = 1, nz
579 qv(k) = max(min_qv, qv1d(k) + qvten(k)*dt)
580 temp(k) = t1d(k) + tten(k)*dt
581 rho(k) = roverrv*pres(k)/(rdry*temp(k)*(qv(k)+roverrv))
582 enddo
583
584 call thermo_vars(qv, temp, pres, rho, rhof, rhof2, qvs, delqvs, qvsi, &
585 satw, sati, ssatw, ssati, diffu, visco, vsc2, ocp, lvap, tcond, lvt2, &
586 supersaturated)
587 endif
588
589 ! sedimentation ------------------------------------------------------------------------------
590
591 ! rain
592 ktop_sedi = 1
593 substeps_sedi = 1
594 semi_sedi_factor = 10._wp
595 if (any(l_qr)) then
596 call rain_fallspeed(rhof=rhof, l_qr=l_qr, rr=rr, ilamr=ilamr, dz1d=dz1d, &
597 vt=vtrr, vtn=vtnr, substeps_sedi=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
598
599 if (tempo_cfgs%semi_sedi_flag) then
600 substeps_sedi = max(int(substeps_sedi/semi_sedi_factor) + 1, 1)
601 do n = 1, substeps_sedi
602 call semilagrangian_sedimentation(dz1d=dz1d, rho=rho, xr=rr, xten=qrten, &
603 vt=vtrr, steps=substeps_sedi, limit=r1, precip=tempo_main_diags%rain_precip, dt=dt, odt=odt)
604 call semilagrangian_sedimentation(dz1d=dz1d, rho=rho, xr=nr, xten=nrten, &
605 vt=vtnr, steps=substeps_sedi, limit=r2, dt=dt, odt=odt)
606 vtrr = 0._wp
607 vtnr = 0._wp
608 xrx = qr1d
609 xnx = nr1d
610 call rain_check_and_update(rho, l_qr, xrx, xnx, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
611 call rain_fallspeed(rhof=rhof, l_qr=l_qr, rr=rr, ilamr=ilamr, dz1d=dz1d, &
612 vt=vtrr, vtn=vtnr, dt=dt)
613 enddo
614 else
615 do n = 1, substeps_sedi
616 call sedimentation(xr=rr, vt=vtrr, dz1d=dz1d, rho=rho, xten=qrten, limit=r1, &
617 steps=substeps_sedi, ktop_sedi=ktop_sedi, precip=tempo_main_diags%rain_precip, dt=dt)
618 call sedimentation(xr=nr, vt=vtnr, dz1d=dz1d, rho=rho, xten=nrten, limit=r2, &
619 steps=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
620 ! vtrr = 0._wp
621 ! vtnr = 0._wp
622 ! xrx = qr1d
623 ! xnx = nr1d
624 ! call rain_check_and_update(rho, l_qr, xrx, xnx, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
625 ! call rain_fallspeed(rhof=rhof, l_qr=l_qr, rr=rr, ilamr=ilamr, dz1d=dz1d, &
626 ! vt=vtrr, vtn=vtnr, dt=dt)
627 enddo
628 endif
629 endif
630
631 ! graupel
632 ktop_sedi = 1
633 substeps_sedi = 1
634 semi_sedi_factor = 10._wp
635 if (any(l_qg)) then
636 call graupel_fallspeed(rhof=rhof, rho=rho, visco=visco, &
637 l_qg=l_qg, rg=rg, rb=rb, qb1d=qb1d, idx=idx_bg, ilamg=ilamg, dz1d=dz1d, &
638 vt=vtrg, vtn=vtng, substeps_sedi=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
639
640 if (tempo_cfgs%semi_sedi_flag) then
641 substeps_sedi = max(int(substeps_sedi/semi_sedi_factor) + 1, 1)
642 do n = 1, substeps_sedi
643 call semilagrangian_sedimentation(dz1d=dz1d, rho=rho, xr=rg, xten=qgten, &
644 vt=vtrg, steps=substeps_sedi, limit=r1, precip=tempo_main_diags%graupel_liquid_equiv_precip, &
645 dt=dt, odt=odt)
646 call semilagrangian_sedimentation(dz1d=dz1d, rho=rho, xr=ng, xten=ngten, &
647 vt=vtng, steps=substeps_sedi, limit=r2, dt=dt, odt=odt)
648 call semilagrangian_sedimentation(dz1d=dz1d, rho=rho, xr=rb, xten=qbten, &
649 vt=vtrg, steps=substeps_sedi, limit=meters3_to_liters*r1/rho_g(nrhg), dt=dt, odt=odt)
650 vtrg = 0._wp
651 vtng = 0._wp
652 xrx = qg1d
653 if (present(ng1d) .and. present(qb1d)) then
654 if (.not. allocated(xngx)) allocate(xngx(nz), source=0._wp)
655 if (.not. allocated(xqbx)) allocate(xqbx(nz), source=0._wp)
656 xngx = ng1d
657 xqbx = qb1d
658 endif
659 call graupel_check_and_update(rho=rho, l_qg=l_qg, qg1d=xrx, ng1d=xngx, &
660 qb1d=xqbx, rg=rg, ng=ng, rb=rb, idx=idx_bg, qgten=qgten, ngten=ngten, &
661 qbten=qbten, ilamg=ilamg, mvd_g=mvd_g, dt=dt, odt=odt)
662 call graupel_fallspeed(rhof=rhof, rho=rho, visco=visco, &
663 l_qg=l_qg, rg=rg, rb=rb, qb1d=qb1d, idx=idx_bg, ilamg=ilamg, dz1d=dz1d, &
664 vt=vtrg, vtn=vtng, dt=dt)
665 enddo
666 else
667 do n = 1, substeps_sedi
668 call sedimentation(xr=rg, vt=vtrg, dz1d=dz1d, rho=rho, xten=qgten, limit=r1, &
669 steps=substeps_sedi, ktop_sedi=ktop_sedi, precip=tempo_main_diags%graupel_liquid_equiv_precip, dt=dt)
670 call sedimentation(xr=ng, vt=vtng, dz1d=dz1d, rho=rho, xten=ngten, limit=r2, &
671 steps=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
672 call sedimentation(xr=rb, vt=vtrg, dz1d=dz1d, rho=rho, xten=qbten, &
673 limit=meters3_to_liters*r1/rho_g(nrhg), steps=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
674 ! vtrg = 0._wp
675 ! vtng = 0._wp
676 ! xrx = qg1d
677 ! if (present(ng1d) .and. present(qb1d)) then
678 ! if (.not. allocated(xngx)) allocate(xngx(nz), source=0._wp)
679 ! if (.not. allocated(xqbx)) allocate(xqbx(nz), source=0._wp)
680 ! xngx = ng1d
681 ! xqbx = qb1d
682 ! endif
683 ! call graupel_check_and_update(rho=rho, l_qg=l_qg, qg1d=xrx, ng1d=xngx, &
684 ! qb1d=xqbx, rg=rg, ng=ng, rb=rb, idx=idx_bg, qgten=qgten, ngten=ngten, &
685 ! qbten=qbten, ilamg=ilamg, mvd_g=mvd_g, dt=dt, odt=odt)
686 ! call graupel_fallspeed(rhof=rhof, rho=rho, visco=visco, &
687 ! l_qg=l_qg, rg=rg, rb=rb, qb1d=qb1d, idx=idx_bg, ilamg=ilamg, dz1d=dz1d, &
688 ! vt=vtrg, vtn=vtng, dt=dt)
689 enddo
690 endif
691 endif
692
693 ! snow
694 ktop_sedi = 1
695 substeps_sedi = 1
696 if (any(l_qs)) then
697 call snow_fallspeed(rhof=rhof, l_qs=l_qs, rs=rs, prr_sml=tend%prr_sml, smob=smob, smoc=smoc, &
698 rr=rr, vtrr=vtrr, dz1d=dz1d, vt=vtrs, vtboost=vtboost, substeps_sedi=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
699 do n = 1, substeps_sedi
700 call sedimentation(xr=rs, vt=vtrs, dz1d=dz1d, rho=rho, xten=qsten, limit=r1, &
701 steps=substeps_sedi, ktop_sedi=ktop_sedi, precip=tempo_main_diags%snow_liquid_equiv_precip, dt=dt)
702 enddo
703 endif
704
705 ! ice
706 ktop_sedi = 1
707 substeps_sedi = 1
708 if (any(l_qi)) then
709 call ice_fallspeed(rhof, l_qi, ri, ilami, dz1d, vtri, vtni, &
710 substeps_sedi, ktop_sedi, dt=dt)
711 call sedimentation(xr=ri, vt=vtri, dz1d=dz1d, rho=rho, xten=qiten, limit=r1, &
712 steps=substeps_sedi, ktop_sedi=ktop_sedi, precip=tempo_main_diags%ice_liquid_equiv_precip, dt=dt)
713 call sedimentation(xr=ni, vt=vtni, dz1d=dz1d, rho=rho, xten=niten, limit=r2, &
714 steps=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
715 endif
716
717 ! cloud
718 ktop_sedi = 1
719 substeps_sedi = 1
720 if (any(l_qc)) then
721 call cloud_fallspeed(rhof, w1d, l_qc, rc, nc, ilamc, dz1d, vtrc, vtnc, ktop_sedi)
722 call sedimentation(xr=rc, vt=vtrc, dz1d=dz1d, rho=rho, xten=qcten, limit=r1, &
723 steps=substeps_sedi, ktop_sedi=ktop_sedi, precip=tempo_main_diags%cloud_precip, dt=dt)
724 call sedimentation(xr=nc, vt=vtnc, dz1d=dz1d, rho=rho, xten=ncten, limit=r2, &
725 steps=substeps_sedi, ktop_sedi=ktop_sedi, dt=dt)
726 endif
727
728 ! after sedimentation freeze all cloud water below hgfrz temperature
729 ! and melt all cloud ice above freezing
730 if (.not. tempo_cfgs%turn_off_micro_flag) then
731 call freeze_cloud_melt_ice(temp=temp, rho=rho, ocp=ocp, lvap=lvap, &
732 qi1d=qi1d, ni1d=ni1d, qiten=qiten, niten=niten, qc1d=qc1d, nc1d=nc1d, &
733 qcten=qcten, ncten=ncten, tten=tten, ncsave=ncsave, dt=dt, odt=odt)
734 endif
735
736 ! final update -------------------------------------------------------------------------------
737 do k = 1, nz
738 t1d(k) = t1d(k) + tten(k)*dt
739 qv1d(k) = max(min_qv, (qv1d(k) + qvten(k)*dt))
740 rho(k) = roverrv*pres(k)/(rdry*temp(k)*(qv(k)+roverrv))
741 if (present(nwfa1d)) then
742 nwfa1d(k) = max(nwfa_default, min(aero_max, (nwfa1d(k)+nwfaten(k)*dt)))
743 endif
744 if (present(nifa1d)) then
745 nifa1d(k) = max(nifa_default, min(aero_max, (nifa1d(k)+nifaten(k)*dt)))
746 endif
747 enddo
748
749 call cloud_check_and_update(rho=rho, l_qc=l_qc, qc1d=qc1d, nc1d=nc1d, &
750 ncsave=ncsave, rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c, &
751 dt=dt, odt=odt)
752
753 call rain_check_and_update(rho, l_qr, qr1d, nr1d, rr, nr, qrten, nrten, ilamr, mvd_r, dt, odt)
754
755 call ice_check_and_update(rho, l_qi, qi1d, ni1d, ri, ni, qiten, niten, ilami, dt, odt)
756
757 call snow_check_and_update(rho, l_qs, qs1d, rs, qsten, dt, odt)
758 ! snow moments
759 do k = 1, nz
760 smo0(k) = 0._dp
761 smo1(k) = 0._dp
762 smo2(k) = 0._dp
763 smob(k) = 0._dp
764 smoc(k) = 0._dp
765 smoe(k) = 0._dp
766 smof(k) = 0._dp
767 smog(k) = 0._dp
768 smoz(k) = 0._dp
769 ns(k) = 0._dp
770 if (l_qs(k)) then
771 tc0 = min(-0.1, temp(k)-t0)
772 call snow_moments(rs=rs(k), tc=tc0, &
773 smob=smob(k), smoc=smoc(k), &
774 smo2=smo2(k), smoz=smoz(k))
775 endif
776 enddo
777
778 call graupel_check_and_update(rho=rho, l_qg=l_qg, qg1d=qg1d, ng1d=ng1d, &
779 qb1d=qb1d, rg=rg, ng=ng, rb=rb, idx=idx_bg, qgten=qgten, ngten=ngten, &
780 qbten=qbten, ilamg=ilamg, mvd_g=mvd_g, dt=dt, odt=odt)
781
782 ! diagnostic output --------------------------------------------------------------------------
783 ! frozen fraction
784 tempo_main_diags%frozen_fraction = &
785 (tempo_main_diags%ice_liquid_equiv_precip + tempo_main_diags%snow_liquid_equiv_precip + &
786 tempo_main_diags%graupel_liquid_equiv_precip) / &
787 (tempo_main_diags%ice_liquid_equiv_precip + tempo_main_diags%snow_liquid_equiv_precip + &
788 tempo_main_diags%graupel_liquid_equiv_precip + tempo_main_diags%rain_precip + r1)
789
790 ! freezing rain
791 call freezing_rain(temp=temp(1), rain_precip=tempo_main_diags%rain_precip, &
792 cloud_precip=tempo_main_diags%cloud_precip, &
793 frz_rain=tempo_main_diags%frz_rain_precip)
794
795 if (tempo_cfgs%cloud_number_mixing_ratio_flag) then
796 allocate(tempo_main_diags%cloud_number_mixing_ratio(nz), source=nc*rho)
797 endif
798
799 ! median volume diameter of rain and graupel
800 if (tempo_cfgs%rain_med_vol_diam_flag) then
801 allocate(tempo_main_diags%rain_med_vol_diam(nz), source=0._wp)
802 tempo_main_diags%rain_med_vol_diam = mvd_r
803 endif
804 if (tempo_cfgs%graupel_med_vol_diam_flag) then
805 allocate(tempo_main_diags%graupel_med_vol_diam(nz), source=0._wp)
806 tempo_main_diags%graupel_med_vol_diam = mvd_g
807 endif
808
809 ! max hail diameter
810 if (tempo_cfgs%max_hail_diameter_flag) then
811 allocate(tempo_main_diags%max_hail_diameter(nz), source=0._wp)
812 call max_hail_diam(rho, rg, ng, ilamg, idx_bg, &
813 tempo_main_diags%max_hail_diameter)
814 endif
815
816 ! 10-cm reflectivity
817 if (tempo_cfgs%refl10cm_flag) then
818 allocate(tempo_main_diags%refl10cm(nz), source=-35._wp)
819 call reflectivity_10cm(tempo_cfgs%refl10cm_from_melting_flag, &
820 temp, l_qr, rr, nr, ilamr, &
821 l_qs, rs, smoc, smob, smoz, l_qg, rg, ng, idx_bg, ilamg, &
822 tempo_main_diags%refl10cm)
823 endif
824
825 ! effective radii
826 if ((tempo_cfgs%re_cloud_flag) .and. (tempo_cfgs%re_ice_flag) .and. (tempo_cfgs%re_snow_flag)) then
827 allocate(tempo_main_diags%re_cloud(nz), source=0._wp)
828 allocate(tempo_main_diags%re_ice(nz), source=0._wp)
829 allocate(tempo_main_diags%re_snow(nz), source=0._wp)
830
831 ! this next code block optionally adds pbl clouds to resolved clouds
832 ! for the effective radius calculation
833 ! thus qc -> qc + qc_bl, a new value of nc is predicted with ML,
834 ! and then ilamc is updated along with rc and nc before re is calculated
835 ! please output any cloud diagnostics before this calculation
836 ! because rc, nc, ilamc, and mvd_c will include contributions from
837 ! resolved and explicit clouds and qcten and ncten are zeroed
838 if (present(qc_bl1d) .and. present(qcfrac_bl1d)) then
839 xrx = qc1d
840 if (.not. allocated(xncx)) allocate(xncx(nz), source=0._wp)
841 xncx = nc1d
842 do k = 1, nz
843 if ((xrx(k) <= r1) .and. &
844 (qc_bl1d(k) > 1.e-9_wp) .and. (qcfrac_bl1d(k) > 0._wp)) then
845 xrx(k) = xrx(k) + qc_bl1d(k) / qcfrac_bl1d(k) ! use in-cloud PBL mass
846 endif
847 enddo
848 where(xrx <= 1.e-12_wp) xrx = 0._wp
849 ! ml prediction
850 call get_cloud_number(xrx, qr1d, qi1d, qs1d, pres, temp, w1d, xncx)
851
852 ! xrx and xncx have been updated to include pbl contribution -> update ilamc and nc
853 ! for effective radius calculation
854 qcten = 0._wp
855 ncten = 0._wp
856 call cloud_check_and_update(rho=rho, l_qc=l_qc, qc1d=xrx, nc1d=xncx, &
857 rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c, &
858 dt=dt, odt=odt)
859 endif
860 call effective_radius(temp, l_qc, nc, ilamc, l_qi, ilami, l_qs, rs, &
861 tempo_main_diags%re_cloud, tempo_main_diags%re_ice, tempo_main_diags%re_snow)
862 endif
863 end subroutine tempo_main
864
865
866 subroutine aerosol_check_and_update(rho, nwfa1d, nifa1d, nwfa, nifa, nwfaten, nifaten, dt)
867 !! sets aerosol number concentrations and checks bounds
868 use module_mp_tempo_params, only : nwfa_default, aero_max, nifa_default
869
870 real(wp), intent(in) :: dt
871 real(wp), dimension(:), intent(in) :: rho
872 real(wp), dimension(:), intent(inout) :: nwfa, nifa, nwfaten, nifaten
873 real(wp), dimension(:), intent(inout), optional :: nwfa1d, nifa1d
874 integer :: k, nz
875
876 nz = size(rho)
877 do k = 1, nz
878 if (present(nwfa1d)) then
879 nwfa(k) = (nwfa1d(k)+nwfaten(k)*dt)*rho(k)
880 endif
881 if (present(nifa1d)) then
882 nifa(k) = (nifa1d(k)+nifaten(k)*dt)*rho(k)
883 endif
884 nwfa(k) = max(nwfa_default*rho(k), min(aero_max*rho(k), nwfa(k)))
885 nifa(k) = max(nifa_default*rho(k), min(aero_max*rho(k), nifa(k)))
886 enddo
887 end subroutine aerosol_check_and_update
888
889
890 subroutine cloud_check_and_update(rho, l_qc, qc1d, nc1d, ncsave, rc, nc, &
891 qcten, ncten, ilamc, mvd_c, dt, odt)
892 !! computes cloud water contents, ilamc, and mvd_c and checks bounds
893 use module_mp_tempo_params, only : r1, nt_c_max, nt_c_min, nu_c_scale, &
894 am_r, bm_r, cce, ccg, d0c, d0r, ocg1, ocg2, obmr, nt_c_l, d0r, nt_c_l
895
896 real(wp), intent(in) :: dt, odt
897 real(wp), dimension(:), intent(in) :: rho
898 real(wp), dimension(:), intent(inout) :: qc1d, qcten, ncten, rc, nc
899 real(wp), dimension(:), intent(out) :: mvd_c
900 real(dp), dimension(:), intent(out) :: ilamc
901 real(wp), dimension(:), intent(inout), optional :: nc1d, ncsave
902 logical, dimension(:), intent(inout) :: l_qc
903 integer :: k, nz, nu_c
904 real(dp) :: lamc, xdc
905 logical :: hit_limit
906
907 nz = size(qc1d)
908 do k = 1, nz
909 hit_limit = .false.
910 if (qc1d(k)+qcten(k)*dt > r1) then
911 l_qc(k) = .true.
912 ! update mass
913 rc(k) = (qc1d(k)+qcten(k)*dt)*rho(k)
914 qc1d(k) = qc1d(k)+qcten(k)*dt
915
916 ! update number
917 if (present(nc1d)) then
918 nc(k) = max(nt_c_min, (nc1d(k)+ncten(k)*dt)*rho(k))
919
920 ! number check
921 if (nc(k) <= nt_c_min) then
922 hit_limit = .true.
923 nc(k) = nt_c_min
924 endif
925 if (nc(k) > nt_c_max) then
926 hit_limit = .true.
927 nc(k) = nt_c_max
928 endif
929
930 ! size check
931 nu_c = get_nuc(nc(k))
932 lamc = (nc(k)*am_r*ccg(2,nu_c)*ocg1(nu_c)/rc(k))**obmr
933 xdc = (bm_r + nu_c + 1._dp) / lamc
934 if (xdc < d0c) then
935 lamc = cce(2,nu_c)/d0c
936 hit_limit = .true.
937 elseif (xdc > d0r*2._dp) then
938 lamc = cce(2,nu_c)/(d0r*2._dp)
939 hit_limit = .true.
940 endif
941 ! update number to be consistent with lamc
942 nc(k) = ccg(1,nu_c)*ocg2(nu_c)*rc(k) / am_r*lamc**bm_r
943
944 if (hit_limit) ncten(k) = (nc(k)/rho(k) - nc1d(k)) * odt
945 nc1d(k) = max(nt_c_min/rho(k), &
946 min(real(ccg(1,nu_c)*ocg2(nu_c)*qc1d(k)/am_r*lamc**bm_r, kind=wp), nt_c_max/rho(k)))
947 else
948 if (present(ncsave)) then
949 nc(k) = ncsave(k)
950 else
951 nc(k) = nt_c_l
952 endif
953 endif
954 nu_c = get_nuc(nc(k))
955 lamc = (nc(k)*am_r*ccg(2,nu_c)*ocg1(nu_c)/rc(k))**obmr
956 ilamc(k) = 1._dp / lamc
957 mvd_c(k) = max(min(real((3.0_wp + nu_c + 0.672_wp) * ilamc(k), kind=wp), d0r), d0c)
958 else
959 l_qc(k) = .false.
960 rc(k) = r1
961 nc(k) = nt_c_min
962 mvd_c(k) = d0c
963 ilamc(k) = 0._dp
964 qcten(k) = -qc1d(k) * odt
965 qc1d(k) = 0.0_wp
966 if (present(nc1d)) then
967 ncten(k) = -nc1d(k) * odt
968 nc1d(k) = 0.0_wp
969 endif
970 endif
971 enddo
972 end subroutine cloud_check_and_update
973
974
975 subroutine rain_check_and_update(rho, l_qr, qr1d, nr1d, rr, nr, &
976 qrten, nrten, ilamr, mvd_r, dt, odt)
977 !! computes rain water contents, ilamr, and mvd_r and checks bounds
978 use module_mp_tempo_params, only : r1, r2, mu_r, crg, &
979 am_r, bm_r, obmr, d0r, d0r_max, org2, org3, rho_g
980
981 real(wp), intent(in) :: dt, odt
982 real(wp), dimension(:), intent(in) :: rho
983 real(wp), dimension(:), intent(inout) :: qr1d, nr1d, qrten, nrten, rr, nr
984 real(wp), dimension(:), intent(out) :: mvd_r
985 real(dp), dimension(:), intent(out) :: ilamr
986 logical, dimension(:), intent(inout) :: l_qr
987 integer :: k, nz
988 real(dp) :: lamr
989 logical :: hit_limit
990
991 nz = size(qr1d)
992 do k = 1, nz
993 hit_limit = .false.
994 if (qr1d(k)+qrten(k)*dt > r1) then
995 l_qr(k) = .true.
996 ! update mass
997 rr(k) = (qr1d(k)+qrten(k)*dt)*rho(k)
998 qr1d(k) = qr1d(k)+qrten(k)*dt
999
1000 ! update number
1001 nr(k) = max(r2, (nr1d(k)+nrten(k)*dt)*rho(k))
1002
1003 ! number check
1004 if (nr(k) <= r2) then
1005 hit_limit = .true.
1006 mvd_r(k) = 1.0e-3_wp
1007 lamr = (3.0_dp + mu_r + 0.672_dp) / mvd_r(k)
1008 nr(k) = crg(2)*org3*rr(k)*lamr**bm_r / am_r
1009 endif
1010
1011 ! size check
1012 lamr = (am_r*crg(3)*org2*nr(k)/rr(k))**obmr
1013 mvd_r(k) = (3.0_wp + mu_r + 0.672_wp) / lamr
1014 if (mvd_r(k) > d0r_max) then
1015 hit_limit = .true.
1016 mvd_r(k) = d0r_max
1017 lamr = (3.0_dp + mu_r + 0.672_dp) / mvd_r(k)
1018 nr(k) = crg(2)*org3*rr(k)*lamr**bm_r / am_r
1019 elseif (mvd_r(k) < d0r*0.75_wp) then
1020 hit_limit = .true.
1021 mvd_r(k) = d0r*0.75_wp
1022 lamr = (3.0_dp + mu_r + 0.672_dp) / mvd_r(k)
1023 nr(k) = crg(2)*org3*rr(k)*lamr**bm_r / am_r
1024 endif
1025 ! update number to be consistent with lamc
1026 if (hit_limit) nrten(k) = (nr(k)/rho(k) - nr1d(k))*odt
1027 nr1d(k) = crg(2)*org3*qr1d(k)*lamr**bm_r / am_r
1028 ilamr(k) = 1._dp / lamr
1029 else
1030 l_qr(k) = .false.
1031 rr(k) = r1
1032 nr(k) = r2
1033 mvd_r(k) = d0r
1034 ilamr(k) = 0._dp
1035 qrten(k) = -qr1d(k) * odt
1036 nrten(k) = -nr1d(k) * odt
1037 qr1d(k) = 0.0_wp
1038 nr1d(k) = 0.0_wp
1039 endif
1040 enddo
1041 end subroutine rain_check_and_update
1042
1043
1044 subroutine ice_check_and_update(rho, l_qi, qi1d, ni1d, ri, ni, &
1045 qiten, niten, ilami, dt, odt)
1046 !! computes ice contents, ilami and checks bounds
1047 use module_mp_tempo_params, only : max_ni, r1, r2, cie, cig, &
1048 mu_i, am_i, bm_i, oig1, oig2, obmi , d0s
1049
1050 real(wp), intent(in) :: dt, odt
1051 real(wp), dimension(:), intent(in) :: rho
1052 real(wp), dimension(:), intent(inout) :: qi1d, ni1d, qiten, niten, ri, ni
1053 real(dp), dimension(:), intent(out) :: ilami
1054 logical, dimension(:), intent(inout) :: l_qi
1055 integer :: k, nz
1056 real(dp) :: lami, xdi
1057 logical :: hit_limit
1058
1059 nz = size(qi1d)
1060 do k = 1, nz
1061 hit_limit = .false.
1062 if (qi1d(k)+qiten(k)*dt > r1) then
1063 l_qi(k) = .true.
1064 !update mass
1065 ri(k) = (qi1d(k)+qiten(k)*dt)*rho(k)
1066 qi1d(k) = qi1d(k)+qiten(k)*dt
1067
1068 !update number
1069 ni(k) = max(r2, (ni1d(k)+niten(k)*dt)*rho(k))
1070
1071 ! check number
1072 if (ni(k) <= r2) then
1073 hit_limit = .true.
1074 lami = cie(2)/5.e-6_dp
1075 ni(k) = min(max_ni, real(cig(1)*oig2*ri(k)/am_i*lami**bm_i, kind=wp))
1076 endif
1077
1078 ! check size
1079 lami = (am_i*cig(2)*oig1*ni(k)/ri(k))**obmi
1080 xdi = (bm_i + mu_i + 1._dp) / lami
1081 if (xdi < 5.e-6_dp) then
1082 hit_limit = .true.
1083 lami = cie(2)/5.e-6_dp
1084 ni(k) = min(max_ni, real(cig(1)*oig2*ri(k)/am_i*lami**bm_i, kind=wp))
1085 elseif (xdi > d0s) then
1086 hit_limit = .true.
1087 lami = cie(2)/d0s
1088 ni(k) = cig(1)*oig2*ri(k)/am_i*lami**bm_i
1089 endif
1090
1091 if (hit_limit) niten(k) = (ni(k)/rho(k) - ni1d(k))*odt
1092 ni1d(k) = max(r2/rho(k), &
1093 min(real(cig(1)*oig2*qi1d(k)/am_i*lami**bm_i, kind=wp), max_ni/rho(k)))
1094 ilami(k) = 1._dp / lami
1095 else
1096 l_qi(k) = .false.
1097 ri(k) = r1
1098 ni(k) = r2
1099 ilami(k) = 0._dp
1100 qiten(k) = -qi1d(k) * odt
1101 niten(k) = -ni1d(k) * odt
1102 qi1d(k) = 0.0_wp
1103 ni1d(k) = 0.0_wp
1104 endif
1105 enddo
1106 end subroutine ice_check_and_update
1107
1108
1109 subroutine snow_check_and_update(rho, l_qs, qs1d, rs, qsten, dt, odt)
1110 !! computes snow mass
1111 use module_mp_tempo_params, only : max_ni, r1, r2
1112
1113 real(wp), intent(in) :: dt, odt
1114 real(wp), dimension(:), intent(in) :: rho
1115 real(wp), dimension(:), intent(inout) :: qs1d, rs, qsten
1116 logical, dimension(:), intent(inout) :: l_qs
1117 integer :: k, nz
1118
1119 nz = size(qs1d)
1120 do k = 1, nz
1121 if (qs1d(k)+qsten(k)*dt > r1) then
1122 l_qs(k) = .true.
1123 ! update mass
1124 rs(k) = (qs1d(k)+qsten(k)*dt)*rho(k)
1125 qs1d(k) = qs1d(k)+qsten(k)*dt
1126 else
1127 l_qs(k) = .false.
1128 rs(k) = r1
1129 qsten(k) = -qs1d(k) * odt
1130 qs1d(k) = 0.0_wp
1131 endif
1132 enddo
1133 end subroutine snow_check_and_update
1134
1135
1136 subroutine graupel_check_and_update(rho, l_qg, qg1d, ng1d, qb1d, rg, ng, rb, &
1137 idx, qgten, ngten, qbten, ilamg, mvd_g, dt, odt)
1138 !! computes graupel contents, ilamg, and mvd_g and checks bounds
1139 use module_mp_tempo_params, only : r1, r2, nrhg, rho_g, mu_g, &
1140 am_g, bm_g, ogg3, cgg, ogg2, obmg, d0r, idx_bg1, gonv_max, &
1141 gonv_min, oge1, ogg1, d0g, meters3_to_liters
1142
1143 real(wp), intent(in) :: dt, odt
1144 real(wp), dimension(:), intent(in) :: rho
1145 real(wp), dimension(:), intent(inout) :: qg1d, qgten, rg, ng, rb, ngten, qbten
1146 real(wp), dimension(:), intent(inout), optional :: ng1d, qb1d
1147 real(dp), dimension(:), intent(out) :: ilamg
1148 real(wp), dimension(:), intent(out) :: mvd_g
1149 logical, dimension(:), intent(inout) :: l_qg
1150 integer, dimension(:), intent(inout) :: idx
1151 integer :: k, nz
1152 real(dp) :: lamg, ygra1, zans1, n0_exp, lam_exp
1153 logical :: hit_limit
1154
1155 nz = size(qg1d)
1156 do k = 1, nz
1157 hit_limit = .false.
1158 if (qg1d(k)+qgten(k)*dt > r1) then
1159 l_qg(k) = .true.
1160 !update mass
1161 rg(k) = (qg1d(k)+qgten(k)*dt)*rho(k)
1162 qg1d(k) = qg1d(k)+qgten(k)*dt
1163
1164 !update number and density
1165 if (present(ng1d) .and. present(qb1d)) then
1166 ng(k) = max(r2, (ng1d(k)+ngten(k)*dt)*rho(k))
1167 ! qb1d is L/kg and rb is L/m^3
1168 rb(k) = min(max(rg(k)*meters3_to_liters/rho_g(nrhg), &
1169 (qb1d(k)+qbten(k)*dt)*rho(k)), rg(k)*meters3_to_liters/rho_g(1))
1170 idx(k) = max(1, min(nint(10._wp*rg(k)/rb(k))+1, nrhg))
1171
1172 ! check number
1173 if (ng(k) <= r2) then
1174 hit_limit = .true.
1175 mvd_g(k) = 1.5e-3_wp
1176 lamg = (3.0_dp + mu_g + 0.672_dp) / mvd_g(k)
1177 ng(k) = cgg(2,1)*ogg3*rg(k)*lamg**bm_g / am_g(idx(k))
1178 endif
1179
1180 ! check size
1181 lamg = (am_g(idx(k))*cgg(3,1)*ogg2*ng(k)/rg(k))**obmg
1182 mvd_g(k) = (3.0_wp + mu_g + 0.672_wp) / lamg
1183 if (mvd_g(k) > 25.4e-3_wp) then
1184 hit_limit = .true.
1185 mvd_g(k) = 25.4e-3_wp
1186 lamg = (3.0_dp + mu_g + 0.672_dp) / mvd_g(k)
1187 ng(k) = cgg(2,1)*ogg3*rg(k)*lamg**bm_g / am_g(idx(k))
1188 elseif (mvd_g(k) < d0r) then
1189 hit_limit = .true.
1190 mvd_g(k) = d0r
1191 lamg = (3.0_dp + mu_g + 0.672_dp) / mvd_g(k)
1192 ng(k) = cgg(2,1)*ogg3*rg(k)*lamg**bm_g / am_g(idx(k))
1193 endif
1194
1195 if (hit_limit) ngten(k) = (ng(k)/rho(k) - ng1d(k)) * odt
1196 ng1d(k) = cgg(2,1)*ogg3*qg1d(k)*lamg**bm_g / am_g(idx(k))
1197 qb1d(k) = min(max(qg1d(k)*meters3_to_liters/rho_g(nrhg), &
1198 qb1d(k)+qbten(k)*dt), meters3_to_liters*qg1d(k)/rho_g(1))
1199 idx(k) = max(1, min(nint(10._wp*qg1d(k)/qb1d(k))+1, nrhg))
1200 else
1201 idx(k) = idx_bg1
1202 ygra1 = log10(max(1.e-9_dp, real(rg(k), kind=dp)))
1203 zans1 = 3.4_dp + 2._dp/7._dp*(ygra1+8._dp)
1204 n0_exp = max(gonv_min, min(10._dp**(zans1), gonv_max))
1205 lam_exp = (n0_exp*am_g(idx(k))*cgg(1,1)/rg(k))**oge1
1206 lamg = lam_exp * (cgg(3,1)*ogg2*ogg1)**obmg
1207 ng(k) = cgg(2,1)*ogg3*rg(k)*lamg**bm_g / am_g(idx(k))
1208 rb(k) = meters3_to_liters*rg(k)/rho_g(idx(k))
1209 endif
1210 ilamg(k) = 1._dp / lamg
1211 mvd_g(k) = (3.0_wp + mu_g + 0.672_wp) * ilamg(k)
1212 else
1213 l_qg(k) = .false.
1214 rg(k) = r1
1215 ng(k) = r2
1216 mvd_g(k) = d0g
1217 ilamg(k) = 0._dp
1218 idx(k) = idx_bg1
1219 rb(k) = meters3_to_liters*r1/rho_g(idx(k))
1220 qgten(k) = -qg1d(k) * odt
1221 qg1d(k) = 0.0_wp
1222 if (present(ng1d) .and. present(qb1d)) then
1223 ngten(k) = -ng1d(k) * odt
1224 qbten(k) = -qb1d(k) * odt
1225 ng1d(k) = 0.0_wp
1226 qb1d(k) = 0.0_wp
1227 endif
1228 endif
1229 enddo
1230 end subroutine graupel_check_and_update
1231
1232
1233 subroutine graupel_init(rho, qg1d, ng1d, qb1d)
1234 !! initializes graupel number and volume if both are zero
1235 !! and hail-aware = true
1236 use module_mp_tempo_params, only : r1, meters3_to_liters, &
1237 idx_bg1, am_g, bm_g, mu_g, ogg3, cgg
1238
1239 real(wp), dimension(:), intent(in) :: rho
1240 real(wp), dimension(:), intent(in) :: qg1d
1241 real(wp), dimension(:), intent(inout) :: ng1d, qb1d
1242 integer :: k, nz, idx
1243 real(dp) :: lamg
1244 real(wp) :: mvd_g, rg, ng, rb
1245
1246 nz = size(rho)
1247 do k = 1, nz
1248 if (qg1d(k) > r1) then
1249 rg = qg1d(k)*rho(k)
1250 rb = rg*meters3_to_liters/rho_g(idx_bg1)
1251 idx = max(1, min(nint(10._wp*rg/rb)+1, nrhg))
1252 mvd_g = 5.e-3_wp
1253 lamg = (3.0_dp + mu_g + 0.672_dp) / mvd_g
1254 ng = cgg(2,1)*ogg3*rg*lamg**bm_g / am_g(idx)
1255 ng1d(k) = ng/rho(k)
1256 qb1d(k) = rb/rho(k)
1257 endif
1258 enddo
1259 end subroutine graupel_init
1260
1261
1262 subroutine thermo_vars(qv, temp, pres, rho, rhof, rhof2, qvs, delqvs, qvsi, &
1263 satw, sati, ssatw, ssati, diffu, visco, vsc2, ocp, lvap, tcond, lvt2, &
1264 supersaturated)
1265 !! computes thermodynamic variables
1266 use module_mp_tempo_params, only : t0, rho_not, eps, cp, lvap0, orv
1267
1268 real(wp), dimension(:), intent(in) :: qv, temp, pres, rho
1269 real(wp), dimension(:), intent(out) :: rhof, rhof2, qvs, &
1270 delqvs, qvsi, satw, sati, ssatw, ssati, diffu, visco, vsc2, &
1271 ocp, lvap, tcond, lvt2
1272 logical, intent(inout) :: supersaturated
1273 integer :: k, nz
1274 real(wp) :: tempc, otemp
1275
1276 nz = size(temp)
1277 supersaturated = .false.
1278 do k = 1, nz
1279 otemp = 1._wp / temp(k)
1280 tempc = temp(k) - t0
1281 rhof(k) = sqrt(rho_not/rho(k))
1282 rhof2(k) = sqrt(rhof(k))
1283 qvs(k) = calc_rslf(pres(k), temp(k))
1284 delqvs(k) = max(0._wp, calc_rslf(pres(k), t0)-qv(k))
1285 if (tempc <= 0._wp) then
1286 qvsi(k) = calc_rsif(pres(k), temp(k))
1287 else
1288 qvsi(k) = qvs(k)
1289 endif
1290 satw(k) = qv(k)/qvs(k)
1291 sati(k) = qv(k)/qvsi(k)
1292 ssatw(k) = satw(k) - 1._wp
1293 ssati(k) = sati(k) - 1._wp
1294 if (abs(ssatw(k)) < eps) ssatw(k) = 0._wp
1295 if (abs(ssati(k)) < eps) ssati(k) = 0._wp
1296 if (ssati(k) > 0._wp) supersaturated = .true.
1297 diffu(k) = 2.11e-5_wp*(temp(k)/t0)**1.94_wp * (101325._wp/pres(k))
1298 if (tempc >= 0._wp) then
1299 visco(k) = (1.718_wp+0.0049_wp*tempc)*1.0e-5_wp
1300 else
1301 visco(k) = (1.718_wp+0.0049_wp*tempc-1.2e-5_wp*tempc*tempc)*1.0e-5_wp
1302 endif
1303 ocp(k) = 1._wp/(cp*(1._wp+0.887_wp*qv(k)))
1304 vsc2(k) = sqrt(rho(k)/visco(k))
1305 lvap(k) = lvap0 + (2106.0_wp - 4218.0_wp)*tempc
1306 tcond(k) = (5.69_wp + 0.0168_wp*tempc)*1.0e-5_wp * 418.936_wp
1307 lvt2(k) = lvap(k)*lvap(k)*ocp(k)*orv*otemp*otemp
1308 enddo
1309 end subroutine thermo_vars
1310
1311
1312 subroutine check_over_depletion(rho, temp, qvsi, qv, l_qc, rc, l_qi, ri, &
1313 l_qr, rr, l_qs, rs, l_qg, rg, tend, odt)
1314 !! check to ensure that loss terms don't over-deplete a category and
1315 !! adjusts tendencies if needed
1316 use module_mp_tempo_params, only : eps, rho_i, t0, meters3_to_liters
1317
1318 real(wp), intent(in) :: odt
1319 type(ty_tend), intent(inout) :: tend
1320 logical, dimension(:), intent(in) :: l_qc, l_qi, l_qr, l_qs, l_qg
1321 real(wp), dimension(:), intent(in) :: rho, temp, qvsi, qv, rc, ri, rr, rs, rg
1322 real(wp) :: sump, rate_max, ratio
1323 integer :: k, nz
1324
1325 nz = size(qv)
1326 do k = 1, nz
1327 ! losses to vapor include, deposition nucleation; ice, snow, and graupel
1328 ! depositional growth; Koop nucleation
1329 sump = tend%pri_inu(k) + tend%pri_ide(k) + tend%prs_ide(k) + &
1330 tend%prs_sde(k) + tend%prg_gde(k) + tend%pri_iha(k)
1331 rate_max = (qv(k)-qvsi(k))*rho(k)*odt*0.999_wp
1332 if ((sump > eps .and. sump > rate_max) .or. &
1333 (sump < -eps .and. sump < rate_max)) then
1334 ratio = rate_max/sump
1335 tend%pri_inu(k) = tend%pri_inu(k) * ratio
1336 tend%pri_ide(k) = tend%pri_ide(k) * ratio
1337 tend%pni_ide(k) = tend%pni_ide(k) * ratio ! scales with pri_ide
1338 tend%prs_ide(k) = tend%prs_ide(k) * ratio
1339 tend%prs_sde(k) = tend%prs_sde(k) * ratio
1340 tend%prg_gde(k) = tend%prg_gde(k) * ratio
1341 tend%pri_iha(k) = tend%pri_iha(k) * ratio
1342 endif
1343
1344 ! losses to cloud water include conversion to rain;
1345 ! freezing; collection by rain, snow, and graupel.
1346 sump = -tend%prr_wau(k) - tend%pri_wfz(k) - tend%prr_rcw(k) - &
1347 tend%prs_scw(k) - tend%prg_scw(k) - tend%prg_gcw(k)
1348 rate_max = -rc(k)*odt
1349 if (l_qc(k)) then
1350 if (sump < rate_max) then
1351 ratio = rate_max/sump
1352 tend%prr_wau(k) = tend%prr_wau(k) * ratio
1353 tend%pri_wfz(k) = tend%pri_wfz(k) * ratio
1354 tend%prr_rcw(k) = tend%prr_rcw(k) * ratio
1355 tend%prs_scw(k) = tend%prs_scw(k) * ratio
1356 tend%prg_scw(k) = tend%prg_scw(k) * ratio
1357 tend%prg_gcw(k) = tend%prg_gcw(k) * ratio
1358 endif
1359 endif
1360
1361 ! losses to cloud ice include sublimation; conversion to snow;
1362 ! collection by snow and rain
1363 sump = tend%pri_ide(k) - tend%prs_iau(k) - tend%prs_sci(k) - tend%pri_rci(k)
1364 rate_max = -ri(k)*odt
1365 if (l_qi(k)) then
1366 if (sump < rate_max) then
1367 ratio = rate_max/sump
1368 tend%pri_ide(k) = tend%pri_ide(k) * ratio
1369 tend%prs_iau(k) = tend%prs_iau(k) * ratio
1370 tend%prs_sci(k) = tend%prs_sci(k) * ratio
1371 tend%pri_rci(k) = tend%pri_rci(k) * ratio
1372 endif
1373 endif
1374
1375 ! losses to rain include freezing; collection by ice, snow, and graupel
1376 ! resulting in freezing
1377 sump = -tend%prg_rfz(k) - tend%pri_rfz(k) - tend%prr_rci(k) + &
1378 tend%prr_rcs(k) + tend%prr_rcg(k)
1379 rate_max = -rr(k)*odt
1380 if (l_qr(k)) then
1381 if (sump < rate_max) then
1382 ratio = rate_max/sump
1383 tend%prg_rfz(k) = tend%prg_rfz(k) * ratio
1384 tend%pbg_rfz(k) = tend%pbg_rfz(k) * ratio ! scales with prg_rfz
1385 tend%pri_rfz(k) = tend%pri_rfz(k) * ratio
1386 tend%prr_rci(k) = tend%prr_rci(k) * ratio
1387 tend%prr_rcs(k) = tend%prr_rcs(k) * ratio
1388 tend%prr_rcg(k) = tend%prr_rcg(k) * ratio
1389 endif
1390 endif
1391
1392 ! losses to snow include sublimation; melting; collection by rain;
1393 ! rime splintering
1394 sump = tend%prs_sde(k) - tend%prs_ihm(k) - tend%prr_sml(k) + &
1395 tend%prs_rcs(k)
1396 rate_max = -rs(k)*odt
1397 if (l_qs(k)) then
1398 if (sump < rate_max) then
1399 ratio = rate_max/sump
1400 tend%prs_sde(k) = tend%prs_sde(k) * ratio
1401 tend%prs_ihm(k) = tend%prs_ihm(k) * ratio
1402 tend%prr_sml(k) = tend%prr_sml(k) * ratio
1403 tend%prs_rcs(k) = tend%prs_rcs(k) * ratio
1404 endif
1405 endif
1406
1407 ! losses to graupel include sublimation; melting; rime splintering;
1408 ! collection by rain
1409 sump = tend%prg_gde(k) - tend%prg_ihm(k) - tend%prr_gml(k) + tend%prg_rcg(k)
1410 rate_max = -rg(k)*odt
1411 if (l_qg(k)) then
1412 if (sump < rate_max) then
1413 ratio = rate_max/sump
1414 tend%prg_gde(k) = tend%prg_gde(k) * ratio
1415 tend%prg_ihm(k) = tend%prg_ihm(k) * ratio
1416 tend%prr_gml(k) = tend%prr_gml(k) * ratio
1417 tend%prg_rcg(k) = tend%prg_rcg(k) * ratio
1418 tend%pbg_rcg(k) = tend%pbg_rcg(k) * ratio ! scales with prg_rcg
1419 endif
1420 endif
1421
1422 ! updates after adjustments
1423 ! reset sum of rime splintering
1424 tend%pri_ihm(k) = tend%prs_ihm(k) + tend%prg_ihm(k)
1425 ! reset total rain-graupel collection amount if reduced
1426 ratio = min(abs(tend%prr_rcg(k)), abs(tend%prg_rcg(k)))
1427 tend%prr_rcg(k) = ratio * sign(1.0_dp, tend%prr_rcg(k))
1428 tend%prg_rcg(k) = -tend%prr_rcg(k)
1429 tend%pbg_rcg(k) = meters3_to_liters*tend%prg_rcg(k)/rho_i ! scale density change
1430 ! reset total rain-snow collection amount if reduced
1431 if (temp(k) > t0) then
1432 ratio = min(abs(tend%prr_rcs(k)), abs(tend%prs_rcs(k)))
1433 tend%prr_rcs(k) = ratio * sign(1.0_dp, tend%prr_rcs(k))
1434 tend%prs_rcs(k) = -tend%prr_rcs(k)
1435 endif
1436 enddo
1437 end subroutine check_over_depletion
1438
1439
1440 subroutine sum_tendencies(rho, temp, idx, lvap, ocp, tend, tten, qvten, qcten, &
1441 ncten, qiten, niten, qsten, qrten, nrten, qgten, ngten, qbten)
1442 !! sums tendencies for each hydrometeor category and temperature and moisture
1443 use module_mp_tempo_params, only : lsub, rho_g, t0, lfus, meters3_to_liters
1444
1445 type(ty_tend), intent(in) :: tend
1446 real(wp), dimension(:), intent(in) :: rho, temp, lvap, ocp
1447 integer, dimension(:), intent(in) :: idx
1448 real(wp), dimension(:), intent(inout) :: qvten, qcten, ncten, qiten, niten, &
1449 qsten, qrten, nrten, qgten, ngten, qbten, tten
1450 real(wp) :: orho, lfus2
1451 integer :: k, nz
1452
1453 nz = size(temp)
1454 do k = 1, nz
1455 orho = 1./rho(k)
1456 lfus2 = lsub - lvap(k)
1457
1458 qvten(k) = qvten(k) + (-tend%pri_inu(k) - tend%pri_iha(k) - tend%pri_ide(k) - &
1459 tend%prs_ide(k) - tend%prs_sde(k) - tend%prg_gde(k)) * orho
1460
1461 qcten(k) = qcten(k) + (-tend%prr_wau(k) - tend%pri_wfz(k) - tend%prr_rcw(k) - &
1462 tend%prs_scw(k) - tend%prg_scw(k) - tend%prg_gcw(k)) * orho
1463
1464 ncten(k) = ncten(k) + (-tend%pnc_wau(k) - tend%pnc_rcw(k) - tend%pni_wfz(k) - &
1465 tend%pnc_scw(k) - tend%pnc_gcw(k)) * orho
1466
1467 qiten(k) = qiten(k) + (tend%pri_inu(k) + tend%pri_iha(k) + tend%pri_ihm(k) + &
1468 tend%pri_wfz(k) + tend%pri_rfz(k) + tend%pri_ide(k) - tend%prs_iau(k) - &
1469 tend%prs_sci(k) - tend%pri_rci(k)) * orho
1470
1471 niten(k) = niten(k) + (tend%pni_inu(k) + tend%pni_iha(k) + tend%pni_ihm(k) + &
1472 tend%pni_wfz(k) + tend%pni_rfz(k) + tend%pni_ide(k) - tend%pni_iau(k) - &
1473 tend%pni_sci(k) - tend%pni_rci(k)) * orho
1474
1475 qrten(k) = qrten(k) + (tend%prr_wau(k) + tend%prr_rcw(k) + tend%prr_sml(k) + &
1476 tend%prr_gml(k) + tend%prr_rcs(k) + tend%prr_rcg(k) - tend%prg_rfz(k) - &
1477 tend%pri_rfz(k) - tend%prr_rci(k)) * orho
1478
1479 nrten(k) = nrten(k) + (tend%pnr_wau(k) + tend%pnr_sml(k) + tend%pnr_gml(k) - &
1480 (tend%pnr_rfz(k) + tend%pnr_rcr(k) + tend%pnr_rcg(k) + tend%pnr_rcs(k) + &
1481 tend%pnr_rci(k) + tend%pni_rfz(k))) * orho
1482
1483 qsten(k) = qsten(k) + (tend%prs_iau(k) + tend%prs_sde(k) + tend%prs_sci(k) + &
1484 tend%prs_scw(k) + tend%prs_rcs(k) + tend%prs_ide(k) - tend%prs_ihm(k) - &
1485 tend%prr_sml(k)) * orho
1486
1487 qgten(k) = qgten(k) + (tend%prg_scw(k) + tend%prg_rfz(k) + tend%prg_gde(k) + &
1488 tend%prg_rcg(k) + tend%prg_gcw(k) + tend%prg_rci(k) + tend%prg_rcs(k) - &
1489 tend%prg_ihm(k) - tend%prr_gml(k)) * orho
1490
1491 ngten(k) = ngten(k) + (tend%png_scw(k) + tend%png_rfz(k) - tend%png_rcg(k) + &
1492 tend%png_rci(k) + tend%png_rcs(k) + tend%png_gde(k) - tend%pnr_gml(k)) * orho
1493
1494 qbten(k) = qbten(k) + (tend%pbg_scw(k) + tend%pbg_rfz(k) + tend%pbg_gcw(k) + &
1495 tend%pbg_rci(k) + tend%pbg_rcs(k) + tend%pbg_rcg(k) + tend%pbg_sml(k) - &
1496 tend%pbg_gml(k) + meters3_to_liters * (tend%prg_gde(k) - tend%prg_ihm(k)) / rho_g(idx(k))) * orho
1497
1498 if (temp(k) < t0) then
1499 tten(k) = tten(k) + &
1500 (lsub*ocp(k)*(tend%pri_inu(k) + tend%pri_ide(k) + &
1501 tend%prs_ide(k) + tend%prs_sde(k) + tend%prg_gde(k) + tend%pri_iha(k)) + &
1502 lfus2*ocp(k)*(tend%pri_wfz(k) + tend%pri_rfz(k) + tend%prg_rfz(k) + &
1503 tend%prs_scw(k) + tend%prg_scw(k) + tend%prg_gcw(k) + tend%prg_rcs(k) + &
1504 tend%prs_rcs(k) + tend%prr_rci(k) + tend%prg_rcg(k)))*orho
1505 else
1506 tten(k) = tten(k) + &
1507 (lfus*ocp(k)*(-tend%prr_sml(k) - tend%prr_gml(k) - &
1508 tend%prr_rcg(k) - tend%prr_rcs(k)) + &
1509 lsub*ocp(k)*(tend%prs_sde(k) + tend%prg_gde(k)))*orho
1510 endif
1511 enddo
1512 end subroutine sum_tendencies
1513
1514
1515 subroutine sedimentation(xr, vt, dz1d, rho, xten, limit, steps, ktop_sedi, precip, dt)
1516 !! computes sedimentation fluxes, adds fluxes to tendencies, and updates hydrometeor
1517 !! mass (and number and volume)
1518 use module_mp_tempo_params, only : low_limit_mass_for_precip
1519
1520 real(wp), intent(in) :: dt
1521 integer, intent(in) :: steps
1522 integer, intent(in), optional :: ktop_sedi
1523 real(wp), dimension(:), intent(inout) :: xr, xten
1524 real(wp), dimension(:), intent(in) :: dz1d, rho
1525 real(wp), dimension(:), intent(in) :: vt
1526 real(wp), intent(in) :: limit
1527 real(wp), intent(inout), optional :: precip
1528 real(wp) :: odz, orho
1529 real(wp), allocatable, dimension(:) :: sed_r
1530 integer :: k, nz, ktop
1531
1532 nz = size(xr)
1533 allocate(sed_r(nz), source=0._wp)
1534 ktop = nz-1
1535 if (present(ktop_sedi)) ktop = ktop_sedi
1536
1537 do k = nz, 1, -1
1538 sed_r(k) = vt(k)*xr(k)
1539 enddo
1540 k = nz
1541 odz = 1._wp/dz1d(k)
1542 orho = 1._wp/rho(k)
1543 xten(k) = xten(k) - sed_r(k)*odz*(1._wp/real(steps, kind=wp))*orho
1544 xr(k) = max(limit, xr(k) - sed_r(k)*odz*dt*(1._wp/real(steps, kind=wp)))
1545
1546 do k = ktop, 1, -1
1547 odz = 1._wp/dz1d(k)
1548 orho = 1._wp/rho(k)
1549 xten(k) = xten(k) + (sed_r(k+1)-sed_r(k))*odz*(1._wp/real(steps, kind=wp))*orho
1550 xr(k) = max(limit, xr(k) + (sed_r(k+1)-sed_r(k))*odz*dt*(1._wp/real(steps, kind=wp)))
1551 enddo
1552
1553 if (present(precip)) then
1554 if (xr(1) > low_limit_mass_for_precip) then
1555 precip = precip + sed_r(1)*dt*(1._wp/real(steps, kind=wp))
1556 endif
1557 endif
1558 end subroutine sedimentation
1559
1560
1561 subroutine semilagrangian_sedimentation(dz1d, rho, xr, xten, vt, steps, limit, precip, dt, odt)
1562 !! semi-lagrangian sedimentation scheme from
1563 !! [Juang and Hong (2010)](https://doi.org/10.1175/2009MWR3109.1)
1564 !!
1565 !! original author: hann-ming henry juang <henry.juang@noaa.gov>
1566 !! original implemented by: song-you hong
1567
1568 real(wp), intent(in) :: dt, odt
1569 integer, intent(in) :: steps
1570 real(wp), intent(in) :: limit
1571 real(wp), dimension(:), intent(in) :: dz1d, rho
1572 real(wp), dimension(:), intent(inout) :: xr, xten
1573 real(wp), dimension(:), intent(in) :: vt
1574 real(wp) :: fa1, fa2, con1, decfl, dip, dim, tl, th, tl2, th2, qqd, qqh, qql, zsum, qsum, &
1575 orho, dql, dqh
1576 real(wp), dimension(:), allocatable :: zi, wi, za, dza, qa, qmi, qpi, net_flx, precip_flx, rr_save
1577 real(wp), intent(out), optional :: precip
1578 integer :: k, nz, kk, kb, kt, m
1579
1580 nz = size(dz1d)
1581 allocate(zi(nz+1), source=0._wp)
1582 allocate(wi(nz+1), source=0._wp)
1583 allocate(dza(nz+1), source=0._wp)
1584 allocate(za(nz+2), source=0._wp)
1585 allocate(qa(nz+1), source=0._wp)
1586 allocate(qmi(nz+1), source=0._wp)
1587 allocate(qpi(nz+1), source=0._wp)
1588 allocate(net_flx(nz), source=0._wp)
1589 allocate(precip_flx(nz), source=0._wp)
1590 allocate(rr_save(nz), source=xr)
1591
1592 zi(1) = 0._wp ! zi(1) needs to be zero so zero out explicitly
1593 do k = 1, nz
1594 zi(k+1) = zi(k) + dz1d(k)
1595 enddo
1596
1597 ! 3rd order interpolation to get wi
1598 fa1 = 9._wp/16._wp
1599 fa2 = 1._wp/16._wp
1600 wi(1) = vt(1)
1601 wi(2) = 0.5_wp*(vt(2)+vt(1))
1602 do k = 3, nz-1
1603 wi(k) = fa1*(vt(k)+vt(k-1))-fa2*(vt(k+1)+vt(k-2))
1604 enddo
1605 wi(nz) = 0.5_wp*(vt(nz)+vt(nz-1))
1606 wi(nz+1) = vt(nz+1)
1607
1608 do k = 2, nz
1609 if(vt(k) == 0._wp) wi(k) = vt(k-1)
1610 enddo
1611
1612 ! diffusivity of wi
1613 ! con1 should be > 0 and < 1
1614 con1 = 0.05_wp
1615 do k = nz, 1, -1
1616 decfl = (wi(k+1)-wi(k))*dt*(1._wp/real(steps, kind=wp))/dz1d(k)
1617 if(decfl > con1) then
1618 wi(k) = wi(k+1) - con1*dz1d(k)*odt*real(steps, kind=wp)
1619 endif
1620 enddo
1621
1622 ! compute arrival point
1623 do k = 1, nz+1
1624 za(k) = zi(k) - wi(k)*dt*(1._wp/real(steps, kind=wp))
1625 enddo
1626 za(nz+2) = zi(nz+1)
1627 do k = 1, nz+1
1628 dza(k) = za(k+1)-za(k)
1629 enddo
1630
1631 ! computer deformation at arrival point
1632 do k = 1, nz
1633 qa(k) = xr(k)*dz1d(k)/dza(k)
1634 enddo
1635 qa(nz+1) = 0._wp
1636
1637 ! estimate values at arrival cell interface with monotone
1638 do k = 2, nz
1639 dip=(qa(k+1)-qa(k))/(dza(k+1)+dza(k))
1640 dim=(qa(k)-qa(k-1))/(dza(k-1)+dza(k))
1641 if(dip*dim <= 0._wp) then
1642 qmi(k)=qa(k)
1643 qpi(k)=qa(k)
1644 else
1645 qpi(k)=qa(k)+0.5_wp*(dip+dim)*dza(k)
1646 qmi(k)=2._wp*qa(k)-qpi(k)
1647 if(qpi(k) > 0._wp .or. qmi(k) < 0._wp) then
1648 qpi(k) = qa(k)
1649 qmi(k) = qa(k)
1650 endif
1651 endif
1652 enddo
1653 qpi(1) = qa(1)
1654 qmi(1) = qa(1)
1655 qmi(nz+1) = qa(nz+1)
1656 qpi(nz+1) = qa(nz+1)
1657
1658 ! interpolation to regular point
1659 kb = 1
1660 kt = 1
1661 intp : do k = 1, nz
1662 kb = max(kb-1,1)
1663 kt = max(kt-1,1)
1664 ! find kb and kt
1665 if(zi(k) >= za(nz+1)) then
1666 exit intp
1667 else
1668 find_kb : do kk = kb, nz
1669 if(zi(k) <= za(kk+1)) then
1670 kb = kk
1671 exit find_kb
1672 else
1673 cycle find_kb
1674 endif
1675 enddo find_kb
1676 find_kt : do kk = kt, nz+2
1677 if(zi(k+1) <= za(kk)) then
1678 kt = kk
1679 exit find_kt
1680 else
1681 cycle find_kt
1682 endif
1683 enddo find_kt
1684 kt = kt - 1
1685
1686 ! compute q with piecewise constant method
1687 if(kt == kb) then
1688 tl = (zi(k)-za(kb))/dza(kb)
1689 th = (zi(k+1)-za(kb))/dza(kb)
1690 tl2 = tl*tl
1691 th2 = th*th
1692 qqd = 0.5_wp*(qpi(kb)-qmi(kb))
1693 qqh = qqd*th2+qmi(kb)*th
1694 qql = qqd*tl2+qmi(kb)*tl
1695 xr(k) = (qqh-qql)/(th-tl)
1696 elseif(kt > kb) then
1697 tl = (zi(k)-za(kb))/dza(kb)
1698 tl2 = tl*tl
1699 qqd = 0.5_wp*(qpi(kb)-qmi(kb))
1700 qql = qqd*tl2+qmi(kb)*tl
1701 dql = qa(kb)-qql
1702 zsum = (1._wp-tl)*dza(kb)
1703 qsum = dql*dza(kb)
1704 if(kt-kb > 1) then
1705 do m = kb+1, kt-1
1706 zsum = zsum + dza(m)
1707 qsum = qsum + qa(m) * dza(m)
1708 enddo
1709 endif
1710 th = (zi(k+1)-za(kt))/dza(kt)
1711 th2 = th*th
1712 qqd = 0.5_wp*(qpi(kt)-qmi(kt))
1713 dqh = qqd*th2+qmi(kt)*th
1714 zsum = zsum + th*dza(kt)
1715 qsum = qsum + dqh*dza(kt)
1716 xr(k) = qsum/zsum
1717 endif
1718 endif
1719 orho = 1._wp / rho(k)
1720 xr(k) = max(xr(k), limit)
1721 xten(k) = xten(k) + (xr(k) - rr_save(k)) * &
1722 orho*odt
1723 enddo intp
1724
1725 precip_loop: do k = 1, nz
1726 if(za(k) < 0._wp .and. za(k+1) <= 0.0_wp) then
1727 if (present(precip)) precip = precip + qa(k)*dza(k)
1728 net_flx(k) = qa(k)*dza(k)
1729 elseif (za(k) < 0._wp .and. za(k+1) > 0._wp) then
1730 th = (0._wp-za(k))/dza(k)
1731 th2 = th*th
1732 qqd = 0.5_wp*(qpi(k)-qmi(k))
1733 qqh = qqd*th2+qmi(k)*th
1734 if (present(precip)) precip = precip + qqh*dza(k)
1735 net_flx(k) = qqh*dza(k)
1736 exit precip_loop
1737 endif
1738 enddo precip_loop
1739
1740 ! calculating precipitation fluxes
1741 do k = nz, 1, -1
1742 if(k == nz) then
1743 precip_flx(k) = net_flx(k)
1744 else
1745 precip_flx(k) = precip_flx(k+1) + net_flx(k)
1746 end if
1747 enddo
1748 end subroutine semilagrangian_sedimentation
1749
1750
1751 subroutine rain_fallspeed(rhof, l_qr, rr, ilamr, dz1d, vt, vtn, substeps_sedi, ktop_sedi, dt)
1752 !! calculates mass and number weighted fall speeds for rain
1753 !! and optionally the substepping required and the top k-level of sedimentation
1754 use module_mp_tempo_params, only : crg, av_r, org3, fv_r, cre
1755
1756 real(wp), intent(in) :: dt
1757 real(wp), dimension(:), intent(in) :: rhof, dz1d, rr
1758 real(dp), dimension(:), intent(in) :: ilamr
1759 logical, dimension(:), intent(in) :: l_qr
1760 real(wp), dimension(:), intent(inout) :: vt, vtn
1761 integer, intent(out), optional :: substeps_sedi, ktop_sedi
1762 real(wp) :: dz_by_vt
1763 real(dp) :: lamr
1764 integer :: k, nz
1765
1766 nz = size(l_qr)
1767 if (present(ktop_sedi)) ktop_sedi = 1
1768 if (present(substeps_sedi)) substeps_sedi = 1
1769 do k = nz, 1, -1
1770 if (rr(k) > r1) then
1771 lamr = 1._dp / ilamr(k)
1772 vt(k) = rhof(k)*av_r*crg(6)*org3 * lamr**cre(3) *((lamr+fv_r)**(-cre(6)))
1773 vtn(k) = rhof(k)*av_r*crg(7)/crg(12) * lamr**cre(12)*((lamr+fv_r)**(-cre(7)))
1774 else
1775 vt(k) = vt(k+1)
1776 vtn(k) = vtn(k+1)
1777 endif
1778 if (max(vt(k), vtn(k)) > 1.e-3_wp) then
1779 if (present(ktop_sedi)) ktop_sedi = max(ktop_sedi, k)
1780 dz_by_vt = dz1d(k) / (max(vt(k), vtn(k)))
1781 if (present(substeps_sedi)) then
1782 substeps_sedi = max(substeps_sedi, int(dt/dz_by_vt + 1._wp))
1783 endif
1784 endif
1785 enddo
1786 if (present(ktop_sedi)) then
1787 if (ktop_sedi == nz) ktop_sedi = nz-1
1788 endif
1789 end subroutine rain_fallspeed
1790
1791
1792 subroutine graupel_fallspeed(rhof, rho, visco, l_qg, rg, rb, qb1d, idx, ilamg, &
1793 dz1d, vt, vtn, substeps_sedi, ktop_sedi, dt)
1794 !! calculates mass and number weighted fall speeds for graupel
1795 !! and optionally the substepping required and the top k-level of sedimentation
1796 use module_mp_tempo_params, only : nrhg, rho_g, av_g_old, bv_g_old, &
1797 cgg, t0, mu_g, ogg2, ogg3, a_coeff, b_coeff, meters3_to_liters, earth_gravity
1798
1799 real(wp), intent(in) :: dt
1800 real(wp), dimension(:), intent(in) :: rhof, rho, visco, dz1d, rg, rb
1801 real(wp), dimension(:), intent(in), optional :: qb1d
1802 real(dp), dimension(:), intent(in) :: ilamg
1803 logical, dimension(:), intent(in) :: l_qg
1804 integer, dimension(:), intent(in) :: idx
1805 real(wp), dimension(:), intent(inout) :: vt, vtn
1806 integer, intent(out), optional :: substeps_sedi, ktop_sedi
1807 real(wp) :: dz_by_vt, dens_g, afall, bfall
1808 integer :: k, nz
1809
1810 nz = size(l_qg)
1811 if (present(ktop_sedi)) ktop_sedi = 1
1812 if (present(substeps_sedi)) substeps_sedi = 1
1813 do k = nz, 1, -1
1814 if (rg(k) > r1) then
1815 if (present(qb1d)) then
1816 dens_g = max(rho_g(1), min(meters3_to_liters*rg(k)/rb(k), rho_g(nrhg)))
1817 afall = a_coeff*((4._wp*dens_g*earth_gravity)/(3._wp*rho(k)))**b_coeff
1818 afall = afall * visco(k)**(1._wp-2._wp*b_coeff)
1819 bfall = 3._wp*b_coeff - 1._wp
1820 else
1821 afall = av_g_old
1822 bfall = bv_g_old
1823 endif
1824 vt(k) = rhof(k)*afall*cgg(6,idx(k))*ogg3 * ilamg(k)**bfall
1825 ! idea: if (temp(k) > t0) vt(k) = max(vt(k), vtrr(k))
1826
1827 if (mu_g == 0) then
1828 vtn(k) = rhof(k)*afall*cgg(7,idx(k))/cgg(12,idx(k)) * ilamg(k)**bfall
1829 else
1830 vtn(k) = rhof(k)*afall*cgg(8,idx(k))*ogg2 * ilamg(k)**bfall
1831 endif
1832 else
1833 vt(k) = vt(k+1)
1834 vtn(k) = vtn(k+1)
1835 endif
1836 if (vt(k) > 1.e-3_wp) then
1837 if (present(ktop_sedi)) ktop_sedi = max(ktop_sedi, k)
1838 dz_by_vt = dz1d(k) / vt(k)
1839 if (present(substeps_sedi)) then
1840 substeps_sedi = max(substeps_sedi, int(dt/dz_by_vt + 1._wp))
1841 endif
1842 endif
1843 enddo
1844 if (present(ktop_sedi)) then
1845 if (ktop_sedi == nz) ktop_sedi = nz-1
1846 endif
1847 end subroutine graupel_fallspeed
1848
1849
1850 subroutine snow_fallspeed(rhof, l_qs, rs, prr_sml, smob, smoc, &
1851 rr, vtrr, dz1d, vt, vtboost, substeps_sedi, ktop_sedi, dt)
1852 !! calcules mass weighted fall speeds for snow
1853 !! and optionally the substepping required and the top k-level of sedimentation
1854 use module_mp_tempo_params, only : lam0, lam1, fv_s, kap0, kap1, mu_s, &
1855 cse, csg, av_s
1856
1857 real(wp), intent(in) :: dt
1858 real(wp), dimension(:), intent(in) :: rhof, dz1d, rs, rr, vtboost
1859 real(wp), dimension(:), intent(in) :: vtrr
1860 logical, dimension(:), intent(in) :: l_qs
1861 real(wp), dimension(:), intent(inout) :: vt
1862 real(dp), dimension(:), intent(in) :: smob, smoc, prr_sml
1863 integer, intent(out), optional :: substeps_sedi, ktop_sedi
1864 real(wp) :: dz_by_vt, vts, sr
1865 real(dp) :: xds, mrat, ils1, ils2, t1_vts, t2_vts, t3_vts, t4_vts
1866 integer :: k, nz
1867
1868 nz = size(l_qs)
1869 if (present(ktop_sedi)) ktop_sedi = 1
1870 if (present(substeps_sedi)) substeps_sedi = 1
1871 do k = nz, 1, -1
1872 if (rs(k) > r1) then
1873 xds = smoc(k) / smob(k)
1874 mrat = 1._dp/xds
1875 ils1 = 1._dp/(mrat*lam0 + fv_s)
1876 ils2 = 1._dp/(mrat*lam1 + fv_s)
1877 t1_vts = kap0*csg(4)*ils1**cse(4)
1878 t2_vts = kap1*mrat**mu_s*csg(10)*ils2**cse(10)
1879 ils1 = 1._dp/(mrat*lam0)
1880 ils2 = 1._dp/(mrat*lam1)
1881 t3_vts = kap0*csg(1)*ils1**cse(1)
1882 t4_vts = kap1*mrat**mu_s*csg(7)*ils2**cse(7)
1883 vts = rhof(k)*av_s * (t1_vts+t2_vts)/(t3_vts+t4_vts)
1884
1885 if (prr_sml(k) > 0._dp) then
1886 sr = rs(k)/(rs(k)+rr(k))
1887 vt(k) = vts*sr + (1._wp-sr)*vtrr(k)
1888 else
1889 vt(k) = vts*vtboost(k)
1890 endif
1891 else
1892 vt(k) = vt(k+1)
1893 endif
1894 if (vt(k) > 1.e-3_wp) then
1895 if (present(ktop_sedi)) ktop_sedi = max(ktop_sedi, k)
1896 dz_by_vt = dz1d(k) / vt(k)
1897 if (present(substeps_sedi)) then
1898 substeps_sedi = max(substeps_sedi, int(dt/dz_by_vt + 1._wp))
1899 endif
1900 endif
1901 enddo
1902 if (present(ktop_sedi)) then
1903 if (ktop_sedi == nz) ktop_sedi = nz-1
1904 endif
1905 end subroutine snow_fallspeed
1906
1907
1908 subroutine ice_fallspeed(rhof, l_qi, ri, ilami, dz1d, vt, vtn, &
1909 substeps_sedi, ktop_sedi, dt)
1910 !! calculates mass and number weighted fall speeds for ice
1911 !! and the substepping required and the top k-level of sedimentation
1912 use module_mp_tempo_params, only : av_i, cig, oig2, bv_i
1913
1914 real(wp), intent(in) :: dt
1915 real(wp), dimension(:), intent(in) :: rhof, dz1d, ri
1916 real(dp), dimension(:), intent(in) :: ilami
1917 logical, dimension(:), intent(in) :: l_qi
1918 real(wp), dimension(:), intent(inout) :: vt, vtn
1919 integer, intent(out) :: substeps_sedi, ktop_sedi
1920 real(wp) :: dz_by_vt
1921 integer :: k, nz
1922
1923 nz = size(l_qi)
1924 ktop_sedi = 1
1925 substeps_sedi = 1
1926 do k = nz, 1, -1
1927 if (ri(k) > r1) then
1928 vt(k) = rhof(k)*av_i*cig(3)*oig2 * ilami(k)**bv_i
1929 vtn(k) = rhof(k)*av_i*cig(6)/cig(7) * ilami(k)**bv_i
1930 else
1931 vt(k) = vt(k+1)
1932 vtn(k) = vtn(k+1)
1933 endif
1934 if (vt(k) > 1.e-3_wp) then
1935 ktop_sedi = max(ktop_sedi, k)
1936 dz_by_vt = dz1d(k) / vt(k)
1937 substeps_sedi = max(substeps_sedi, int(dt/dz_by_vt + 1._wp))
1938 endif
1939 enddo
1940 if (ktop_sedi == nz) ktop_sedi = nz-1
1941 end subroutine ice_fallspeed
1942
1943
1944 subroutine cloud_fallspeed(rhof, w1d, l_qc, rc, nc, ilamc, dz1d, vt, vtn, &
1945 ktop_sedi)
1946 !! calculates mass and number weighted fall speeds for cloud
1947 !! and the top k-level of sedimentation
1948 use module_mp_tempo_params, only : av_c, ccg, ocg1, ocg2, bv_c, r2
1949
1950 real(wp), dimension(:), intent(in) :: rhof, w1d, dz1d, rc, nc
1951 real(dp), dimension(:), intent(in) :: ilamc
1952 logical, dimension(:), intent(in) :: l_qc
1953 real(wp), dimension(:), intent(inout) :: vt, vtn
1954 integer, intent(out) :: ktop_sedi
1955 real(wp) :: hgt
1956 integer :: k, nz, nu_c
1957
1958 nz = size(l_qc)
1959 ktop_sedi = 1
1960
1961 ! clouds/fog settle below 500 m agl
1962 hgt = 0._wp
1963 hgt_loop : do k = 1, nz-1
1964 if (rc(k) > r2) ktop_sedi = k
1965 hgt = hgt + dz1d(k)
1966 if (hgt > 500._wp) exit hgt_loop
1967 enddo hgt_loop
1968
1969 do k = ktop_sedi, 1, -1
1970 if (rc(k) > r1 .and. w1d(k) < 0.1_wp) then
1971 nu_c = get_nuc(nc(k))
1972 vt(k) = rhof(k)*av_c*ccg(5,nu_c)*ocg2(nu_c) * ilamc(k)**bv_c
1973 vtn(k) = rhof(k)*av_c*ccg(4,nu_c)*ocg1(nu_c) * ilamc(k)**bv_c
1974 endif
1975 enddo
1976 end subroutine cloud_fallspeed
1977
1978
1979 subroutine cloud_condensation(rho, temp, w1d, ssatw, lvap, tcond, diffu, lvt2, &
1980 nwfa1d, nwfa, ncsave, qv, qvs, l_qc, rc, nc, tend, dt, odt)
1981 !! cloud condensation and evaporation
1982 use module_mp_tempo_params, only : eps, r1, t0, orv, pi, rho_w, nbc, &
1983 tnc_wev, nt_c_min, nt_c_l
1984
1985 real(wp), intent(in) :: dt, odt
1986 type(ty_tend), intent(inout) :: tend
1987 real(wp), dimension(:), intent(in) :: rho, temp, w1d, ssatw, lvap, tcond, diffu, lvt2, &
1988 nwfa, qv, qvs, rc, nc
1989 real(wp), dimension(:), intent(in), optional :: nwfa1d, ncsave
1990 logical, dimension(:), intent(in) :: l_qc
1991 real(wp) :: clap, fcd, dfcd, xrc, xnc, orho, tempc, otemp, &
1992 rvs, rvs_p, rvs_pp, gamsc, alphsc, xsat, t1_evap
1993 real(dp) :: dc_star
1994 integer :: k, nz, n, idx_d, idx_n, idx_c
1995
1996 nz = size(qv)
1997 do k = 1, nz
1998 if (abs(ssatw(k)) < eps) cycle ! RH = 100%
1999
2000 orho = 1._wp/rho(k)
2001 clap = (qv(k)-qvs(k))/(1._wp + lvt2(k)*qvs(k))
2002 do n = 1, 3
2003 fcd = qvs(k)*exp(lvt2(k)*clap) - qv(k) + clap
2004 dfcd = qvs(k)*lvt2(k)*exp(lvt2(k)*clap) + 1._wp
2005 clap = clap - fcd/dfcd
2006 enddo
2007 xrc = rc(k) + clap*rho(k)
2008 xnc = 0._wp
2009
2010 if (xrc > r1) then
2011 ! mass tendency
2012 tend%prw_vcd(k) = clap*odt
2013
2014 if (clap > eps) then ! condensation
2015 if (present(nwfa1d)) then
2016 xnc = max(nt_c_min, activate_cloud_number(temp(k), w1d(k), nwfa(k)))
2017 elseif (present(ncsave)) then
2018 xnc = ncsave(k)
2019 else
2020 xnc = nt_c_l
2021 endif
2022 tend%pnc_wcd(k) = 0.5_wp*(xnc-nc(k) + abs(xnc-nc(k)))*odt*orho
2023 elseif (l_qc(k) .and. ssatw(k) < -1.e-6_wp .and. clap < -eps) then ! evaporation
2024 tempc = temp(k) - t0
2025 otemp = 1._wp/temp(k)
2026 rvs = rho(k)*qvs(k)
2027 rvs_p = rvs*otemp*(lvap(k)*otemp*orv - 1._wp)
2028 rvs_pp = rvs * (otemp*(lvap(k)*otemp*orv - 1._wp) * &
2029 otemp*(lvap(k)*otemp*orv - 1._wp) + &
2030 (-2._wp*lvap(k)*otemp*otemp*otemp*orv) + otemp*otemp)
2031 gamsc = lvap(k)*diffu(k)/tcond(k) * rvs_p
2032 alphsc = 0.5_wp*(gamsc/(1._wp+gamsc))*(gamsc/(1._wp+gamsc)) * &
2033 rvs_pp/rvs_p * rvs/rvs_p
2034 alphsc = max(1.e-9_wp, alphsc)
2035 xsat = ssatw(k)
2036 if (abs(xsat) < 1.e-9_wp) xsat = 0._wp
2037 t1_evap = 2._wp*pi*(1.0_wp - alphsc*xsat + 2._wp*alphsc*alphsc*xsat*xsat - &
2038 5._wp*alphsc*alphsc*alphsc*xsat*xsat*xsat) / (1._wp+gamsc)
2039
2040 dc_star = sqrt(-2._dp*dt * t1_evap/(2._dp*pi) * &
2041 4._dp*diffu(k)*ssatw(k)*rvs/rho_w)
2042 idx_d = max(1, min(int(1.e6_wp*dc_star), nbc))
2043 call get_cloud_table_index(rc(k), nc(k), idx_c, idx_n)
2044
2045 tend%prw_vcd(k) = max(real(-rc(k)*0.99_wp*orho*odt, kind=dp), &
2046 tend%prw_vcd(k))
2047 tend%pnc_wcd(k) = max(real(-nc(k)*0.99_wp*orho*odt, kind=dp), &
2048 -tnc_wev(idx_d, idx_c, idx_n)*orho*odt)
2049 endif
2050 else
2051 tend%prw_vcd(k) = -rc(k)*orho*odt
2052 tend%pnc_wcd(k) = -nc(k)*orho*odt
2053 endif
2054 enddo
2055 end subroutine cloud_condensation
2056
2057
2058 subroutine rain_evaporation(rho, temp, ssatw, lvap, tcond, diffu, &
2059 vsc2, rhof2, qv, qvs, l_qr, rr, nr, ilamr, tend, odt)
2060 !! rain evaporation that includes reduction in the evaporation rate
2061 !! in the presence of melting graupel
2062 use module_mp_tempo_params, only : eps, r1, t0, orv, pi, rho_w, &
2063 org2, cre, t1_qr_ev, t2_qr_ev, fv_r
2064
2065 real(wp), intent(in) :: odt
2066 type(ty_tend), intent(inout) :: tend
2067 real(wp), dimension(:), intent(in) :: rho, temp, ssatw, lvap, tcond, diffu, vsc2, rhof2, &
2068 qv, qvs, rr, nr
2069 logical, dimension(:), intent(in) :: l_qr
2070 real(dp), dimension(:), intent(in) :: ilamr
2071 real(wp) :: orho, tempc, otemp, &
2072 rvs, rvs_p, rvs_pp, gamsc, alphsc, xsat, t1_evap, rate_max, eva_factor
2073 real(dp) :: lamr, n0_r
2074 integer :: k, nz
2075
2076 nz = size(qv)
2077 do k = 1, nz
2078 if(l_qr(k)) then
2079 if ((ssatw(k) < -eps) .and. tend%prw_vcd(k) <= 0._dp) then
2080 orho = 1._wp/rho(k)
2081 tempc = temp(k) - t0
2082 otemp = 1._wp/temp(k)
2083 rvs = rho(k)*qvs(k)
2084 rvs_p = rvs*otemp*(lvap(k)*otemp*orv - 1._wp)
2085 rvs_pp = rvs * (otemp*(lvap(k)*otemp*orv - 1._wp) * &
2086 otemp*(lvap(k)*otemp*orv - 1._wp) + &
2087 (-2._wp*lvap(k)*otemp*otemp*otemp*orv) + otemp*otemp)
2088 gamsc = lvap(k)*diffu(k)/tcond(k) * rvs_p
2089 alphsc = 0.5_wp*(gamsc/(1._wp+gamsc))*(gamsc/(1._wp+gamsc)) * &
2090 rvs_pp/rvs_p * rvs/rvs_p
2091 alphsc = max(1.e-9_wp, alphsc)
2092 xsat = min(-1.e-9_wp, ssatw(k))
2093 t1_evap = 2._wp*pi*(1.0_wp - alphsc*xsat + 2._wp*alphsc*alphsc*xsat*xsat - &
2094 5._wp*alphsc*alphsc*alphsc*xsat*xsat*xsat) / (1._wp+gamsc)
2095
2099 if (qv(k)/qvs(k) < 0.95_wp .and. rr(k)*orho <= 1.e-8_wp) then
2100 tend%prv_rev(k) = rr(k)*orho*odt
2101 else
2102 lamr = 1._dp/ilamr(k)
2103 n0_r = nr(k)*org2*lamr**cre(2)
2104 tend%prv_rev(k) = t1_evap*diffu(k)*(-ssatw(k))*n0_r*rvs * &
2105 (t1_qr_ev*ilamr(k)**cre(10) + t2_qr_ev*vsc2(k)*rhof2(k)* &
2106 ((lamr+0.5*fv_r)**(-cre(11))))
2107 rate_max = min((rr(k)*orho*odt), &
2108 (qvs(k)-qv(k))*odt)
2109 tend%prv_rev(k) = min(real(rate_max, kind=dp), tend%prv_rev(k)*orho)
2110 if (tend%prr_gml(k) > 0._dp) then
2111 eva_factor = min(1._wp, 0.01_wp+(0.99_wp-0.01_wp)*(tempc/20._wp))
2112 tend%prv_rev(k) = tend%prv_rev(k)*eva_factor
2113 endif
2114 endif
2115 tend%pnr_rev(k) = min(real(nr(k)*0.99*orho*odt, kind=dp), &
2116 tend%prv_rev(k) * nr(k)/rr(k))
2117 endif
2118 endif
2119 enddo
2120 end subroutine rain_evaporation
2121
2122
2123 subroutine freeze_cloud_melt_ice(temp, rho, ocp, lvap, qi1d, ni1d, qiten, niten, &
2124 qc1d, nc1d, qcten, ncten, tten, ncsave, dt, odt)
2125 ! freezes all cloud water and melts all cloud ice instantly given the temperature
2126 use module_mp_tempo_params, only : t0, lfus, lsub, hgfrz, nt_c_l
2127
2128 real(wp), intent(in) :: dt, odt
2129 real(wp), dimension(:), intent(in) :: temp, rho, ocp, lvap, qi1d, ni1d, qc1d
2130 real(wp), dimension(:), intent(inout) :: qiten, niten, qcten, ncten, tten
2131 real(wp), dimension(:), intent(in), optional :: nc1d, ncsave
2132 real(wp) :: xri, xrc, lfus2, xnc
2133 integer :: k, nz
2134
2135 nz = size(temp)
2136 do k = 1, nz
2137 ! instantly melt all cloud ice
2138 xri = max(0._wp, qi1d(k)+qiten(k)*dt)
2139 if ((temp(k) > t0) .and. (xri > 0._wp)) then
2140 qcten(k) = qcten(k) + xri*odt
2141 ncten(k) = ncten(k) + ni1d(k)*odt
2142 qiten(k) = qiten(k) - xri*odt
2143 niten(k) = -ni1d(k)*odt
2144 tten(k) = tten(k) - lfus*ocp(k)*xri*odt
2145 endif
2146 ! instantly freeze all cloud water
2147 xrc = max(0._wp, qc1d(k)+qcten(k)*dt)
2148 if ((temp(k) < hgfrz) .and. (xrc > 0._wp)) then
2149 lfus2 = lsub - lvap(k)
2150 if (present(nc1d)) then
2151 xnc = nc1d(k) + ncten(k)*dt
2152 elseif (present(ncsave)) then
2153 xnc = ncsave(k)/rho(k) + ncten(k)*dt
2154 else
2155 xnc = nt_c_l/rho(k) + ncten(k)*dt
2156 endif
2157 qiten(k) = qiten(k) + xrc*odt
2158 niten(k) = niten(k) + xnc*odt
2159 qcten(k) = qcten(k) - xrc*odt
2160 ncten(k) = ncten(k) - xnc*odt
2161 tten(k) = tten(k) + lfus2*ocp(k)*xrc*odt
2162 endif
2163 enddo
2164 end subroutine freeze_cloud_melt_ice
2165
2166
2167 function koop_nucleation(temp, satw, naero, dt) result(nuc)
2168 !! aqueous solution freezing of water from
2169 !! [Koop et al. (2000)](https://doi.org/10.1038/35020537)
2170 !! newer research suggests that the freezing rate should be lower
2171 !! than original paper, so J_rate is reduced by two orders of magnitude
2172 use module_mp_tempo_params, only : r_uni, ar_volume
2173
2174 real(wp), intent(in) :: temp, satw, naero, dt
2175 real(wp) :: xni, mu_diff, a_w_i, delta_aw, log_j_rate, j_rate, prob_h
2176 real(wp) :: nuc
2177
2178 xni = 0.0_wp
2179
2180 mu_diff = 210368._wp + (131.438_wp*temp) - &
2181 (3.32373e6_wp/temp) - (41729.1_wp*log(temp))
2182 a_w_i = exp(mu_diff/(r_uni*temp))
2183 delta_aw = satw - a_w_i
2184
2185 log_j_rate = -906.7_wp + (8502._wp*delta_aw) - &
2186 (26924._wp*delta_aw*delta_aw) + (29180._wp*delta_aw*delta_aw*delta_aw)
2187 log_j_rate = min(20._wp, log_j_rate)
2188 j_rate = 10._wp**log_j_rate ! cm-3 s-1
2189 prob_h = min(1._wp-exp(-j_rate*ar_volume*dt), 1._wp)
2190 if (prob_h > 0._wp) then
2191 xni = min(prob_h*naero, 1000.e3_wp)
2192 endif
2193 nuc = max(0._wp, xni)
2194 end function koop_nucleation
2195
2196
2197 function activate_cloud_number(temp, w1d, nwfa, land) result(activ)
2198 !! calculations numer of cloud droplets activated
2199 use module_mp_tempo_params, only : ta_na, ntb_arc, ta_ww, ntb_arw, &
2200 ta_tk, ntb_art, tnccn_act
2201
2202 real(wp), intent(in) :: temp, w1d, nwfa
2203 integer, intent(in), optional :: land
2204 real(wp) :: n_local, w_local
2205 real(wp) :: a, b, c, d, t, u, x1, x2, y1, y2, nx, wy, fraction
2206 real(wp) :: lower_lim_nuc_frac
2207 integer :: i, j, k, l, m, n
2208 real(wp) :: activ
2209
2210 ! index for number of aerosols
2211 n_local = nwfa * 1.e-6_wp
2212 if (n_local >= ta_na(ntb_arc)) then
2213 n_local = ta_na(ntb_arc) - 1.0_wp
2214 elseif (n_local <= ta_na(1)) then
2215 n_local = ta_na(1) + 1.0_wp
2216 endif
2217 nindex: do n = 2, ntb_arc
2218 if (n_local >= ta_na(n-1) .and. n_local < ta_na(n)) exit nindex
2219 enddo nindex
2220 i = n
2221 x1 = log(ta_na(i-1))
2222 x2 = log(ta_na(i))
2223
2224 ! index for vertical velocity
2225 w_local = w1d
2226 if (w_local >= ta_ww(ntb_arw)) then
2227 w_local = ta_ww(ntb_arw) - 1.0_wp
2228 elseif (w_local <= ta_ww(1)) then
2229 w_local = ta_ww(1) + 0.001_wp
2230 endif
2231 windex: do n = 2, ntb_arw
2232 if (w_local >= ta_ww(n-1) .and. w_local < ta_ww(n)) exit windex
2233 enddo windex
2234 j = n
2235 y1 = log(ta_ww(j-1))
2236 y2 = log(ta_ww(j))
2237
2238 k = max(1, min(nint((temp - ta_tk(1))*0.1_wp) + 1, ntb_art))
2239
2240 ! the next two values are indexes of mean aerosol radius and
2241 ! hygroscopicity and are currently constant
2245 l = 3
2246 m = 2
2247
2251 lower_lim_nuc_frac = 0.
2252 if (present(land)) then
2253 if (land == 1) then ! land
2254 lower_lim_nuc_frac = 0.
2255 elseif (land == 0) then ! not land (water/ice)
2256 lower_lim_nuc_frac = 0.15
2257 else
2258 lower_lim_nuc_frac = 0.15 ! catch-all for anything else
2259 endif
2260 endif
2261
2262 a = tnccn_act(i-1,j-1,k,l,m)
2263 b = tnccn_act(i,j-1,k,l,m)
2264 c = tnccn_act(i,j,k,l,m)
2265 d = tnccn_act(i-1,j,k,l,m)
2266 nx = log(n_local)
2267 wy = log(w_local)
2268 t = (nx-x1)/(x2-x1)
2269 u = (wy-y1)/(y2-y1)
2270
2271 fraction = (1.0_wp-t)*(1.0_wp-u)*a + t*(1.0_wp-u)*b + t*u*c + (1.0_wp-t)*u*d
2272 fraction = max(fraction, lower_lim_nuc_frac)
2273
2274 activ = nwfa*fraction
2275 end function activate_cloud_number
2276
2277
2278 subroutine warm_rain(rhof, l_qc, rc, nc, ilamc, mvd_c, l_qr, rr, nr, mvd_r, tend, odt)
2279 !! computes warm-rain process rates -- condensation/evaporation happen later
2280 use module_mp_tempo_params, only : d0r, d0c, r1, nbr, t_efrw, &
2281 t1_qr_qc, mu_r, am_r, ccg, obmr, ocg2, dr, org2, cre, fv_r, &
2282 autocon_nr_factor
2283
2284 real(wp), intent(in) :: odt
2285 real(wp), dimension(:), intent(in) :: rhof, mvd_r, mvd_c, rr, nr, rc, nc
2286 real(dp), dimension(:), intent(in) :: ilamc
2287 logical, dimension(:), intent(in) :: l_qc, l_qr
2288 type(ty_tend), intent(inout) :: tend
2289
2290 real(dp) :: lamr, lamc, n0_r
2291 real(wp) :: ef_rr, dc_g, dc_b, xdc, zeta1, zeta, taud, tau, ef_rw
2292 integer :: k, nz, nu_c, idx
2293
2294 nz = size(l_qc)
2300 do k = 1, nz
2301 if (l_qr(k)) then
2302 if (mvd_r(k) > d0r) then
2303 ef_rr = max(-0.1_wp, 1.0_wp - exp(2300.0_wp*(mvd_r(k)-1950.0e-6_wp)))
2304 tend%pnr_rcr(k) = ef_rr * 2.0_wp*nr(k)*rr(k)
2305 endif
2306 endif
2307
2312 if (l_qc(k)) then
2313 if (rc(k) > 0.01e-3_wp) then
2314 nu_c = get_nuc(nc(k))
2315 lamc = 1._dp / ilamc(k)
2316 xdc = max(d0c*1.e6_wp, ((rc(k)/(am_r*nc(k)))**obmr) * 1.e6_wp)
2317 dc_g = ((ccg(3,nu_c)*ocg2(nu_c))**obmr / lamc) * 1.e6_wp
2318 dc_b = (xdc*xdc*xdc*dc_g*dc_g*dc_g - xdc*xdc*xdc*xdc*xdc*xdc) &
2319 **(1._wp/6._wp)
2320 zeta1 = 0.5_wp*((6.25e-6_wp*xdc*dc_b*dc_b*dc_b - 0.4_wp) &
2321 + abs(6.25e-6_wp*xdc*dc_b*dc_b*dc_b - 0.4_wp))
2322 zeta = 0.027_wp*rc(k)*zeta1
2323 taud = 0.5_wp*((0.5_wp*dc_b - 7.5_wp) + abs(0.5_wp*dc_b - 7.5_wp)) + r1
2324 tau = 3.72_wp/(rc(k)*taud)
2325 tend%prr_wau(k) = zeta/tau
2326 tend%prr_wau(k) = min(real(rc(k)*odt, kind=dp), &
2327 tend%prr_wau(k))
2328 tend%pnr_wau(k) = tend%prr_wau(k) / (am_r*nu_c*autocon_nr_factor*d0r*d0r*d0r)
2329 tend%pnc_wau(k) = min(real(nc(k)*odt, kind=dp), &
2330 tend%prr_wau(k) / (am_r*mvd_c(k)*mvd_c(k)*mvd_c(k)))
2331 endif
2332 endif
2333
2337 if (l_qr(k) .and. l_qc(k)) then
2338 if (mvd_r(k) > d0r .and. mvd_c(k) > d0c) then
2339 lamr = (3.0_dp + mu_r + 0.672_dp) / mvd_r(k)
2340 idx = 1 + int(nbr*log(real(mvd_r(k)/dr(1), kind=dp)) / &
2341 log(real(dr(nbr)/dr(1), kind=dp)))
2342 idx = min(idx, nbr)
2343 ef_rw = t_efrw(idx, int(mvd_c(k)*1.e6_wp))
2344 n0_r = nr(k)*org2*lamr**cre(2)
2345 tend%prr_rcw(k) = rhof(k)*t1_qr_qc*ef_rw*rc(k)*n0_r * &
2346 ((lamr+fv_r)**(-cre(9)))
2347 tend%prr_rcw(k) = min(real(rc(k)*odt, kind=dp), tend%prr_rcw(k))
2348 tend%pnc_rcw(k) = rhof(k)*t1_qr_qc*ef_rw*nc(k)*n0_r * &
2349 ((lamr+fv_r)**(-cre(9)))
2350 tend%pnc_rcw(k) = min(real(nc(k)*odt, kind=dp), tend%pnc_rcw(k))
2351 endif
2352 endif
2353 enddo
2354 end subroutine warm_rain
2355
2356
2357 subroutine riming(temp, rhof, visco, l_qc, rc, nc, ilamc, mvd_c, &
2358 l_qs, rs, smo0, smob, smoc, smoe, vtboost, l_qg, rg, ng, ilamg, idx, tend, odt)
2359 !! snow and graupel riming
2360 use module_mp_tempo_params, only : d0c, d0s, nbs, ds, t_efsw, t1_qs_qc, &
2361 r_g, bm_g, mu_g, av_g, cgg, ogg3, bv_g, rho_w, t0, d0g, pi, cge, ogg2, &
2362 rime_threshold, rime_conversion, av_s, bv_s, rho_s, xm0i, eps, fv_s, &
2363 meters3_to_liters
2364
2365 real(wp), intent(in) :: odt
2366 type(ty_tend), intent(inout) :: tend
2367 real(wp), dimension(:), intent(in) :: rhof, visco, temp, rc, nc, rs, rg, ng
2368 real(wp), dimension(:), intent(in) :: mvd_c
2369 real(dp), dimension(:), intent(in) :: smo0, smob, smoc, smoe, ilamg, ilamc
2370 logical, dimension(:), intent(in) :: l_qc, l_qs, l_qg
2371 integer, dimension(:), intent(in) :: idx
2372 real(wp), dimension(:), intent(out) :: vtboost
2373
2374 real(dp) :: xds, xdg, n0_g, lamc
2375 real(wp) :: ef_sw, vtg, stoke_g, const_ri, tempc, rime_dens, ef_gw
2376 real(wp) :: t1_qg_qc, r_frac, g_frac, vts, tf, snow_dens_frac
2377 integer :: k, nz, idxs, nu_c
2378
2379 nz = size(l_qc)
2380 do k = 1, nz
2381 tempc = temp(k) - t0
2382 vtboost(k) = 1._wp
2383 if (l_qc(k) .and. l_qs(k)) then
2384 nu_c = get_nuc(nc(k))
2385 lamc = 1._dp / ilamc(k)
2386 xds = smoc(k) / smob(k)
2387 if ((mvd_c(k) > d0c) .and. (xds > d0s)) then
2390 idxs = 1 + int(nbs*log(real(xds/ds(1), kind=dp)) / log(real(ds(nbs)/ds(1), kind=dp)))
2391 idxs = min(idxs, nbs)
2392 ef_sw = t_efsw(idxs, int(mvd_c(k)*1.e6_wp))
2393 tend%prs_scw(k) = rhof(k)*t1_qs_qc*ef_sw*rc(k)*smoe(k)
2394 tend%prs_scw(k) = min(real(rc(k)*odt, kind=dp), tend%prs_scw(k))
2395 tend%pnc_scw(k) = rhof(k)*t1_qs_qc*ef_sw*nc(k)*smoe(k)
2396 tend%pnc_scw(k) = min(real(nc(k)*odt, kind=dp), tend%pnc_scw(k))
2397
2402 if (temp(k) < t0) then
2403 if (tend%prs_scw(k) > rime_threshold*tend%prs_sde(k) .and. &
2404 tend%prs_sde(k) > eps) then
2405 r_frac = min(30.0_dp, tend%prs_scw(k)/tend%prs_sde(k))
2406 g_frac = min(rime_conversion, 0.15_wp + (r_frac-2._wp)*.028_wp)
2407 vtboost(k) = min(1.5_wp, 1.1_wp + (r_frac-2.)*.014_wp)
2408 tend%prg_scw(k) = g_frac*tend%prs_scw(k)
2409 tend%png_scw(k) = tend%prg_scw(k)*smo0(k)/rs(k)
2410 vts = av_s*xds**bv_s * exp(-fv_s*xds)
2411 const_ri = -1._wp*(mvd_c(k)*0.5e6_wp)*vts/min(-0.1_wp,tempc)
2412 const_ri = max(0.1_wp, min(const_ri, 10._wp))
2413 rime_dens = (0.051_wp + 0.114_wp*const_ri - 0.0055_wp*const_ri*const_ri)*1000._wp
2414 if(rime_dens < 150._wp) then
2415 g_frac = 0._wp
2416 tend%prg_scw(k) = 0._dp
2417 tend%png_scw(k) = 0._dp
2418 endif
2419 snow_dens_frac = min(1._wp, max(0._wp, real(rs(k)*odt / &
2420 (rs(k)*odt + tend%prg_scw(k)), kind=wp)))
2421 tend%pbg_scw(k) = meters3_to_liters*tend%prg_scw(k) / &
2422 (rho_s * snow_dens_frac + rime_dens * (1._wp-snow_dens_frac))
2423 ! tend%pbg_scw(k) = meters3_to_liters*tend%prg_scw(k) / &
2424 ! (0.5_wp*(rho_s+rime_dens))
2425 tend%prs_scw(k) = (1._wp - g_frac)*tend%prs_scw(k)
2426 endif
2427 endif
2428 endif
2429 endif
2430
2431 if (l_qc(k) .and. l_qg(k)) then
2434 if (rg(k) >= r_g(1) .and. mvd_c(k) > d0c) then
2435 xdg = (bm_g + mu_g + 1._wp) * ilamg(k)
2436 vtg = rhof(k)*av_g(idx(k))*cgg(6,idx(k))*ogg3 * ilamg(k)**bv_g(idx(k))
2437 stoke_g = mvd_c(k)*mvd_c(k)*vtg*rho_w/(9._wp*visco(k)*xdg)
2441 const_ri = -1._wp*(mvd_c(k)*0.5e6_wp)*vtg/min(-0.1_wp, tempc)
2442 const_ri = max(0.1_wp, min(const_ri, 10._wp))
2443 rime_dens = (0.051_wp + 0.114_wp*const_ri - 0.0055_wp*const_ri*const_ri)*1000._wp
2444 if (xdg > d0g) then
2445 if (stoke_g >= 0.4_wp .and. stoke_g <= 10._wp) then
2446 ef_gw = 0.55_wp*log10(2.51_wp*stoke_g)
2447 elseif (stoke_g < 0.4_wp) then
2448 ef_gw = 0.0_wp
2449 elseif (stoke_g > 10._wp) then
2450 ef_gw = 0.77_wp
2451 endif
2455 if (temp(k) > t0) ef_gw = ef_gw*0.1_wp
2456 t1_qg_qc = pi*.25_wp*av_g(idx(k)) * cgg(9,idx(k))
2457 n0_g = ng(k)*ogg2*(1._wp/ilamg(k))**cge(2,1)
2458 tend%prg_gcw(k) = rhof(k)*t1_qg_qc*ef_gw*rc(k)* &
2459 n0_g*ilamg(k)**cge(9,idx(k))
2460 tend%pnc_gcw(k) = rhof(k)*t1_qg_qc*ef_gw*nc(k)* &
2461 n0_g*ilamg(k)**cge(9,idx(k))
2462 tend%pnc_gcw(k) = min(real(nc(k)*odt, kind=dp), tend%pnc_gcw(k))
2463 if (temp(k) < t0) tend%pbg_gcw(k) = meters3_to_liters*tend%prg_gcw(k)/rime_dens
2464
2465 if (temp(k) < t0) then
2470 if (tend%prg_gcw(k) > eps .and. tempc > -8._wp) then
2471 tf = 0._wp
2472 if (tempc >= -5._wp .and. tempc < -3._wp) then
2473 tf = 0.5_wp*(-3.0_wp - tempc)
2474 elseif (tempc > -8._wp .and. tempc < -5._wp) then
2475 tf = 0.33333333_wp*(8._wp + tempc)
2476 endif
2477 tend%pni_ihm(k) = 3.5e8_wp*tf*tend%prg_gcw(k)
2478 tend%pri_ihm(k) = xm0i*tend%pni_ihm(k)
2479 tend%prs_ihm(k) = tend%prs_scw(k)/(tend%prs_scw(k)+tend%prg_gcw(k)) * &
2480 tend%pri_ihm(k)
2481 tend%prg_ihm(k) = tend%prg_gcw(k)/(tend%prs_scw(k)+tend%prg_gcw(k)) * &
2482 tend%pri_ihm(k)
2483 endif
2484 endif
2485 endif
2486 endif
2487 endif
2488 end do
2489 end subroutine riming
2490
2491
2492 subroutine get_snow_table_index(rs, idx_s)
2493 !! get snow table index from snow mass
2494 use module_mp_tempo_params, only : ntb_s, nis2
2495
2496 real(wp), intent(in) :: rs
2497 integer :: nis, nn, n
2498 integer, intent(out) :: idx_s
2499
2500 nis = nint(log10(rs))
2501 do_loop_rs: do nn = nis-1, nis+1
2502 n = nn
2503 if ((rs/10._wp**nn) >= 1._wp .and. (rs/10._wp**nn) < 10._wp) exit do_loop_rs
2504 enddo do_loop_rs
2505 idx_s = int(rs/10._wp**n) + 10*(n-nis2) - (n-nis2)
2506 idx_s = max(1, min(idx_s, ntb_s))
2507 end subroutine get_snow_table_index
2508
2509
2510 subroutine get_temperature_table_index(tempk, idx_t)
2511 !! get temperature table index
2512 use module_mp_tempo_params, only : t0, ntb_t
2513
2514 real(wp), intent(in) :: tempk
2515 real(wp) :: tempc
2516 integer, intent(out) :: idx_t
2517
2518 tempc = tempk - t0
2519 idx_t = int((tempc-2.5_wp)/5._wp) - 1
2520 idx_t = max(1, -idx_t)
2521 idx_t = min(idx_t, ntb_t)
2522 end subroutine get_temperature_table_index
2523
2524
2525 subroutine get_rain_table_index(rr, ilamr, idx_r, idx_r1)
2526 !! get rain table indices from rain mass and lambda
2527 use module_mp_tempo_params, only : nir2, nir3, ntb_r, ntb_r1, &
2528 org2, org1, bm_r, am_r, crg, cre
2529
2530 real(wp), intent(in) :: rr
2531 real(dp), intent(in) :: ilamr
2532 real(dp) :: lamr, lam_exp, n0_exp
2533 integer :: nir, nn, n
2534 integer, intent(out) :: idx_r, idx_r1
2535
2536 nir = nint(log10(rr))
2537 do_loop_rr: do nn = nir-1, nir+1
2538 n = nn
2539 if ((rr/10._wp**nn) >= 1._wp .and. (rr/10._wp**nn) < 10._wp) exit do_loop_rr
2540 enddo do_loop_rr
2541 idx_r = int(rr/10._wp**n) + 10*(n-nir2) - (n-nir2)
2542 idx_r = max(1, min(idx_r, ntb_r))
2543
2544 lamr = 1./ilamr
2545 lam_exp = lamr * (crg(3)*org2*org1)**bm_r
2546 n0_exp = org1*rr/am_r * lam_exp**cre(1)
2547 nir = nint(log10(real(n0_exp, kind=dp)))
2548 do_loop_nr: do nn = nir-1, nir+1
2549 n = nn
2550 if ((n0_exp/10._wp**nn) >= 1._wp .and. (n0_exp/10._wp**nn) < 10._wp) exit do_loop_nr
2551 enddo do_loop_nr
2552 idx_r1 = int(n0_exp/10._wp**n) + 10*(n-nir3) - (n-nir3)
2553 idx_r1 = max(1, min(idx_r1, ntb_r1))
2554 end subroutine get_rain_table_index
2555
2556
2557 subroutine get_graupel_table_index(rg, ilamg, idx, idx_g, idx_g1)
2558 !! get graupel table indices from graupel mass, lambda, and density index
2559 use module_mp_tempo_params, only : nig2, ntb_g, ntb_g1, ogg2, ogg1, &
2560 bm_g, cgg, ogg1, am_g, cge, nig3
2561
2562 real(wp), intent(in) :: rg
2563 real(dp), intent(in) :: ilamg
2564 integer, intent(in) :: idx
2565 real(dp) :: lamg, lam_exp, n0_exp
2566 integer :: nig, nn, n
2567 integer, intent(out) :: idx_g, idx_g1
2568
2569 nig = nint(log10(rg))
2570 do_loop_rg: do nn = nig-1, nig+1
2571 n = nn
2572 if ( (rg/10._wp**nn) >= 1._wp .and. (rg/10._wp**nn).lt.10._wp) exit do_loop_rg
2573 enddo do_loop_rg
2574 idx_g = int(rg/10._wp**n) + 10*(n-nig2) - (n-nig2)
2575 idx_g = max(1, min(idx_g, ntb_g))
2576
2577 lamg = 1./ilamg
2578 lam_exp = lamg * (cgg(3,1)*ogg2*ogg1)**bm_g
2579 n0_exp = ogg1*rg/am_g(idx) * lam_exp**cge(1,1)
2580 nig = nint(log10(real(n0_exp, kind=dp)))
2581 do_loop_ng: do nn = nig-1, nig+1
2582 n = nn
2583 if ( (n0_exp/10._wp**nn) >= 1._wp .and. (n0_exp/10._wp**nn) < 10._wp) exit do_loop_ng
2584 enddo do_loop_ng
2585 idx_g1 = int(n0_exp/10._wp**n) + 10*(n-nig3) - (n-nig3)
2586 idx_g1 = max(1, min(idx_g1, ntb_g1))
2587 end subroutine get_graupel_table_index
2588
2589
2590 subroutine get_cloud_table_index(rc, nc, idx_c, idx_n)
2591 !! get cloud table index from mass and number
2592 use module_mp_tempo_params, only : nbc, ntb_c, r_c, nic2, t_nc, nic1
2593
2594 real(wp), intent(in) :: rc, nc
2595 integer, intent(out) :: idx_c, idx_n
2596 integer :: nic, nn, n
2597
2598 nic = nint(log10(rc))
2599 do_loop_rc: do nn = nic-1, nic+1
2600 n = nn
2601 if ( (rc/10._wp**nn) >= 1._wp .and. (rc/10._wp**nn) < 10._wp) exit do_loop_rc
2602 enddo do_loop_rc
2603 idx_c = int(rc/10._wp**n) + 10*(n-nic2) - (n-nic2)
2604 idx_c = max(1, min(idx_c, ntb_c))
2605
2606 idx_n = nint(1._wp + real(nbc, kind=wp) * log(real(nc/t_nc(1), kind=dp)) / nic1)
2607 idx_n = max(1, min(idx_n, nbc))
2608 end subroutine get_cloud_table_index
2609
2610
2611 subroutine get_ice_table_index(ri, ni, idx_i, idx_i1)
2612 !! get ice table index from mass and number
2613 use module_mp_tempo_params, only : ntb_i, ntb_i1, nii2, nii3
2614
2615 real(wp), intent(in) :: ri, ni
2616 integer, intent(out) :: idx_i, idx_i1
2617 integer :: nii, nn, n
2618
2619 nii = nint(log10(ri))
2620 do_loop_ri: do nn = nii-1, nii+1
2621 n = nn
2622 if ( (ri/10._wp**nn) >= 1._wp .and. (ri/10._wp**nn) < 10._wp) exit do_loop_ri
2623 enddo do_loop_ri
2624 idx_i = int(ri/10._wp**n) + 10*(n-nii2) - (n-nii2)
2625 idx_i = max(1, min(idx_i, ntb_i))
2626
2627 nii = nint(log10(ni))
2628 do_loop_ni: do nn = nii-1, nii+1
2629 n = nn
2630 if ( (ni/10._wp**nn) >= 1._wp .and. (ni/10._wp**nn) < 10._wp) exit do_loop_ni
2631 enddo do_loop_ni
2632 idx_i1 = int(ni/10._wp**n) + 10*(n-nii3) - (n-nii3)
2633 idx_i1 = max(1, min(idx_i1, ntb_i1))
2634 end subroutine get_ice_table_index
2635
2636
2637 subroutine rain_snow_rain_graupel(temp, l_qr, rr, nr, ilamr, l_qs, rs, &
2638 l_qg, rg, ng, ilamg, idx, tend, odt)
2639 !! calculates rain-snow and rain-graupel collection
2640 use module_mp_tempo_params, only : t0, r_r, r_s, r_g, rho_i, rho_g, meters3_to_liters, &
2641 tmr_racs2, tcr_sacr2, tmr_racs1, tcr_sacr1, tms_sacr1, tcs_racs1, &
2642 tnr_sacr1, tnr_sacr2, tnr_racs1, tnr_racs2, &
2643 tcr_gacr, tmr_racg, tcg_racg, tnr_gacr, tnr_racg
2644
2645 real(wp), intent(in) :: odt
2646 type(ty_tend), intent(inout) :: tend
2647 real(wp), dimension(:), intent(in) :: temp, rr, rs, rg, nr, ng
2648 real(dp), dimension(:), intent(in) :: ilamr, ilamg
2649 logical, dimension(:), intent(in) :: l_qr, l_qs, l_qg
2650 integer, dimension(:), intent(in) :: idx
2651 integer :: k, nz, idx_r, idx_r1, idx_s, idx_t, &
2652 idx_g, idx_g1
2653
2654 nz = size(l_qg)
2655 do k = 1, nz
2656 if (l_qr(k) .and. l_qs(k)) then
2657 if (rr(k) >= r_r(1) .and. rs(k) >= r_s(1)) then
2658 call get_temperature_table_index(temp(k), idx_t)
2659 call get_rain_table_index(rr(k), ilamr(k), idx_r, idx_r1)
2660 call get_snow_table_index(rs(k), idx_s)
2661 if (temp(k) < t0) then
2662 tend%prr_rcs(k) = -(tmr_racs2(idx_s,idx_t,idx_r1,idx_r) &
2663 + tcr_sacr2(idx_s,idx_t,idx_r1,idx_r) &
2664 + tmr_racs1(idx_s,idx_t,idx_r1,idx_r) &
2665 + tcr_sacr1(idx_s,idx_t,idx_r1,idx_r))
2666 tend%prs_rcs(k) = tmr_racs2(idx_s,idx_t,idx_r1,idx_r) &
2667 + tcr_sacr2(idx_s,idx_t,idx_r1,idx_r) &
2668 - tcs_racs1(idx_s,idx_t,idx_r1,idx_r) &
2669 - tms_sacr1(idx_s,idx_t,idx_r1,idx_r)
2670 tend%prg_rcs(k) = tmr_racs1(idx_s,idx_t,idx_r1,idx_r) &
2671 + tcr_sacr1(idx_s,idx_t,idx_r1,idx_r) &
2672 + tcs_racs1(idx_s,idx_t,idx_r1,idx_r) &
2673 + tms_sacr1(idx_s,idx_t,idx_r1,idx_r)
2674 tend%prr_rcs(k) = max(real(-rr(k)*odt, kind=dp), tend%prr_rcs(k))
2675 tend%prs_rcs(k) = max(real(-rs(k)*odt, kind=dp), tend%prs_rcs(k))
2676 tend%prg_rcs(k) = min(real((rr(k)+rs(k))*odt, kind=dp), &
2677 tend%prg_rcs(k))
2678 tend%pnr_rcs(k) = tnr_racs1(idx_s,idx_t,idx_r1,idx_r) &
2679 + tnr_racs2(idx_s,idx_t,idx_r1,idx_r) &
2680 + tnr_sacr1(idx_s,idx_t,idx_r1,idx_r) &
2681 + tnr_sacr2(idx_s,idx_t,idx_r1,idx_r)
2682 tend%pnr_rcs(k) = min(real(nr(k)*odt, kind=dp), tend%pnr_rcs(k))
2683 tend%png_rcs(k) = tend%pnr_rcs(k)
2684 tend%pbg_rcs(k) = meters3_to_liters*tend%prg_rcs(k)/rho_i
2685 else
2686 tend%prs_rcs(k) = -tcs_racs1(idx_s,idx_t,idx_r1,idx_r) &
2687 - tms_sacr1(idx_s,idx_t,idx_r1,idx_r) &
2688 + tmr_racs2(idx_s,idx_t,idx_r1,idx_r) &
2689 + tcr_sacr2(idx_s,idx_t,idx_r1,idx_r)
2690 tend%prs_rcs(k) = max(real(-rs(k)*odt, kind=dp), tend%prs_rcs(k))
2691 tend%prr_rcs(k) = -tend%prs_rcs(k)
2692 endif
2693 endif
2694 endif
2695
2696 if (l_qr(k) .and. l_qg(k)) then
2697 if (rr(k) >= r_r(1) .and. rg(k) >= r_g(1)) then
2698 call get_temperature_table_index(temp(k), idx_t)
2699 call get_rain_table_index(rr(k), ilamr(k), idx_r, idx_r1)
2700 call get_graupel_table_index(rg(k), ilamg(k), idx(k), idx_g, idx_g1)
2701 if (temp(k) < t0) then
2702 tend%prg_rcg(k) = tmr_racg(idx_g1,idx_g,idx(k),idx_r1,idx_r) &
2703 + tcr_gacr(idx_g1,idx_g,idx(k),idx_r1,idx_r)
2704 tend%prg_rcg(k) = min(real(rr(k)*odt, kind=dp), tend%prg_rcg(k))
2705 tend%prr_rcg(k) = -tend%prg_rcg(k)
2706 tend%pnr_rcg(k) = tnr_racg(idx_g1,idx_g,idx(k),idx_r1,idx_r) &
2707 + tnr_gacr(idx_g1,idx_g,idx(k),idx_r1,idx_r)
2708 tend%pnr_rcg(k) = min(real(nr(k)*odt, kind=dp), tend%pnr_rcg(k))
2709 tend%pbg_rcg(k) = meters3_to_liters*tend%prg_rcg(k)/rho_i
2710 else
2711 tend%prr_rcg(k) = tcg_racg(idx_g1,idx_g,idx(k),idx_r1,idx_r)
2712 tend%prr_rcg(k) = min(real(rg(k)*odt, kind=dp), tend%prr_rcg(k))
2713 tend%prg_rcg(k) = -tend%prr_rcg(k)
2714 tend%png_rcg(k) = tnr_racg(idx_g1,idx_g,idx(k),idx_r1,idx_r)
2715 tend%png_rcg(k) = min(real(ng(k)*odt, kind=dp), tend%png_rcg(k))
2716 tend%pbg_rcg(k) = meters3_to_liters*tend%prg_rcg(k)/rho_g(idx(k))
2721 tend%pnr_rcg(k) = -1.5_wp*tnr_gacr(idx_g1,idx_g,idx(k),idx_r1,idx_r)
2722 endif
2723 endif
2724 endif
2725 enddo
2726 end subroutine rain_snow_rain_graupel
2727
2728
2729 subroutine ice_nucleation(temp, rho, w1d, qv, qvsi, ssati, ssatw, &
2730 nwfa1d, nifa1d, nwfa, nifa, ni, smo0, rc, nc, rr, nr, ilamr, tend, dt, odt)
2731 !! ice nulceation
2732 use module_mp_tempo_params, only : r_r, r_c, hgfrz, rho_i, xm0i, &
2733 tpg_qrfz, tpi_qrfz, tni_qrfz, tnr_qrfz, tpi_qcfz, tni_qcfz, &
2734 demott_nuc_ssati, eps, icenuc_max, tno, ato, max_ni, meters3_to_liters, &
2735 demott_nuc_tempc
2736
2737 real(wp), intent(in) :: dt, odt
2738 type(ty_tend), intent(inout) :: tend
2739 real(wp), dimension(:), intent(in) :: qv, temp, rho, qvsi, rr, nr, rc, nc, w1d, &
2740 ssati, ssatw, ni, nwfa, nifa
2741 real(dp), dimension(:), intent(in) :: ilamr, smo0
2742 real(wp), dimension(:), intent(in), optional :: nwfa1d, nifa1d
2743 real(wp) :: rate_max, tempc, xni, xnc
2744 integer :: k, nz, idx_in, idx_r, idx_r1, idx_tc, idx_c, idx_n
2745
2746 nz = size(qv)
2747 do k = 1, nz
2748 if (temp(k) < t0) then
2749 tempc = temp(k) - t0
2750 idx_tc = max(1, min(nint(-tempc), 45))
2751 rate_max = (qv(k)-qvsi(k))*rho(k)*odt*0.999_wp
2752 if (present(nifa1d)) then
2753 xni = demott_nucleation(tempc, rho(k), nifa(k))
2754 else
2755 xni = 1._wp * 1000._wp ! 1 / Liter
2756 endif
2757 call get_in_table_index(xni, idx_in)
2758
2762 if (rr(k) > r_r(1)) then
2763 call get_rain_table_index(rr(k), ilamr(k), idx_r, idx_r1)
2764 tend%prg_rfz(k) = tpg_qrfz(idx_r,idx_r1,idx_tc,idx_in)*odt
2765 tend%pri_rfz(k) = tpi_qrfz(idx_r,idx_r1,idx_tc,idx_in)*odt
2766 tend%pni_rfz(k) = tni_qrfz(idx_r,idx_r1,idx_tc,idx_in)*odt
2767 tend%pnr_rfz(k) = tnr_qrfz(idx_r,idx_r1,idx_tc,idx_in)*odt
2768 tend%prg_rfz(k) = min(real(rr(k)*odt, kind=dp), tend%prg_rfz(k))
2769 tend%pnr_rfz(k) = min(real(nr(k)*odt, kind=dp), tend%pnr_rfz(k))
2770 ! reduce number of graupel particles created at higher vertical velocities
2771 tend%png_rfz(k) = tend%pnr_rfz(k) * &
2772 max(min((10._wp**(-0.1_wp*w1d(k)) + 0.1_wp), 1._wp), 0.1_wp)
2773 ! tend%png_rfz(k) = tend%pnr_rfz(k)
2774 elseif (rr(k) > r1 .and. temp(k) < hgfrz) then
2775 tend%pri_rfz(k) = rr(k)*odt
2776 tend%pni_rfz(k) = nr(k)*odt
2777 endif
2778 tend%pbg_rfz(k) = meters3_to_liters*tend%prg_rfz(k)/rho_i
2779
2780 if (rc(k) > r_c(1)) then
2781 call get_cloud_table_index(rc(k), nc(k), idx_c, idx_n)
2782 tend%pri_wfz(k) = tpi_qcfz(idx_c,idx_n,idx_tc,idx_in)*odt
2783 tend%pri_wfz(k) = min(real(rc(k)*odt, kind=dp), tend%pri_wfz(k))
2784 tend%pni_wfz(k) = tni_qcfz(idx_c,idx_n,idx_tc,idx_in)*odt
2785 tend%pni_wfz(k) = min(real(nc(k)*odt, kind=dp), &
2786 tend%pri_wfz(k)/(2.0_dp*xm0i), tend%pni_wfz(k))
2787 elseif (rc(k) > r1 .and. temp(k) < hgfrz) then
2788 tend%pri_wfz(k) = rc(k)*odt
2789 tend%pni_wfz(k) = nc(k)*odt
2790 endif
2794 if ((ssati(k) >= demott_nuc_ssati) .or. (ssatw(k) > eps &
2795 .and. tempc < demott_nuc_tempc)) then
2796 if (present(nifa1d)) then
2797 xnc = demott_nucleation(tempc, rho(k), nifa(k))
2798 else
2799 xnc = min(icenuc_max, tno*exp(ato*(t0-temp(k))))
2800 endif
2801 xni = ni(k) + (tend%pni_rfz(k)+tend%pni_wfz(k))*dt
2802 tend%pni_inu(k) = 0.5_wp*(xnc-xni + abs(xnc-xni))*odt
2803 tend%pri_inu(k) = min(real(rate_max, kind=dp), xm0i*tend%pni_inu(k))
2804 tend%pni_inu(k) = tend%pri_inu(k)/xm0i
2805 endif
2808 xni = smo0(k)+ni(k) + (tend%pni_rfz(k)+tend%pni_wfz(k)+tend%pni_inu(k))*dt
2809 if (present(nwfa1d)) then
2810 if ((xni <= max_ni) .and.(temp(k) < 238._wp) .and. (ssati(k) >= 0.4_wp)) then
2811 xnc = koop_nucleation(temp(k), ssatw(k), nwfa(k), dt)
2812 tend%pni_iha(k) = xnc*odt
2813 tend%pri_iha(k) = min(real(rate_max, kind=dp), xm0i*0.1_wp*tend%pni_iha(k))
2814 tend%pni_iha(k) = tend%pri_iha(k)/(xm0i*0.1_wp)
2815 endif
2816 endif
2817 endif
2818 enddo
2819 end subroutine ice_nucleation
2820
2821
2822 function demott_nucleation(tempc, rho, nifa) result(nuc)
2823 !! DeMott nucleation
2824 use module_mp_tempo_params, only : rho_not0
2825
2826 real(wp), intent(in) :: tempc, rho, nifa
2827 real(wp) :: xni, nifa_cc
2828 real(wp) :: nuc
2829
2830 xni = 0._wp
2831 nifa_cc = max(0.5_wp, nifa*rho_not0*1.e-6_wp/rho)
2832 xni = (5.94e-5_wp*(-tempc)**3.33_wp) * (nifa_cc**((-0.0264_wp*(tempc))+0.0033_wp))
2833 xni = xni*rho/rho_not0 * 1000._wp
2834 nuc = max(0._wp, xni)
2835 end function demott_nucleation
2836
2837
2838 subroutine get_in_table_index(xni, idx_in)
2839 !! get ice nuclei table index
2840 use module_mp_tempo_params, only : ntb_in, nt_in, niin2
2841
2842 real(wp), intent(in) :: xni
2843 integer, intent(out) :: idx_in
2844 integer :: niin, nn, n
2845
2846 if (xni > nt_in(1)) then
2847 niin = nint(log10(xni))
2848 do_loop_xni: do nn = niin-1, niin+1
2849 n = nn
2850 if ( (xni/10._wp**nn) >= 1._wp .and. (xni/10._wp**nn) < 10._wp) exit do_loop_xni
2851 enddo do_loop_xni
2852 idx_in = int(xni/10._wp**n) + 10*(n-niin2) - (n-niin2)
2853 idx_in = max(1, min(idx_in, ntb_in))
2854 else
2855 idx_in = 1
2856 endif
2857 end subroutine get_in_table_index
2858
2859
2860 subroutine get_t1_subl(rho, temp, qvsi, tcond, diffu, ssati, t1_subl)
2861 !! calculations thermodynamic term used in depositional growth and melting
2862 use module_mp_tempo_params, only : t0, bm_i, mu_i, lsub, orv, &
2863 pi, c_sqrd, c_cube, d0s, ntb_i, r_s, ef_si, r_r, fv_r, ef_ri, &
2864 rho_i, eps, rho_w, rho_g
2865
2866 real(wp), dimension(:), intent(in) :: rho, temp, qvsi, tcond, diffu, ssati
2867 real(wp) :: otemp, rvs, rvs_p, rvs_pp, gamsc, alphsc, xsat
2868 real(wp), dimension(:), intent(out) :: t1_subl
2869 integer :: k, nz
2870
2871 nz = size(rho)
2872 do k = 1, nz
2873 otemp = 1._wp/temp(k)
2874 rvs = rho(k)*qvsi(k)
2875 rvs_p = rvs*otemp*(lsub*otemp*orv - 1._wp)
2876 rvs_pp = rvs * (otemp*(lsub*otemp*orv - 1._wp) * otemp*(lsub*otemp*orv - 1._wp) + &
2877 (-2.*lsub*otemp*otemp*otemp*orv) + otemp*otemp)
2878 gamsc = lsub*diffu(k)/tcond(k) * rvs_p
2879 alphsc = 0.5_wp*(gamsc/(1._wp+gamsc))*(gamsc/(1._wp+gamsc)) * &
2880 rvs_pp/rvs_p * rvs/rvs_p
2881 alphsc = max(1.e-9_wp, alphsc)
2882 xsat = ssati(k)
2883 if (abs(xsat) < 1.e-9_wp) xsat = 0._wp
2884 t1_subl(k) = 4._wp*pi*(1._wp - alphsc*xsat + 2._wp*alphsc*alphsc*xsat*xsat - &
2885 5._wp*alphsc*alphsc*alphsc*xsat*xsat*xsat) / (1._wp+gamsc)
2886 end do
2887 end subroutine get_t1_subl
2888
2889
2890 subroutine ice_processes(rhof, rhof2, rho, w1d, temp, qv, qvsi, tcond, diffu, &
2891 vsc2, ssati, l_qi, ri, ni, ilami, l_qs, rs, smoe, smof, smo1, rr, nr, ilamr, &
2892 mvd_r, l_qg, rg, ng, ilamg, idx, tend, odt)
2893 !! ice processes including cloud ice depositional growth, conversion of cloud ice
2894 !! to snow, snow collecting cloud ice, rain collecting cloud ice, snow depositional growth,
2895 !! and graupel sublimation
2896 use module_mp_tempo_params, only : t0, d0i, bm_i, mu_i, am_i, &
2897 c_sqrd, c_cube, oig1, cig, d0s, ntb_i, tpi_ide, tps_iaus, tni_iaus, &
2898 obmi, r_s, ef_si, t1_qs_qi, r_r, org2, cre, t1_qr_qi, t2_qr_qi, &
2899 fv_r, ef_ri, rho_i, t1_qs_sd, t2_qs_sd, eps, t1_qg_sd, &
2900 sc3, ogg2, cge, cgg, av_g, rho_w, rho_g
2901
2902 real(wp), intent(in) :: odt
2903 type(ty_tend), intent(inout) :: tend
2904 logical, dimension(:), intent(in) :: l_qi, l_qs, l_qg
2905 real(wp), dimension(:), intent(in) :: rhof, rhof2, rho, w1d, ri, ni, rs, rr, nr, &
2906 temp, qv, qvsi, tcond, diffu, ssati, vsc2, mvd_r, rg, ng
2907 real(dp), dimension(:), intent(in) :: ilami, smoe, smof, smo1, ilamr, ilamg
2908 integer, dimension(:), intent(in) :: idx
2909 real(wp) :: xdi, xmi, oxmi, c_snow, rate_max, otemp, rvs, t2_qg_sd
2910 real(dp) :: lami, lamr, n0_r, n0_g
2911 integer :: k, nz, idx_i, idx_i1
2912 real(wp), dimension(:), allocatable :: t1_subl
2913
2914 nz = size(l_qi)
2915 allocate(t1_subl(nz), source=0._wp)
2916 call get_t1_subl(rho, temp, qvsi, tcond, diffu, ssati, t1_subl)
2917
2918 do k = 1, nz
2919 otemp = 1._wp/temp(k)
2920 rvs = rho(k)*qvsi(k)
2921 rate_max = (qv(k)-qvsi(k))*rho(k)*odt*0.999_wp
2922
2923 if (temp(k) < t0) then
2924 if (l_qi(k)) then
2925 call get_ice_table_index(ri(k), ni(k), idx_i, idx_i1)
2926 lami = 1._dp/ilami(k)
2927 xdi = max(real(d0i, kind=dp), (bm_i + mu_i + 1.) * ilami(k))
2928 xmi = am_i*xdi**bm_i
2929 oxmi = 1._wp/xmi
2930 tend%pri_ide(k) = c_cube*t1_subl(k)*diffu(k)*ssati(k)*rvs &
2931 *oig1*cig(5)*ni(k)*ilami(k)
2932 if (tend%pri_ide(k) < 0._dp) then
2933 tend%pri_ide(k) = max(real(-ri(k)*odt, kind=dp), &
2934 tend%pri_ide(k), real(rate_max, kind=dp))
2935 tend%pni_ide(k) = tend%pri_ide(k)*oxmi
2936 tend%pni_ide(k) = max(real(-ni(k)*odt, kind=dp), tend%pni_ide(k))
2937 else
2938 tend%pri_ide(k) = min(tend%pri_ide(k), real(rate_max, kind=dp))
2939 tend%prs_ide(k) = (1.0_dp-tpi_ide(idx_i,idx_i1))*tend%pri_ide(k)
2940 tend%pri_ide(k) = tpi_ide(idx_i,idx_i1)*tend%pri_ide(k)
2941 endif
2942
2943 ! conversion of cloud ice to snow
2944 if ((idx_i == ntb_i) .or. (xdi > 5.0_wp*d0s)) then
2945 tend%prs_iau(k) = ri(k)*.99_wp*odt
2946 tend%pni_iau(k) = ni(k)*.95_wp*odt
2947 elseif (xdi < 0.1_wp*d0s) then
2948 tend%prs_iau(k) = 0._dp
2949 tend%pni_iau(k) = 0._dp
2950 else
2951 tend%prs_iau(k) = tps_iaus(idx_i,idx_i1)*odt
2952 tend%prs_iau(k) = min(real(ri(k)*.99_wp*odt, kind=dp), tend%prs_iau(k))
2953 tend%pni_iau(k) = tni_iaus(idx_i,idx_i1)*odt
2954 tend%pni_iau(k) = min(real(ni(k)*.95_wp*odt, kind=dp), tend%pni_iau(k))
2955 endif
2956
2957 ! snow collecting cloud ice assumes di << ds and vti ~ 0
2958 lami = (am_i*cig(2)*oig1*ni(k)/ri(k))**obmi
2959 xdi = max(real(d0i, kind=dp), (bm_i + mu_i + 1.) * ilami(k))
2960 xmi = am_i*xdi**bm_i
2961 oxmi = 1./xmi
2962 if (rs(k) >= r_s(1)) then
2963 tend%prs_sci(k) = t1_qs_qi*rhof(k)*ef_si*ri(k)*smoe(k)
2964 tend%pni_sci(k) = tend%prs_sci(k) * oxmi
2965 endif
2966
2967 ! rain collecting cloud ice assumes di << dr and vti= ~ 0
2968 if (rr(k) >= r_r(1) .and. mvd_r(k) > 4._wp*xdi) then
2969 lamr = 1._wp/ilamr(k)
2970 n0_r = nr(k)*org2*lamr**cre(2)
2971 tend%pri_rci(k) = rhof(k)*t1_qr_qi*ef_ri*ri(k)*n0_r * &
2972 ((lamr+fv_r)**(-cre(9)))
2973 tend%pnr_rci(k) = rhof(k)*t1_qr_qi*ef_ri*ni(k)*n0_r * &
2974 ((lamr+fv_r)**(-cre(9)))
2975 tend%pnr_rci(k) = min(real(nr(k)*odt, kind=dp), tend%pnr_rci(k))
2976 tend%png_rci(k) = tend%pnr_rci(k) * &
2977 max(min((10._wp**(-0.1*w1d(k)) + 0.1_wp), 1._wp), 0.1_wp)
2978 tend%pni_rci(k) = tend%pri_rci(k) * oxmi
2979 tend%prr_rci(k) = rhof(k)*t2_qr_qi*ef_ri*ni(k)*n0_r * &
2980 ((lamr+fv_r)**(-cre(8)))
2981 tend%prr_rci(k) = min(real(rr(k)*odt, kind=dp), tend%prr_rci(k))
2982 tend%prg_rci(k) = tend%pri_rci(k) + tend%prr_rci(k)
2983 tend%pbg_rci(k) = tend%prg_rci(k)/rho_i
2984 endif
2985 endif
2986
2987 if (l_qs(k)) then
2988 c_snow = c_sqrd + (temp(k)-t0+1.5_wp)*(c_cube-c_sqrd)/(-30._wp+1.5_wp)
2989 c_snow = max(c_sqrd, min(c_snow, c_cube))
2990 tend%prs_sde(k) = c_snow*t1_subl(k)*diffu(k)*ssati(k)*rvs * (t1_qs_sd*smo1(k) + &
2991 t2_qs_sd*rhof2(k)*vsc2(k)*smof(k))
2992 if (tend%prs_sde(k) < 0._dp) then
2993 tend%prs_sde(k) = max(real(-rs(k)*odt, kind=dp), &
2994 tend%prs_sde(k), real(rate_max, kind=dp))
2995 else
2996 tend%prs_sde(k) = min(tend%prs_sde(k), real(rate_max, kind=dp))
2997 endif
2998 endif
2999 if (l_qg(k)) then
3000 if (ssati(k) < -eps) then
3001 n0_g = ng(k)*ogg2*(1._wp/ilamg(k))**cge(2,1)
3002 t2_qg_sd = 0.28_wp*sc3*sqrt(av_g(idx(k))) * cgg(11,idx(k))
3003 tend%prg_gde(k) = c_cube*t1_subl(k)*diffu(k)*ssati(k)*rvs &
3004 * n0_g * (t1_qg_sd*ilamg(k)**cge(10,1) &
3005 + t2_qg_sd*vsc2(k)*rhof2(k)*ilamg(k)**cge(11,idx(k)))
3006 if (tend%prg_gde(k) < 0._wp) then
3007 tend%prg_gde(k) = max(real(-rg(k)*odt, kind=dp), &
3008 tend%prg_gde(k), real(rate_max, kind=dp))
3009 tend%png_gde(k) = tend%prg_gde(k) * ng(k)/rg(k)
3010 else
3011 tend%prg_gde(k) = min(tend%prg_gde(k), real(rate_max, kind=dp))
3012 endif
3013 endif
3014 endif
3015 endif
3016 enddo
3017 end subroutine ice_processes
3018
3019
3020 subroutine melting(rhof2, rho, temp, qvsi, tcond, diffu, vsc2, ssati, &
3021 delqvs, l_qs, rs, smof, smo0, smo1, l_qg, rg, ng, ilamg, idx, tend, dt, odt)
3022 !! melting of snow and graupel
3023 use module_mp_tempo_params, only : t0, bm_i, mu_i, pi, c_sqrd, c_cube, d0s, &
3024 ntb_i, r_s, ef_si, r_r, fv_r, ef_ri, rho_i, t1_qs_sd, t2_qs_sd, eps, &
3025 t1_qg_sd, sc3, ogg2, cge, cgg, av_g, t1_qs_me, t2_qs_me, lvap0, olfus, &
3026 t1_qg_me, rho_w, rho_g, meters3_to_liters, timestep_conversion_rime_to_rain
3027
3028 real(wp), intent(in) :: dt, odt
3029 type(ty_tend), intent(inout) :: tend
3030 logical, dimension(:), intent(in) :: l_qs, l_qg
3031 real(wp), dimension(:), intent(in) :: rhof2, rho, rs, &
3032 temp, qvsi, tcond, diffu, ssati, delqvs, vsc2, rg, ng
3033 real(dp), dimension(:), intent(in) :: smof, smo0, smo1, ilamg
3034 integer, dimension(:), intent(in) :: idx
3035 real(wp) :: tempc, otemp, rvs, melt_f, t2_qg_me, t2_qg_sd
3036 real(dp) :: n0_g, n0_melt, lamg
3037 integer :: k, nz
3038 real(wp), dimension(:), allocatable :: t1_subl
3039
3040 nz = size(l_qs)
3041 allocate(t1_subl(nz), source=0._wp)
3042 call get_t1_subl(rho, temp, qvsi, tcond, diffu, ssati, t1_subl)
3043
3044 do k = 1, nz
3045 otemp = 1._wp/temp(k)
3046 tempc = temp(k) - t0
3047 rvs = rho(k)*qvsi(k)
3048
3049 if (temp(k) > t0) then
3050 if(l_qs(k)) then
3051 tend%prr_sml(k) = (tempc*tcond(k)-lvap0*diffu(k)*delqvs(k)) * &
3052 (t1_qs_me*smo1(k) + t2_qs_me*rhof2(k)*vsc2(k)*smof(k))
3053
3054 if (tend%prr_sml(k) > 0._dp) then
3055 tend%prr_sml(k) = tend%prr_sml(k) + 4218._wp*olfus*tempc * &
3056 (tend%prr_rcs(k)+tend%prs_scw(k))
3057 tend%prr_sml(k) = min(real(rs(k)*odt, kind=dp), &
3058 max(0._dp, tend%prr_sml(k)))
3059 tend%pnr_sml(k) = smo0(k)/rs(k)*tend%prr_sml(k) * 10.0_wp**(-0.25_wp*tempc)
3060 tend%pnr_sml(k) = min(real(smo0(k)*odt, kind=dp), tend%pnr_sml(k))
3061 else
3062 tend%prr_sml(k) = 0._dp
3063 tend%pnr_sml(k) = 0._dp
3064 if (ssati(k) < 0._wp) then
3065 tend%prs_sde(k) = c_cube*t1_subl(k)*diffu(k)*ssati(k)*rvs * &
3066 (t1_qs_sd*smo1(k) + t2_qs_sd*rhof2(k)*vsc2(k)*smof(k))
3067 tend%prs_sde(k) = max(real(-rs(k)*odt, kind=dp), tend%prs_sde(k))
3068 endif
3069 endif
3070 endif
3071
3072 if (l_qg(k)) then
3073 n0_g = ng(k)*ogg2*(1._wp/ilamg(k))**cge(2,1)
3074 n0_melt = ng(k)*ogg2*(1._dp/ilamg(k))**cge(2,1)
3075 if ((rg(k)*ng(k)) < 1.e-4_wp) then
3076 lamg = 1./ilamg(k)
3077 n0_melt = (1.e-4_wp/rg(k))*ogg2*lamg**cge(2,1)
3078 endif
3079 t2_qg_me = pi*4._wp * c_cube*olfus * &
3080 0.28_wp*sc3*sqrt(av_g(idx(k))) * cgg(11,idx(k))
3081 tend%prr_gml(k) = (tempc*tcond(k)-lvap0*diffu(k)*delqvs(k)) * &
3082 n0_melt*(t1_qg_me*ilamg(k)**cge(10,1) + &
3083 t2_qg_me*rhof2(k)*vsc2(k)*ilamg(k)**cge(11,idx(k)))
3084 tend%prr_gml(k) = min(real(rg(k)*odt, kind=dp), max(0._dp, tend%prr_gml(k)))
3085 if (tend%prr_gml(k) > 0._dp) then
3086 melt_f = max(0.05_wp, min(real(tend%prr_gml(k)*dt/rg(k), kind=wp),1._wp))
3087 ! 1000 is density water, 50 is lower limit (max ice density is 800)
3088 tend%pbg_gml(k) = meters3_to_liters*tend%prr_gml(k) / &
3089 max(min(melt_f*rho_g(idx(k)), rho_w), 50._wp)
3090 tend%pnr_gml(k) = tend%prr_gml(k)*ng(k)/rg(k) * 10.0_wp**(-0.33_wp*(temp(k)-t0))
3091 else
3092 tend%prr_gml(k) = 0._dp
3093 tend%pnr_gml(k) = 0._dp
3094 tend%pbg_gml(k) = 0._dp
3095 if (ssati(k) < 0._wp) then
3096 t2_qg_sd = 0.28_wp*sc3*sqrt(av_g(idx(k))) * cgg(11,idx(k))
3097 tend%prg_gde(k) = c_cube*t1_subl(k)*diffu(k)*ssati(k)*rvs * n0_g * &
3098 (t1_qg_sd*ilamg(k)**cge(10,1) + &
3099 t2_qg_sd*vsc2(k)*rhof2(k)*ilamg(k)**cge(11,idx(k)))
3100 tend%prg_gde(k) = max(real(-rg(k)*odt, kind=dp), tend%prg_gde(k))
3101 tend%png_gde(k) = tend%prg_gde(k) * ng(k)/rg(k)
3102 endif
3103 endif
3104 endif
3111 if (dt > timestep_conversion_rime_to_rain) then
3112 tend%prr_rcw(k) = tend%prr_rcw(k)+tend%prs_scw(k)+tend%prg_gcw(k)
3113 tend%prs_scw(k) = 0._dp
3114 tend%prg_gcw(k) = 0._dp
3115 endif
3116 endif
3117 enddo
3118 end subroutine melting
3119
3120
3121 subroutine aerosol_scavenging(temp, rho, rhof, visco, nwfa, nifa, &
3122 l_qr, nr, ilamr, mvd_r, l_qs, rs, smob, smoc, smoe, &
3123 l_qg, rg, ng, ilamg, idx, tend, odt)
3124 !! scavenging of aerosols by rain, snow, and graupel
3125 use module_mp_tempo_params, only : d0r, t1_qr_qc, fv_r, cre, &
3126 org2, r_s, t1_qs_qc, r_g, bm_g, mu_g, av_g, cge, cgg, pi, ogg2
3127
3128 real(wp), intent(in) :: odt
3129 real(wp), dimension(:), intent(in) :: temp, rho,rhof, visco, nr, mvd_r, &
3130 nwfa, nifa, rs, rg, ng
3131 real(dp), dimension(:), intent(in) :: smob, smoc, smoe, ilamg, ilamr
3132 integer, dimension(:), intent(in) :: idx
3133 logical, dimension(:), intent(in) :: l_qr, l_qs, l_qg
3134 type(ty_tend), intent(inout) :: tend
3135 real(wp) :: ef_ra, ef_sa, ef_ga, t1_qg_qc
3136 real(dp) :: n0_r, xds, xdg, n0_g, lamr
3137 real(wp), parameter :: wf_aerosol_size = 0.04e-6_wp
3138 real(wp), parameter :: if_aerosol_size = 0.8e-6_wp
3139 integer :: k, nz
3140
3141 nz = size(l_qr)
3142 do k = 1, nz
3143 if (l_qr(k) .and. mvd_r(k).gt. d0r) then
3144 ef_ra = aerosol_collection_efficiency(real(mvd_r(k), kind=dp), &
3145 wf_aerosol_size, visco(k), rho(k), temp(k), 'r')
3146 lamr = 1._dp/ilamr(k)
3147 n0_r = nr(k)*org2*lamr**cre(2)
3148 tend%pna_rca(k) = rhof(k)*t1_qr_qc*ef_ra*nwfa(k)*n0_r * &
3149 ((lamr+fv_r)**(-cre(9)))
3150 tend%pna_rca(k) = min(real(nwfa(k)*odt, kind=dp), &
3151 tend%pna_rca(k))
3152 ef_ra = aerosol_collection_efficiency(real(mvd_r(k), kind=dp), &
3153 if_aerosol_size, visco(k), rho(k), temp(k), 'r')
3154 tend%pnd_rcd(k) = rhof(k)*t1_qr_qc*ef_ra*nifa(k)*n0_r * &
3155 ((lamr+fv_r)**(-cre(9)))
3156 tend%pnd_rcd(k) = min(real(nifa(k)*odt, kind=dp), &
3157 tend%pnd_rcd(k))
3158 endif
3159
3160 if (l_qs(k) .and. rs(k) > r_s(1)) then
3161 xds = smoc(k) / smob(k)
3162 ef_sa = aerosol_collection_efficiency(xds,wf_aerosol_size, &
3163 visco(k), rho(k), temp(k), 's')
3164 tend%pna_sca(k) = rhof(k)*t1_qs_qc*ef_sa*nwfa(k)*smoe(k)
3165 tend%pna_sca(k) = min(real(nwfa(k)*odt, kind=dp), &
3166 tend%pna_sca(k))
3167 ef_sa = aerosol_collection_efficiency(xds, if_aerosol_size, &
3168 visco(k), rho(k), temp(k), 's')
3169 tend%pnd_scd(k) = rhof(k)*t1_qs_qc*ef_sa*nifa(k)*smoe(k)
3170 tend%pnd_scd(k) = min(real(nifa(k)*odt, kind=dp), &
3171 tend%pnd_scd(k))
3172 endif
3173
3174 if (l_qg(k) .and. rg(k) > r_g(1)) then
3175 xdg = (bm_g + mu_g + 1._dp) * ilamg(k)
3176 ef_ga = aerosol_collection_efficiency(xdg, wf_aerosol_size, &
3177 visco(k), rho(k), temp(k), 'g')
3178 t1_qg_qc = pi*.25_wp*av_g(idx(k)) * cgg(9,idx(k))
3179 n0_g = ng(k)*ogg2*(1._wp/ilamg(k))**cge(2,1)
3180 tend%pna_gca(k) = rhof(k)*t1_qg_qc*ef_ga*nwfa(k)*n0_g * &
3181 ilamg(k)**cge(9,idx(k))
3182 tend%pna_gca(k) = min(real(nwfa(k)*odt, kind=dp), &
3183 tend%pna_gca(k))
3184 ef_ga = aerosol_collection_efficiency(xdg, if_aerosol_size, &
3185 visco(k), rho(k), temp(k), 'g')
3186 tend%pnd_gcd(k) = rhof(k)*t1_qg_qc*ef_ga*nifa(k)*n0_g * &
3187 ilamg(k)**cge(9,idx(k))
3188 tend%pnd_gcd(k) = min(real(nifa(k)*odt, kind=dp), &
3189 tend%pnd_gcd(k))
3190 endif
3191 enddo
3192 end subroutine aerosol_scavenging
3193
3194end module module_mp_tempo_main