CCPP SciDoc v7.0.0  v7.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
module_mp_tempo_driver.F90
2 !! tempo driver that converts 3d model input to 1d arrays used by the main code
3 !! also allocates and fills diagnostic arrays
5 use module_mp_tempo_params, only : wp, sp, dp
6 use module_mp_tempo_main, only : tempo_main, ty_tempo_main_diags
7 use module_mp_tempo_utils, only : compute_efrw, compute_efsw, compute_drop_evap, qi_aut_qs
8 use module_mp_tempo_ml, only : ty_tempo_ml_data, nc_ml_nodes, nc_ml_input, nc_ml_output, &
9 nc_ml_trans_mean, nc_ml_trans_var, nc_ml_w00, nc_ml_w01, nc_ml_b00, nc_ml_b01, save_or_read_ml_data
10
11 implicit none
12 private
13
14 public :: tempo_init, tempo_run, ty_tempo_driver_diags, tempo_aerosol_surface_emissions
15
16 type(ty_tempo_table_cfgs) :: tempo_table_cfgs
17
19 real(wp), dimension(:,:), allocatable :: rain_precip
20 real(wp), dimension(:,:), allocatable :: ice_liquid_equiv_precip
21 real(wp), dimension(:,:), allocatable :: snow_liquid_equiv_precip
22 real(wp), dimension(:,:), allocatable :: graupel_liquid_equiv_precip
23 real(wp), dimension(:,:), allocatable :: frozen_fraction
24 real(wp), dimension(:,:), allocatable :: frz_rain_precip
25 real(wp), dimension(:,:), allocatable :: max_hail_diameter_sfc
26 real(wp), dimension(:,:), allocatable :: max_hail_diameter_column
27 real(wp), dimension(:,:,:), allocatable :: refl10cm
28 real(wp), dimension(:,:,:), allocatable :: re_cloud
29 real(wp), dimension(:,:,:), allocatable :: re_ice
30 real(wp), dimension(:,:,:), allocatable :: re_snow
31 real(wp), dimension(:,:,:), allocatable :: rain_med_vol_diam
32 real(wp), dimension(:,:,:), allocatable :: graupel_med_vol_diam
33 real(wp), dimension(:,:,:), allocatable :: cloud_number_mixing_ratio
34 end type
35
36 contains
37
42 subroutine tempo_init(aerosolaware_flag, hailaware_flag, semi_sedi_flag, cloud_condensation_flag, &
43 refl10cm_from_melting_flag, ml_for_bl_nc_flag, ml_for_nc_flag, force_init_flag, tempo_cfgs)
44 !! initialize tempo microphysics
45 use module_mp_tempo_params, only : get_version, tempo_version, t_efrw, &
46 initialize_graupel_vars, initialize_parameters, initialize_bins_for_tables, &
47 initialize_array_efrw, initialize_array_efsw, initialize_arrays_drop_evap, &
48 initialize_arrays_ccn, initialize_arrays_qi_aut_qs, &
49 initialize_arrays_qr_acr_qs, initialize_arrays_qr_acr_qg, initialize_arrays_freezewater, &
50 initialize_bins_for_hail_size, initialize_bins_for_radar
51
52 logical, intent(in), optional :: aerosolaware_flag, hailaware_flag, refl10cm_from_melting_flag, &
53 ml_for_bl_nc_flag, ml_for_nc_flag, force_init_flag, semi_sedi_flag, cloud_condensation_flag
54 type(ty_tempo_cfgs), intent(inout) :: tempo_cfgs
55
56 character(len=100) :: table_filename
57 integer :: table_size
58 logical :: initialize_mp_vars, force_init
59
60 ! get tempo version from readme file
61 call get_version(tempo_version, tempo_cfgs%verbose)
62
63 ! check an allocatable array (t_efrw) to see if initialization can be skipped
64 ! but allow for force initialization useful for testing
65 force_init = .false.
66 if (present(force_init_flag)) force_init = force_init_flag
67
68 initialize_mp_vars = .true.
69 if (allocated(t_efrw)) initialize_mp_vars = .false.
70 if (force_init) initialize_mp_vars = .true.
71
72 if (initialize_mp_vars) then
73 if (present(aerosolaware_flag)) tempo_cfgs%aerosolaware_flag = aerosolaware_flag
74 if (present(hailaware_flag)) tempo_cfgs%hailaware_flag = hailaware_flag
75 if (present(ml_for_bl_nc_flag)) tempo_cfgs%ml_for_bl_nc_flag = ml_for_bl_nc_flag
76 if (present(ml_for_nc_flag)) tempo_cfgs%ml_for_nc_flag = ml_for_nc_flag
77 if (present(semi_sedi_flag)) tempo_cfgs%semi_sedi_flag = semi_sedi_flag
78 if (present(cloud_condensation_flag)) tempo_cfgs%cloud_condensation_flag = cloud_condensation_flag
79 if (present(refl10cm_from_melting_flag)) tempo_cfgs%refl10cm_from_melting_flag = refl10cm_from_melting_flag
80
81 if (tempo_cfgs%verbose) then
82 write(*,'(A)') 'tempo_init() --- TEMPO microphysics configuration options: '
83 write(*,'(A,L)') 'tempo_init() --- aerosol aware = ', tempo_cfgs%aerosolaware_flag
84 write(*,'(A,L)') 'tempo_init() --- hail aware = ', tempo_cfgs%hailaware_flag
85 write(*,'(A,L)') 'tempo_init() --- ML for subgrid cloud number = ', tempo_cfgs%ml_for_bl_nc_flag
86 write(*,'(A,L)') 'tempo_init() --- ML for cloud number = ', tempo_cfgs%ml_for_nc_flag
87 write(*,'(A,L)') 'tempo_init() --- reflectivity from melting snow/graupel = ', tempo_cfgs%refl10cm_from_melting_flag
88 write(*,'(A,L)') 'tempo_init() --- semi-lagrangian sedimentation = ', tempo_cfgs%semi_sedi_flag
89 endif
90
91 ! set graupel variables from hail_aware_flag
92 call initialize_graupel_vars(tempo_cfgs%hailaware_flag)
93 if (tempo_cfgs%verbose) then
94 write(*,'(A,L)') 'tempo_init() --- initialized graupel variables using hail aware = ', tempo_cfgs%hailaware_flag
95 endif
96
97 ! set parameters that can depend on the host model
98 call initialize_parameters()
99 if (tempo_cfgs%verbose) write(*,'(A)') 'tempo_init() --- initialized parameters'
100
101 ! creates log-spaced bins of hydrometers for tables
102 call initialize_bins_for_tables()
103 if (tempo_cfgs%verbose) write(*,'(A)') 'tempo_init() --- initialized bins for lookup tables'
104
105 ! collision efficiencies between rain/snow and cloud water.
106 call initialize_array_efrw()
107 call compute_efrw()
108 if (tempo_cfgs%verbose) then
109 write(*,'(A)') 'tempo_init() --- initialized collision efficiency data for rain collecting cloud water'
110 endif
111 call initialize_array_efsw()
112 call compute_efsw()
113 if (tempo_cfgs%verbose) then
114 write(*,'(A)') 'tempo_init() --- initialized collision efficiency data for snow collecting cloud water'
115 endif
116
117 ! drop evaporation
118 call initialize_arrays_drop_evap()
119 call compute_drop_evap()
120 if (tempo_cfgs%verbose) write(*,'(A)') 'tempo_init() --- initialized drop evaporation data'
121
122 ! cloud ice to snow and depositional growth
123 call initialize_arrays_qi_aut_qs()
124 call qi_aut_qs()
125
126 ! CCN activation table
127 table_filename = tempo_table_cfgs%ccn_table_name
128 call initialize_arrays_ccn(table_size)
129 call read_table_ccn(trim(table_filename), table_size, tempo_cfgs)
130 if (tempo_cfgs%verbose) write(*,'(A)') 'tempo_init() --- initialized data for ccn lookup table'
131
132 ! freeze water collection lookup table
133 table_filename = tempo_table_cfgs%freezewater_table_name
134 call initialize_arrays_freezewater(table_size)
135 call read_table_freezewater(trim(table_filename), table_size, tempo_cfgs)
136 if (tempo_cfgs%verbose) then
137 write(*,'(A)') 'tempo_init() --- initialized data for frozen cloud water and rain lookup table'
138 endif
139
140 ! rain-snow collection lookup table
141 table_filename = tempo_table_cfgs%qrqs_table_name
142 call initialize_arrays_qr_acr_qs(table_size)
143 call read_table_qr_acr_qs(trim(table_filename), table_size, tempo_cfgs)
144 if (tempo_cfgs%verbose) then
145 write(*,'(A)') 'tempo_init() --- initialized data for rain-snow collection lookup table'
146 endif
147
148 ! rain-graupel collection lookup table
149 table_filename = tempo_table_cfgs%qrqg_table_name
150 call initialize_arrays_qr_acr_qg(table_size)
151 call read_table_qr_acr_qg(trim(table_filename), table_size, tempo_cfgs)
152 if (tempo_cfgs%verbose) then
153 write(*,'(A)') 'tempo_init() --- initialized data for rain-graupel collection lookup table'
154 endif
155
156 ! bins used for optional refl10cm calculation with melting
157 if (tempo_cfgs%refl10cm_from_melting_flag) then
158 call initialize_bins_for_radar()
159 if (tempo_cfgs%verbose) then
160 write(*,'(A,L)') 'tempo_init() --- flag to calcuate reflectivity with contributions from melting snow and graupel = ', &
161 tempo_cfgs%refl10cm_from_melting_flag
162 write(*,'(A)') 'tempo_init() --- initialized bins for reflectivity calcuation with meting snow and graupel'
163 endif
164 endif
165
166 ! bins used for optional hail size calculation
167 if (tempo_cfgs%max_hail_diameter_flag) then
168 call initialize_bins_for_hail_size()
169 if (tempo_cfgs%verbose) then
170 write(*,'(A,L)') 'tempo_init() --- flag to calculate max hail diameter = ', &
171 tempo_cfgs%max_hail_diameter_flag
172 write(*,'(A)') 'tempo_init() --- initialized bins for hail size calculation'
173 endif
174 endif
175
176 ! data for machine learning
177 if(tempo_cfgs%ml_for_bl_nc_flag .or. tempo_cfgs%ml_for_nc_flag) then
178 call init_ml_data()
179 if (tempo_cfgs%verbose) write(*,'(A)') 'tempo_init() --- initialized data for cloud number machine learning'
180 endif
181 endif
182 end subroutine tempo_init
183
187 subroutine tempo_run(tempo_cfgs, dt, itimestep, &
188 t, th, pii, p, w, dz, &
189 qv, qc, qr, qi, qs, qg, ni, nr, &
190 nc, nwfa, nifa, ng, qb, &
191 qc_bl, qcfrac_bl, &
192 qcfrac, qifrac, &
193 thten_bl, qvten_bl, qcten_bl, qiten_bl, &
194 thten_lwrad, thten_swrad, &
195 land_input, &
196 ids, ide, jds, jde, kds, kde, &
197 ims, ime, jms, jme, kms, kme, &
198 its, ite, jts, jte, kts, kte, tempo_diags)
199
200 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
201 real(wp), intent(in) :: dt !! timestep \‍([s]]\‍)
202 integer, intent(in) :: itimestep !! integer timestep = integration time / dt
203 integer, intent(in) :: ids, ide, jds, jde, kds, kde !! domain locations
204 integer, intent(in) :: ims, ime, jms, jme, kms, kme !! memory locations
205 integer, intent(in) :: its, ite, jts, jte, kts, kte !! tile locations
206
207 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: t !! temperature \‍([K]\‍)
208 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: th !! theta \‍([K]\‍)
209
210 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in) :: p !! pressure \‍([Pa]\‍)
211 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in) :: w !! vertical velocity \‍([m\; s^{-1}]\‍)
212 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in) :: dz !! vertical grid spacing \‍([m]\‍)
213 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: pii !! exner function
214
215 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qv !! 3D water vapor mixing ratio \‍([kg\; kg^{-1}]\‍)
216 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qc !! 3D cloud water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
217 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qr !! 3D rain water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
218 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qi !! 3D cloud ice mass mixing ratio \‍([kg\; kg^{-1}]\‍)
219 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qs !! 3D snow mass mixing ratio \‍([kg\; kg^{-1}]\‍)
220 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: qg !! 3D graupel mass mixing ratio \‍([kg\; kg^{-1}]\‍)
221 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: ni !! 3D cloud ice number mixing ratio \‍([kg^{-1}]\‍)
222 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: nr !! 3D rain water number mixing ratio \‍([kg^{-1}]\‍)
223
224 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: nc !! 3D cloud water number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
225 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: nwfa !! 3D water-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
226 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: nifa !! 3D ice-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
227 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: qb !! 3D graupel volume mixing ratio \‍([m^{-3}\; kg^{-1}]\‍) (hail-aware)
228 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: ng !! 3D graupel number mixing ratio \‍([kg^{-1}]\‍) (hail-aware)
229 integer, dimension(ims:ime, jms:jme), intent(in), optional :: land_input !! land input value to differentiate land from ocean
230
231 ! additional optional arguments
232 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: qcfrac
233 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout), optional :: qifrac
234 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: qc_bl
235 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: qcfrac_bl
236 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: thten_bl
237 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: qvten_bl
238 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: qcten_bl
239 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: qiten_bl
240 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: thten_lwrad
241 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(in), optional :: thten_swrad
242 integer, allocatable :: land1d
243
244 real(wp), dimension(kts:kte) :: t1d !! 1D temperature \‍([K]\‍)
245 real(wp), dimension(kts:kte) :: p1d !! 1D pressure \‍([Pa]\‍)
246 real(wp), dimension(kts:kte) :: qv1d !! 1D water vapor mixing ratio \‍([kg\; kg^{-1}]\‍)
247 real(wp), dimension(kts:kte) :: qc1d !! 1D cloud water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
248 real(wp), dimension(kts:kte) :: qr1d !! 1D rain water mass mixing ratio \‍([kg\; kg^{-1}]\‍)
249 real(wp), dimension(kts:kte) :: qi1d !! 1D cloud ice mass mixing ratio \‍([kg\; kg^{-1}]\‍)
250 real(wp), dimension(kts:kte) :: qs1d !! 1D snow mass mixing ratio \‍([kg\; kg^{-1}]\‍)
251 real(wp), dimension(kts:kte) :: qg1d !! 1D graupel mass mixing ratio \‍([kg\; kg^{-1}]\‍)
252 real(wp), dimension(kts:kte) :: ni1d !! 1D cloud ice number mixing ratio \‍([kg^{-1}]\‍)
253 real(wp), dimension(kts:kte) :: nr1d !! 1D rain water number mixing ratio \‍([kg^{-1}]\‍)
254 real(wp), dimension(kts:kte) :: w1d !! 1D vertical velocity \‍(m\; s^{-1}]\‍)
255 real(wp), dimension(kts:kte) :: dz1d !! 1D vertical grid spacing \‍([m]\‍)
256
257 real(wp), dimension(:), allocatable :: nc1d !! 1D cloud water number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
258 real(wp), dimension(:), allocatable :: nwfa1d !! 1D water-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
259 real(wp), dimension(:), allocatable :: nifa1d !! 1D ice-friendly aerosol number mixing ratio \‍([kg^{-1}]\‍) (aerosol-aware)
260 real(wp), dimension(:), allocatable :: qb1d !! 1D graupel volume mixing ratio \‍([m^{-3}\; kg^{-1}]\‍) (hail-aware)
261 real(wp), dimension(:), allocatable :: ng1d !! 1D graupel number mixing ratio \‍([kg^{-1}]\‍) (hail-aware)
262
263 ! additional optional 1d arrays
264 real(wp), dimension(:), allocatable :: qcfrac1d
265 real(wp), dimension(:), allocatable :: qifrac1d
266 real(wp), dimension(:), allocatable :: qc_bl1d
267 real(wp), dimension(:), allocatable :: qcfrac_bl1d
268 real(wp), dimension(:), allocatable :: thten_bl1d
269 real(wp), dimension(:), allocatable :: qvten_bl1d
270 real(wp), dimension(:), allocatable :: qcten_bl1d
271 real(wp), dimension(:), allocatable :: qiten_bl1d
272 real(wp), dimension(:), allocatable :: thten_lwrad1d
273 real(wp), dimension(:), allocatable :: thten_swrad1d
274
275 integer :: i, j, k, nz
276 logical :: use_temperature
277
278 type(ty_tempo_main_diags) :: tempo_main_diags
279 type(ty_tempo_driver_diags), intent(inout) :: tempo_diags
280
281 nz = kte - kts + 1
282 ! allocate 1d arrays if 3d arrays are present
283 if (present(nwfa)) allocate(nwfa1d(nz), source=0._wp)
284 if (present(nifa)) allocate(nifa1d(nz), source=0._wp)
285 if (present(nc)) allocate(nc1d(nz), source=0._wp)
286 if (present(ng)) allocate(ng1d(nz), source=0._wp)
287 if (present(qb)) allocate(qb1d(nz), source=0._wp)
288
289 ! additional optional 1d arrays
290 if (present(qcfrac)) allocate(qcfrac1d(nz), source=0._wp)
291 if (present(qifrac)) allocate(qifrac1d(nz), source=0._wp)
292 if (present(qc_bl)) allocate(qc_bl1d(nz), source=0._wp)
293 if (present(qcfrac_bl)) allocate(qcfrac_bl1d(nz), source=0._wp)
294 if (present(thten_bl)) allocate(thten_bl1d(nz), source=0._wp)
295 if (present(qvten_bl)) allocate(qvten_bl1d(nz), source=0._wp)
296 if (present(qcten_bl)) allocate(qcten_bl1d(nz), source=0._wp)
297 if (present(qiten_bl)) allocate(qiten_bl1d(nz), source=0._wp)
298 if (present(thten_lwrad)) allocate(thten_lwrad1d(nz), source=0._wp)
299 if (present(thten_swrad)) allocate(thten_swrad1d(nz), source=0._wp)
300 if (present(land_input)) allocate(land1d)
301
302 ! allocate diagnostics
303 ! 3d diagnostics have configuration flags
304 if (tempo_cfgs%cloud_number_mixing_ratio_flag) then
305 if (.not. allocated(tempo_diags%cloud_number_mixing_ratio)) then
306 allocate(tempo_diags%cloud_number_mixing_ratio(its:ite, kts:kte, jts:jte), source=0._wp)
307 else
308 tempo_diags%cloud_number_mixing_ratio = 0._wp
309 endif
310 endif
311
312 if (tempo_cfgs%rain_med_vol_diam_flag) then
313 if (.not. allocated(tempo_diags%rain_med_vol_diam)) then
314 allocate(tempo_diags%rain_med_vol_diam(its:ite, kts:kte, jts:jte), source=0._wp)
315 else
316 tempo_diags%rain_med_vol_diam = 0._wp
317 endif
318 endif
319
320 if (tempo_cfgs%graupel_med_vol_diam_flag) then
321 if (.not. allocated(tempo_diags%graupel_med_vol_diam)) then
322 allocate(tempo_diags%graupel_med_vol_diam(its:ite, kts:kte, jts:jte), source=0._wp)
323 else
324 tempo_diags%graupel_med_vol_diam = 0._wp
325 endif
326 endif
327
328 if (tempo_cfgs%refl10cm_flag) then
329 if (.not. allocated(tempo_diags%refl10cm)) then
330 allocate(tempo_diags%refl10cm(its:ite, kts:kte, jts:jte), source=-35._wp)
331 else
332 tempo_diags%refl10cm = -35._wp
333 endif
334 endif
335
336 if (tempo_cfgs%re_cloud_flag) then
337 if (.not. allocated(tempo_diags%re_cloud)) then
338 allocate(tempo_diags%re_cloud(its:ite, kts:kte, jts:jte), source=0._wp)
339 else
340 tempo_diags%re_cloud = 0._wp
341 endif
342 endif
343
344 if (tempo_cfgs%re_ice_flag) then
345 if (.not. allocated(tempo_diags%re_ice)) then
346 allocate(tempo_diags%re_ice(its:ite, kts:kte, jts:jte), source=0._wp)
347 else
348 tempo_diags%re_ice = 0._wp
349 endif
350 endif
351
352 if (tempo_cfgs%re_snow_flag) then
353 if (.not. allocated(tempo_diags%re_snow)) then
354 allocate(tempo_diags%re_snow(its:ite, kts:kte, jts:jte), source=0._wp)
355 else
356 tempo_diags%re_snow = 0._wp
357 endif
358 endif
359
360 ! 2d diagnostics
361 if (tempo_cfgs%max_hail_diameter_flag) then
362 if (.not. allocated(tempo_diags%max_hail_diameter_sfc)) then
363 allocate(tempo_diags%max_hail_diameter_sfc(its:ite, jts:jte), source=0._wp)
364 allocate(tempo_diags%max_hail_diameter_column(its:ite, jts:jte), source=0._wp)
365 else
366 tempo_diags%max_hail_diameter_sfc = 0._wp
367 tempo_diags%max_hail_diameter_column = 0._wp
368 endif
369 endif
370
371 ! precipitation
372 if (.not. allocated(tempo_diags%rain_precip)) then
373 allocate(tempo_diags%rain_precip(its:ite, jts:jte), source=0._wp)
374 allocate(tempo_diags%ice_liquid_equiv_precip(its:ite, jts:jte), source=0._wp)
375 allocate(tempo_diags%snow_liquid_equiv_precip(its:ite, jts:jte), source=0._wp)
376 allocate(tempo_diags%graupel_liquid_equiv_precip(its:ite, jts:jte), source=0._wp)
377 allocate(tempo_diags%frozen_fraction(its:ite, jts:jte), source=0._wp)
378 allocate(tempo_diags%frz_rain_precip(its:ite, jts:jte), source=0._wp)
379 else
380 tempo_diags%rain_precip = 0._wp
381 tempo_diags%ice_liquid_equiv_precip = 0._wp
382 tempo_diags%snow_liquid_equiv_precip = 0._wp
383 tempo_diags%graupel_liquid_equiv_precip = 0._wp
384 tempo_diags%frozen_fraction = 0._wp
385 tempo_diags%frz_rain_precip = 0._wp
386 endif
387
388 ! temperature or theta and exner
389 if (present(t)) then
390 use_temperature = .true.
391 elseif (present(th) .and. present(pii)) then
392 use_temperature = .false.
393 ! else
394 ! error stop "tempo_run() --- requires either temperature or theta and Exner function"
395 endif
396
397 ! tempo driver code
398 do j = jts, jte
399 do i = its, ite
400 do k = kts, kte
401 if (use_temperature) then
402 t1d(k) = t(i,k,j)
403 else
404 t1d(k) = th(i,k,j) * pii(i,k,j)
405 endif
406 p1d(k) = p(i,k,j)
407 w1d(k) = w(i,k,j)
408 dz1d(k) = dz(i,k,j)
409 qv1d(k) = qv(i,k,j)
410 qc1d(k) = qc(i,k,j)
411 qi1d(k) = qi(i,k,j)
412 qr1d(k) = qr(i,k,j)
413 qs1d(k) = qs(i,k,j)
414 qg1d(k) = qg(i,k,j)
415 ni1d(k) = ni(i,k,j)
416 nr1d(k) = nr(i,k,j)
417
418 ! nwfa, nifa, and nc are optional aerosol-aware variables
419 if (present(nwfa)) nwfa1d(k) = nwfa(i,k,j)
420 if (present(nifa)) nifa1d(k) = nifa(i,k,j)
421 if (present(nc)) nc1d(k) = nc(i,k,j)
422
423 ! ng and qb are optional hail-aware variables
424 if ((present(ng)) .and. (present(qb))) then
425 ng1d(k) = ng(i,k,j)
426 qb1d(k) = qb(i,k,j)
427 endif
428
429 ! machine learning for pbl clouds
430 if (present(qc_bl) .and. present(qcfrac_bl)) then
431 qc_bl1d(k) = qc_bl(i,k,j)
432 qcfrac_bl1d(k) = qcfrac_bl(i,k,j)
433 endif
434 enddo
435
436 ! land input
437 if (present(land_input)) land1d = land_input(i,j)
438
439 ! main call to the 1d tempo microphysics
440 call tempo_main(tempo_cfgs=tempo_cfgs, &
441 qv1d=qv1d, qc1d=qc1d, qi1d=qi1d, qr1d=qr1d, qs1d=qs1d, qg1d=qg1d, qb1d=qb1d, &
442 ni1d=ni1d, nr1d=nr1d, nc1d=nc1d, ng1d=ng1d, nwfa1d=nwfa1d, nifa1d=nifa1d, t1d=t1d, p1d=p1d, &
443 w1d=w1d, dz1d=dz1d, land1d=land1d, &
444 qcfrac1d=qcfrac1d, qifrac1d=qifrac1d, qc_bl1d=qc_bl1d, qcfrac_bl1d=qcfrac_bl1d, &
445 thten_bl1d=thten_bl1d, qvten_bl1d=qvten_bl1d, qcten_bl1d=qcten_bl1d, qiten_bl1d=qiten_bl1d, &
446 thten_lwrad1d=thten_lwrad1d, thten_swrad1d=thten_swrad1d, &
447 kts=kts, kte=kte, dt=dt, ii=i, jj=j, tempo_main_diags=tempo_main_diags)
448
449 ! precipitation
450 tempo_diags%rain_precip(i,j) = tempo_main_diags%rain_precip
451 tempo_diags%ice_liquid_equiv_precip(i,j) = tempo_main_diags%ice_liquid_equiv_precip
452 tempo_diags%snow_liquid_equiv_precip(i,j) = tempo_main_diags%snow_liquid_equiv_precip
453 tempo_diags%graupel_liquid_equiv_precip(i,j) = tempo_main_diags%graupel_liquid_equiv_precip
454 tempo_diags%frozen_fraction(i,j) = tempo_main_diags%frozen_fraction
455 tempo_diags%frz_rain_precip(i,j) = tempo_main_diags%frz_rain_precip
456
457 ! 3d diagnostics
458 if (allocated(tempo_diags%cloud_number_mixing_ratio) .and. allocated(tempo_main_diags%cloud_number_mixing_ratio)) then
459 tempo_diags%cloud_number_mixing_ratio(i,:,j) = tempo_main_diags%cloud_number_mixing_ratio
460 endif
461 if (allocated(tempo_diags%rain_med_vol_diam) .and. allocated(tempo_main_diags%rain_med_vol_diam)) then
462 tempo_diags%rain_med_vol_diam(i,:,j) = tempo_main_diags%rain_med_vol_diam
463 endif
464 if (allocated(tempo_diags%graupel_med_vol_diam) .and. allocated(tempo_main_diags%graupel_med_vol_diam)) then
465 tempo_diags%graupel_med_vol_diam(i,:,j) = tempo_main_diags%graupel_med_vol_diam
466 endif
467 if (allocated(tempo_diags%re_cloud) .and. allocated(tempo_main_diags%re_cloud)) then
468 tempo_diags%re_cloud(i,:,j) = tempo_main_diags%re_cloud
469 endif
470 if (allocated(tempo_diags%re_ice) .and. allocated(tempo_main_diags%re_ice)) then
471 tempo_diags%re_ice(i,:,j) = tempo_main_diags%re_ice
472 endif
473 if (allocated(tempo_diags%re_snow) .and. allocated(tempo_main_diags%re_snow)) then
474 tempo_diags%re_snow(i,:,j) = tempo_main_diags%re_snow
475 endif
476 if (allocated(tempo_diags%refl10cm) .and. allocated(tempo_main_diags%refl10cm)) then
477 tempo_diags%refl10cm(i,:,j) = tempo_main_diags%refl10cm
478 endif
479 if (allocated(tempo_diags%max_hail_diameter_sfc) .and. allocated(tempo_diags%max_hail_diameter_column) .and. allocated(tempo_main_diags%max_hail_diameter)) then
480 tempo_diags%max_hail_diameter_sfc(i,j) = tempo_main_diags%max_hail_diameter(1)
481 tempo_diags%max_hail_diameter_column(i,j) = maxval(tempo_main_diags%max_hail_diameter)
482 endif
483
484 ! return variables to model
485 do k = kts, kte
486 if (present(nc)) nc(i,k,j) = nc1d(k)
487 if (present(nwfa)) nwfa(i,k,j) = nwfa1d(k)
488 if (present(nifa)) nifa(i,k,j) = nifa1d(k)
489 if ((present(ng)) .and. (present(qb))) then
490 ng(i,k,j) = ng1d(k)
491 qb(i,k,j) = qb1d(k)
492 endif
493 qv(i,k,j) = qv1d(k)
494 qc(i,k,j) = qc1d(k)
495 qi(i,k,j) = qi1d(k)
496 qr(i,k,j) = qr1d(k)
497 qs(i,k,j) = qs1d(k)
498 qg(i,k,j) = qg1d(k)
499 ni(i,k,j) = ni1d(k)
500 nr(i,k,j) = nr1d(k)
501
502 ! tempo main returns temperature (t1d), so convert to theta if needed
503 if (use_temperature) then
504 t(i,k,j) = t1d(k)
505 else
506 th(i,k,j) = t1d(k) / pii(i,k,j)
507 endif
508 enddo
509 enddo
510 enddo
511 end subroutine tempo_run
512
513
514 subroutine tempo_aerosol_surface_emissions(dt, nwfa, nwfa2d, ims, ime, jms, jme, kms, kme, kts)
515 !! adds aerosol surface emissions to the 3D field
516 real(wp), intent(in) :: dt
517 integer, intent(in) :: ims, ime, jms, jme, kms, kme, kts
518 real(wp), dimension(ims:ime, kms:kme, jms:jme), intent(inout) :: nwfa
519 real(wp), dimension(ims:ime, jms:jme), intent(in) :: nwfa2d
520 integer :: i, j
521
522 do j = jms, jme
523 do i = ims, ime
524 nwfa(i,kts,j) = nwfa(i,kts,j) + nwfa2d(i,j) * dt
525 enddo
526 enddo
527 end subroutine tempo_aerosol_surface_emissions
528
529
530 subroutine read_table_freezewater(filename, table_size, tempo_cfgs)
531 !! read lookup table for frozen cloud and rain water
532 use module_mp_tempo_params, only : tpi_qrfz, tni_qrfz, &
533 tpg_qrfz, tnr_qrfz, tpi_qcfz, tni_qcfz
534
535 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
536 character(len=*), intent(in) :: filename
537 integer, intent(in) :: table_size
538
539 integer :: mp_unit, istat
540
541 mp_unit = 11
542 if (tempo_cfgs%check_tables) call check_before_table_read(filename, table_size)
543 open(unit=mp_unit, file=filename, form='unformatted', status='old', access='stream', &
544 action='read', iostat=istat &
545#ifndef TEMPO_IGNORE_CONVERT_ARG
546 , convert='big_endian' &
547#endif
548 )
549 read(mp_unit) tpi_qrfz
550 read(mp_unit) tni_qrfz
551 read(mp_unit) tpg_qrfz
552 read(mp_unit) tnr_qrfz
553 read(mp_unit) tpi_qcfz
554 read(mp_unit) tni_qcfz
555 close(unit=mp_unit)
556 end subroutine read_table_freezewater
557
558
559 subroutine read_table_qr_acr_qs(filename, table_size, tempo_cfgs)
560 !! read lookup table for rain-snow collection
561 use module_mp_tempo_params, only : tcs_racs1, tmr_racs1, &
562 tcs_racs2, tmr_racs2, tcr_sacr1, tms_sacr1, tcr_sacr2, &
563 tms_sacr2, tnr_racs1, tnr_racs2, tnr_sacr1, tnr_sacr2
564
565 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
566 character(len=*), intent(in) :: filename
567 integer, intent(in) :: table_size
568
569 integer :: mp_unit, istat
570
571 mp_unit = 11
572 if (tempo_cfgs%check_tables) call check_before_table_read(filename, table_size)
573 open(unit=mp_unit, file=filename, form='unformatted', status='old', access='stream', &
574 action='read', iostat=istat &
575#ifndef TEMPO_IGNORE_CONVERT_ARG
576 , convert='big_endian' &
577#endif
578 )
579 read(mp_unit) tcs_racs1
580 read(mp_unit) tmr_racs1
581 read(mp_unit) tcs_racs2
582 read(mp_unit) tmr_racs2
583 read(mp_unit) tcr_sacr1
584 read(mp_unit) tms_sacr1
585 read(mp_unit) tcr_sacr2
586 read(mp_unit) tms_sacr2
587 read(mp_unit) tnr_racs1
588 read(mp_unit) tnr_racs2
589 read(mp_unit) tnr_sacr1
590 read(mp_unit) tnr_sacr2
591 close(unit=mp_unit)
592 end subroutine read_table_qr_acr_qs
593
594
595 subroutine read_table_qr_acr_qg(filename, table_size, tempo_cfgs)
596 !! read lookup table for rain-graupel collection
597 use module_mp_tempo_params, only : tcg_racg, tmr_racg, &
598 tcr_gacr, tnr_racg, tnr_gacr
599
600 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
601 character(len=*), intent(in) :: filename
602 integer, intent(in) :: table_size
603
604 integer :: mp_unit, istat
605
606 mp_unit = 11
607 if (tempo_cfgs%check_tables) call check_before_table_read(filename, table_size)
608 open(unit=mp_unit, file=filename, form='unformatted', status='old', access='stream', &
609 action='read', iostat=istat &
610#ifndef TEMPO_IGNORE_CONVERT_ARG
611 , convert='big_endian' &
612#endif
613 )
614 read(mp_unit) tcg_racg
615 read(mp_unit) tmr_racg
616 read(mp_unit) tcr_gacr
617 read(mp_unit) tnr_racg
618 read(mp_unit) tnr_gacr
619 close(unit=mp_unit)
620 end subroutine read_table_qr_acr_qg
621
622
623 subroutine read_table_ccn(filename, table_size, tempo_cfgs)
624 !! read static file containing CCN activation of aerosols;
625 !! the data were created from a parcel model by Feingold and Heymsfield (1992)
626 !! https://doi.org/10.1175/1520-0469(1992)049<2325:POCGOD>2.0.CO;2
627 !! with further changes by Eidhammer and Kreidenweis
628 use module_mp_tempo_params, only : tnccn_act
629
630 type(ty_tempo_cfgs), intent(in) :: tempo_cfgs
631 character(len=*), intent(in) :: filename
632 integer, intent(in) :: table_size
633
634 integer :: mp_unit, istat
635
636 if (tempo_cfgs%check_tables) call check_before_table_read(filename=filename, table_size=table_size)
637
638 mp_unit = 11
639 open(unit=mp_unit, file=filename, form='unformatted', status='old', &
640 action='read', iostat=istat &
641#ifndef TEMPO_IGNORE_CONVERT_ARG
642 , convert='big_endian' &
643#endif
644 )
645 read(mp_unit) tnccn_act
646 close(unit=mp_unit)
647 end subroutine read_table_ccn
648
649
650 subroutine check_before_table_read(filename, table_size)
651 !! checks that lookup tables exist and are the correct size
652 !! before attempting to read them
653
654 character(len=*), intent(in) :: filename
655 integer, intent(in) :: table_size
656
657 logical :: fileexists
658 integer :: filesize
659 character(len=100) :: int_to_str1, int_to_str2
660
661 inquire(file=filename, size=filesize, exist=fileexists)
662 if (.not. fileexists) then
663 write(*,'(3A)') 'tempo_init() --- *** FATAL *** file "', filename, &
664 '" was not found in this directory.'
665 write(*,'(A)') ''
666 write(*,'(A)') 'How to fix issues with tables (datasets stored in files):'
667 write(*,'(3A)') ' (1) The table ', trim(tempo_table_cfgs%ccn_table_name), &
668 ' is located in the TEMPO/tables/ directory. Copy this file to the directory where the model executable is located.'
669 write(*,'(8A)') ' (2) Three tables:', trim(tempo_table_cfgs%qrqs_table_name), ', ', trim(tempo_table_cfgs%qrqg_table_name), ', and ', &
670 trim(tempo_table_cfgs%freezewater_table_name), &
671 ' can be build by compiling and running the executable "build_tables" in the main TEMPO directory. ', &
672 'Then copy the file to the directory where the model executable is located.'
673 write(*,'(A)') ' (3) Ask the developers for tables. They are willing to share.'
674 write(*,'(A)') ''
675 write(*,'(A)') '--- file "' // filename // '" needed for TEMPO microphysics was not found.'
676 error stop 'program aborted'
677 endif
678
679 if (filesize /= table_size) then
680 write(int_to_str1, '(I0)') filesize
681 write(int_to_str2, '(I0)') table_size
682 write(*,'(7A)') 'tempo_init() --- *** FATAL *** file "', filename, '" has a size of ', &
683 trim(int_to_str1), ' bytes but the array allocated to hold the data expects a file size of ', &
684 trim(int_to_str2), ' bytes.'
685 write(*,'(A)') ''
686 write(*,'(A)') 'How to fix issues with tables (datasets stored in files):'
687 write(*,'(3A)') ' (1) The table ', trim(tempo_table_cfgs%ccn_table_name), &
688 ' is located in the TEMPO/tables/ directory. Copy this file to the directory where the model executable is located.'
689 write(*,'(8A)') ' (2) Three tables: ', trim(tempo_table_cfgs%qrqs_table_name), ', ', trim(tempo_table_cfgs%qrqg_table_name), ', and ', &
690 trim(tempo_table_cfgs%freezewater_table_name), &
691 ' can be build by compiling and running the executable "build_tables" in the main TEMPO directory. ', &
692 'Then copy the file to the directory where the model executable is located.'
693 write(*,'(A)') ' (3) Ask the developers for tables. They are willing to share.'
694 write(*,'(A)') ''
695 write(*,'(A)') '--- size of file "' // filename // '" needed for TEMPO microphysics is inconsistent with expected size.'
696 error stop 'program aborted'
697 endif
698 end subroutine check_before_table_read
699
700
701 subroutine init_ml_data()
702 !! initialize machine learning data for tempo microphysics
703 type(ty_tempo_ml_data), dimension(1) :: tempo_ml_data
704
705 ! cloud water
706 tempo_ml_data(1)%input_size = nc_ml_input
707 tempo_ml_data(1)%node_size = nc_ml_nodes
708 tempo_ml_data(1)%output_size = nc_ml_output
709
710 if (.not.allocated(tempo_ml_data(1)%transform_mean)) allocate(tempo_ml_data(1)%transform_mean(nc_ml_input))
711 if (.not.allocated(tempo_ml_data(1)%transform_var)) allocate(tempo_ml_data(1)%transform_var(nc_ml_input))
712
713 tempo_ml_data(1)%transform_mean = nc_ml_trans_mean
714 tempo_ml_data(1)%transform_var = nc_ml_trans_var
715
716 if (.not.allocated(tempo_ml_data(1)%weights00)) allocate(tempo_ml_data(1)%weights00(nc_ml_nodes,nc_ml_input))
717 if (.not.allocated(tempo_ml_data(1)%weights01)) allocate(tempo_ml_data(1)%weights01(nc_ml_output,nc_ml_nodes))
718 if (.not.allocated(tempo_ml_data(1)%bias00)) allocate(tempo_ml_data(1)%bias00(nc_ml_nodes))
719 if (.not.allocated(tempo_ml_data(1)%bias01)) allocate(tempo_ml_data(1)%bias01(nc_ml_output))
720
721 tempo_ml_data(1)%weights00 = reshape(nc_ml_w00, (/nc_ml_nodes, nc_ml_input/))
722 tempo_ml_data(1)%weights01 = reshape(nc_ml_w01, (/nc_ml_output, nc_ml_nodes/))
723 tempo_ml_data(1)%bias00 = nc_ml_b00
724 tempo_ml_data(1)%bias01 = nc_ml_b01
725
726 ! save neural network
727 call save_or_read_ml_data(ml_data_in=tempo_ml_data)
728 end subroutine init_ml_data
729
730end module module_mp_tempo_driver
subroutine error(parameters, swdown,fsa,fsr,fira,fsh,fcev, fgev,fctr,ssoil,beg_wb,canliq,canice, sneqv,wa,smc,dzsnso,prcp,ecan, etran,edir,runsrf,runsub,dt,nsoil, nsnow,ist,errwat, iloc,jloc,fveg, sav,sag,fsrv,fsrg,zwt,pah, ifdef ccpp
check surface energy balance and water balance.