CCPP SciDoc v7.0.x  v7.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
cires_ugwp.F90
1
3
16
17 use machine, only: kind_phys
18
19 use cires_ugwpv0_module, only: knob_ugwp_version, cires_ugwpv0_mod_init, cires_ugwpv0_mod_finalize
21 use gwdps, only: gwdps_run
23
24 implicit none
25
26 private
27
28 public cires_ugwp_init, cires_ugwp_run, cires_ugwp_finalize
29
30 logical :: is_initialized = .false.
31
32contains
33
34! ------------------------------------------------------------------------
35! CCPP entry points for CIRES Unified Gravity Wave Physics (UGWP) scheme v0
36! ------------------------------------------------------------------------
41 subroutine cires_ugwp_init (me, master, nlunit, input_nml_file, logunit, &
42 fn_nml2, lonr, levs, ak, bk, dtp, cdmbgwd, cgwf, &
43 pa_rf_in, tau_rf_in, con_p0, gwd_opt,do_ugwp, errmsg, errflg)
44
45!---- initialization of cires_ugwp
46 implicit none
47
48 integer, intent (in) :: me
49 integer, intent (in) :: master
50 integer, intent (in) :: nlunit
51 character(len=*), intent (in) :: input_nml_file(:)
52 integer, intent (in) :: logunit
53 integer, intent (in) :: lonr
54 integer, intent (in) :: levs
55 real(kind=kind_phys), intent (in) :: ak(:), bk(:)
56 real(kind=kind_phys), intent (in) :: dtp
57 real(kind=kind_phys), intent (in) :: cdmbgwd(:), cgwf(:) ! "scaling" controls for "old" GFS-GW schemes
58 real(kind=kind_phys), intent (in) :: pa_rf_in, tau_rf_in
59 real(kind=kind_phys), intent (in) :: con_p0
60 integer, intent(in) :: gwd_opt
61 logical, intent (in) :: do_ugwp
62
63 character(len=*), intent (in) :: fn_nml2
64 !character(len=*), parameter :: fn_nml='input.nml'
65
66 character(len=*), intent(out) :: errmsg
67 integer, intent(out) :: errflg
68
69 ! Initialize CCPP error handling variables
70 errmsg = ''
71 errflg = 0
72
73 if (is_initialized) return
74
75 ! Consistency checks
76 if (gwd_opt/=1) then
77 write(errmsg,'(*(a))') "Logic error: namelist choice of gravity wave &
78 & drag is different from cires_ugwp scheme"
79 errflg = 1
80 return
81 end if
82
83 if (do_ugwp .or. cdmbgwd(3) > 0.0) then
84 call cires_ugwpv0_mod_init (me, master, nlunit, input_nml_file, logunit, &
85 fn_nml2, lonr, levs, ak, bk, con_p0, dtp, &
86 cdmbgwd(1:2), cgwf, pa_rf_in, tau_rf_in, &
87 errmsg, errflg)
88 if (errflg/=0) return
89 else
90 write(errmsg,'(*(a))') "Logic error: cires_ugwp_init called but do_ugwp is false and cdmbgwd(3) <= 0"
91 errflg = 1
92 return
93 end if
94
95 if (.not.knob_ugwp_version==0) then
96 write(errmsg,'(*(a))') 'Logic error: CCPP only supports version zero of UGWP'
97 errflg = 1
98 return
99 end if
100
101 is_initialized = .true.
102
103 end subroutine cires_ugwp_init
104
105! -----------------------------------------------------------------------
106! finalize of cires_ugwp (_finalize)
107! -----------------------------------------------------------------------
108
110#if 0
111
114#endif
115 subroutine cires_ugwp_finalize(errmsg, errflg)
116
117 implicit none
118!
119 character(len=*), intent(out) :: errmsg
120 integer, intent(out) :: errflg
121
122! Initialize CCPP error handling variables
123 errmsg = ''
124 errflg = 0
125
126 if (.not.is_initialized) return
127
128 call cires_ugwpv0_mod_finalize()
129
130 is_initialized = .false.
131
132 end subroutine cires_ugwp_finalize
133
134! -----------------------------------------------------------------------
135! originally from ugwp_driver_v0.f
136! driver of cires_ugwp (_driver)
137! -----------------------------------------------------------------------
138! driver is called after pbl & before chem-parameterizations
139! -----------------------------------------------------------------------
140! order = dry-adj=>conv=mp-aero=>radiation -sfc/land- chem -> vertdiff-> [rf-gws]=> ion-re
141! -----------------------------------------------------------------------
188! \section det_cires_ugwp CIRES UGWP V0 Scheme Detailed Algorithm
189 subroutine cires_ugwp_run(do_ugwp, me, master, im, levs, ntrac, dtp, kdt, lonr, &
190 oro, oro_uf, hprime, nmtvr, oc, theta, sigma, gamma, elvmax, clx, oa4, &
191 do_tofd, ldiag_ugwp, cdmbgwd, xlat, xlat_d, sinlat, coslat, &
192 area, ugrs, vgrs, tgrs, qgrs, prsi, prsl, prslk, phii, phil, &
193 del, kpbl, dusfcg, dvsfcg, gw_dudt, gw_dvdt, gw_dtdt, gw_kdis, &
194 tau_tofd, tau_mtb, tau_ogw, tau_ngw, zmtb, zlwb, zogw, &
195 dusfc_ms, dvsfc_ms, dusfc_bl, dvsfc_bl, &
196 dudt_ogw, dtauy2d_ms, dtaux2d_bl, dtauy2d_bl, &
197 dudt_mtb, dudt_tms, du3dt_mtb, du3dt_ogw, du3dt_tms, &
198 dudt, dvdt, dtdt, rdxzb, con_g, con_pi, con_cp, con_rd, con_rv, con_fvirt, &
199 con_omega, rain, ntke, q_tke, dqdt_tke, lprnt, ipr, &
200 dtend, dtidx, index_of_x_wind, index_of_y_wind, index_of_temperature, &
201 index_of_process_orographic_gwd, index_of_process_nonorographic_gwd, &
202 ldiag3d, lssav, flag_for_gwd_generic_tend, errmsg, errflg)
203
204 implicit none
205
206 ! interface variables
207 integer, intent(in) :: me, master, im, levs, ntrac, kdt, lonr, nmtvr
208 integer, intent(in), dimension(:) :: kpbl
209 real(kind=kind_phys), intent(in), dimension(:) :: oro, oro_uf, hprime, oc, theta, sigma, gamma
210 logical, intent(in) :: flag_for_gwd_generic_tend
211 ! elvmax is intent(in) for CIRES UGWP, but intent(inout) for GFS GWDPS
212 real(kind=kind_phys), intent(inout), dimension(:) :: elvmax
213 real(kind=kind_phys), intent(in), dimension(:, :) :: clx, oa4
214 real(kind=kind_phys), intent(in), dimension(:) :: xlat, xlat_d, sinlat, coslat, area
215 real(kind=kind_phys), intent(in), dimension(:, :) :: del, ugrs, vgrs, tgrs, prsl, prslk, phil
216 real(kind=kind_phys), intent(in), dimension(:, :) :: prsi, phii
217 real(kind=kind_phys), intent(in), dimension(:,:,:):: qgrs
218 real(kind=kind_phys), intent(in) :: dtp, cdmbgwd(:)
219 logical, intent(in) :: do_ugwp, do_tofd, ldiag_ugwp
220
221 real(kind=kind_phys), intent(out), dimension(:) :: dusfcg, dvsfcg
222 real(kind=kind_phys), intent(out), dimension(:) :: zmtb, zlwb, zogw, rdxzb
223 real(kind=kind_phys), intent(out), dimension(:) :: tau_mtb, tau_ogw, tau_tofd, tau_ngw
224 real(kind=kind_phys), intent(out), dimension(:, :):: gw_dudt, gw_dvdt, gw_dtdt, gw_kdis
225 real(kind=kind_phys), intent(out), dimension(:, :):: dudt_mtb, dudt_tms
226 real(kind=kind_phys), intent(out), dimension(:, :), optional :: dudt_ogw
227 real(kind=kind_phys), intent(out), dimension(:), optional :: dusfc_ms, dvsfc_ms, dusfc_bl, dvsfc_bl
228 real(kind=kind_phys), intent(out), dimension(:, :), optional :: dtauy2d_ms
229 real(kind=kind_phys), intent(out), dimension(:, :), optional :: dtaux2d_bl, dtauy2d_bl
230
231 ! dtend is only allocated if ldiag=.true.
232 real(kind=kind_phys), optional, intent(inout) :: dtend(:,:,:)
233 integer, intent(in) :: dtidx(:,:), &
234 index_of_x_wind, index_of_y_wind, index_of_temperature, &
235 index_of_process_orographic_gwd, index_of_process_nonorographic_gwd
236
237 logical, intent(in) :: ldiag3d, lssav
238
239 ! These arrays only allocated if ldiag_ugwp = .true.
240 real(kind=kind_phys), intent(inout), dimension(:,:), optional :: du3dt_mtb, du3dt_ogw, du3dt_tms
241
242 real(kind=kind_phys), intent(inout), dimension(:, :):: dudt, dvdt, dtdt
243
244 real(kind=kind_phys), intent(in) :: con_g, con_pi, con_cp, con_rd, con_rv, con_fvirt, con_omega
245
246 real(kind=kind_phys), intent(in), dimension(:) :: rain
247
248 integer, intent(in) :: ntke
249 real(kind=kind_phys), intent(in), dimension(:,:) :: q_tke, dqdt_tke
250
251 logical, intent(in) :: lprnt
252 integer, intent(in) :: ipr
253
254 character(len=*), intent(out) :: errmsg
255 integer, intent(out) :: errflg
256
257 ! local variables
258 integer :: i, k, idtend
259 real(kind=kind_phys), dimension(im) :: sgh30
260 real(kind=kind_phys), dimension(im, levs) :: pdvdt, pdudt
261 real(kind=kind_phys), dimension(im, levs) :: pdtdt, pkdis
262 real(kind=kind_phys), dimension(im, levs) :: ed_dudt, ed_dvdt, ed_dtdt
263 ! from ugwp_driver_v0.f -> cires_ugwp_initialize.F90 -> module ugwp_wmsdis_init
264 real(kind=kind_phys), parameter :: tamp_mpa=30.e-3
265 ! switches that activate impact of OGWs and NGWs (WL* how to deal with them? *WL)
266 real(kind=kind_phys), parameter :: pogw=1., pngw=1., pked=1.
267
268 real(kind=kind_phys), dimension(:,:), allocatable :: tke
269 real(kind=kind_phys), dimension(:), allocatable :: turb_fac, tem
270 real(kind=kind_phys) :: rfac, tx1
271
272 ! Initialize CCPP error handling variables
273 errmsg = ''
274 errflg = 0
275
276 ! 1) ORO stationary GWs
277 ! ------------------
278 ! wrap everything in a do_ugwp 'if test' in order not to break the namelist functionality
279 if (do_ugwp) then ! calling revised old GFS gravity wave drag
280
281 ! topo paras
282 ! w/ orographic effects
283 if(nmtvr == 14)then
284 ! calculate sgh30 for TOFD
285 sgh30 = abs(oro - oro_uf)
286 ! w/o orographic effects
287 else
288 sgh30 = 0.
289 endif
290
291 zlwb(:) = 0.
292
293 call gwdps_v0(im, levs, lonr, do_tofd, pdvdt, pdudt, pdtdt, pkdis, &
294 ugrs, vgrs, tgrs, qgrs(:,:,1), kpbl, prsi,del,prsl, prslk, phii, phil, &
295 dtp, kdt, sgh30, hprime, oc, oa4, clx, theta, sigma, gamma, elvmax, &
296 dusfcg, dvsfcg, xlat_d, sinlat, coslat, area, cdmbgwd(1:2), &
297 me, master, rdxzb, con_g, con_omega, zmtb, zogw, tau_mtb, tau_ogw, &
298 tau_tofd, dudt_mtb, dudt_ogw, dudt_tms)
299
300 else ! calling old GFS gravity wave drag as is
301
302 do k=1,levs
303 do i=1,im
304 pdvdt(i,k) = 0.0
305 pdudt(i,k) = 0.0
306 pdtdt(i,k) = 0.0
307 pkdis(i,k) = 0.0
308 enddo
309 enddo
310
311 if (cdmbgwd(1) > 0.0 .or. cdmbgwd(2) > 0.0) then
312 call gwdps_run(im, levs, pdvdt, pdudt, pdtdt, &
313 ugrs, vgrs, tgrs, qgrs(:,:,1), &
314 kpbl, prsi, del, prsl, prslk, phii, phil, dtp, kdt, &
315 hprime, oc, oa4, clx, theta, sigma, gamma, &
316 elvmax, dusfcg, dvsfcg, dudt_ogw, dtauy2d_ms, &
317 dtaux2d_bl, dtauy2d_bl, dusfc_ms, dvsfc_ms, &
318 dusfc_bl, dvsfc_bl, &
319 con_g, con_cp, con_rd, con_rv, lonr, &
320 nmtvr, cdmbgwd, me, lprnt, ipr, rdxzb, ldiag_ugwp, &
321 errmsg, errflg)
322 if (errflg/=0) return
323 endif
324
325 tau_mtb = 0.0 ; tau_ogw = 0.0 ; tau_tofd = 0.0
326 if (ldiag_ugwp) then
327 du3dt_mtb = 0.0 ; du3dt_ogw = 0.0 ; du3dt_tms= 0.0
328 endif
329
330 endif ! do_ugwp
331
332 if(ldiag3d .and. lssav .and. .not. flag_for_gwd_generic_tend) then
333 idtend = dtidx(index_of_x_wind,index_of_process_orographic_gwd)
334 if(idtend>=1) then
335 dtend(:,:,idtend) = dtend(:,:,idtend) + pdudt*dtp
336 endif
337 idtend = dtidx(index_of_y_wind,index_of_process_orographic_gwd)
338 if(idtend>=1) then
339 dtend(:,:,idtend) = dtend(:,:,idtend) + pdvdt*dtp
340 endif
341 idtend = dtidx(index_of_temperature,index_of_process_orographic_gwd)
342 if(idtend>=1) then
343 dtend(:,:,idtend) = dtend(:,:,idtend) + pdtdt*dtp
344 endif
345 endif
346
347 if (cdmbgwd(3) > 0.0) then
348
349 ! 2) non-stationary GW-scheme with GMAO/MERRA GW-forcing
350 call slat_geos5_tamp_v0(im, tamp_mpa, xlat_d, tau_ngw)
351
352 if (abs(1.0-cdmbgwd(3)) > 1.0e-6) then
353 if (cdmbgwd(4) > 0.0) then
354 allocate(turb_fac(im))
355 do i=1,im
356 turb_fac(i) = 0.0
357 enddo
358 if (ntke > 0) then
359 allocate(tke(im,levs))
360 allocate(tem(im))
361 tke(:,:) = q_tke(:,:) + dqdt_tke(:,:) * dtp
362 tem(:) = 0.0
363 do k=1,(levs+levs)/3
364 do i=1,im
365 turb_fac(i) = turb_fac(i) + del(i,k) * tke(i,k)
366 tem(i) = tem(i) + del(i,k)
367 enddo
368 enddo
369 do i=1,im
370 turb_fac(i) = turb_fac(i) / tem(i)
371 enddo
372 deallocate(tke)
373 deallocate(tem)
374 endif
375 rfac = 86400000 / dtp
376 do i=1,im
377 tx1 = cdmbgwd(4)*min(10.0, max(turb_fac(i),rain(i)*rfac))
378 tau_ngw(i) = tau_ngw(i) * max(0.1, min(5.0, tx1))
379 enddo
380 deallocate(turb_fac)
381 endif
382 do i=1,im
383 tau_ngw(i) = tau_ngw(i) * cdmbgwd(3)
384 enddo
385 endif
386
387 call fv3_ugwp_solv2_v0(im, levs, dtp, tgrs, ugrs, vgrs,qgrs(:,:,1), &
388 prsl, prsi, phil, xlat_d, sinlat, coslat, &
389 gw_dudt, gw_dvdt, gw_dtdt, gw_kdis, tau_ngw, &
390 me, master, kdt)
391
392 do k=1,levs
393 do i=1,im
394 gw_dtdt(i,k) = pngw*gw_dtdt(i,k) + pogw*pdtdt(i,k)
395 gw_dudt(i,k) = pngw*gw_dudt(i,k) + pogw*pdudt(i,k)
396 gw_dvdt(i,k) = pngw*gw_dvdt(i,k) + pogw*pdvdt(i,k)
397 gw_kdis(i,k) = pngw*gw_kdis(i,k) + pogw*pkdis(i,k)
398 ! accumulation of tendencies for CCPP to replicate EMC-physics updates (!! removed in latest code commit to VLAB)
399 !dudt(i,k) = dudt(i,k) + gw_dudt(i,k)
400 !dvdt(i,k) = dvdt(i,k) + gw_dvdt(i,k)
401 !dtdt(i,k) = dtdt(i,k) + gw_dtdt(i,k)
402 enddo
403 enddo
404
405 else
406
407 do k=1,levs
408 do i=1,im
409 gw_dtdt(i,k) = pdtdt(i,k)
410 gw_dudt(i,k) = pdudt(i,k)
411 gw_dvdt(i,k) = pdvdt(i,k)
412 gw_kdis(i,k) = pkdis(i,k)
413 enddo
414 enddo
415
416 endif
417
418 if (pogw == 0.0) then
419 tau_mtb = 0. ; tau_ogw = 0. ; tau_tofd = 0.
420 dudt_mtb = 0. ; dudt_ogw = 0. ; dudt_tms = 0.
421 endif
422
423 if(ldiag3d .and. lssav .and. .not. flag_for_gwd_generic_tend) then
424 idtend = dtidx(index_of_x_wind,index_of_process_nonorographic_gwd)
425 if(idtend>=1) then
426 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dudt - pdudt)*dtp
427 endif
428 idtend = dtidx(index_of_y_wind,index_of_process_nonorographic_gwd)
429 if(idtend>=1) then
430 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dvdt - pdvdt)*dtp
431 endif
432 idtend = dtidx(index_of_temperature,index_of_process_nonorographic_gwd)
433 if(idtend>=1) then
434 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dtdt - pdtdt)*dtp
435 endif
436 endif
437
438 end subroutine cires_ugwp_run
439end module cires_ugwp
subroutine gwdps_run(im, km, a, b, c, u1, v1, t1, q1, kpbl, prsi, del, prsl, prslk, phii, phil, deltim, kdt, hprime, oc, oa4, clx4, theta, sigma, gamma, elvmax, dusfc, dvsfc, dtaux2d_ms, dtauy2d_ms, dtaux2d_bl, dtauy2d_bl, dusfc_ms, dvsfc_ms, dusfc_bl, dvsfc_bl, g, cp, rd, rv, imx, nmtvr, cdmbgwd, me, lprnt, ipr, rdxzb, ldiag_ugwp, errmsg, errflg)
Definition gwdps.f:203
This module contains routines describing the the latitudinal shape of vertical momentum flux function...
This module contains the UGWP v0 scheme by Valery Yudin (University of Colorado, CIRES)
This module contains the UGWPv0 driver.
This module contains the CCPP-compliant orographic gravity wave dray scheme. This version of gwdps is...
Definition gwdps.f:7
This module contains the UGWP v0 driver module.