!copyright (C) 2001 MSC-RPN COMM %%%CCC%%%
***S/P LIN_SGOFLX1
*
subroutine lin_sgoflx1(uu,vv,utend,vtend, 1,8
+ tth,ttf,ss,ssh,
+ ilev,lref,ilg,il1,il2,
+ grav,rgas,rgocp,tau,taufac,
+ gc,height,slope,xcent,mtdir,
+ psurf,fcor,
+ gwdrag,blocking,orolift,leewave,
+ applytend)
*
#include "phy_macros_f.h"
#include "impnone.cdk"
*
*
logical gwdrag,blocking,orolift,leewave,applytend
*
integer ilev,lref,ilg,il1,il2
real grav,rgas,rgocp,tau,taufac
real*8 uu(ilg,ilev), vv(ilg,ilev), utend(ilg,ilev),
+ vtend(ilg,ilev), tth(ilg,ilev), ttf(ilg,ilev),
+ ss(ilg,ilev), ssh(ilg,ilev), gc(ilg),
+ height(ilg), slope(ilg), xcent(ilg),
+ mtdir(ilg), psurf(ilg), fcor(ilg)
*
*Author
* A. Zadra - May 2002
*
*Object
* Simplified version of subgrid orographic drag (sgoflx2) scheme:
* - reduced, non-smoothed buoyancy frequency
* - shortened gravity-wave drag (McFarlane 87)
* - shortened low-level blocking (Lott & Miller 97)
* - orographic lift (not yet included)
* - lee-wave breaking (not yet included)
*
*
*Arguments
*
*
**
AUTOMATIC ( VMOD , REAL*8 , (ILG ) )
AUTOMATIC ( UUB , REAL*8 , (ILG ) )
AUTOMATIC ( VVB , REAL*8 , (ILG ) )
AUTOMATIC ( DRAG , INTEGER , (ILG ) )
AUTOMATIC ( UB , REAL*8 , (ILG ) )
AUTOMATIC ( VB , REAL*8 , (ILG ) )
AUTOMATIC ( VMODB , REAL*8 , (ILG ) )
AUTOMATIC ( ENV , REAL*8 , (ILG ) )
AUTOMATIC ( SLP2 , REAL*8 , (ILG ) )
AUTOMATIC ( SLPF , REAL*8 , (ILG ) )
AUTOMATIC ( GAMMA , REAL*8 , (ILG ) )
AUTOMATIC ( THETA , REAL*8 , (ILG ) )
AUTOMATIC ( IZT1 , INTEGER , (ILG ) )
AUTOMATIC ( IZT2 , INTEGER , (ILG ) )
AUTOMATIC ( IZT3 , INTEGER , (ILG ) )
AUTOMATIC ( IZB , INTEGER , (ILG ) )
AUTOMATIC ( HBLK , REAL*8 , (ILG ) )
AUTOMATIC ( UAV , REAL*8 , (ILG ) )
AUTOMATIC ( VAV , REAL*8 , (ILG ) )
AUTOMATIC ( VELAV , REAL*8 , (ILG ) )
AUTOMATIC ( DELZ , REAL*8 , (ILG ) )
AUTOMATIC ( FDIR , REAL*8 , (ILG ) )
AUTOMATIC ( BLOFF , REAL*8 , (ILG ) )
c
AUTOMATIC ( U , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( V , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( TF , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( TH , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( S , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( SH , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( BVFREQ , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( UTENDGWD , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VTENDGWD , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VELN , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( ASQ , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( ASQI , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( ASQS , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( DEPFAC , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( GRAD , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( DENFAC , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( ZB , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( UTENDLLB , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VTENDLLB , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( UTENDLFT , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VTENDLFT , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( UTENDLWB , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VTENDLWB , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( UTENDTOT , REAL*8 , (ILG,ILEV) )
AUTOMATIC ( VTENDTOT , REAL*8 , (ILG,ILEV) )
**
integer i,l,ii,len,lrefm,jyes,jno
real*8 aux,eta,dz,uparl,piotwo,psi,cpsi,spsi,
+ fvert,amp,ampmax,vmin,v0,hmin,zero,unit,cdblk
**
vmin = 2.
v0 = 1.e-12
hmin = 3.
zero = 0.
unit = 1.
cdblk = 1.
**
len = il2 - il1 + 1
lref = ilev
lrefm = lref - 1
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c INITIAL STEPS
c
c--------------------------------------------------------------------
c Initialize total tendency
c
do l=1,ilev
do i=il1,il2
utend(i,l) = zero
vtend(i,l) = zero
enddo
enddo
c-------------------------------------------------------------------
c Find and gather active grid columns
c
c Wind and unit vector at reference level LREFM:
c
do i=il1,il2
vmod(i) = sqrt ( uu(i,lrefm)**2 + vv(i,lrefm)**2 )
if (vmod(i).le.vmin) vmod(i) = vmin
uub(i) = uu(i,lrefm)/vmod(i)
vvb(i) = vv(i,lrefm)/vmod(i)
enddo
c
c-------------------------------------------------------------------
c Gather columns where orographic drag is active
c
jyes = 0
jno = len + 1
c
do i=il1,il2
if ( gc(i).eq.-1. .and. vmod(i).gt.vmin .and.
+ height(i).ge.hmin ) then
jyes = jyes + 1
drag(jyes) = i
else
jno = jno - 1
drag(jno) = i
endif
enddo
c
c Check if there is AT LEAST ONE active column
c
if (jyes.le.0) then
goto 600
endif
c
do i=1,len
ii = drag(i) + il1 - 1
ub(i) = uub(ii)
vb(i) = vvb(ii)
vmodb(i) = vmod(ii)
env(i) = height(ii)
slp2(i) = slope(ii)
gamma
(i) = xcent(ii)
theta(i) = mtdir(ii)
enddo
c
do i=1,len
if (env(i) .lt. hmin) then
slpf(i) = slp2(i)/hmin
else
slpf(i) = slp2(i)/env(i)
endif
enddo
c
do l=1,ilev
do i=1,len
ii = drag(i) + il1 - 1
u(i,l) = uu(ii,l)
v(i,l) = vv(ii,l)
tf(i,l) = ttf(ii,l)
th(i,l) = tth(ii,l)
s(i,l) = ss(ii,l)
sh(i,l) = ssh(ii,l)
enddo
enddo
c
c--------------------------------------------------------------------
c Recalculate temperature at intermediate levels
c using a geometric average:
c
do l=1,ilev-1
do i=1,len
th(i,l) = sqrt( tf(i,l)*tf(i,l+1) )
enddo
enddo
do i=1,len
th(i,ilev) = tf(i,ilev)
enddo
c
c--------------------------------------------------------------------
c Calculate BF frequency at all active levels (no smoothing):
c
do l=2,ilev
do i=1,len
aux = ( grav*grav/(rgas*tf(i,l)) )*
+ ( rgocp - (s(i,l)/tf(i,l))*
+ (th(i,l)- th(i,l-1))/(sh(i,l) - sh(i,l-1)) )
if (aux.le.1.0e-10) then
bvfreq(i,l) = 1.0e-5
else
bvfreq(i,l) = sqrt( aux )
endif
enddo
enddo
do i=1,len
bvfreq(i,1) = bvfreq(i,2)
enddo
c
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c GRAVITY-WAVE DRAG
c
c--------------------------------------------------------------------
c Initialize tendencies
do l=1,ilev
do i=1,len
utendgwd(i,l) = zero
vtendgwd(i,l) = zero
enddo
enddo
c
if (gwdrag) then
c
c--------------------------------------------------------------------
c Project wind field on reference wind:
c
do l=1,ilev
do i=1,jyes
veln(i,l) = u(i,l)*ub(i)+v(i,l)*vb(i)
if (veln(i,l).le.v0) veln(i,l) = v0
enddo
enddo
c
c--------------------------------------------------------------------
c Stress field
c
c Compute stress at reference level:
c
do i=1,jyes
asq(i,lref) = env(i)*env(i)
asqs(i,lref) = env(i)*env(i)
asqi(i,lref) = env(i)*env(i)
depfac(i,lref) = taufac*grav
+ *(bvfreq(i,lrefm)*s(i,lrefm)*vmodb(i)/tf(i,lrefm))
+ *asq(i,lref)/rgas
enddo
c
c Compute stress at other levels (bottom-up):
c
do l=lrefm,1,-1
do i=1,jyes
asqi(i,l) = asq(i,l+1)
+ *(bvfreq(i,l+1)*s(i,l+1)*veln(i,l+1)/tf(i,l+1))
+ /(bvfreq(i,l) *s(i,l) *veln(i,l) /tf(i,l) )
if (veln(i,l).ge.1.) then
asqs(i,l) = 0.5*(veln(i,l)/bvfreq(i,l))**2
else
asqs(i,l) = 1.e-6
endif
if (asqi(i,l).le.asqs(i,l)) then
asq(i,l) = asqi(i,l)
else
asq(i,l) = asqs(i,l)
endif
depfac(i,l) = taufac*grav
+ *(bvfreq(i,l)*s(i,l)*veln(i,l)/tf(i,l))
+ *asq(i,l)/rgas
enddo
enddo
do i=1,jyes
depfac(i,lref) = depfac(i,lrefm)
enddo
c
c--------------------------------------------------------------------
c Compute gwd tendencies:
c
do i=1,jyes
if ((depfac(i,2) - depfac(i,1)).gt.1.e-10) then
eta = 1.
else
eta = 0.
endif
c
grad(i,1) = 2.*eta*depfac(i,1)
+ /( 2.*sh(i,1) + eta*3.*tau*depfac(i,1)/veln(i,1) )
utendgwd(i,1) = -ub(i)*grad(i,1)
vtendgwd(i,1) = -vb(i)*grad(i,1)
denfac(i,1) = grad(i,1)*3.*tau*depfac(i,1)/veln(i,1)
utendgwd(i,lref) = zero
vtendgwd(i,lref) = zero
enddo
c
do l=2,lrefm
do i=1,jyes
if ((depfac(i,l) - depfac(i,l-1)).gt.1.e-10) then
eta = 1.
else
eta = 0.
endif
grad(i,l) = ( 2.*depfac(i,l)-2.*depfac(i,l-1) +
+ eta*denfac(i,l-1) )/
+ ( 2.*(sh(i,l)-sh(i,l-1)) +
+ eta*3.*tau*depfac(i,l)/veln(i,l) )
utendgwd(i,l) = -ub(i)*grad(i,l)
vtendgwd(i,l) = -vb(i)*grad(i,l)
denfac(i,l) = grad(i,l)*3.*tau*depfac(i,l)/veln(i,l)
enddo
enddo
c
endif
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c LOW-LEVEL BLOCKING
c
c--------------------------------------------------------------------
c Initialize arrays
do l=1,ilev
do i=1,len
zb(i,l) = zero
utendllb(i,l) = zero
vtendllb(i,l) = zero
enddo
enddo
c
do i=1,len
izt1(i) = ilev-1
izt2(i) = ilev
izt3(i) = ilev
hblk(i) = zero
izb(i) = ilev
uav(i) = v0
vav(i) = v0
velav(i) = v0
delz(i) = zero
fdir(i) = unit
bloff(i) = 0
enddo
c
if (blocking) then
c--------------------------------------------------------------------
c Build elevation field:
do i=1,jyes
zb(i,ilev) = -(rgas/grav)*tf(i,ilev)*log(sh(i,ilev))
enddo
do l=ilev-1,1,-1
do i=1,jyes
zb(i,l) = zb(i,l+1) +
+ (rgas/grav)*tf(i,l)*log(sh(i,l+1)/sh(i,l))
enddo
enddo
c
c--------------------------------------------------------------------
c Blocking height
c
c Find maximum blocking level, upper level for averaging and
c lower level for averaging:
do l=ilev-2,1,-1
do i=1,jyes
if (zb(i,l).lt.(1.5*env(i))) izt3(i) = l
if (zb(i,l).lt. env(i) ) izt1(i) = l
enddo
enddo
c
do l=ilev-1,1,-1
do i=1,jyes
if (zb(i,l).lt.(0.5*env(i))) izt2(i) = l
enddo
enddo
c
c Compute averages:
do l=ilev,2,-1
do i=1,jyes
if (l.le.izt2(i) .and. l.ge.izt1(i)) then
dz = zb(i,l-1) - zb(i,l)
delz(i) = delz(i) + dz
uav(i) = uav(i) + dz*u(i,l)
vav(i) = vav(i) + dz*v(i,l)
endif
enddo
enddo
do i=1,jyes
uav(i) = uav(i)/delz(i)
vav(i) = vav(i)/delz(i)
if (abs(vav(i)).lt.v0 .and. abs(uav(i)).lt.v0) then
velav(i) = v0
else
velav(i) = sqrt( uav(i)**2 + vav(i)**2 )
endif
enddo
c
c Compute blocking height and blocking level:
c
do l=2,ilev
do i=1,jyes
if (l.ge.izt3(i) .and. bloff(i).eq.0) then
dz = zb(i,l-1) - zb(i,l)
uparl = (u(i,l)*uav(i) + v(i,l)*vav(i))/velav(i)
if (uparl .lt. v0) then
izb(i) = l-1
bloff(i) = 1
else
hblk(i) = hblk(i) + dz*bvfreq(i,l)/uparl
if (hblk(i) .gt. 0.5) then
izb(i) = l-1
bloff(i) = 1
endif
endif
endif
enddo
enddo
c
c--------------------------------------------------------------------
c Compute directional factor:
c
piotwo = .5*acos(-1.)
do i=1,jyes
c
c Angle between mean wind and topography:
if ( abs(vav(i)) .lt. v0 .and. abs(uav(i)) .lt. v0) then
psi = zero
else
psi = theta(i) - atan2(vav(i),uav(i))
if (psi .gt. piotwo ) psi = psi - 2.*piotwo
if (psi .lt. (-piotwo)) psi = psi + 2.*piotwo
endif
cpsi = ( cos(psi) )**2
spsi = ( sin(psi) )**2
c
c Directional factor:
amp = cpsi + gamma
(i)*spsi
if (amp .lt. 1.e-10) then
amp = zero
else
amp = 2. - ( gamma
(i)*cpsi + spsi )
+ /( cpsi + gamma
(i)*spsi )
if (amp.lt.zero) amp = zero
endif
fdir(i) = amp*
+ ( (1.-.18*gamma
(i) -.04*(gamma
(i)**2))*cpsi
+ +( .48*gamma
(i) +.30*(gamma
(i)**2))*spsi )
c
enddo
c--------------------------------------------------------------------
c Compute llb tendencies:
c
do l=ilev,1,-1
do i=1,jyes
if ( velav(i).ge.vmin .and.
+ l.gt.izb(i) .and. zb(i,izb(i)).ge.hmin ) then
c
c Vertical factor:
fvert = sqrt( (zb(i,izb(i)) - zb(i,l))
+ /(0.5*env(i) + zb(i,l)) )
c
c Drag intensity:
amp = 0.5*cdblk*slpf(i)*fdir(i)*fvert*
+ (u(i,l)**2 + v(i,l)**2)
ampmax = sqrt( u(i,l)**2 + v(i,l)**2 )/tau
if (amp.gt.ampmax) then
utendllb(i,l) = -u(i,l)/tau
vtendllb(i,l) = -v(i,l)/tau
else
utendllb(i,l) = -0.5*cdblk*slpf(i)*fdir(i)*fvert*
+ u(i,l)*sqrt(u(i,l)**2 + v(i,l)**2)
vtendllb(i,l) = -0.5*cdblk*slpf(i)*fdir(i)*fvert*
+ v(i,l)*sqrt(u(i,l)**2 + v(i,l)**2)
endif
endif
enddo
enddo
c
endif
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c OROGRAPHIC LIFT
c
c--------------------------------------------------------------------
c Initialize arrays
do l=1,ilev
do i=1,len
utendlft(i,l) = zero
vtendlft(i,l) = zero
enddo
enddo
c
if (orolift) then
c
endif
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c LEE-WAVE BREAKING
c
c--------------------------------------------------------------------
c Initialize arrays
do l=1,ilev
do i=1,len
utendlwb(i,l) = zero
vtendlwb(i,l) = zero
enddo
enddo
c
if (leewave) then
c
endif
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c TOTAL DRAG AND RESULTING WIND FIELD
c
c--------------------------------------------------------------------
do l=1,ilev
do i=1,len
utendtot(i,l) = zero
vtendtot(i,l) = zero
enddo
enddo
c
c Add and scatter tendencies
do l=1,ilev
do i=1,len
utendtot(i,l) = utendgwd(i,l) +
+ utendllb(i,l) +
+ utendlft(i,l) +
+ utendlwb(i,l)
vtendtot(i,l) = vtendgwd(i,l) +
+ vtendllb(i,l) +
+ vtendlft(i,l) +
+ vtendlwb(i,l)
enddo
enddo
c
do l=1,ilev
do i=1,len
ii = drag(i) + il1 - 1
utend(ii,l) = utendtot(i,l)
vtend(ii,l) = vtendtot(i,l)
enddo
enddo
c
c--------------------------------------------------------------------
600 continue
c--------------------------------------------------------------------
c Apply sgo tendency onto U and V:
c
if (applytend) then
c
do l=1,ilev
do i=il1,il2
uu(i,l) = uu(i,l) + tau*utend(i,l)
vv(i,l) = vv(i,l) + tau*vtend(i,l)
enddo
enddo
c
endif
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
return
end