1 !WRF:model_layer:physics
6 module module_bl_gwdo_gsl
8 !-------------------------------------------------------------------------------
9 subroutine gwdo_gsl(u3d,v3d,t3d,qv3d,p3d,p3di,pi3d,z, &
10 rublten,rvblten,rthblten, &
11 dtaux3d_ls,dtauy3d_ls,dtaux3d_bl,dtauy3d_bl, &
12 dtaux3d_ss,dtauy3d_ss,dtaux3d_fd,dtauy3d_fd, &
13 dusfcg_ls,dvsfcg_ls,dusfcg_bl,dvsfcg_bl,dusfcg_ss,dvsfcg_ss, &
14 dusfcg_fd,dvsfcg_fd,xland,br, &
15 var2d,oc12d,oa2d1,oa2d2,oa2d3,oa2d4,ol2d1,ol2d2,ol2d3,ol2d4, &
17 oa2d1ss,oa2d2ss,oa2d3ss,oa2d4ss, &
18 ol2d1ss,ol2d2ss,ol2d3ss,ol2d4ss, &
19 sina,cosa,znu,znw,p_top,dz,pblh, &
21 dt,dx,kpbl2d,itimestep,gwd_opt,gwd_diags, &
22 spp_pbl,pattern_spp_pbl, &
23 ids,ide, jds,jde, kds,kde, &
24 ims,ime, jms,jme, kms,kme, &
25 its,ite, jts,jte, kts,kte)
26 !-------------------------------------------------------------------------------
28 !-------------------------------------------------------------------------------
30 !-- u3d 3d u-velocity interpolated to theta points (m/s)
31 !-- v3d 3d v-velocity interpolated to theta points (m/s)
32 !-- t3d temperature (k)
33 !-- qv3d 3d water vapor mixing ratio (kg/kg)
34 !-- p3d 3d pressure (pa)
35 !-- p3di 3d pressure (pa) at interface level
36 !-- pi3d 3d exner function (dimensionless)
37 !-- rublten u tendency due to pbl parameterization (m/s/s)
38 !-- rvblten v tendency due to pbl parameterization (m/s/s)
39 !-- rthblten theta tendency due to pbl parameterization (K/s)
40 !-- sina sine rotation angle
41 !-- cosa cosine rotation angle
42 !-- znu eta values (sigma values)
43 !-- cp heat capacity at constant pressure for dry air (j/kg/k)
44 !-- g acceleration due to gravity (m/s^2)
45 !-- rd gas constant for dry air (j/kg/k)
46 !-- z height above sea level (m)
47 !-- rv gas constant for water vapor (j/kg/k)
49 !-- dx model grid interval (m)
50 !-- dz height of model layers (m)
51 !-- xland land mask (1 for land, 2 for water)
52 !-- br bulk richardson number in surface layer
53 !-- pblh planetary boundary layer height (m)
54 !-- ep1 constant for virtual temperature (r_v/r_d - 1) (dimensionless)
55 !-- ids start index for i in domain
56 !-- ide end index for i in domain
57 !-- jds start index for j in domain
58 !-- jde end index for j in domain
59 !-- kds start index for k in domain
60 !-- kde end index for k in domain
61 !-- ims start index for i in memory
62 !-- ime end index for i in memory
63 !-- jms start index for j in memory
64 !-- jme end index for j in memory
65 !-- kms start index for k in memory
66 !-- kme end index for k in memory
67 !-- its start index for i in tile
68 !-- ite end index for i in tile
69 !-- jts start index for j in tile
70 !-- jte end index for j in tile
71 !-- kts start index for k in tile
72 !-- kte end index for k in tile
74 !-------------------------------------------------------------------------------
75 integer, intent(in ) :: ids,ide, jds,jde, kds,kde, &
76 ims,ime, jms,jme, kms,kme, &
77 its,ite, jts,jte, kts,kte
78 integer, intent(in ) :: itimestep,gwd_opt,gwd_diags
80 real, intent(in ) :: dt,dx,cp,g,rd,rv,ep1,pi
82 real, dimension( ims:ime, kms:kme, jms:jme ) , &
83 intent(in ) :: qv3d, &
89 real, dimension( ims:ime, kms:kme, jms:jme ) , &
92 real, dimension( ims:ime, kms:kme, jms:jme ) , &
93 intent(inout) :: rublten, &
96 real, dimension( ims:ime, kms:kme, jms:jme ), optional , &
97 intent(inout) :: dtaux3d_ls,dtauy3d_ls,dtaux3d_bl,dtauy3d_bl, &
98 dtaux3d_ss,dtauy3d_ss,dtaux3d_fd,dtauy3d_fd
100 real, dimension( ims:ime, kms:kme) :: &
101 dtaux2d_ls,dtauy2d_ls,dtaux2d_bl,dtauy2d_bl, &
102 dtaux2d_ss,dtauy2d_ss,dtaux2d_fd,dtauy2d_fd
104 real, dimension( ims:ime, kms:kme, jms:jme ) , &
105 intent(in ) :: u3d, &
108 integer, dimension( ims:ime, jms:jme ) , &
109 intent(in ) :: kpbl2d
111 real, dimension( ims:ime, jms:jme ) , &
112 intent(in ) :: pblh, &
116 real, dimension( ims:ime, jms:jme ), optional , &
117 intent(inout ) :: dusfcg_ls,dvsfcg_ls,dusfcg_bl,dvsfcg_bl, &
118 dusfcg_ss,dvsfcg_ss,dusfcg_fd,dvsfcg_fd
120 real, dimension( ims:ime ) :: dusfc_ls,dvsfc_ls,dusfc_bl,dvsfc_bl, &
121 dusfc_ss,dvsfc_ss,dusfc_fd,dvsfc_fd
123 real, dimension( ims:ime, jms:jme ) , &
124 intent(in ) :: var2d, &
126 oa2d1,oa2d2,oa2d3,oa2d4, &
127 ol2d1,ol2d2,ol2d3,ol2d4, &
128 ! additional topographic statistics based on 1km orographic dataset
129 ! for small-scale orographic drag schemes
131 oa2d1ss,oa2d2ss,oa2d3ss,oa2d4ss, &
132 ol2d1ss,ol2d2ss,ol2d3ss,ol2d4ss, &
133 ! info for converting velocities to/from zonal and meridional components
136 real, dimension( kms:kme ) , &
138 intent(in ) :: znu, &
141 real, optional, intent(in ) :: p_top
144 INTEGER, INTENT(IN) ::spp_pbl
145 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(IN),OPTIONAL ::pattern_spp_pbl
146 REAL, DIMENSION(ITS:ITE) :: rstoch1D
151 real, dimension( its:ite, kts:kte ) :: delprsi, &
153 real, dimension( its:ite, kts:kte+1 ) :: pdhi
154 real, dimension( its:ite, 4 ) :: oa4, &
158 real, dimension( its:ite, kts:kte ) :: ugeo, vgeo, dudt, dvdt
160 integer :: i,j,k,kdt,kpblmax
163 if(znu(k).gt.0.6) kpblmax = k + 1
170 if(k.le.kte)pdh(i,k) = p3d(i,k,j)
171 pdhi(i,k) = p3di(i,k,j)
177 delprsi(i,k) = pdhi(i,k)-pdhi(i,k+1)
178 ! rotate winds to zonal/meridional
179 ugeo(i,k) = u3d(i,k,j)*cosa(i,j) - v3d(i,k,j)*sina(i,j)
180 vgeo(i,k) = u3d(i,k,j)*sina(i,j) + v3d(i,k,j)*cosa(i,j)
189 rstoch1D(i)=pattern_spp_pbl(i,kts,j)
198 oa4(i,1) = oa2d1(i,j)
199 oa4(i,2) = oa2d2(i,j)
200 oa4(i,3) = oa2d3(i,j)
201 oa4(i,4) = oa2d4(i,j)
202 ol4(i,1) = ol2d1(i,j)
203 ol4(i,2) = ol2d2(i,j)
204 ol4(i,3) = ol2d3(i,j)
205 ol4(i,4) = ol2d4(i,j)
206 oa4ss(i,1) = oa2d1ss(i,j)
207 oa4ss(i,2) = oa2d2ss(i,j)
208 oa4ss(i,3) = oa2d3ss(i,j)
209 oa4ss(i,4) = oa2d4ss(i,j)
210 ol4ss(i,1) = ol2d1ss(i,j)
211 ol4ss(i,2) = ol2d2ss(i,j)
212 ol4ss(i,3) = ol2d3ss(i,j)
213 ol4ss(i,4) = ol2d4ss(i,j)
215 call gwdo2d(dudt=dudt(its,kts),dvdt=dvdt(its,kts) &
216 ,dthdt=rthblten(ims,kms,j) &
217 ,dtaux2d_ls=dtaux2d_ls,dtauy2d_ls=dtauy2d_ls &
218 ,dtaux2d_bl=dtaux2d_bl,dtauy2d_bl=dtauy2d_bl &
219 ,dtaux2d_ss=dtaux2d_ss,dtauy2d_ss=dtauy2d_ss &
220 ,dtaux2d_fd=dtaux2d_fd,dtauy2d_fd=dtauy2d_fd &
221 ,u1=ugeo(its,kts),v1=vgeo(its,kts) &
222 ,t1=t3d(ims,kms,j),q1=qv3d(ims,kms,j) &
223 ,del=delprsi(its,kts) &
224 ,prsi=pdhi(its,kts) &
225 ,prsl=pdh(its,kts),prslk=pi3d(ims,kms,j) &
226 ,zl=z(ims,kms,j),rcl=1.0 &
227 ,xland1=xland(ims,j),br1=br(ims,j),hpbl=pblh(ims,j) &
230 ,dusfc_ls=dusfc_ls,dvsfc_ls=dvsfc_ls &
231 ,dusfc_bl=dusfc_bl,dvsfc_bl=dvsfc_bl &
232 ,dusfc_ss=dusfc_ss,dvsfc_ss=dvsfc_ss &
233 ,dusfc_fd=dusfc_fd,dvsfc_fd=dvsfc_fd &
234 ,var=var2d(ims,j),oc1=oc12d(ims,j) &
236 ,varss=var2dss(ims,j),oc1ss=oc12dss(ims,j) &
237 ,oa4ss=oa4ss,ol4ss=ol4ss &
238 ,g=g,cp=cp,rd=rd,rv=rv,fv=ep1,pi=pi &
239 ,dxmeter=dx,deltim=dt &
240 ,kpbl=kpbl2d(ims,j),kdt=itimestep,lat=j &
242 ,ids=ids,ide=ide, jds=jds,jde=jde, kds=kds,kde=kde &
243 ,ims=ims,ime=ime, jms=jms,jme=jme, kms=kms,kme=kme &
244 ,its=its,ite=ite, jts=jts,jte=jte, kts=kts,kte=kte )
248 ! rotate tendencies from zonal/meridional to model grid
249 rublten(i,k,j) = rublten(i,k,j)+dudt(i,k)*cosa(i,j) + dvdt(i,k)*sina(i,j)
250 rvblten(i,k,j) = rvblten(i,k,j)-dudt(i,k)*sina(i,j) + dvdt(i,k)*cosa(i,j)
255 IF (gwd_diags == 1) then !research mode
258 ! rotate tendencies from zonal/meridional to model grid
259 dtaux3d_ls(i,k,j)=dtaux2d_ls(i,k)*cosa(i,j)+dtauy2d_ls(i,k)*sina(i,j)
260 dtaux3d_bl(i,k,j)=dtaux2d_bl(i,k)*cosa(i,j)+dtauy2d_bl(i,k)*sina(i,j)
261 dtaux3d_ss(i,k,j)=dtaux2d_ss(i,k)*cosa(i,j)+dtauy2d_ss(i,k)*sina(i,j)
262 dtaux3d_fd(i,k,j)=dtaux2d_fd(i,k)*cosa(i,j)+dtauy2d_fd(i,k)*sina(i,j)
263 dtauy3d_ls(i,k,j)=-dtaux2d_ls(i,k)*sina(i,j)+dtauy2d_ls(i,k)*cosa(i,j)
264 dtauy3d_bl(i,k,j)=-dtaux2d_bl(i,k)*sina(i,j)+dtauy2d_bl(i,k)*cosa(i,j)
265 dtauy3d_ss(i,k,j)=-dtaux2d_ss(i,k)*sina(i,j)+dtauy2d_ss(i,k)*cosa(i,j)
266 dtauy3d_fd(i,k,j)=-dtaux2d_fd(i,k)*sina(i,j)+dtauy2d_fd(i,k)*cosa(i,j)
270 ! rotate tendencies from zonal/meridional to model grid
271 dusfcg_ls(i,j)=dusfc_ls(i)*cosa(i,j)+dvsfc_ls(i)*sina(i,j)
272 dusfcg_bl(i,j)=dusfc_bl(i)*cosa(i,j)+dvsfc_bl(i)*sina(i,j)
273 dusfcg_ss(i,j)=dusfc_ss(i)*cosa(i,j)+dvsfc_ss(i)*sina(i,j)
274 dusfcg_fd(i,j)=dusfc_fd(i)*cosa(i,j)+dvsfc_fd(i)*sina(i,j)
275 dvsfcg_ls(i,j)=-dusfc_ls(i)*sina(i,j)+dvsfc_ls(i)*cosa(i,j)
276 dvsfcg_bl(i,j)=-dusfc_bl(i)*sina(i,j)+dvsfc_bl(i)*cosa(i,j)
277 dvsfcg_ss(i,j)=-dusfc_ss(i)*sina(i,j)+dvsfc_ss(i)*cosa(i,j)
278 dvsfcg_fd(i,j)=-dusfc_fd(i)*sina(i,j)+dvsfc_fd(i)*cosa(i,j)
284 end subroutine gwdo_gsl
285 !-------------------------------------------------------------------------------
287 !-------------------------------------------------------------------------------
288 subroutine gwdo2d(dudt,dvdt,dthdt,dtaux2d_ls,dtauy2d_ls, &
289 dtaux2d_bl,dtauy2d_bl,dtaux2d_ss,dtauy2d_ss, &
290 dtaux2d_fd,dtauy2d_fd,u1,v1,t1,q1, &
292 prsi,prsl,prslk,zl,rcl, &
293 xland1,br1,hpbl,dz2, &
294 kpblmax,dusfc_ls,dvsfc_ls,dusfc_bl,dvsfc_bl, &
295 dusfc_ss,dvsfc_ss,dusfc_fd,dvsfc_fd,var,oc1,oa4,ol4, &
296 varss,oc1ss,oa4ss,ol4ss, &
297 g,cp,rd,rv,fv,pi,dxmeter,deltim,kpbl,kdt,lat,rstoch, &
298 ids,ide, jds,jde, kds,kde, &
299 ims,ime, jms,jme, kms,kme, &
300 its,ite, jts,jte, kts,kte)
301 !-------------------------------------------------------------------------------
303 ! this code handles the time tendencies of u v due to the effect of mountain
304 ! induced gravity wave drag from sub-grid scale orography. this routine
305 ! not only treats the traditional upper-level wave breaking due to mountain
306 ! variance (alpert 1988), but also the enhanced lower-tropospheric wave
307 ! breaking due to mountain convexity and asymmetry (kim and arakawa 1995).
308 ! thus, in addition to the terrain height data in a model grid gox,
309 ! additional 10-2d topographic statistics files are needed, including
310 ! orographic standard deviation (var), convexity (oc1), asymmetry (oa4)
311 ! and ol (ol4). these data sets are prepared based on the 30 sec usgs orography
312 ! hong (1999). the current scheme was implmented as in hong et al.(2008)
314 ! coded by song-you hong and young-joon kim and implemented by song-you hong
316 ! program history log:
317 ! 2014-10-01 Hyun-Joo Choi (from KIAPS) flow-blocking drag of kim and doyle
318 ! with blocked height by dividing streamline theory
319 ! 2017-04-06 Joseph Olson (from Gert-Jan Steeneveld) added small-scale
320 ! orographic grabity wave drag:
321 ! 2017-09-15 Joseph Olson, with some bug fixes from Michael Toy: added the
322 ! topographic form drag of Beljaars et al. (2004, QJRMS)
323 ! Activation of each component is done by specifying the integer-parameters
324 ! (defined below) to 0: inactive or 1: active
325 ! gsl_gwd_ls = 0 or 1: large-scale
326 ! gsl_gwd_bl = 0 or 1: blocking drag
327 ! gsl_gwd_ss = 0 or 1: small-scale gravity wave drag
328 ! gsl_gwd_fd = 0 or 1: topographic form drag
329 ! 2017-09-25 Michael Toy (from NCEP GFS model) added dissipation heating
330 ! gsl_diss_ht_opt = 0: dissipation heating off
331 ! gsl_diss_ht_opt = 1: dissipation heating on
334 ! hong et al. (2008), wea. and forecasting
335 ! kim and doyle (2005), Q. J. R. Meteor. Soc.
336 ! kim and arakawa (1995), j. atmos. sci.
337 ! alpet et al. (1988), NWP conference.
338 ! hong (1999), NCEP office note 424.
339 ! steeneveld et al (2008), JAMC
340 ! Tsiringakis et al. (2017), Q. J. R. Meteor. Soc.
342 ! notice : comparible or lower resolution orography files than model resolution
343 ! are desirable in preprocess (wps) to prevent weakening of the drag
344 !-------------------------------------------------------------------------------
347 ! dudt (its:ite,kts:kte) non-lin tendency for u wind component
348 ! dvdt (its:ite,kts:kte) non-lin tendency for v wind component
349 ! u1(its:ite,kts:kte) zonal wind / sqrt(rcl) m/sec at t0-dt
350 ! v1(its:ite,kts:kte) meridional wind / sqrt(rcl) m/sec at t0-dt
351 ! t1(ims:ime,kms:kme) temperature deg k at t0-dt
352 ! q1(ims:ime,kms:kme) specific humidity at t0-dt
354 ! rcl a scaling factor = reciprocal of square of cos(lat)
355 ! for gmp. rcl=1 if u1 and v1 are wind components.
356 ! deltim time step secs
357 ! del(kts:kte) positive increment of pressure across layer (pa)
360 ! dudt, dvdt wind tendency due to gwdo
362 !-------------------------------------------------------------------------------
364 !-------------------------------------------------------------------------------
365 integer :: kdt,lat,latd,lond,kpblmax, &
366 ids,ide, jds,jde, kds,kde, &
367 ims,ime, jms,jme, kms,kme, &
368 its,ite, jts,jte, kts,kte
370 real :: g,rd,rv,fv,cp,pi,dxmeter,deltim,rcl
371 real :: dudt(its:ite,kts:kte),dvdt(its:ite,kts:kte), &
372 dthdt(ims:ime,kms:kme), &
373 dtaux2d_ls(ims:ime,kms:kme),dtauy2d_ls(ims:ime,kms:kme), &
374 dtaux2d_bl(ims:ime,kms:kme),dtauy2d_bl(ims:ime,kms:kme), &
375 dtaux2d_ss(ims:ime,kms:kme),dtauy2d_ss(ims:ime,kms:kme), &
376 dtaux2d_fd(ims:ime,kms:kme),dtauy2d_fd(ims:ime,kms:kme), &
377 t1(ims:ime,kms:kme),q1(ims:ime,kms:kme), &
378 zl(ims:ime,kms:kme),prsl(its:ite,kts:kte), &
379 prslk(ims:ime,kms:kme)
380 real :: u1(its:ite,kts:kte),v1(its:ite,kts:kte)
381 real :: prsi(its:ite,kts:kte+1),del(its:ite,kts:kte)
382 real :: oa4(its:ite,4),ol4(its:ite,4), &
383 oa4ss(its:ite,4),ol4ss(its:ite,4)
385 ! GSL surface drag options to regulate specific components
386 ! Each component is tapered off automatically as a function of dx, so best to
387 ! keep them activated (=1).
388 integer, parameter :: &
389 gsl_gwd_ls = 1, & ! large-scale gravity wave drag
390 gsl_gwd_bl = 1, & ! blocking drag
391 gsl_gwd_ss = 1, & ! small-scale gravity wave drag (Steeneveld et al. 2008)
392 gsl_gwd_fd = 1, & ! form drag (Beljaars et al. 2004, QJRMS)
395 ! added for small-scale orographic wave drag
396 real, dimension(its:ite,kts:kte) :: utendwave,vtendwave,thx,thvx,za
397 real, dimension(ims:ime), intent(in) :: br1,hpbl,xland1
398 real, dimension(its:ite) :: govrth
399 real, dimension(ims:ime,kms:kme), intent(in) :: dz2
400 real, dimension(its:ite,kts:kte+1) :: zq
401 real :: tauwavex0,tauwavey0,XNBV,density, &
403 integer :: kpbl2,kvar
405 real, dimension(its:ite) :: rstoch
406 real :: var_stoch(ims:ime), &
409 integer :: kpbl(ims:ime)
410 real :: var(ims:ime),oc1(ims:ime), &
411 varss(ims:ime),oc1ss(ims:ime), &
412 dusfc_ls(ims:ime),dvsfc_ls(ims:ime), &
413 dusfc_bl(ims:ime),dvsfc_bl(ims:ime), &
414 dusfc_ss(ims:ime),dvsfc_ss(ims:ime), &
415 dusfc_fd(ims:ime),dvsfc_fd(ims:ime)
416 ! Variables for scale-awareness:
417 ! Small-scale GWD + turbulent form drag
418 real, parameter :: dxmin_ss = 1000., dxmax_ss = 12000. ! min,max range of tapering (m)
420 real, parameter :: dxmin_ls = 3000., dxmax_ls = 13000. ! min,max range of tapering (m)
421 real :: ss_taper, ls_taper ! small- and large-scale tapering factors (-)
425 ! added Beljaars orographic form drag
426 real, dimension(its:ite,kts:kte) :: utendform,vtendform
429 ! critical richardson number for wave breaking : ! larger drag with larger value
431 real,parameter :: ric = 0.25
433 real,parameter :: dw2min = 1.
434 real,parameter :: rimin = -100.
435 real,parameter :: bnv2min = 1.0e-5
436 real,parameter :: efmin = 0.0
437 real,parameter :: efmax = 10.0
438 real,parameter :: xl = 4.0e4
439 real,parameter :: critac = 1.0e-5
440 real,parameter :: gmax = 1.
441 real,parameter :: veleps = 1.0
442 real,parameter :: factop = 0.5
443 real,parameter :: frc = 1.0
444 real,parameter :: ce = 0.8
445 real,parameter :: cg = 0.5
446 integer,parameter :: kpblmin = 2
449 ! Variables for limiting topographic standard deviation (var)
450 real, parameter :: varmax_ss = 35., &
455 real, dimension(its:ite) :: &
461 integer :: i,k,lcap,lcapp1,nwd,idir, &
464 real :: rcs,rclcs,csg,fdir,cleff,cleff_ss,cs,rcsks, &
465 wdir,ti,rdz,temp,tem2,dw2,shr2,bvf2,rdelks, &
466 wtkbj,tem,gfobnv,hd,fro,rim,temc,tem1,efact, &
467 temv,dtaux,dtauy,eng0,eng1
469 logical :: ldrag(its:ite),icrilv(its:ite), &
470 flag(its:ite),kloop1(its:ite)
472 real :: taub(its:ite),taup(its:ite,kts:kte+1), &
473 xn(its:ite),yn(its:ite), &
474 ubar(its:ite),vbar(its:ite), &
475 fr(its:ite),ulow(its:ite), &
476 rulow(its:ite),bnv(its:ite), &
477 oa(its:ite),ol(its:ite), &
478 oass(its:ite),olss(its:ite), &
479 roll(its:ite),dtfac(its:ite), &
480 brvf(its:ite),xlinv(its:ite), &
481 delks(its:ite),delks1(its:ite), &
482 bnv2(its:ite,kts:kte),usqj(its:ite,kts:kte), &
483 taud_ls(its:ite,kts:kte),taud_bl(its:ite,kts:kte), &
484 ro(its:ite,kts:kte), &
485 vtk(its:ite,kts:kte),vtj(its:ite,kts:kte), &
486 zlowtop(its:ite),velco(its:ite,kts:kte-1), &
487 coefm(its:ite),coefm_ss(its:ite)
489 integer :: kbl(its:ite),klowtop(its:ite)
492 integer,parameter :: mdir=8
493 integer :: nwdir(mdir)
494 data nwdir/6,7,5,8,2,3,1,4/
496 ! variables for flow-blocking drag
498 real,parameter :: frmax = 10.
499 real,parameter :: olmin = 1.0e-5
500 real,parameter :: odmin = 0.1
501 real,parameter :: odmax = 10.
502 integer :: komax(its:ite)
507 real :: delx,dely,dxy4(4),dxy4p(4)
508 real :: dxy(its:ite),dxyp(its:ite)
509 real :: ol4p(4),olp(its:ite),od(its:ite)
510 real :: taufb(its:ite,kts:kte+1)
516 clf_coeff = 3.4E+07, & ! "effective length" coeff or large-scale GWD
517 ! Note: Can be used as "tuning knob"
518 clf_coeff_ss = 0.1, & ! Adjustment for small-scale GWD
519 a1_coeff = 0.00026615161, & ! Coefficient for TOFD from Beljaars et al. (2004)
520 a2_coeff = 0.005363, & ! ""
521 TOFD_coeff = 0.0759, & ! ""
522 Hefold_nom = 1500. ! Nominal TOFD e-folding height (m)
533 fdir = mdir / (2.0*pi)
535 !--- calculate scale-aware tapering factors
537 if ( dxmeter .ge. dxmax_ls ) then
540 if ( dxmeter .le. dxmin_ls) then
543 ls_taper = 0.5 * ( SIN(pi*(dxmeter-0.5*(dxmax_ls+dxmin_ls))/ &
544 (dxmax_ls-dxmin_ls)) + 1. )
547 if ( dxmeter .ge. dxmax_ss ) then
550 if ( dxmeter .le. dxmin_ss) then
553 ss_taper = dxmax_ss * (1. - dxmin_ss/dxmeter)/(dxmax_ss-dxmin_ss)
557 !--- calculate length of grid for flow-blocking drag
563 dxy4(3) = sqrt(delx*delx + dely*dely)
571 !-----initialize arrays
634 ! SPP (rstoch will be 0 is spp_pbl = 0)
636 var_stoch(i) = var(i) + var(i)*0.666*rstoch(i)
637 varss_stoch(i) = varss(i) + varss(i)*0.666*rstoch(i)
638 varmax_ss_stoch(i) = varmax_ss + varmax_ss*0.5*rstoch(i)
639 varmax_fd_stoch(i) = varmax_fd + varmax_fd*0.5*rstoch(i)
642 ! initialize array for flow-blocking drag
644 taufb(its:ite,kts:kte+1) = 0.0
649 vtj(i,k) = t1(i,k) * (1.+fv*q1(i,k))
650 vtk(i,k) = vtj(i,k) / prslk(i,k)
651 ro(i,k) = 1./rd * prsl(i,k) / vtj(i,k) ! density kg/m**3
655 ! determine reference level: maximum of 2*var and pbl heights
658 zlowtop(i) = 2. * var_stoch(i)
667 if(kloop1(i).and.zl(i,k)-zl(i,1).ge.zlowtop(i)) then
675 kbl(i) = max(kpbl(i), klowtop(i))
676 kbl(i) = max(min(kbl(i),kpblmax),kpblmin)
679 ! determine the level of maximum orographic height
682 komax(:) = klowtop(:) - 1 ! modification by NOAA/GSL March 2018
685 delks(i) = 1.0 / (prsi(i,1) - prsi(i,kbl(i)))
686 delks1(i) = 1.0 / (prsl(i,1) - prsl(i,kbl(i)))
689 ! compute low level averages within pbl
693 if (k.lt.kbl(i)) then
694 rcsks = rcs * del(i,k) * delks(i)
695 rdelks = del(i,k) * delks(i)
696 ubar(i) = ubar(i) + rcsks * u1(i,k) ! pbl u mean
697 vbar(i) = vbar(i) + rcsks * v1(i,k) ! pbl v mean
698 roll(i) = roll(i) + rdelks * ro(i,k) ! ro mean
703 ! figure out low-level horizontal wind direction
705 ! nwd 1 2 3 4 5 6 7 8
706 ! wd w s sw nw e n ne se
709 wdir = atan2(ubar(i),vbar(i)) + pi
710 idir = mod(nint(fdir*wdir),mdir) + 1
712 oa(i) = (1-2*int( (nwd-1)/4 )) * oa4(i,mod(nwd-1,4)+1)
713 ol(i) = ol4(i,mod(nwd-1,4)+1)
714 ! Repeat for small-scale gwd
715 oass(i) = (1-2*int( (nwd-1)/4 )) * oa4ss(i,mod(nwd-1,4)+1)
716 olss(i) = ol4ss(i,mod(nwd-1,4)+1)
719 !----- compute orographic width along (ol) and perpendicular (olp)
720 !----- the direction of wind
726 olp(i) = ol4p(mod(nwd-1,4)+1)
728 !----- compute orographic direction (horizontal orographic aspect ratio)
730 od(i) = olp(i)/max(ol(i),olmin)
731 od(i) = min(od(i),odmax)
732 od(i) = max(od(i),odmin)
734 !----- compute length of grid in the along(dxy) and cross(dxyp) wind directions
736 dxy(i) = dxy4(MOD(nwd-1,4)+1)
737 dxyp(i) = dxy4p(MOD(nwd-1,4)+1)
740 ! END INITIALIZATION; BEGIN GWD CALCULATIONS:
742 IF ( ((gsl_gwd_ls .EQ. 1).or.(gsl_gwd_bl .EQ. 1)).and. &
743 (ls_taper .GT. 1.E-02) ) THEN !====
745 !--- saving richardson number in usqj for migwdi
749 ti = 2.0 / (t1(i,k)+t1(i,k+1))
750 rdz = 1./(zl(i,k+1) - zl(i,k))
751 tem1 = u1(i,k) - u1(i,k+1)
752 tem2 = v1(i,k) - v1(i,k+1)
753 dw2 = rcl*(tem1*tem1 + tem2*tem2)
754 shr2 = max(dw2,dw2min) * rdz * rdz
755 bvf2 = g*(g/cp+rdz*(vtj(i,k+1)-vtj(i,k))) * ti
756 usqj(i,k) = max(bvf2/shr2,rimin)
757 bnv2(i,k) = 2.0*g*rdz*(vtk(i,k+1)-vtk(i,k))/(vtk(i,k+1)+vtk(i,k))
758 bnv2(i,k) = max( bnv2(i,k), bnv2min )
762 !----compute the "low level" or 1/3 wind magnitude (m/s)
765 ulow(i) = max(sqrt(ubar(i)*ubar(i) + vbar(i)*vbar(i)), 1.0)
766 rulow(i) = 1./ulow(i)
771 velco(i,k) = (0.5*rcs) * ((u1(i,k)+u1(i,k+1)) * ubar(i) &
772 + (v1(i,k)+v1(i,k+1)) * vbar(i))
773 velco(i,k) = velco(i,k) * rulow(i)
774 if ((velco(i,k).lt.veleps) .and. (velco(i,k).gt.0.)) then
780 ! no drag when critical level in the base layer
783 ldrag(i) = velco(i,1).le.0.
786 ! no drag when velco.lt.0
788 do k = kpblmin,kpblmax
790 if (k .lt. kbl(i)) ldrag(i) = ldrag(i).or. velco(i,k).le.0.
794 ! no drag when bnv2.lt.0
798 if (k .lt. kbl(i)) ldrag(i) = ldrag(i).or. bnv2(i,k).lt.0.
802 !-----the low level weighted average ri is stored in usqj(1,1; im)
803 !-----the low level weighted average n**2 is stored in bnv2(1,1; im)
804 !---- this is called bnvl2 in phys_gwd_alpert_sub not bnv2
805 !---- rdelks (del(k)/delks) vert ave factor so we can * instead of /
808 wtkbj = (prsl(i,1)-prsl(i,2)) * delks1(i)
809 bnv2(i,1) = wtkbj * bnv2(i,1)
810 usqj(i,1) = wtkbj * usqj(i,1)
813 do k = kpblmin,kpblmax
815 if (k .lt. kbl(i)) then
816 rdelks = (prsl(i,k)-prsl(i,k+1)) * delks1(i)
817 bnv2(i,1) = bnv2(i,1) + bnv2(i,k) * rdelks
818 usqj(i,1) = usqj(i,1) + usqj(i,k) * rdelks
824 ldrag(i) = ldrag(i) .or. bnv2(i,1).le.0.0
825 ldrag(i) = ldrag(i) .or. ulow(i).eq.1.0
826 ldrag(i) = ldrag(i) .or. var_stoch(i) .le. 0.0
829 ! set all ri low level values to the low level value
831 do k = kpblmin,kpblmax
833 if (k .lt. kbl(i)) usqj(i,k) = usqj(i,1)
838 if (.not.ldrag(i)) then
839 bnv(i) = sqrt( bnv2(i,1) )
840 fr(i) = bnv(i) * rulow(i) * 2. * var_stoch(i) * od(i)
841 fr(i) = min(fr(i),frmax)
842 xn(i) = ubar(i) * rulow(i)
843 yn(i) = vbar(i) * rulow(i)
847 ! compute the base level stress and store it in taub
848 ! calculate enhancement factor, number of mountains & aspect
849 ! ratio const. use simplified relationship between standard
850 ! deviation & critical hgt
853 if (.not. ldrag(i)) then
854 efact = (oa(i) + 2.) ** (ce*fr(i)/frc)
855 efact = min( max(efact,efmin), efmax )
856 !!!!!!! cleff ("effective grid length") is highly tunable parameter
857 ! Based on tuning by NOAA on the GFS, the value of cleff should
858 ! be inversely proportional to the square root of the grid length
859 ! (dxmeter). The larger (smaller) the grid size the smaller (larger)
860 ! the value of cleff.
861 cleff = clf_coeff / sqrt(dxmeter)
862 coefm(i) = (1. + ol(i)) ** (oa(i)+1.)
863 xlinv(i) = coefm(i) / cleff
864 tem = fr(i) * fr(i) * oc1(i)
865 gfobnv = gmax * tem / ((tem + cg)*bnv(i))
866 if ( gsl_gwd_ls .NE. 0 ) then
867 taub(i) = xlinv(i) * roll(i) * ulow(i) * ulow(i) &
868 * ulow(i) * gfobnv * efact
869 else ! We've gotten what we need for the blocking scheme
879 ENDIF ! (gsl_gwd_ls .EQ. 1).or.(gsl_gwd_bl .EQ. 1)
880 !=========================================================
881 ! add small-scale wavedrag for stable boundary layer
882 !=========================================================
891 IF ( (gsl_gwd_ss .EQ. 1).and.(ss_taper.GT.1.E-02) ) THEN
893 ! declaring potential temperature
897 thx(i,k) = t1(i,k)/prslk(i,k)
903 tvcon = (1.+fv*q1(i,k))
904 thvx(i,k) = thx(i,k)*tvcon
908 ! Defining layer height
912 zq(i,k+1) = dz2(i,k)+zq(i,k)
918 za(i,k) = 0.5*(zq(i,k)+zq(i,k+1))
926 do k=kts+1,MAX(kpbl(i),kts+1)
927 IF (za(i,k)>300.) then
929 IF (k == kpbl(i)) then
937 if((xland1(i)-1.5).le.0. .and. 2.*varss_stoch(i).le.hpbl(i))then
938 if(br1(i).gt.0. .and. thvx(i,kpbl2)-thvx(i,kts) > 0.)then
939 cleff_ss = sqrt(dxy(i)**2 + dxyp(i)**2)
940 cleff_ss = clf_coeff_ss * max(dxmax_ss,cleff_ss)
941 coefm_ss(i) = (1. + olss(i)) ** (oass(i)+1.)
942 xlinv(i) = coefm_ss(i) / cleff_ss
943 govrth(i)=g/(0.5*(thvx(i,kpbl2)+thvx(i,kts)))
944 XNBV=sqrt(govrth(i)*(thvx(i,kpbl2)-thvx(i,kts))/hpbl2)
946 if(abs(XNBV/u1(i,kpbl2)).gt.xlinv(i))then
947 var_temp = MIN(varss_stoch(i),varmax_ss_stoch(i)) + &
948 MAX(0.,beta_ss*(varss_stoch(i)-varmax_ss_stoch(i)))
949 tauwavex0=0.5*XNBV*xlinv(i)*(2.*var_temp)**2*ro(i,kvar)*u1(i,kvar)
950 tauwavex0=tauwavex0*ss_taper ! "Scale-awareness"
955 if(abs(XNBV/v1(i,kpbl2)).gt.xlinv(i))then
956 var_temp = MIN(varss_stoch(i),varmax_ss_stoch(i)) + &
957 MAX(0.,beta_ss*(varss_stoch(i)-varmax_ss_stoch(i)))
958 tauwavey0=0.5*XNBV*xlinv(i)*(2.*var_temp)**2*ro(i,kvar)*v1(i,kvar)
959 tauwavey0=tauwavey0*ss_taper ! "Scale-awareness"
964 do k=kts,kpbl(i) !MIN(kpbl2+1,kte-1)
965 utendwave(i,k)=-1.*tauwavex0*2.*max((1.-za(i,k)/hpbl2),0.)/hpbl2
966 vtendwave(i,k)=-1.*tauwavey0*2.*max((1.-za(i,k)/hpbl2),0.)/hpbl2
974 dudt(i,k) = dudt(i,k) + utendwave(i,k)
975 dvdt(i,k) = dvdt(i,k) + vtendwave(i,k)
976 dtaux2d_ss(i,k) = utendwave(i,k)
977 dtauy2d_ss(i,k) = vtendwave(i,k)
978 dusfc_ss(i) = dusfc_ss(i) + utendwave(i,k) * del(i,k)
979 dvsfc_ss(i) = dvsfc_ss(i) + vtendwave(i,k) * del(i,k)
983 ENDIF ! end if gsl_gwd_ss == 1
984 !================================================================
985 ! Topographic Form Drag from Beljaars et al. (2004, QJRMS, equ. 16):
986 !================================================================
987 IF ( (gsl_gwd_fd .EQ. 1).and.(ss_taper.GT.1.E-02) ) THEN
993 IF ( (gsl_gwd_ss .NE. 1).and.(ss_taper.GT.1.E-02) ) THEN
994 ! Defining layer height. This is already done above is small-scale GWD is used
997 zq(i,k+1) = dz2(i,k)+zq(i,k)
1003 za(i,k) = 0.5*(zq(i,k)+zq(i,k+1))
1009 IF ((xland1(i)-1.5) .le. 0.) then
1010 var_temp = MIN(varss_stoch(i),varmax_fd_stoch(i)) + &
1011 MAX(0.,beta_fd*(varss_stoch(i)-varmax_fd_stoch(i)))
1012 a1=a1_coeff*var_temp**2
1014 ! Revise e-folding height based on PBL height and topographic std. dev. -- M. Toy 3/12/2018
1015 H_efold = max(2*varss_stoch(i),hpbl(i))
1016 H_efold = min(H_efold,Hefold_nom)
1018 wsp=SQRT(u1(i,k)**2 + v1(i,k)**2)
1019 ! Eqn. (16) of Beljaars et al. (2004)
1020 utendform(i,k)=-TOFD_coeff*wsp*u1(i,k)* &
1021 EXP(-(za(i,k)/H_efold)**1.5)*a2*za(i,k)**(-1.2)*ss_taper
1022 vtendform(i,k)=-TOFD_coeff*wsp*v1(i,k)* &
1023 EXP(-(za(i,k)/H_efold)**1.5)*a2*za(i,k)**(-1.2)*ss_taper
1030 dudt(i,k) = dudt(i,k) + utendform(i,k)
1031 dvdt(i,k) = dvdt(i,k) + vtendform(i,k)
1032 dtaux2d_fd(i,k) = utendform(i,k)
1033 dtauy2d_fd(i,k) = vtendform(i,k)
1034 dusfc_fd(i) = dusfc_fd(i) + utendform(i,k) * del(i,k)
1035 dvsfc_fd(i) = dvsfc_fd(i) + vtendform(i,k) * del(i,k)
1039 ENDIF ! end if gsl_gwd_fd == 1
1040 !=======================================================
1041 ! More for the large-scale gwd component
1042 IF ( (gsl_gwd_ls .EQ. 1).and.(ls_taper.GT.1.E-02) ) THEN
1044 ! now compute vertical structure of the stress.
1048 if (k .le. kbl(i)) taup(i,k) = taub(i)
1052 do k = kpblmin, kte-1 ! vertical level k loop!
1056 ! unstablelayer if ri < ric
1057 ! unstable layer if upper air vel comp along surf vel <=0 (crit lay)
1058 ! at (u-c)=0. crit layer exists and bit vector should be set (.le.)
1060 if (k .ge. kbl(i)) then
1061 icrilv(i) = icrilv(i) .or. ( usqj(i,k) .lt. ric) &
1062 .or. (velco(i,k) .le. 0.0)
1063 brvf(i) = max(bnv2(i,k),bnv2min) ! brunt-vaisala frequency squared
1064 brvf(i) = sqrt(brvf(i)) ! brunt-vaisala frequency
1069 if (k .ge. kbl(i) .and. (.not. ldrag(i))) then
1070 if (.not.icrilv(i) .and. taup(i,k) .gt. 0.0 ) then
1071 temv = 1.0 / velco(i,k)
1072 tem1 = coefm(i)/dxy(i)*(ro(i,kp1)+ro(i,k))*brvf(i)*velco(i,k)*0.5
1073 hd = sqrt(taup(i,k) / tem1)
1074 fro = brvf(i) * hd * temv
1076 ! rim is the minimum-richardson number by shutts (1985)
1078 tem2 = sqrt(usqj(i,k))
1079 tem = 1. + tem2 * fro
1080 rim = usqj(i,k) * (1.-fro) / (tem * tem)
1082 ! check stability to employ the 'saturation hypothesis'
1083 ! of lindzen (1981) except at tropospheric downstream regions
1085 if (rim .le. ric) then ! saturation hypothesis!
1086 if ((oa(i) .le. 0.).or.(kp1 .ge. kpblmin )) then
1087 temc = 2.0 + 1.0 / tem2
1088 hd = velco(i,k) * (2.*sqrt(temc)-temc) / brvf(i)
1089 taup(i,kp1) = tem1 * hd * hd
1091 else ! no wavebreaking!
1092 taup(i,kp1) = taup(i,k)
1099 if(lcap.lt.kte) then
1100 do klcap = lcapp1,kte
1102 taup(i,klcap) = prsi(i,klcap) / prsi(i,lcap) * taup(i,lcap)
1107 ENDIF !END LARGE-SCALE TAU CALCULATION
1109 !===============================================================
1110 !COMPUTE BLOCKING COMPONENT
1111 !===============================================================
1112 IF ( (gsl_gwd_bl .EQ. 1) .and. (ls_taper .GT. 1.E-02) ) THEN
1115 if(.not.ldrag(i)) then
1117 !------- determine the height of flow-blocking layer
1121 do k = kte, kpblmin, -1
1122 if(kblk.eq.0 .and. k.le.komax(i)) then
1123 pe = pe + bnv2(i,k)*(zl(i,komax(i))-zl(i,k))*del(i,k)/g/ro(i,k)
1124 ke = 0.5*((rcs*u1(i,k))**2.+(rcs*v1(i,k))**2.)
1126 !---------- apply flow-blocking drag when pe >= ke
1130 kblk = min(kblk,kbl(i))
1131 zblk = zl(i,kblk)-zl(i,kts)
1137 !--------- compute flow-blocking stress
1139 cd = max(2.0-1.0/od(i),0.0)
1140 taufb(i,kts) = 0.5 * roll(i) * coefm(i) / max(dxmax_ls,dxy(i))**2 * cd * dxyp(i) &
1141 * olp(i) * zblk * ulow(i)**2
1142 tautem = taufb(i,kts)/float(kblk-kts)
1144 taufb(i,k) = taufb(i,k-1) - tautem
1147 !----------sum orographic GW stress and flow-blocking stress
1149 ! taup(i,:) = taup(i,:) + taufb(i,:) ! Keep taup and taufb separate for now
1154 ENDIF ! end blocking drag
1155 !===========================================================
1156 IF ( (gsl_gwd_ls .EQ. 1 .OR. gsl_gwd_bl .EQ. 1) .and. (ls_taper .GT. 1.E-02) ) THEN
1158 ! calculate - (g)*d(tau)/d(pressure) and deceleration terms dtaux, dtauy
1162 taud_ls(i,k) = 1. * (taup(i,k+1) - taup(i,k)) * csg / del(i,k)
1163 taud_bl(i,k) = 1. * (taufb(i,k+1) - taufb(i,k)) * csg / del(i,k)
1167 ! limit de-acceleration (momentum deposition ) at top to 1/2 value
1168 ! the idea is some stuff must go out the 'top'
1172 taud_ls(i,klcap) = taud_ls(i,klcap) * factop
1173 taud_bl(i,klcap) = taud_bl(i,klcap) * factop
1177 ! if the gravity wave drag would force a critical line
1178 ! in the lower ksmm1 layers during the next deltim timestep,
1179 ! then only apply drag until that critical line is reached.
1181 do k = kts,kpblmax-1
1183 if (k .le. kbl(i)) then
1184 if((taud_ls(i,k)+taud_bl(i,k)).ne.0.) &
1185 dtfac(i) = min(dtfac(i),abs(velco(i,k) &
1186 /(deltim*rcs*(taud_ls(i,k)+taud_bl(i,k)))))
1193 taud_ls(i,k) = taud_ls(i,k) * dtfac(i) * ls_taper
1194 taud_bl(i,k) = taud_bl(i,k) * dtfac(i) * ls_taper
1195 ! dtaux = taud(i,k) * xn(i)
1196 ! dtauy = taud(i,k) * yn(i)
1197 dtaux2d_ls(i,k) = taud_ls(i,k) * xn(i)
1198 dtauy2d_ls(i,k) = taud_ls(i,k) * yn(i)
1199 dtaux2d_bl(i,k) = taud_bl(i,k) * xn(i)
1200 dtauy2d_bl(i,k) = taud_bl(i,k) * yn(i)
1201 dudt(i,k) = dtaux2d_ls(i,k) + dtaux2d_bl(i,k) + dudt(i,k)
1202 dvdt(i,k) = dtauy2d_ls(i,k) + dtauy2d_bl(i,k) + dvdt(i,k)
1203 dusfc_ls(i) = dusfc_ls(i) + dtaux2d_ls(i,k) * del(i,k)
1204 dvsfc_ls(i) = dvsfc_ls(i) + dtauy2d_ls(i,k) * del(i,k)
1205 dusfc_bl(i) = dusfc_bl(i) + dtaux2d_bl(i,k) * del(i,k)
1206 dvsfc_bl(i) = dvsfc_bl(i) + dtauy2d_bl(i,k) * del(i,k)
1207 if ( gsl_diss_ht_opt .EQ. 1 ) then
1208 ! Calculate dissipation heating
1209 ! Initial kinetic energy (at t0-dt)
1210 eng0 = 0.5*( (rcs*u1(i,k))**2. + (rcs*v1(i,k))**2. )
1211 ! Kinetic energy after wave-breaking/flow-blocking
1212 eng1 = 0.5*( (rcs*(u1(i,k)+(dtaux2d_ls(i,k)+dtaux2d_bl(i,k))*deltim))**2. + &
1213 (rcs*(v1(i,k)+(dtauy2d_ls(i,k)+dtauy2d_bl(i,k))*deltim))**2. )
1214 ! Modify theta tendency
1215 dthdt(i,k) = dthdt(i,k) + max((eng0-eng1),0.0)/cp/deltim/prslk(i,k)
1222 ! Finalize dusfc and dvsfc diagnoses
1224 dusfc_ls(i) = (-1./g*rcs) * dusfc_ls(i)
1225 dvsfc_ls(i) = (-1./g*rcs) * dvsfc_ls(i)
1226 dusfc_bl(i) = (-1./g*rcs) * dusfc_bl(i)
1227 dvsfc_bl(i) = (-1./g*rcs) * dvsfc_bl(i)
1228 dusfc_ss(i) = (-1./g*rcs) * dusfc_ss(i)
1229 dvsfc_ss(i) = (-1./g*rcs) * dvsfc_ss(i)
1230 dusfc_fd(i) = (-1./g*rcs) * dusfc_fd(i)
1231 dvsfc_fd(i) = (-1./g*rcs) * dvsfc_fd(i)
1236 end subroutine gwdo2d
1237 !-------------------------------------------------------------------
1238 end module module_bl_gwdo_gsl