← Back to Documentation Home
CCPP SciDoc v8.0.0  v8.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
mp_thompson.F90
1
3
4
6
9
10 use mpi_f08
11 use machine, only : kind_phys
12
14 use module_mp_thompson, only : nain0, nain1, naccn0, naccn1, eps
15 use module_mp_thompson, only : re_qc_min, re_qc_max, re_qi_min, re_qi_max, re_qs_min, re_qs_max
16
17 use module_mp_thompson_make_number_concentrations, only: make_icenumber, make_dropletnumber, make_rainnumber
18
19 implicit none
20
21 public :: mp_thompson_init, mp_thompson_run, mp_thompson_final
22
23 private
24
25 integer, parameter :: ext_ndiag3d = 37
26
27 contains
28
33 subroutine mp_thompson_init(ncol, nlev, con_pi, con_t0c, con_rv, &
34 con_cp, con_rgas, con_boltz, con_amd, &
35 con_amw, con_avgd, con_hvap, con_hfus, &
36 con_g, con_rd, con_eps, &
37 con_Nt_c_l, con_Nt_c_o, con_av_i, &
38 con_xnc_max, con_ssati_min, con_Nt_i_max,&
39 con_rr_min, &
40 restart, imp_physics, &
41 imp_physics_thompson, convert_dry_rho, &
42 spechum, qc, qr, qi, qs, qg, ni, nr, &
43 is_aerosol_aware, merra2_aerosol_aware, &
44 nc, nwfa2d, nifa2d, &
45 nwfa, nifa, tgrs, prsl, phil, area, &
46 aerfld, mpicomm, mpirank, mpiroot, &
47 threads, ext_diag, diag3d, &
48 is_initialized, errmsg, errflg)
49 use module_mp_thompson, only : pi, t_0, rv, r, roverrv, cp
50 use module_mp_thompson, only : r_uni, k_b, m_w, m_a, n_avo, lvap0, lfus
51 use module_mp_thompson, only : av_i, av_s, d0s, bv_s, bv_i
52 use module_mp_thompson, only : nt_c_l, nt_c_o, xnc_max, ssati_min, nt_i_max, rr_min
53
54 implicit none
55
56 ! Interface variables
57 integer, intent(in ) :: ncol
58 integer, intent(in ) :: nlev
59 real(kind_phys), intent(in ) :: con_pi, con_t0c, con_rv, con_cp, con_rgas, &
60 con_boltz, con_amd, con_amw, con_avgd, &
61 con_hvap, con_hfus, con_g, con_rd, con_eps
62 real(kind_phys), optional, intent(in ) :: con_nt_c_l, con_nt_c_o, con_av_i, con_xnc_max, &
63 con_ssati_min, con_nt_i_max, con_rr_min
64 logical, intent(in ) :: restart
65 logical, intent(inout) :: is_initialized
66 integer, intent(in ) :: imp_physics
67 integer, intent(in ) :: imp_physics_thompson
68 ! Hydrometeors
69 logical, intent(in ) :: convert_dry_rho
70 real(kind_phys), intent(inout) :: spechum(:,:)
71 real(kind_phys), intent(inout) :: qc(:,:)
72 real(kind_phys), intent(inout) :: qr(:,:)
73 real(kind_phys), intent(inout) :: qi(:,:)
74 real(kind_phys), intent(inout) :: qs(:,:)
75 real(kind_phys), intent(inout) :: qg(:,:)
76 real(kind_phys), intent(inout) :: ni(:,:)
77 real(kind_phys), intent(inout) :: nr(:,:)
78 ! Aerosols
79 logical, intent(in ) :: is_aerosol_aware
80 logical, intent(in ) :: merra2_aerosol_aware
81 real(kind_phys), intent(inout), optional :: nc(:,:)
82 real(kind_phys), intent(inout), optional :: nwfa(:,:)
83 real(kind_phys), intent(inout), optional :: nifa(:,:)
84 real(kind_phys), intent(inout), optional :: nwfa2d(:)
85 real(kind_phys), intent(inout), optional :: nifa2d(:)
86 real(kind_phys), intent(in) :: aerfld(:,:,:)
87 ! State variables
88 real(kind_phys), intent(in ) :: tgrs(:,:)
89 real(kind_phys), intent(in ) :: prsl(:,:)
90 real(kind_phys), intent(in ) :: phil(:,:)
91 real(kind_phys), intent(in ) :: area(:)
92 ! MPI information
93 type(mpi_comm), intent(in ) :: mpicomm
94 integer, intent(in ) :: mpirank
95 integer, intent(in ) :: mpiroot
96 ! Threading/blocking information
97 integer, intent(in ) :: threads
98 ! Extended diagnostics
99 logical, intent(in ) :: ext_diag
100 real(kind_phys), intent(in ), optional :: diag3d(:,:,:)
101 ! CCPP error handling
102 character(len=*), intent( out) :: errmsg
103 integer, intent( out) :: errflg
104
105 !
106 real(kind_phys) :: qv(1:ncol,1:nlev) ! kg kg-1 (water vapor mixing ratio)
107 real(kind_phys) :: hgt(1:ncol,1:nlev) ! m
108 real(kind_phys) :: rho(1:ncol,1:nlev) ! kg m-3
109 real(kind_phys) :: orho(1:ncol,1:nlev) ! m3 kg-1
110 real(kind_phys) :: nc_local(1:ncol,1:nlev) ! needed because nc is only allocated if is_aerosol_aware is true
111 !
112 real (kind=kind_phys) :: h_01, z1, niin3, niccn3
113 integer :: i, k
114
115 ! Initialize the CCPP error handling variables
116 errmsg = ''
117 errflg = 0
118
119 if (is_initialized) return
120
121 ! Set local Thompson MP module constants from host model
122 pi = con_pi
123 t_0 = con_t0c
124 rv = con_rv
125 r = con_rd
126 roverrv = con_eps
127 cp = con_cp
128 r_uni = con_rgas
129 k_b = con_boltz
130 m_w = con_amw*1.0e-3 !module_mp_thompson expects kg/mol
131 m_a = con_amd*1.0e-3 !module_mp_thompson expects kg/mol
132 n_avo = con_avgd
133 lvap0 = con_hvap
134 lfus = con_hfus
135
136 if (present(con_nt_c_l)) nt_c_l = con_nt_c_l
137 if (present(con_nt_c_o)) nt_c_o = con_nt_c_o
138 if (present(con_av_i)) then
139 if (con_av_i > 0.) then
140 av_i = con_av_i
141 else
142 av_i = av_s * d0s ** (bv_s - bv_i) ! Transition value of coefficient matching at crossover from cloud ice to snow
143 end if
144 else
145 av_i = av_s * d0s ** (bv_s - bv_i) ! Transition value of coefficient matching at crossover from cloud ice to snow
146 end if
147 if (present(con_xnc_max)) xnc_max = con_xnc_max
148 if (present(con_ssati_min)) ssati_min = con_ssati_min
149 if (present(con_nt_i_max)) nt_i_max = con_nt_i_max
150 if (present(con_rr_min)) rr_min = con_rr_min
151
152 ! Consistency checks
153 if (imp_physics/=imp_physics_thompson) then
154 write(errmsg,'(*(a))') "Logic error: namelist choice of microphysics is different from Thompson MP"
155 errflg = 1
156 return
157 end if
158
159 if (ext_diag) then
160 if (size(diag3d,dim=3) /= ext_ndiag3d) then
161 write(errmsg,'(*(a))') "Logic error: number of diagnostic 3d arrays from model does not match requirements"
162 errflg = 1
163 return
164 end if
165 end if
166
167 if (is_aerosol_aware .and. merra2_aerosol_aware) then
168 write(errmsg,'(*(a))') "Logic error: Only one Thompson aerosol option can be true, either is_aerosol_aware or merra2_aerosol_aware)"
169 errflg = 1
170 return
171 end if
172
173 ! Call Thompson init
174 call thompson_init(is_aerosol_aware_in=is_aerosol_aware, &
175 merra2_aerosol_aware_in=merra2_aerosol_aware, &
176 mpicomm=mpicomm, mpirank=mpirank, mpiroot=mpiroot, &
177 threads=threads, errmsg=errmsg, errflg=errflg)
178 if (errflg /= 0) return
179
180 ! For restart runs, the init is done here
181 if (restart) then
182 is_initialized = .true.
183 return
184 end if
185
186 ! Geopotential height in m2 s-2 to height in m
187 hgt = phil/con_g
188
189 ! Ensure non-negative mass mixing ratios of all water variables
190 where(spechum<0) spechum = 1.0e-10 ! COMMENT, gthompsn, spechum should *never* be identically zero.
191 where(qc<0) qc = 0.0
192 where(qr<0) qr = 0.0
193 where(qi<0) qi = 0.0
194 where(qs<0) qs = 0.0
195 where(qg<0) qg = 0.0
196
200 if (merra2_aerosol_aware) then
201 call get_niwfa(aerfld, nifa, nwfa, ncol, nlev)
202 end if
203
204
205 qv = spechum/(1.0_kind_phys-spechum)
206
207 if (convert_dry_rho) then
208 qc = qc/(1.0_kind_phys-spechum)
209 qr = qr/(1.0_kind_phys-spechum)
210 qi = qi/(1.0_kind_phys-spechum)
211 qs = qs/(1.0_kind_phys-spechum)
212 qg = qg/(1.0_kind_phys-spechum)
213
214 ni = ni/(1.0_kind_phys-spechum)
215 nr = nr/(1.0_kind_phys-spechum)
216 if (is_aerosol_aware .or. merra2_aerosol_aware) then
217 nc = nc/(1.0_kind_phys-spechum)
218 nwfa = nwfa/(1.0_kind_phys-spechum)
219 nifa = nifa/(1.0_kind_phys-spechum)
220 end if
221 end if
222
223 ! Density of moist air in kg m-3 and inverse density of air
224 rho = con_eps*prsl/(con_rd*tgrs*(qv+con_eps))
225 orho = 1.0/rho
226
227 ! Ensure we have 1st guess ice number where mass non-zero but no number.
228 where(qi .LE. 0.0) ni=0.0
229 where(qi .GT. 0 .and. ni .LE. 0.0) ni = make_icenumber(qi*rho, tgrs) * orho
230 where(qi .EQ. 0.0 .and. ni .GT. 0.0) ni=0.0
231
232 ! Ensure we have 1st guess rain number where mass non-zero but no number.
233 where(qr .LE. 0.0) nr=0.0
234 where(qr .GT. 0 .and. nr .LE. 0.0) nr = make_rainnumber(qr*rho, tgrs) * orho
235 where(qr .EQ. 0.0 .and. nr .GT. 0.0) nr=0.0
236
237
238 !..Check for existing aerosol data, both CCN and IN aerosols. If missing
239 !.. fill in just a basic vertical profile, somewhat boundary-layer following.
240 if (is_aerosol_aware) then
241
242 ! Potential cloud condensation nuclei (CCN)
243 if (maxval(nwfa) .lt. eps) then
244 if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial CCN aerosols.'
245 do i = 1, ncol
246 if (hgt(i,1).le.1000.0) then
247 h_01 = 0.8
248 elseif (hgt(i,1).ge.2500.0) then
249 h_01 = 0.01
250 else
251 h_01 = 0.8*cos(hgt(i,1)*0.001 - 1.0)
252 endif
253 niccn3 = -1.0*alog(naccn1/naccn0)/h_01
254 nwfa(i,1) = naccn1+naccn0*exp(-((hgt(i,2)-hgt(i,1))/1000.)*niccn3)
255 z1 = hgt(i,2)-hgt(i,1)
256 nwfa2d(i) = nwfa(i,1) * 0.000196 * (50./z1)
257 do k = 2, nlev
258 nwfa(i,k) = naccn1+naccn0*exp(-((hgt(i,k)-hgt(i,1))/1000.)*niccn3)
259 enddo
260 enddo
261 else
262 if (mpirank==mpiroot) write(*,*) ' Apparently initial CCN aerosols are present.'
263 if (maxval(nwfa2d) .lt. eps) then
264 !+---+-----------------------------------------------------------------+
265 !..Scale the lowest level aerosol data into an emissions rate. This is
266 !.. very far from ideal, but need higher emissions where larger amount
267 !.. of (climo) existing and lesser emissions where there exists fewer to
268 !.. begin as a first-order simplistic approach. Later, proper connection to
269 !.. emission inventory would be better, but, for now, scale like this:
270 !.. where: Nwfa=50 per cc, emit 0.875E4 aerosols per second per grid box unit
271 !.. that was tested as ~(20kmx20kmx50m = 2.E10 m**-3)
272 !+---+-----------------------------------------------------------------+
273 if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial CCN aerosol surface emission rates.'
274 do i = 1, ncol
275 z1 = hgt(i,2)-hgt(i,1)
276 nwfa2d(i) = nwfa(i,1) * 0.000196 * (50./z1)
277 enddo
278 else
279 if (mpirank==mpiroot) write(*,*) ' Apparently initial CCN aerosol surface emission rates are present.'
280 endif
281 endif
282
283 ! Potential ice nuclei (IN)
284 if (maxval(nifa) .lt. eps) then
285 if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial IN aerosols.'
286 do i = 1, ncol
287 if (hgt(i,1).le.1000.0) then
288 h_01 = 0.8
289 elseif (hgt(i,1).ge.2500.0) then
290 h_01 = 0.01
291 else
292 h_01 = 0.8*cos(hgt(i,1)*0.001 - 1.0)
293 endif
294 niin3 = -1.0*alog(nain1/nain0)/h_01
295 nifa(i,1) = nain1+nain0*exp(-((hgt(i,2)-hgt(i,1))/1000.)*niin3)
296 nifa2d(i) = 0.
297 do k = 2, nlev
298 nifa(i,k) = nain1+nain0*exp(-((hgt(i,k)-hgt(i,1))/1000.)*niin3)
299 enddo
300 enddo
301 else
302 if (mpirank==mpiroot) write(*,*) ' Apparently initial IN aerosols are present.'
303 if (maxval(nifa2d) .lt. eps) then
304 if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial IN aerosol surface emission rates, set to zero.'
305 ! calculate IN surface flux here, right now just set to zero
306 nifa2d = 0.
307 else
308 if (mpirank==mpiroot) write(*,*) ' Apparently initial IN aerosol surface emission rates are present.'
309 endif
310 endif
311
312 ! Ensure we have 1st guess cloud droplet number where mass non-zero but no number.
313 where(qc .LE. 0.0) nc=0.0
314 where(qc .GT. 0 .and. nc .LE. 0.0) nc = make_dropletnumber(qc*rho, nwfa*rho) * orho
315 where(qc .EQ. 0.0 .and. nc .GT. 0.0) nc = 0.0
316
317 ! Ensure non-negative aerosol number concentrations.
318 where(nwfa .LE. 0.0) nwfa = 1.1e6
319 where(nifa .LE. 0.0) nifa = nain1*0.01
320
321 ! Copy to local array for calculating cloud effective radii below
322 nc_local = nc
323
324 else if (merra2_aerosol_aware) then
325
326 ! Ensure we have 1st guess cloud droplet number where mass non-zero but no number.
327 where(qc .LE. 0.0) nc=0.0
328 where(qc .GT. 0 .and. nc .LE. 0.0) nc = make_dropletnumber(qc*rho, nwfa*rho) * orho
329 where(qc .EQ. 0.0 .and. nc .GT. 0.0) nc = 0.0
330
331 else
332
333 ! Constant droplet concentration for single moment cloud water as in
334 ! module_mp_thompson.F90, only needed for effective radii calculation
335 nc_local = nt_c_l/rho
336
337 end if
338
339 if (convert_dry_rho) then
340 !qc = qc/(1.0_kind_phys+qv)
341 !qr = qr/(1.0_kind_phys+qv)
342 !qi = qi/(1.0_kind_phys+qv)
343 !qs = qs/(1.0_kind_phys+qv)
344 !qg = qg/(1.0_kind_phys+qv)
345
346 ni = ni/(1.0_kind_phys+qv)
347 nr = nr/(1.0_kind_phys+qv)
348 if (is_aerosol_aware .or. merra2_aerosol_aware) then
349 nc = nc/(1.0_kind_phys+qv)
350 nwfa = nwfa/(1.0_kind_phys+qv)
351 nifa = nifa/(1.0_kind_phys+qv)
352 end if
353 end if
354
355 is_initialized = .true.
356
357 end subroutine mp_thompson_init
358
359
366 subroutine mp_thompson_run(ncol, nlev, con_g, con_rd, &
367 con_eps, convert_dry_rho, &
368 spechum, qc, qr, qi, qs, qg, ni, nr, &
369 is_aerosol_aware, &
370 merra2_aerosol_aware, nc, nwfa, nifa,&
371 nwfa2d, nifa2d, aero_ind_fdb, &
372 tgrs, prsl, phii, omega, &
373 sedi_semi, decfl, islmsk, dtp, &
374 dt_inner, &
375 first_time_step, istep, nsteps, &
376 prcp, rain, graupel, ice, snow, sr, &
377 refl_10cm, fullradar_diag, &
378 max_hail_diam_sfc, &
379 do_radar_ref, aerfld, &
380 mpicomm, mpirank, mpiroot, &
381 ext_diag, diag3d, reset_diag3d, &
382 spp_wts_mp, spp_mp, n_var_spp, &
383 spp_prt_list, spp_var_list, &
384 spp_stddev_cutoff, &
385 cplchm, pfi_lsan, pfl_lsan, &
386 is_initialized, fs_fac_rain, fs_fac_snow, &
387 ten_q, dspechum, dqc, dqr, &
388 dqi, dqs, dqg, dni, dnr, dnc, dnwfa, &
389 dnifa, dtgrs, ten_u, ten_v, errmsg, errflg)
390
391 implicit none
392
393 ! Interface variables
394 logical, intent(inout) :: is_initialized
395 ! Dimensions and constants
396 integer, intent(in ) :: ncol
397 integer, intent(in ) :: nlev
398 real(kind_phys), intent(in ) :: con_g
399 real(kind_phys), intent(in ) :: con_rd
400 real(kind_phys), intent(in ) :: con_eps
401 ! Hydrometeors
402 logical, intent(in ) :: convert_dry_rho
403 real(kind_phys), intent(in ) :: spechum(:,:)
404 real(kind_phys), intent(in ) :: qc(:,:)
405 real(kind_phys), intent(in ) :: qr(:,:)
406 real(kind_phys), intent(in ) :: qi(:,:)
407 real(kind_phys), intent(in ) :: qs(:,:)
408 real(kind_phys), intent(in ) :: qg(:,:)
409 real(kind_phys), intent(in ) :: ni(:,:)
410 real(kind_phys), intent(in ) :: nr(:,:)
411 ! Aerosols
412 logical, intent(in) :: is_aerosol_aware, fullradar_diag
413 logical, intent(in) :: merra2_aerosol_aware
414 real(kind_phys), optional, intent(in ) :: nc(:,:)
415 real(kind_phys), optional, intent(in ) :: nwfa(:,:)
416 real(kind_phys), optional, intent(in ) :: nifa(:,:)
417 real(kind_phys), optional, intent(in ) :: nwfa2d(:)
418 real(kind_phys), optional, intent(in ) :: nifa2d(:)
419 real(kind_phys), intent(in) :: aerfld(:,:,:)
420 logical, optional, intent(in ) :: aero_ind_fdb
421 ! State variables and timestep information
422 real(kind_phys), intent(in ) :: tgrs(:,:)
423 real(kind_phys), intent(in ) :: prsl(:,:)
424 real(kind_phys), intent(in ) :: phii(:,:)
425 real(kind_phys), intent(in ) :: omega(:,:)
426 integer, intent(in ) :: islmsk(:)
427 real(kind_phys), intent(in ) :: dtp
428 logical, intent(in ) :: first_time_step
429 integer, intent(in ) :: istep, nsteps
430 real(kind=kind_phys), intent(in ) :: dt_inner
431 ! Precip/rain/snow/graupel fall amounts and fraction of frozen precip
432 real(kind_phys), intent(inout) :: prcp(:)
433 real(kind_phys), intent(inout) :: rain(:)
434 real(kind_phys), intent(inout) :: graupel(:)
435 real(kind_phys), intent(inout) :: ice(:)
436 real(kind_phys), intent(inout) :: snow(:)
437 real(kind_phys), intent( out) :: sr(:)
438 ! Radar reflectivity
439 real(kind_phys), intent(inout) :: refl_10cm(:,:)
440 real(kind_phys), intent(inout) :: max_hail_diam_sfc(:)
441 logical, intent(in ) :: do_radar_ref
442 logical, intent(in) :: sedi_semi
443 integer, intent(in) :: decfl
444 ! MPI information
445 type(mpi_comm), intent(in) :: mpicomm
446 integer, intent(in) :: mpirank
447 integer, intent(in) :: mpiroot
448 ! Extended diagnostic output
449 logical, intent(in) :: ext_diag
450 real(kind_phys), target, intent(inout), optional :: diag3d(:,:,:)
451 logical, intent(in) :: reset_diag3d
452
453 real(kind_phys), intent( out) :: ten_q(:,:,:)
454 real(kind_phys), intent( out) :: ten_u(:,:)
455 real(kind_phys), intent( out) :: ten_v(:,:)
456 real(kind_phys), intent( out) :: dspechum(:,:)
457 real(kind_phys), intent( out) :: dqc(:,:)
458 real(kind_phys), intent( out) :: dqr(:,:)
459 real(kind_phys), intent( out) :: dqi(:,:)
460 real(kind_phys), intent( out) :: dqs(:,:)
461 real(kind_phys), intent( out) :: dqg(:,:)
462 real(kind_phys), intent( out) :: dni(:,:)
463 real(kind_phys), intent( out) :: dnr(:,:)
464 real(kind_phys), optional, intent( out) :: dnc(:,:)
465 real(kind_phys), optional, intent( out) :: dnwfa(:,:)
466 real(kind_phys), optional, intent( out) :: dnifa(:,:)
467 real(kind_phys), intent( out) :: dtgrs(:,:)
468
469 ! CCPP error handling
470 character(len=*), intent( out) :: errmsg
471 integer, intent( out) :: errflg
472
473 ! SPP
474 integer, intent(in) :: spp_mp
475 integer, intent(in) :: n_var_spp
476 real(kind_phys), intent(in), optional :: spp_wts_mp(:,:)
477 real(kind_phys), intent(in), optional :: spp_prt_list(:)
478 character(len=10), intent(in), optional :: spp_var_list(:)
479 real(kind_phys), intent(in), optional :: spp_stddev_cutoff(:)
480
481 logical, intent (in) :: cplchm
482 ! ice and liquid water 3d precipitation fluxes - only allocated if cplchm is .true.
483 real(kind=kind_phys), intent(inout), dimension(:,:), optional :: pfi_lsan
484 real(kind=kind_phys), intent(inout), dimension(:,:), optional :: pfl_lsan
485
486 ! fall speed adjustment
487 real(kind_phys), intent(in), optional :: fs_fac_rain, fs_fac_snow
488
489 ! Local variables
490
491 ! Reduced time step if subcycling is used
492 real(kind_phys) :: dtstep
493 integer :: ndt
494 ! Air density
495 real(kind_phys) :: rho(1:ncol,1:nlev)
496 ! Water vapor mixing ratio (instead of specific humidity)
497 real(kind_phys) :: qv(1:ncol,1:nlev)
498 ! Vertical velocity and level width
499 real(kind_phys) :: w(1:ncol,1:nlev)
500 real(kind_phys) :: dz(1:ncol,1:nlev)
501 ! Rain/snow/graupel fall amounts
502 real(kind_phys) :: rain_mp(1:ncol) ! mm, dummy, not used
503 real(kind_phys) :: graupel_mp(1:ncol) ! mm, dummy, not used
504 real(kind_phys) :: ice_mp(1:ncol) ! mm, dummy, not used
505 real(kind_phys) :: snow_mp(1:ncol) ! mm, dummy, not used
506 real(kind_phys) :: delta_rain_mp(1:ncol) ! mm
507 real(kind_phys) :: delta_graupel_mp(1:ncol) ! mm
508 real(kind_phys) :: delta_ice_mp(1:ncol) ! mm
509 real(kind_phys) :: delta_snow_mp(1:ncol) ! mm
510
511 real(kind_phys) :: new_spechum(1:ncol,1:nlev)
512 real(kind_phys) :: new_qc(1:ncol,1:nlev)
513 real(kind_phys) :: new_qr(1:ncol,1:nlev)
514 real(kind_phys) :: new_qi(1:ncol,1:nlev)
515 real(kind_phys) :: new_qs(1:ncol,1:nlev)
516 real(kind_phys) :: new_qg(1:ncol,1:nlev)
517 real(kind_phys) :: new_ni(1:ncol,1:nlev)
518 real(kind_phys) :: new_nr(1:ncol,1:nlev)
519 real(kind_phys), allocatable :: new_nc(:,:), new_nwfa(:,:), new_nifa(:,:)
520 real(kind_phys) :: new_tgrs(1:ncol,1:nlev)
521
522 real(kind_phys) :: pfils(1:ncol,1:nlev,1)
523 real(kind_phys) :: pflls(1:ncol,1:nlev,1)
524 ! Radar reflectivity
525 logical :: diagflag ! must be true if do_radar_ref is true, not used otherwise
526 integer :: do_radar_ref_mp ! integer instead of logical do_radar_ref
527 ! Effective cloud radii - turned off in CCPP (taken care off in radiation)
528 logical, parameter :: do_effective_radii = .false.
529 integer, parameter :: has_reqc = 0
530 integer, parameter :: has_reqi = 0
531 integer, parameter :: has_reqs = 0
532 integer, parameter :: kme_stoch = 1
533 integer :: spp_mp_opt
534 ! Dimensions used in mp_gt_driver
535 integer :: ids,ide, jds,jde, kds,kde, &
536 ims,ime, jms,jme, kms,kme, &
537 its,ite, jts,jte, kts,kte
538 ! Pointer arrays for extended diagnostics
539 !real(kind_phys), dimension(:,:,:), pointer :: vts1 => null()
540 !real(kind_phys), dimension(:,:,:), pointer :: txri => null()
541 !real(kind_phys), dimension(:,:,:), pointer :: txrc => null()
542 real(kind_phys), dimension(:,:,:), pointer :: prw_vcdc => null()
543 real(kind_phys), dimension(:,:,:), pointer :: prw_vcde => null()
544 real(kind_phys), dimension(:,:,:), pointer :: tpri_inu => null()
545 real(kind_phys), dimension(:,:,:), pointer :: tpri_ide_d => null()
546 real(kind_phys), dimension(:,:,:), pointer :: tpri_ide_s => null()
547 real(kind_phys), dimension(:,:,:), pointer :: tprs_ide => null()
548 real(kind_phys), dimension(:,:,:), pointer :: tprs_sde_d => null()
549 real(kind_phys), dimension(:,:,:), pointer :: tprs_sde_s => null()
550 real(kind_phys), dimension(:,:,:), pointer :: tprg_gde_d => null()
551 real(kind_phys), dimension(:,:,:), pointer :: tprg_gde_s => null()
552 real(kind_phys), dimension(:,:,:), pointer :: tpri_iha => null()
553 real(kind_phys), dimension(:,:,:), pointer :: tpri_wfz => null()
554 real(kind_phys), dimension(:,:,:), pointer :: tpri_rfz => null()
555 real(kind_phys), dimension(:,:,:), pointer :: tprg_rfz => null()
556 real(kind_phys), dimension(:,:,:), pointer :: tprs_scw => null()
557 real(kind_phys), dimension(:,:,:), pointer :: tprg_scw => null()
558 real(kind_phys), dimension(:,:,:), pointer :: tprg_rcs => null()
559 real(kind_phys), dimension(:,:,:), pointer :: tprs_rcs => null()
560 real(kind_phys), dimension(:,:,:), pointer :: tprr_rci => null()
561 real(kind_phys), dimension(:,:,:), pointer :: tprg_rcg => null()
562 real(kind_phys), dimension(:,:,:), pointer :: tprw_vcd_c => null()
563 real(kind_phys), dimension(:,:,:), pointer :: tprw_vcd_e => null()
564 real(kind_phys), dimension(:,:,:), pointer :: tprr_sml => null()
565 real(kind_phys), dimension(:,:,:), pointer :: tprr_gml => null()
566 real(kind_phys), dimension(:,:,:), pointer :: tprr_rcg => null()
567 real(kind_phys), dimension(:,:,:), pointer :: tprr_rcs => null()
568 real(kind_phys), dimension(:,:,:), pointer :: tprv_rev => null()
569 real(kind_phys), dimension(:,:,:), pointer :: tten3 => null()
570 real(kind_phys), dimension(:,:,:), pointer :: qvten3 => null()
571 real(kind_phys), dimension(:,:,:), pointer :: qrten3 => null()
572 real(kind_phys), dimension(:,:,:), pointer :: qsten3 => null()
573 real(kind_phys), dimension(:,:,:), pointer :: qgten3 => null()
574 real(kind_phys), dimension(:,:,:), pointer :: qiten3 => null()
575 real(kind_phys), dimension(:,:,:), pointer :: niten3 => null()
576 real(kind_phys), dimension(:,:,:), pointer :: nrten3 => null()
577 real(kind_phys), dimension(:,:,:), pointer :: ncten3 => null()
578 real(kind_phys), dimension(:,:,:), pointer :: qcten3 => null()
579
580 ! Initialize the CCPP error handling variables
581 errmsg = ''
582 errflg = 0
583
584 ten_q = 0.0 ! Since this scheme is outputting tracer tendencies individually,
585 ! we also need to initialize the entire array to 0, so that when
586 ! tendencies are applied, all tracer tendencies other than those
587 ! set in this scheme are 0.
588 ten_u = 0.0
589 ten_v = 0.0
590 dspechum = 0.0
591 dqc = 0.0
592 dqr = 0.0
593 dqi = 0.0
594 dqs = 0.0
595 dqg = 0.0
596 dni = 0.0
597 dnr = 0.0
598 dtgrs = 0.0
599
600 new_spechum = spechum
601 new_qc = qc
602 new_qr = qr
603 new_qi = qi
604 new_qs = qs
605 new_qg = qg
606 new_ni = ni
607 new_nr = nr
608 new_tgrs = tgrs
609
610 if (is_aerosol_aware .or. merra2_aerosol_aware) then
611 dnc = 0.0
612 dnwfa = 0.0
613 dnifa = 0.0
614
615 allocate(new_nc(ncol,nlev))
616 allocate(new_nwfa(ncol,nlev))
617 allocate(new_nifa(ncol,nlev))
618 new_nc = nc
619 new_nwfa = nwfa
620 new_nifa = nifa
621 end if
622
623 if (first_time_step .and. istep==1) then
624 ! Check initialization state
625 if (.not.is_initialized) then
626 write(errmsg, fmt='((a))') 'mp_thompson_run called before mp_thompson_init'
627 errflg = 1
628 return
629 end if
630 ! Check forr optional arguments of aerosol-aware microphysics
631 if (is_aerosol_aware .and. .not. (present(nc) .and. &
632 present(nwfa) .and. &
633 present(nifa) .and. &
634 present(nwfa2d) .and. &
635 present(nifa2d) )) then
636 write(errmsg,fmt='(*(a))') 'Logic error in mp_thompson_run:', &
637 ' aerosol-aware microphysics require all of the', &
638 ' following optional arguments:', &
639 ' nc, nwfa, nifa, nwfa2d, nifa2d'
640 errflg = 1
641 return
642 else if (merra2_aerosol_aware .and. .not. (present(nc) .and. &
643 present(nwfa) .and. &
644 present(nifa) )) then
645 write(errmsg,fmt='(*(a))') 'Logic error in mp_thompson_run:', &
646 ' merra2 aerosol-aware microphysics require the', &
647 ' following optional arguments: nc, nwfa, nifa'
648 errflg = 1
649 return
650 end if
651 ! Consistency cheecks - subcycling and inner loop at the same time are not supported
652 if (nsteps>1 .and. dt_inner < dtp) then
653 write(errmsg,'(*(a))') "Logic error: Subcycling and inner loop cannot be used at the same time"
654 errflg = 1
655 return
656 else if (mpirank==mpiroot .and. nsteps>1) then
657 write(*,'(a,i0,a,a,f6.2,a)') 'Thompson MP is using ', nsteps, ' substep(s) per time step with an ', &
658 'effective time step of ', dtp/real(nsteps, kind=kind_phys), ' seconds'
659 else if (mpirank==mpiroot .and. dt_inner < dtp) then
660 ndt = max(nint(dtp/dt_inner),1)
661 write(*,'(a,i0,a,a,f6.2,a)') 'Thompson MP is using ', ndt, ' inner loops per time step with an ', &
662 'effective time step of ', dtp/real(ndt, kind=kind_phys), ' seconds'
663 end if
664 end if
665
666 ! Set stochastic physics selection to apply all perturbations
667 if ( spp_mp==7 ) then
668 spp_mp_opt=7
669 else
670 spp_mp_opt=0
671 endif
672
673 ! Set reduced time step if subcycling is used
674 if (nsteps>1) then
675 dtstep = dtp/real(nsteps, kind=kind_phys)
676 else
677 dtstep = dtp
678 end if
679 if (merra2_aerosol_aware) then
680 call get_niwfa(aerfld, new_nifa, new_nwfa, ncol, nlev)
681 end if
682
686
687 ! DH* - do this only if istep == 1? Would be ok if it was
688 ! guaranteed that nothing else in the same subcycle group
689 ! was using these arrays, but it is somewhat dangerous.
690 qv = new_spechum/(1.0_kind_phys-new_spechum)
691
692 if (convert_dry_rho) then
693 new_qc = new_qc/(1.0_kind_phys-new_spechum)
694 new_qr = new_qr/(1.0_kind_phys-new_spechum)
695 new_qi = new_qi/(1.0_kind_phys-new_spechum)
696 new_qs = new_qs/(1.0_kind_phys-new_spechum)
697 new_qg = new_qg/(1.0_kind_phys-new_spechum)
698
699 new_ni = new_ni/(1.0_kind_phys-new_spechum)
700 new_nr = new_nr/(1.0_kind_phys-new_spechum)
701 if (is_aerosol_aware .or. merra2_aerosol_aware) then
702 new_nc = new_nc/(1.0_kind_phys-new_spechum)
703 new_nwfa = new_nwfa/(1.0_kind_phys-new_spechum)
704 new_nifa = new_nifa/(1.0_kind_phys-new_spechum)
705 end if
706 end if
707 ! *DH
708
710 rho = con_eps*prsl/(con_rd*new_tgrs*(qv+con_eps))
711
713 w = -omega/(rho*con_g)
714
716 dz = (phii(:,2:nlev+1) - phii(:,1:nlev)) / con_g
717
718 ! Accumulated values inside Thompson scheme, not used;
719 ! only use delta and add to inout variables (different units)
720 rain_mp = 0
721 graupel_mp = 0
722 ice_mp = 0
723 snow_mp = 0
724 delta_rain_mp = 0
725 delta_graupel_mp = 0
726 delta_ice_mp = 0
727 delta_snow_mp = 0
728
729 ! Flags for calculating radar reflectivity; diagflag is redundant
730 if (do_radar_ref) then
731 diagflag = .true.
732 do_radar_ref_mp = 1
733 else
734 diagflag = .false.
735 do_radar_ref_mp = 0
736 end if
737
738 ! Set internal dimensions
739 ids = 1
740 ims = 1
741 its = 1
742 ide = ncol
743 ime = ncol
744 ite = ncol
745 jds = 1
746 jms = 1
747 jts = 1
748 jde = 1
749 jme = 1
750 jte = 1
751 kds = 1
752 kms = 1
753 kts = 1
754 kde = nlev
755 kme = nlev
756 kte = nlev
757 if(cplchm) then
758 pfi_lsan = 0.0
759 pfl_lsan = 0.0
760 end if
761
762 ! Set pointers for extended diagnostics
763 set_extended_diagnostic_pointers: if (ext_diag) then
764 if (reset_diag3d) then
765 diag3d = 0.0
766 end if
767 !vts1 => diag3d(:,:,X:X)
768 !txri => diag3d(:,:,X:X)
769 !txrc => diag3d(:,:,X:X)
770 prw_vcdc => diag3d(:,:,1:1)
771 prw_vcde => diag3d(:,:,2:2)
772 tpri_inu => diag3d(:,:,3:3)
773 tpri_ide_d => diag3d(:,:,4:4)
774 tpri_ide_s => diag3d(:,:,5:5)
775 tprs_ide => diag3d(:,:,6:6)
776 tprs_sde_d => diag3d(:,:,7:7)
777 tprs_sde_s => diag3d(:,:,8:8)
778 tprg_gde_d => diag3d(:,:,9:9)
779 tprg_gde_s => diag3d(:,:,10:10)
780 tpri_iha => diag3d(:,:,11:11)
781 tpri_wfz => diag3d(:,:,12:12)
782 tpri_rfz => diag3d(:,:,13:13)
783 tprg_rfz => diag3d(:,:,14:14)
784 tprs_scw => diag3d(:,:,15:15)
785 tprg_scw => diag3d(:,:,16:16)
786 tprg_rcs => diag3d(:,:,17:17)
787 tprs_rcs => diag3d(:,:,18:18)
788 tprr_rci => diag3d(:,:,19:19)
789 tprg_rcg => diag3d(:,:,20:20)
790 tprw_vcd_c => diag3d(:,:,21:21)
791 tprw_vcd_e => diag3d(:,:,22:22)
792 tprr_sml => diag3d(:,:,23:23)
793 tprr_gml => diag3d(:,:,24:24)
794 tprr_rcg => diag3d(:,:,25:25)
795 tprr_rcs => diag3d(:,:,26:26)
796 tprv_rev => diag3d(:,:,27:27)
797 tten3 => diag3d(:,:,28:28)
798 qvten3 => diag3d(:,:,29:29)
799 qrten3 => diag3d(:,:,30:30)
800 qsten3 => diag3d(:,:,31:31)
801 qgten3 => diag3d(:,:,32:32)
802 qiten3 => diag3d(:,:,33:33)
803 niten3 => diag3d(:,:,34:34)
804 nrten3 => diag3d(:,:,35:35)
805 ncten3 => diag3d(:,:,36:36)
806 qcten3 => diag3d(:,:,37:37)
807 end if set_extended_diagnostic_pointers
809 if (is_aerosol_aware) then
810 call mp_gt_driver(qv=qv, qc=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, &
811 nc=new_nc, nwfa=new_nwfa, nifa=new_nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, &
812 tt=new_tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, &
813 sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, &
814 rainnc=rain_mp, rainncv=delta_rain_mp, &
815 snownc=snow_mp, snowncv=delta_snow_mp, &
816 icenc=ice_mp, icencv=delta_ice_mp, &
817 graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, &
818 refl_10cm=refl_10cm, &
819 diagflag=diagflag, do_radar_ref=do_radar_ref_mp, &
820 max_hail_diam_sfc=max_hail_diam_sfc, &
821 has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, &
822 aero_ind_fdb=aero_ind_fdb, rand_perturb_on=spp_mp_opt, &
823 kme_stoch=kme_stoch, &
824 rand_pert=spp_wts_mp, spp_var_list=spp_var_list, &
825 spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, &
826 spp_stddev_cutoff=spp_stddev_cutoff, &
827 ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, &
828 ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, &
829 its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, &
830 fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, &
831 first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, &
832 ! Extended diagnostics
833 ext_diag=ext_diag, &
834 ! vts1=vts1, txri=txri, txrc=txrc, &
835 prw_vcdc=prw_vcdc, &
836 prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, &
837 tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, &
838 tprs_sde_d=tprs_sde_d, &
839 tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, &
840 tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, &
841 tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, &
842 tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, &
843 tprs_rcs=tprs_rcs, &
844 tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, &
845 tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, &
846 tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, &
847 tprv_rev=tprv_rev, tten3=tten3, &
848 qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, &
849 qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, &
850 qcten3=qcten3, pfils=pfils, pflls=pflls, &
851 fs_fac_rain=fs_fac_rain, fs_fac_snow=fs_fac_snow)
852 else if (merra2_aerosol_aware) then
853 call mp_gt_driver(qv=qv, qc=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, &
854 nc=new_nc, nwfa=new_nwfa, nifa=new_nifa, &
855 tt=new_tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, &
856 sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, &
857 rainnc=rain_mp, rainncv=delta_rain_mp, &
858 snownc=snow_mp, snowncv=delta_snow_mp, &
859 icenc=ice_mp, icencv=delta_ice_mp, &
860 graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, &
861 refl_10cm=refl_10cm, &
862 diagflag=diagflag, do_radar_ref=do_radar_ref_mp, &
863 max_hail_diam_sfc=max_hail_diam_sfc, &
864 has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, &
865 aero_ind_fdb=aero_ind_fdb, rand_perturb_on=spp_mp_opt, &
866 kme_stoch=kme_stoch, &
867 rand_pert=spp_wts_mp, spp_var_list=spp_var_list, &
868 spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, &
869 spp_stddev_cutoff=spp_stddev_cutoff, &
870 ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, &
871 ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, &
872 its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, &
873 fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, &
874 first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, &
875 ! Extended diagnostics
876 ext_diag=ext_diag, &
877 ! vts1=vts1, txri=txri, txrc=txrc, &
878 prw_vcdc=prw_vcdc, &
879 prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, &
880 tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, &
881 tprs_sde_d=tprs_sde_d, &
882 tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, &
883 tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, &
884 tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, &
885 tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, &
886 tprs_rcs=tprs_rcs, &
887 tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, &
888 tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, &
889 tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, &
890 tprv_rev=tprv_rev, tten3=tten3, &
891 qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, &
892 qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, &
893 qcten3=qcten3, pfils=pfils, pflls=pflls, &
894 fs_fac_rain=fs_fac_rain, fs_fac_snow=fs_fac_snow)
895 else
896 call mp_gt_driver(qv=qv, qc=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, &
897 tt=new_tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, &
898 sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, &
899 rainnc=rain_mp, rainncv=delta_rain_mp, &
900 snownc=snow_mp, snowncv=delta_snow_mp, &
901 icenc=ice_mp, icencv=delta_ice_mp, &
902 graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, &
903 refl_10cm=refl_10cm, &
904 diagflag=diagflag, do_radar_ref=do_radar_ref_mp, &
905 max_hail_diam_sfc=max_hail_diam_sfc, &
906 has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, &
907 rand_perturb_on=spp_mp_opt, kme_stoch=kme_stoch, &
908 rand_pert=spp_wts_mp, spp_var_list=spp_var_list, &
909 spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, &
910 spp_stddev_cutoff=spp_stddev_cutoff, &
911 ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, &
912 ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, &
913 its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, &
914 fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, &
915 first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, &
916 ! Extended diagnostics
917 ext_diag=ext_diag, &
918 ! vts1=vts1, txri=txri, txrc=txrc, &
919 prw_vcdc=prw_vcdc, &
920 prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, &
921 tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, &
922 tprs_sde_d=tprs_sde_d, &
923 tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, &
924 tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, &
925 tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, &
926 tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, &
927 tprs_rcs=tprs_rcs, &
928 tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, &
929 tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, &
930 tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, &
931 tprv_rev=tprv_rev, tten3=tten3, &
932 qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, &
933 qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, &
934 qcten3=qcten3, pfils=pfils, pflls=pflls, &
935 fs_fac_rain=fs_fac_rain, fs_fac_snow=fs_fac_snow)
936 end if
937 if (errflg/=0) return
938
939 ! DH* - do this only if istep == nsteps? Would be ok if it was
940 ! guaranteed that nothing else in the same subcycle group
941 ! was using these arrays, but it is somewhat dangerous.
942
944 new_spechum = qv/(1.0_kind_phys+qv)
945
946 if (convert_dry_rho) then
947 new_qc = new_qc/(1.0_kind_phys+qv)
948 new_qr = new_qr/(1.0_kind_phys+qv)
949 new_qi = new_qi/(1.0_kind_phys+qv)
950 new_qs = new_qs/(1.0_kind_phys+qv)
951 new_qg = new_qg/(1.0_kind_phys+qv)
952
953 new_ni = new_ni/(1.0_kind_phys+qv)
954 new_nr = new_nr/(1.0_kind_phys+qv)
955 if (is_aerosol_aware .or. merra2_aerosol_aware) then
956 new_nc = new_nc/(1.0_kind_phys+qv)
957 new_nwfa = new_nwfa/(1.0_kind_phys+qv)
958 new_nifa = new_nifa/(1.0_kind_phys+qv)
959 end if
960 end if
961 ! *DH
962
964 ! "rain" in Thompson MP refers to precipitation (total of liquid rainfall+snow+graupel+ice)
965 prcp = prcp + max(0.0, delta_rain_mp/1000.0_kind_phys)
966 graupel = graupel + max(0.0, delta_graupel_mp/1000.0_kind_phys)
967 ice = ice + max(0.0, delta_ice_mp/1000.0_kind_phys)
968 snow = snow + max(0.0, delta_snow_mp/1000.0_kind_phys)
969 rain = rain + max(0.0, (delta_rain_mp - (delta_graupel_mp + delta_ice_mp + delta_snow_mp))/1000.0_kind_phys)
970
971 ! Recompute sr at last subcycling step
972 if (nsteps>1 .and. istep == nsteps) then
973 ! Unlike inside mp_gt_driver, rain does not contain frozen precip
974 sr = (snow + graupel + ice)/(rain + snow + graupel + ice +1.e-12)
975 end if
976
977 ! output instantaneous ice/snow and rain water 3d precipitation fluxes
978 if(cplchm) then
979 pfi_lsan(:,:) = pfils(:,:,1)
980 pfl_lsan(:,:) = pflls(:,:,1)
981 end if
982
983 dspechum = (new_spechum - spechum)/dtp
984 dqc = (new_qc - qc)/dtp
985 dqr = (new_qr - qr)/dtp
986 dqi = (new_qi - qi)/dtp
987 dqs = (new_qs - qs)/dtp
988 dqg = (new_qg - qg)/dtp
989 dni = (new_ni - ni)/dtp
990 dnr = (new_nr - nr)/dtp
991 dtgrs = (new_tgrs - tgrs)/dtp
992 if (is_aerosol_aware .or. merra2_aerosol_aware) then
993 dnc = (new_nc - nc)/dtp
994 dnwfa = (new_nwfa - nwfa)/dtp
995 dnifa = (new_nifa - nifa)/dtp
996
997 deallocate(new_nc, new_nwfa, new_nifa)
998 end if
999
1000 end subroutine mp_thompson_run
1002
1006 subroutine mp_thompson_final(is_initialized, errmsg, errflg)
1007
1008 implicit none
1009 logical, intent(inout) :: is_initialized
1010 character(len=*), intent( out) :: errmsg
1011 integer, intent( out) :: errflg
1012
1013 ! Initialize the CCPP error handling variables
1014 errmsg = ''
1015 errflg = 0
1016
1017 if (.not.is_initialized) return
1018
1019 call thompson_final()
1020
1021 is_initialized = .false.
1022
1023 end subroutine mp_thompson_final
1024
1025 subroutine get_niwfa(aerfld, nifa, nwfa, ncol, nlev)
1026 ! To calculate nifa and nwfa from bins of aerosols.
1027 ! In GOCART and MERRA2, aerosols are given as mixing ratio (kg/kg). To
1028 ! convert from kg/kg to #/kg, the "unit mass" (mass of one particle)
1029 ! within the mass bins is calculated. A lognormal size distribution
1030 ! within aerosol bins is used to find the size based upon the median
1031 ! mass. NIFA is mainly summarized over five dust bins and NWFA over the
1032 ! other 10 bins. The parameters besides each bins are carefully tuned
1033 ! for a good performance of the scheme.
1034 !
1035 ! The fields for the last index of the aerfld array
1036 ! are specified as below.
1037 ! 1: dust bin 1, 0.1 to 1.0 micrometers
1038 ! 2: dust bin 2, 1.0 to 1.8 micrometers
1039 ! 3: dust bin 3, 1.8 to 3.0 micrometers
1040 ! 4: dust bin 4, 3.0 to 6.0 micrometers
1041 ! 5: dust bin 5, 6.0 to 10.0 micrometers
1042 ! 6: sea salt bin 1, 0.03 to 0.1 micrometers
1043 ! 7: sea salt bin 2, 0.1 to 0.5 micrometers
1044 ! 8: sea salt bin 3, 0.5 to 1.5 micrometers
1045 ! 9: sea salt bin 4, 1.5 to 5.0 micrometers
1046 ! 10: sea salt bin 5, 5.0 to 10.0 micrometers
1047 ! 11: Sulfate, 0.35 (mean) micrometers
1048 ! 15: water-friendly organic carbon, 0.35 (mean) micrometers
1049 !
1050 ! Bin densities are as follows:
1051 ! 1: dust bin 1: 2500 kg/m2
1052 ! 2-5: dust bin 2-5: 2650 kg/m2
1053 ! 6-10: sea salt bins 6-10: 2200 kg/m2
1054 ! 11: sulfate: 1700 kg/m2
1055 ! 15: organic carbon: 1800 kg/m2
1056
1057 implicit none
1058 integer, intent(in)::ncol, nlev
1059 real (kind=kind_phys), dimension(:,:,:), intent(in) :: aerfld
1060 real (kind=kind_phys), dimension(:,:), intent(out ):: nifa, nwfa
1061
1062 nifa=(aerfld(:,:,1)/4.0737762+aerfld(:,:,2)/30.459203+aerfld(:,:,3)/153.45048+ &
1063 aerfld(:,:,4)/1011.5142+ aerfld(:,:,5)/5683.3501)*1.e15
1064
1065 nwfa=((aerfld(:,:,6)/0.0045435214+aerfld(:,:,7)/0.2907854+aerfld(:,:,8)/12.91224+ &
1066 aerfld(:,:,9)/206.2216+ aerfld(:,:,10)/4326.23)*9.+aerfld(:,:,11)/0.3053104*5+ &
1067 aerfld(:,:,15)/0.3232698*8)*1.e15
1068 end subroutine get_niwfa
1069
1070end module mp_thompson
subroutine, public mp_thompson_run(ncol, nlev, con_g, con_rd, con_eps, convert_dry_rho, spechum, qc, qr, qi, qs, qg, ni, nr, is_aerosol_aware, merra2_aerosol_aware, nc, nwfa, nifa, nwfa2d, nifa2d, aero_ind_fdb, tgrs, prsl, phii, omega, sedi_semi, decfl, islmsk, dtp, dt_inner, first_time_step, istep, nsteps, prcp, rain, graupel, ice, snow, sr, refl_10cm, fullradar_diag, max_hail_diam_sfc, do_radar_ref, aerfld, mpicomm, mpirank, mpiroot, ext_diag, diag3d, reset_diag3d, spp_wts_mp, spp_mp, n_var_spp, spp_prt_list, spp_var_list, spp_stddev_cutoff, cplchm, pfi_lsan, pfl_lsan, is_initialized, fs_fac_rain, fs_fac_snow, ten_q, dspechum, dqc, dqr, dqi, dqs, dqg, dni, dnr, dnc, dnwfa, dnifa, dtgrs, ten_u, ten_v, errmsg, errflg)
subroutine thompson_init(is_aerosol_aware_in, merra2_aerosol_aware_in, mpicomm, mpirank, mpiroot, threads, errmsg, errflg)
This subroutine calculates simplified cloud species equations and create lookup tables in Thomspson s...
subroutine mp_gt_driver(wrf_chem)
This is a wrapper routine designed to transfer values from 3D to 1D.
subroutine calc_effectrad(t1d, p1d, qv1d, qc1d, nc1d, qi1d, ni1d, qs1d, re_qc1d, re_qi1d, re_qs1d, lsml, kts, kte)
Compute radiation effective radii of cloud water, ice, and snow. These are entirely consistent with m...
elemental real function, public make_icenumber(q_ice, temp)
Table of lookup values of radiative effective radius of ice crystals as a function of Temperature fro...
This module ocntains lookup tables of radiative effective radius of cloud ice, rain and water.
This module computes the moisture tendencies of water vapor, cloud droplets, rain,...
This module contains the aerosol-aware Thompson microphysics scheme.