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