Merge branch 'master' into devel
[wrffire.git] / wrfv2_fire / phys / module_bl_gwdo.F
blob280e328069ceeaa24ac98a3b750e99dada23b5af
1 ! WRf:model_layer:physics
7 module module_bl_gwdo
8 contains
10 !-------------------------------------------------------------------
12    subroutine gwdo(u3d,v3d,t3d,qv3d,p3d,p3di,pi3d,z, &
13                   rublten,rvblten, &
14                   dtaux3d,dtauy3d,dusfcg,dvsfcg, &
15                   var2d,oc12d,oa2d1,oa2d2,oa2d3,oa2d4,ol2d1,ol2d2,ol2d3,ol2d4, &
16                   znu,znw,mut,p_top, &
17                   cp,g,rd,rv,ep1,pi, &
18                   dt,dx,kpbl2d,itimestep, &
19                   ids,ide, jds,jde, kds,kde, &
20                   ims,ime, jms,jme, kms,kme, &
21                   its,ite, jts,jte, kts,kte)
22 !-------------------------------------------------------------------
23       implicit none
24 !------------------------------------------------------------------------------
26 !-- u3d 3d u-velocity interpolated to theta points (m/s)
27 !-- v3d 3d v-velocity interpolated to theta points (m/s)
28 !-- t3d temperature (k)
29 !-- qv3d 3d water vapor mixing ratio (kg/kg)
30 !-- p3d 3d pressure (pa)
31 !-- p3di 3d pressure (pa) at interface level
32 !-- pi3d 3d exner function (dimensionless)
33 !-- rublten u tendency due to
34 ! pbl parameterization (m/s/s)
35 !-- rvblten v tendency due to
36 !-- cp heat capacity at constant pressure for dry air (j/kg/k)
37 !-- g acceleration due to gravity (m/s^2)
38 !-- rd gas constant for dry air (j/kg/k)
39 !-- z height above sea level (m)
40 !-- rv gas constant for water vapor (j/kg/k)
41 !-- dt time step (s)
42 !-- dx model grid interval (m)
43 !-- ep1 constant for virtual temperature (r_v/r_d - 1) (dimensionless)
44 !-- ids start index for i in domain
45 !-- ide end index for i in domain
46 !-- jds start index for j in domain
47 !-- jde end index for j in domain
48 !-- kds start index for k in domain
49 !-- kde end index for k in domain
50 !-- ims start index for i in memory
51 !-- ime end index for i in memory
52 !-- jms start index for j in memory
53 !-- jme end index for j in memory
54 !-- kms start index for k in memory
55 !-- kme end index for k in memory
56 !-- its start index for i in tile
57 !-- ite end index for i in tile
58 !-- jts start index for j in tile
59 !-- jte end index for j in tile
60 !-- kts start index for k in tile
61 !-- kte end index for k in tile
62 !-------------------------------------------------------------------
64   integer, intent(in ) :: ids,ide, jds,jde, kds,kde, &
65                                      ims,ime, jms,jme, kms,kme, &
66                                      its,ite, jts,jte, kts,kte
67   integer, intent(in ) :: itimestep
69   real, intent(in ) :: dt,dx,cp,g,rd,rv,ep1,pi
71   real, dimension( ims:ime, kms:kme, jms:jme ) , &
72             intent(in ) :: qv3d, &
73                                                                           p3d, &
74                                                                          pi3d, &
75                                                                           t3d, &
76                                                                              z
77   real, dimension( ims:ime, kms:kme, jms:jme ) , &
78             intent(in ) :: p3di
80   real, dimension( ims:ime, kms:kme, jms:jme ) , &
81             intent(inout) :: rublten, &
82                                                                       rvblten
83   real, dimension( ims:ime, kms:kme, jms:jme ) , &
84             intent(inout) :: dtaux3d, &
85                                                                       dtauy3d
87   real, dimension( ims:ime, kms:kme, jms:jme ) , &
88              intent(in ) :: u3d, &
89                                                                           v3d
91   integer, dimension( ims:ime, jms:jme ) , &
92              intent(in ) :: kpbl2d
93   real, dimension( ims:ime, jms:jme ) , &
94              intent(inout ) :: dusfcg, &
95                                                                        dvsfcg
97   real, dimension( ims:ime, jms:jme ) , &
98              intent(in ) :: var2d, &
99                                                                         oc12d, &
100                                                       oa2d1,oa2d2,oa2d3,oa2d4, &
101                                                       ol2d1,ol2d2,ol2d3,ol2d4
103   real, dimension( ims:ime, jms:jme ) , &
104              optional , &
105              intent(in ) :: mut
107   real, dimension( kms:kme ) , &
108              optional , &
109              intent(in ) :: znu, &
110                                                                           znw
112   real, optional, intent(in ) :: p_top
114 !local
116   real, dimension( its:ite, kts:kte ) :: delprsi, &
117                                                                           pdh
118   real, dimension( its:ite, kts:kte+1 ) :: pdhi
119   real, dimension( its:ite, 4 ) :: oa4, &
120                                                                           ol4
121   integer :: i,j,k,kdt
123    do j = jts,jte
124       if(present(mut))then
125 ! For ARW we will replace p and p8w with dry hydrostatic pressure
126         do k = kts,kte+1
127           do i = its,ite
128              if(k.le.kte)pdh(i,k) = mut(i,j)*znu(k) + p_top
129              pdhi(i,k) = mut(i,j)*znw(k) + p_top
130           enddo
131         enddo
132       else
133         do k = kts,kte+1
134           do i = its,ite
135              if(k.le.kte)pdh(i,k) = p3d(i,k,j)
136              pdhi(i,k) = p3di(i,k,j)
137           enddo
138         enddo
139       endif
141       do k = kts,kte
142         do i = its,ite
143           delprsi(i,k) = pdhi(i,k)-pdhi(i,k+1)
144         enddo
145       enddo
146         do i = its,ite
147             oa4(i,1) = oa2d1(i,j)
148             oa4(i,2) = oa2d2(i,j)
149             oa4(i,3) = oa2d3(i,j)
150             oa4(i,4) = oa2d4(i,j)
151             ol4(i,1) = ol2d1(i,j)
152             ol4(i,2) = ol2d2(i,j)
153             ol4(i,3) = ol2d3(i,j)
154             ol4(i,4) = ol2d4(i,j)
155         enddo
156       call gwdo2d(dudt=rublten(ims,kms,j),dvdt=rvblten(ims,kms,j) &
157               ,dtaux2d=dtaux3d(ims,kms,j),dtauy2d=dtauy3d(ims,kms,j) &
158               ,u1=u3d(ims,kms,j),v1=v3d(ims,kms,j) &
159               ,t1=t3d(ims,kms,j),q1=qv3d(ims,kms,j) &
160               ,prsi=pdhi(its,kts),del=delprsi(its,kts) &
161               ,prsl=pdh(its,kts),prslk=pi3d(ims,kms,j) &
162               ,zl=z(ims,kms,j),rcl=1.0 &
163               ,dusfc=dusfcg(ims,j),dvsfc=dvsfcg(ims,j) &
164               ,var=var2d(ims,j),oc1=oc12d(ims,j) &
165               ,oa4=oa4,ol4=ol4 &
166               ,g=g,cp=cp,rd=rd,rv=rv,fv=ep1,pi=pi &
167               ,dxmeter=dx,deltim=dt &
168               ,kpbl=kpbl2d(ims,j),kdt=itimestep,lat=j &
169               ,ids=ids,ide=ide, jds=jds,jde=jde, kds=kds,kde=kde &
170               ,ims=ims,ime=ime, jms=jms,jme=jme, kms=kms,kme=kme &
171               ,its=its,ite=ite, jts=jts,jte=jte, kts=kts,kte=kte )
172    enddo
175    end subroutine gwdo
177 !-------------------------------------------------------------------
182    subroutine gwdo2d(dudt,dvdt,dtaux2d,dtauy2d, &
183                     u1,v1,t1,q1, &
184                     prsi,del,prsl,prslk,zl,rcl, &
185                     var,oc1,oa4,ol4,dusfc,dvsfc, &
186                     g,cp,rd,rv,fv,pi,dxmeter,deltim,kpbl,kdt,lat, &
187                     ids,ide, jds,jde, kds,kde, &
188                     ims,ime, jms,jme, kms,kme, &
189                     its,ite, jts,jte, kts,kte)
190 !-------------------------------------------------------------------
192 ! this code handles the time tendencies of u v due to the effect of mountain
193 ! induced gravity wave drag from sub-grid scale orography. this routine
194 ! not only treats the traditional upper-level wave breaking due to mountain
195 ! variance (alpert 1988), but also the enhanced lower-tropospheric wave
196 ! breaking due to mountain convexity and asymmetry (kim and arakawa 1995).
197 ! thus, in addition to the terrain height data in a model grid gox,
198 ! additional 10-2d topographic statistics files are needed, including
199 ! orographic standard deviation (var), convexity (oc1), asymmetry (oa4)
200 ! and ol (ol4). these data sets are prepared based on the 30 sec usgs orography
201 ! hong (1999). the current scheme was implmented as in hong et al.(2008)
203 ! coded by song-you hong and young-joon kim and implemented by song-you hong
205 ! references:
206 ! hong et al. (2008), wea. and forecasting
207 ! kim and arakawa (1995), j. atmos. sci.
208 ! alpet et al. (1988), NWP conference.
209 ! hong (1999), NCEP office note 424.
211 ! notice : comparible or lower resolution orography files than model resolution
212 ! are desirable in preprocess (wps) to prevent weakening of the drag
213 !-------------------------------------------------------------------
215 ! input
216 ! dudt (ims:ime,kms:kme) non-lin tendency for u wind component
217 ! dvdt (ims:ime,kms:kme) non-lin tendency for v wind component
218 ! u1(ims:ime,kms:kme) zonal wind / sqrt(rcl) m/sec at t0-dt
219 ! v1(ims:ime,kms:kme) meridional wind / sqrt(rcl) m/sec at t0-dt
220 ! t1(ims:ime,kms:kme) temperature deg k at t0-dt
221 ! q1(ims:ime,kms:kme) specific humidity at t0-dt
223 ! rcl a scaling factor = reciprocal of square of cos(lat)
224 ! for mrf gsm. rcl=1 if u1 and v1 are wind components.
225 ! deltim time step secs
226 ! del(kts:kte) positive increment of pressure across layer (pa)
228 ! output
229 ! dudt, dvdt wind tendency due to gwdo
231 !-------------------------------------------------------------------
232    implicit none
233 !-------------------------------------------------------------------
234    integer :: kdt,lat,latd,lond, &
235                             ids,ide, jds,jde, kds,kde, &
236                             ims,ime, jms,jme, kms,kme, &
237                             its,ite, jts,jte, kts,kte
239    real :: g,rd,rv,fv,cp,pi,dxmeter,deltim,rcl
240    real :: dudt(ims:ime,kms:kme),dvdt(ims:ime,kms:kme), &
241                             dtaux2d(ims:ime,kms:kme),dtauy2d(ims:ime,kms:kme), &
242                             u1(ims:ime,kms:kme),v1(ims:ime,kms:kme), &
243                             t1(ims:ime,kms:kme),q1(ims:ime,kms:kme), &
244                             zl(ims:ime,kms:kme),prslk(ims:ime,kms:kme)
245    real :: prsl(its:ite,kts:kte),prsi(its:ite,kts:kte+1), &
246                             del(its:ite,kts:kte)
247    real :: oa4(its:ite,4),ol4(its:ite,4)
249    integer :: kpbl(ims:ime)
250    real :: var(ims:ime),oc1(ims:ime), &
251                             dusfc(ims:ime),dvsfc(ims:ime)
252 ! critical richardson number for wave breaking : ! larger drag with larger value
254    real,parameter :: ric = 0.25
256    real,parameter :: dw2min = 1.
257    real,parameter :: rimin = -100.
258    real,parameter :: bnv2min = 1.0e-5
259    real,parameter :: efmin = 0.0
260    real,parameter :: efmax = 10.0
261    real,parameter :: xl = 4.0e4
262    real,parameter :: critac = 1.0e-5
263    real,parameter :: gmax = 1.
264    real,parameter :: veleps = 1.0
265    real,parameter :: factop = 0.5
266    real,parameter :: frc = 1.0
267    real,parameter :: ce = 0.8
268    real,parameter :: cg = 0.5
270 ! local variables
272    integer :: i,k,lcap,lcapp1,nwd,idir,kpblmin,kpblmax, &
273                             klcap,kp1,ikount,kk
275    real :: rcs,rclcs,csg,fdir,cleff,cs,rcsks, &
276                             wdir,ti,rdz,temp,tem2,dw2,shr2,bvf2,rdelks, &
277                             wtkbj,coefm,tem,gfobnv,hd,fro,rim,temc,tem1,efact, &
278                             temv,dtaux,dtauy
280    logical :: ldrag(its:ite),icrilv(its:ite), &
281                             flag(its:ite),kloop1(its:ite)
283    real :: taub(its:ite),taup(its:ite,kts:kte+1), &
284                             xn(its:ite),yn(its:ite), &
285                             ubar(its:ite),vbar(its:ite), &
286                             fr(its:ite),ulow(its:ite), &
287                             rulow(its:ite),bnv(its:ite), &
288                             oa(its:ite),ol(its:ite), &
289                             roll(its:ite),dtfac(its:ite), &
290                             brvf(its:ite),xlinv(its:ite), &
291                             delks(its:ite),delks1(its:ite), &
292                             bnv2(its:ite,kts:kte),usqj(its:ite,kts:kte), &
293                             taud(its:ite,kts:kte),ro(its:ite,kts:kte), &
294                             vtk(its:ite,kts:kte),vtj(its:ite,kts:kte), &
295                             zlowtop(its:ite),velco(its:ite,kts:kte-1)
297    integer :: kbl(its:ite),klowtop(its:ite), &
298                             lowlv(its:ite)
300    logical :: iope
301    integer,parameter :: mdir=8
302    integer :: nwdir(mdir)
303    data nwdir/6,7,5,8,2,3,1,4/
305 ! initialize local variables
307    kbl=0 ; klowtop=0 ; lowlv=0
309 !---- constants
311    rcs = sqrt(rcl)
312    cs = 1. / sqrt(rcl)
313    csg = cs * g
314    lcap = kte
315    lcapp1 = lcap + 1
316    fdir = mdir / (2.0*pi)
319 !!!!!!! cleff (subgrid mountain scale ) is highly tunable parameter
320 !!!!!!! the bigger (smaller) value produce weaker (stronger) wave drag
322    cleff = max(dxmeter,50.e3)
324 ! initialize!!
326    dtaux = 0.0
327    dtauy = 0.0
328    do k = kts,kte
329      do i = its,ite
330        usqj(i,k) = 0.0
331        bnv2(i,k) = 0.0
332        vtj(i,k) = 0.0
333        vtk(i,k) = 0.0
334        taup(i,k) = 0.0
335        taud(i,k) = 0.0
336        dtaux2d(i,k)= 0.0
337        dtauy2d(i,k)= 0.0
338      enddo
339    enddo
340    do i = its,ite
341      taup(i,kte+1) = 0.0
342      xlinv(i) = 1.0/xl
343    enddo
345    do k = kts,kte
346      do i = its,ite
347        vtj(i,k) = t1(i,k) * (1.+fv*q1(i,k))
348        vtk(i,k) = vtj(i,k) / prslk(i,k)
349        ro(i,k) = 1./rd * prsl(i,k) / vtj(i,k) ! density kg/m**3
350      enddo
351    enddo
353    do i = its,ite
354      zlowtop(i) = 2. * var(i)
355    enddo
357 !--- determine new reference level > 2*var
359    do i = its,ite
360      kloop1(i) = .true.
361    enddo
362    do k = kts+1,kte
363      do i = its,ite
364        if(kloop1(i).and.zl(i,k)-zl(i,1).ge.zlowtop(i)) then
365          klowtop(i) = k+1
366          kloop1(i) = .false.
367        endif
368      enddo
369    enddo
371    kpblmax = 2
372    do i = its,ite
373      kbl(i) = max(2, kpbl(i))
374      kbl(i) = max(kbl(i), klowtop(i))
375      delks(i) = 1.0 / (prsi(i,1) - prsi(i,kbl(i)))
376      ubar (i) = 0.0
377      vbar (i) = 0.0
378      taup(i,1) = 0.0
379      oa(i) = 0.0
380      kpblmax = max(kpblmax,kbl(i))
381      flag(i) = .true.
382      lowlv(i) = 2
383    enddo
384    kpblmax = min(kpblmax+1,kte-1)
386 ! compute low level averages within pbl
388    do k = kts,kpblmax
389      do i = its,ite
390        if (k.lt.kbl(i)) then
391          rcsks = rcs * del(i,k) * delks(i)
392          ubar(i) = ubar(i) + rcsks * u1(i,k) ! pbl u mean
393          vbar(i) = vbar(i) + rcsks * v1(i,k) ! pbl v mean
394        endif
395      enddo
396    enddo
398 ! figure out low-level horizontal wind direction
400 ! nwd 1 2 3 4 5 6 7 8
401 ! wd w s sw nw e n ne se
403    do i = its,ite
404      wdir = atan2(ubar(i),vbar(i)) + pi
405      idir = mod(nint(fdir*wdir),mdir) + 1
406      nwd = nwdir(idir)
407      oa(i) = (1-2*int( (nwd-1)/4 )) * oa4(i,mod(nwd-1,4)+1)
408      ol(i) = ol4(i,mod(nwd-1,4)+1)
409    enddo
411    kpblmin = kte
412    do i = its,ite
413      kpblmin = min(kpblmin, kbl(i))
414    enddo
416    do i = its,ite
417      if (oa(i).le.0.0) kbl(i) = kpbl(i) + 1
418    enddo
420    do i = its,ite
421      delks(i) = 1.0 / (prsi(i,1) - prsi(i,kbl(i)))
422      delks1(i) = 1.0 / (prsl(i,1) - prsl(i,kbl(i)))
423    enddo
425 !--- saving richardson number in usqj for migwdi
427    do k = kts,kte-1
428      do i = its,ite
429        ti = 2.0 / (t1(i,k)+t1(i,k+1))
430        rdz = 1./(zl(i,k+1) - zl(i,k))
431        tem1 = u1(i,k) - u1(i,k+1)
432        tem2 = v1(i,k) - v1(i,k+1)
433        dw2 = rcl*(tem1*tem1 + tem2*tem2)
434        shr2 = max(dw2,dw2min) * rdz * rdz
435        bvf2 = g*(g/cp+rdz*(vtj(i,k+1)-vtj(i,k))) * ti
436        usqj(i,k) = max(bvf2/shr2,rimin)
437        bnv2(i,k) = 2*g*rdz*(vtk(i,k+1)-vtk(i,k))/(vtk(i,k+1)+vtk(i,k))
438        bnv2(i,k) = max( bnv2(i,k), bnv2min )
439      enddo
440    enddo
442 !-----initialize arrays
444    do i = its,ite
445      xn(i) = 0.0
446      yn(i) = 0.0
447      ubar (i) = 0.0
448      vbar (i) = 0.0
449      roll (i) = 0.0
450      taub (i) = 0.0
451      ulow (i) = 0.0
452      dtfac(i) = 1.0
453      ldrag(i) = .false.
454      icrilv(i) = .false. ! initialize critical level control vector
455    enddo
457 !---- compute low level averages
458 !---- (u,v)*cos(lat) use uv=(u1,v1) which is wind at t0-1
459 !---- use rcs=1/cos(lat) to get wind field
461    do k = 1,kpblmax
462      do i = its,ite
463        if (k .lt. kbl(i)) then
464          rdelks = del(i,k) * delks(i)
465          rcsks = rcs * rdelks
466          ubar(i) = ubar(i) + rcsks * u1(i,k) ! u mean
467          vbar(i) = vbar(i) + rcsks * v1(i,k) ! v mean
468          roll(i) = roll(i) + rdelks * ro(i,k) ! ro mean
469        endif
470      enddo
471    enddo
473 !----compute the "low level" or 1/3 wind magnitude (m/s)
475    do i = its,ite
476      ulow(i) = max(sqrt(ubar(i)*ubar(i) + vbar(i)*vbar(i)), 1.0)
477      rulow(i) = 1./ulow(i)
478    enddo
480    do k = kts,kte-1
481      do i = its,ite
482        velco(i,k) = (0.5*rcs) * ((u1(i,k)+u1(i,k+1)) * ubar(i) &
483                                 + (v1(i,k)+v1(i,k+1)) * vbar(i))
484        velco(i,k) = velco(i,k) * rulow(i)
485        if ((velco(i,k).lt.veleps) .and. (velco(i,k).gt.0.)) then
486          velco(i,k) = veleps
487        endif
488      enddo
489    enddo
491 ! no drag when critical level in the base layer
493    do i = its,ite
494      ldrag(i) = velco(i,1).le.0.
495    enddo
497    do k = kts+1,kpblmax-1
498      do i = its,ite
499        if (k .lt. kbl(i)) ldrag(i) = ldrag(i).or. velco(i,k).le.0.
500      enddo
501    enddo
503 ! no drag when bnv2.lt.0
505    do k = kts,kpblmax-1
506      do i = its,ite
507        if (k .lt. kbl(i)) ldrag(i) = ldrag(i).or. bnv2(i,k).lt.0.
508      enddo
509    enddo
511 !-----the low level weighted average ri is stored in usqj(1,1; im)
512 !-----the low level weighted average n**2 is stored in bnv2(1,1; im)
513 !---- this is called bnvl2 in phys_gwd_alpert_sub not bnv2
514 !---- rdelks (del(k)/delks) vert ave factor so we can * instead of /
516    do i = its,ite
517      wtkbj = (prsl(i,1)-prsl(i,2)) * delks1(i)
518      bnv2(i,1) = wtkbj * bnv2(i,1)
519      usqj(i,1) = wtkbj * usqj(i,1)
520    enddo
522    do k = kts+1,kpblmax-1
523      do i = its,ite
524        if (k .lt. kbl(i)) then
525          rdelks = (prsl(i,k)-prsl(i,k+1)) * delks1(i)
526          bnv2(i,1) = bnv2(i,1) + bnv2(i,k) * rdelks
527          usqj(i,1) = usqj(i,1) + usqj(i,k) * rdelks
528        endif
529      enddo
530    enddo
532    do i = its,ite
533      ldrag(i) = ldrag(i) .or. bnv2(i,1).le.0.0
534      ldrag(i) = ldrag(i) .or. ulow(i).eq.1.0
535      ldrag(i) = ldrag(i) .or. var(i) .le. 0.0
536    enddo
538 ! ----- set all ri low level values to the low level value
540    do k = kts+1,kpblmax-1
541      do i = its,ite
542        if (k .lt. kbl(i)) usqj(i,k) = usqj(i,1)
543      enddo
544    enddo
546    do i = its,ite
547      if (.not.ldrag(i)) then
548        bnv(i) = sqrt( bnv2(i,1) )
549        fr(i) = bnv(i) * rulow(i) * var(i)
550        xn(i) = ubar(i) * rulow(i)
551        yn(i) = vbar(i) * rulow(i)
552      endif
553    enddo
555 ! compute the base level stress and store it in taub
556 ! calculate enhancement factor, number of mountains & aspect
557 ! ratio const. use simplified relationship between standard
558 ! deviation & critical hgt
560    do i = its,ite
561      if (.not. ldrag(i)) then
562        efact = (oa(i) + 2.) ** (ce*fr(i)/frc)
563        efact = min( max(efact,efmin), efmax )
564        coefm = (1. + ol(i)) ** (oa(i)+1.)
565        xlinv(i) = coefm / cleff
566        tem = fr(i) * fr(i) * oc1(i)
567        gfobnv = gmax * tem / ((tem + cg)*bnv(i))
568        taub(i) = xlinv(i) * roll(i) * ulow(i) * ulow(i) &
569                 * ulow(i) * gfobnv * efact
570      else
571        taub(i) = 0.0
572        xn(i) = 0.0
573        yn(i) = 0.0
574      endif
575    enddo
577 ! now compute vertical structure of the stress.
579 !----set up bottom values of stress
581    do k = kts,kpblmax
582      do i = its,ite
583        if (k .le. kbl(i)) taup(i,k) = taub(i)
584      enddo
585    enddo
587    do k = kpblmin, kte-1 ! vertical level k loop!
588      kp1 = k + 1
589      do i = its,ite
591 !-----unstablelayer if ri < ric
592 !-----unstable layer if upper air vel comp along surf vel <=0 (crit lay)
593 !---- at (u-c)=0. crit layer exists and bit vector should be set (.le.)
595        if (k .ge. kbl(i)) then
596          icrilv(i) = icrilv(i) .or. ( usqj(i,k) .lt. ric) &
597                                .or. (velco(i,k) .le. 0.0)
598          brvf(i) = max(bnv2(i,k),bnv2min) ! brunt-vaisala frequency squared
599          brvf(i) = sqrt(brvf(i)) ! brunt-vaisala frequency
600        endif
601      enddo
603      do i = its,ite
604        if (k .ge. kbl(i) .and. (.not. ldrag(i))) then
605          if (.not.icrilv(i) .and. taup(i,k) .gt. 0.0 ) then
606            temv = 1.0 / velco(i,k)
607            tem1 = xlinv(i)*(ro(i,kp1)+ro(i,k))*brvf(i)*velco(i,k)*0.5
608            hd = sqrt(taup(i,k) / tem1)
609            fro = brvf(i) * hd * temv
611 ! rim is the minimum-richardson number by shutts (1985)
613            tem2 = sqrt(usqj(i,k))
614            tem = 1. + tem2 * fro
615            rim = usqj(i,k) * (1.-fro) / (tem * tem)
617 ! check stability to employ the 'saturation hypothesis'
618 ! of lindzen (1981) except at tropospheric downstream regions
620            if (rim .le. ric) then ! saturation hypothesis!
621              if ((oa(i) .le. 0. .or. kp1 .ge. lowlv(i) )) then
622                temc = 2.0 + 1.0 / tem2
623                hd = velco(i,k) * (2.*sqrt(temc)-temc) / brvf(i)
624                taup(i,kp1) = tem1 * hd * hd
625              endif
626            else ! no wavebreaking!
627              taup(i,kp1) = taup(i,k)
628            endif
629          endif
630        endif
631      enddo
632    enddo
634    if(lcap.lt.kte) then
635      do klcap = lcapp1,kte
636        do i = its,ite
637          taup(i,klcap) = prsi(i,klcap) / prsi(i,lcap) * taup(i,lcap)
638        enddo
639      enddo
640    endif
642 ! calculate - (g)*d(tau)/d(pressure) and deceleration terms dtaux, dtauy
644    do k = kts,kte
645      do i = its,ite
646        taud(i,k) = 1. * (taup(i,k+1) - taup(i,k)) * csg / del(i,k)
647      enddo
648    enddo
650 !------limit de-acceleration (momentum deposition ) at top to 1/2 value
651 !------the idea is some stuff must go out the 'top'
653    do klcap = lcap,kte
654      do i = its,ite
655        taud(i,klcap) = taud(i,klcap) * factop
656      enddo
657    enddo
659 !------if the gravity wave drag would force a critical line
660 !------in the lower ksmm1 layers during the next deltim timestep,
661 !------then only apply drag until that critical line is reached.
663    do k = kts,kpblmax-1
664      do i = its,ite
665        if (k .le. kbl(i)) then
666          if(taud(i,k).ne.0.) &
667          dtfac(i) = min(dtfac(i),abs(velco(i,k) &
668                    /(deltim*rcs*taud(i,k))))
669        endif
670      enddo
671    enddo
673    do i = its,ite
674      dusfc(i) = 0.
675      dvsfc(i) = 0.
676    enddo
678    do k = kts,kte
679      do i = its,ite
680        taud(i,k) = taud(i,k) * dtfac(i)
681        dtaux = taud(i,k) * xn(i)
682        dtauy = taud(i,k) * yn(i)
683        dtaux2d(i,k) = dtaux
684        dtauy2d(i,k) = dtauy
685        dudt(i,k) = dtaux + dudt(i,k)
686        dvdt(i,k) = dtauy + dvdt(i,k)
687        dusfc(i) = dusfc(i) + dtaux * del(i,k)
688        dvsfc(i) = dvsfc(i) + dtauy * del(i,k)
689      enddo
690    enddo
692    do i = its,ite
693      dusfc(i) = (-1./g*rcs) * dusfc(i)
694      dvsfc(i) = (-1./g*rcs) * dvsfc(i)
695    enddo
697    return
698    end subroutine gwdo2d
699 !-------------------------------------------------------------------
700 end module module_bl_gwdo