← Back to Documentation Home
CCPP SciDoc v8.0.0  v8.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_final
21 use gwdps, only: gwdps_run
23
24 implicit none
25
26 private
27
28 public cires_ugwp_init, cires_ugwp_run, cires_ugwp_final
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 (_final)
107! -----------------------------------------------------------------------
108
110#if 0
111
114#endif
115 subroutine cires_ugwp_final(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_final()
129
130 is_initialized = .false.
131
132 end subroutine cires_ugwp_final
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 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, ten_q, 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(in) :: con_g, con_pi, con_cp, con_rd, con_rv, con_fvirt, con_omega
243
244 real(kind=kind_phys), intent(in), dimension(:) :: rain
245
246 integer, intent(in) :: ntke
247 real(kind=kind_phys), intent(in), dimension(:,:), optional :: q_tke, dqdt_tke
248
249 logical, intent(in) :: lprnt
250 integer, intent(in) :: ipr
251
252 real(kind=kind_phys), intent(out) :: ten_q(:,:,:)
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 ten_q = 0.0
277
278 ! 1) ORO stationary GWs
279 ! ------------------
280 ! wrap everything in a do_ugwp 'if test' in order not to break the namelist functionality
281 if (do_ugwp) then ! calling revised old GFS gravity wave drag
282
283 ! topo paras
284 ! w/ orographic effects
285 if(nmtvr == 14)then
286 ! calculate sgh30 for TOFD
287 sgh30 = abs(oro - oro_uf)
288 ! w/o orographic effects
289 else
290 sgh30 = 0.
291 endif
292
293 zlwb(:) = 0.
294
295 call gwdps_v0(im, levs, lonr, do_tofd, pdvdt, pdudt, pdtdt, pkdis, &
296 ugrs, vgrs, tgrs, qgrs(:,:,1), kpbl, prsi,del,prsl, prslk, phii, phil, &
297 dtp, kdt, sgh30, hprime, oc, oa4, clx, theta, sigma, gamma, elvmax, &
298 dusfcg, dvsfcg, xlat_d, sinlat, coslat, area, cdmbgwd(1:2), &
299 me, master, rdxzb, zmtb, zogw, tau_mtb, tau_ogw, &
300 tau_tofd, dudt_mtb, dudt_ogw, dudt_tms, &
301 errmsg, errflg)
302
303 else ! calling old GFS gravity wave drag as is
304
305 do k=1,levs
306 do i=1,im
307 pdvdt(i,k) = 0.0
308 pdudt(i,k) = 0.0
309 pdtdt(i,k) = 0.0
310 pkdis(i,k) = 0.0
311 enddo
312 enddo
313
314 if (cdmbgwd(1) > 0.0 .or. cdmbgwd(2) > 0.0) then
315 call gwdps_run(im, levs, pdvdt, pdudt, pdtdt, ten_q, &
316 ugrs, vgrs, tgrs, qgrs(:,:,1), &
317 kpbl, prsi, del, prsl, prslk, phii, phil, dtp, kdt, &
318 hprime, oc, oa4, clx, theta, sigma, gamma, &
319 elvmax, dusfcg, dvsfcg, dudt_ogw, dtauy2d_ms, &
320 dtaux2d_bl, dtauy2d_bl, dusfc_ms, dvsfc_ms, &
321 dusfc_bl, dvsfc_bl, &
322 con_g, con_cp, con_rd, con_rv, lonr, &
323 nmtvr, cdmbgwd, me, lprnt, ipr, rdxzb, ldiag_ugwp, &
324 errmsg, errflg)
325 if (errflg/=0) return
326 endif
327
328 tau_mtb = 0.0 ; tau_ogw = 0.0 ; tau_tofd = 0.0
329 if (ldiag_ugwp) then
330 du3dt_mtb = 0.0 ; du3dt_ogw = 0.0 ; du3dt_tms= 0.0
331 endif
332
333 endif ! do_ugwp
334
335 if(ldiag3d .and. lssav .and. .not. flag_for_gwd_generic_tend) then
336 idtend = dtidx(index_of_x_wind,index_of_process_orographic_gwd)
337 if(idtend>=1) then
338 dtend(:,:,idtend) = dtend(:,:,idtend) + pdudt*dtp
339 endif
340 idtend = dtidx(index_of_y_wind,index_of_process_orographic_gwd)
341 if(idtend>=1) then
342 dtend(:,:,idtend) = dtend(:,:,idtend) + pdvdt*dtp
343 endif
344 idtend = dtidx(index_of_temperature,index_of_process_orographic_gwd)
345 if(idtend>=1) then
346 dtend(:,:,idtend) = dtend(:,:,idtend) + pdtdt*dtp
347 endif
348 endif
349
350 if (cdmbgwd(3) > 0.0) then
351
352 ! 2) non-stationary GW-scheme with GMAO/MERRA GW-forcing
353 call slat_geos5_tamp_v0(im, tamp_mpa, xlat_d, tau_ngw)
354
355 if (abs(1.0-cdmbgwd(3)) > 1.0e-6) then
356 if (cdmbgwd(4) > 0.0) then
357 allocate(turb_fac(im))
358 do i=1,im
359 turb_fac(i) = 0.0
360 enddo
361 if (ntke > 0) then
362 allocate(tke(im,levs))
363 allocate(tem(im))
364 tke(:,:) = q_tke(:,:) + dqdt_tke(:,:) * dtp
365 tem(:) = 0.0
366 do k=1,(levs+levs)/3
367 do i=1,im
368 turb_fac(i) = turb_fac(i) + del(i,k) * tke(i,k)
369 tem(i) = tem(i) + del(i,k)
370 enddo
371 enddo
372 do i=1,im
373 turb_fac(i) = turb_fac(i) / tem(i)
374 enddo
375 deallocate(tke)
376 deallocate(tem)
377 endif
378 rfac = 86400000 / dtp
379 do i=1,im
380 tx1 = cdmbgwd(4)*min(10.0, max(turb_fac(i),rain(i)*rfac))
381 tau_ngw(i) = tau_ngw(i) * max(0.1, min(5.0, tx1))
382 enddo
383 deallocate(turb_fac)
384 endif
385 do i=1,im
386 tau_ngw(i) = tau_ngw(i) * cdmbgwd(3)
387 enddo
388 endif
389
390 call fv3_ugwp_solv2_v0(im, levs, dtp, tgrs, ugrs, vgrs,qgrs(:,:,1), &
391 prsl, prsi, phil, xlat_d, sinlat, coslat, &
392 gw_dudt, gw_dvdt, gw_dtdt, gw_kdis, tau_ngw, &
393 me, master, kdt)
394
395 do k=1,levs
396 do i=1,im
397 gw_dtdt(i,k) = pngw*gw_dtdt(i,k) + pogw*pdtdt(i,k)
398 gw_dudt(i,k) = pngw*gw_dudt(i,k) + pogw*pdudt(i,k)
399 gw_dvdt(i,k) = pngw*gw_dvdt(i,k) + pogw*pdvdt(i,k)
400 gw_kdis(i,k) = pngw*gw_kdis(i,k) + pogw*pkdis(i,k)
401 enddo
402 enddo
403
404 else
405
406 do k=1,levs
407 do i=1,im
408 gw_dtdt(i,k) = pdtdt(i,k)
409 gw_dudt(i,k) = pdudt(i,k)
410 gw_dvdt(i,k) = pdvdt(i,k)
411 gw_kdis(i,k) = pkdis(i,k)
412 enddo
413 enddo
414
415 endif
416
417 if (pogw == 0.0) then
418 tau_mtb = 0. ; tau_ogw = 0. ; tau_tofd = 0.
419 dudt_mtb = 0. ; dudt_ogw = 0. ; dudt_tms = 0.
420 endif
421
422 if(ldiag3d .and. lssav .and. .not. flag_for_gwd_generic_tend) then
423 idtend = dtidx(index_of_x_wind,index_of_process_nonorographic_gwd)
424 if(idtend>=1) then
425 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dudt - pdudt)*dtp
426 endif
427 idtend = dtidx(index_of_y_wind,index_of_process_nonorographic_gwd)
428 if(idtend>=1) then
429 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dvdt - pdvdt)*dtp
430 endif
431 idtend = dtidx(index_of_temperature,index_of_process_nonorographic_gwd)
432 if(idtend>=1) then
433 dtend(:,:,idtend) = dtend(:,:,idtend) + (gw_dtdt - pdtdt)*dtp
434 endif
435 endif
436
437 end subroutine cires_ugwp_run
438end module cires_ugwp
subroutine gwdps_run(im, km, a, b, c, ten_q, 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.