forked from 3rdparty/wrf-python
8 changed files with 1901 additions and 34 deletions
@ -0,0 +1,404 @@
@@ -0,0 +1,404 @@
|
||||
CThe subroutines in this file were taken directly from RIP code written |
||||
C by Dr. Mark Stoelinga. They were modified by Sherrie |
||||
C Fredrick(NCAR/MMM) to work with NCL February 2015. |
||||
C NCLFORTSTART |
||||
subroutine wrf_monotonic(out,in,lvprs,cor,idir,delta, |
||||
& ew,ns,nz,icorsw) |
||||
implicit none |
||||
integer idir,ew,ns,nz,icorsw |
||||
double precision delta |
||||
double precision in(ew,ns,nz),out(ew,ns,nz) |
||||
double precision lvprs(ew,ns,nz),cor(ew,ns) |
||||
C NCLEND |
||||
|
||||
integer i,j,k,ripk,k300 |
||||
|
||||
do j=1,ns |
||||
do i=1,ew |
||||
if (icorsw.eq.1.and.cor(i,j).lt.0.) then |
||||
do k=1,nz |
||||
in(i,j,k)=-in(i,j,k) |
||||
enddo |
||||
endif |
||||
|
||||
|
||||
c |
||||
c First find k index that is at or below (height-wise) the 300 hPa |
||||
c level. |
||||
c |
||||
do k = 1,nz |
||||
ripk = nz-k+1 |
||||
if (lvprs(i,j,k) .le. 300.d0) then |
||||
k300=k |
||||
goto 40 |
||||
endif |
||||
enddo |
||||
c |
||||
40 continue |
||||
|
||||
do k = k300, 1,-1 |
||||
if (idir.eq.1) then |
||||
out(i,j,k)=min(in(i,j,k),in(i,j,k+1)+delta) |
||||
elseif (idir.eq.-1) then |
||||
out(i,j,k)=max(in(i,j,k),in(i,j,k+1)-delta) |
||||
endif |
||||
enddo |
||||
|
||||
|
||||
do k = k300+1, nz |
||||
if (idir.eq.1) then |
||||
out(i,j,k)=max(in(i,j,k),in(i,j,k-1)-delta) |
||||
elseif (idir.eq.-1) then |
||||
out(i,j,k)=min(in(i,j,k),in(i,j,k-1)+delta) |
||||
endif |
||||
enddo |
||||
|
||||
end do |
||||
end do |
||||
|
||||
return |
||||
end |
||||
|
||||
c-------------------------------------------------------------------- |
||||
|
||||
C NCLFORTSTART |
||||
FUNCTION wrf_intrp_value (wvalp0,wvalp1,vlev,vcp0,vcp1,icase) |
||||
implicit none |
||||
|
||||
integer icase |
||||
double precision wvalp0,wvalp1,vlev,vcp0,vcp1 |
||||
C NCLEND |
||||
double precision valp0,valp1,rvalue,rgas,ussalr,sclht |
||||
|
||||
double precision wrf_intrp_value,chkdiff |
||||
|
||||
rgas = 287.04d0 !J/K/kg |
||||
ussalr = 0.0065d0 ! deg C per m |
||||
sclht = rgas*256.d0/9.81d0 |
||||
|
||||
valp0 = wvalp0 |
||||
valp1 = wvalp1 |
||||
if ( icase .eq. 2) then !GHT |
||||
valp0=exp(-wvalp0/sclht) |
||||
valp1=exp(-wvalp1/sclht) |
||||
end if |
||||
|
||||
chkdiff = vcp1 - vcp0 |
||||
if(chkdiff .eq. 0) then |
||||
print *,"bad difference in vcp's" |
||||
stop |
||||
end if |
||||
|
||||
rvalue = (vlev-vcp0)*(valp1-valp0)/(vcp1-vcp0)+valp0 |
||||
if (icase .eq. 2) then !GHT |
||||
wrf_intrp_value = -sclht*log(rvalue) |
||||
else |
||||
wrf_intrp_value = rvalue |
||||
endif |
||||
|
||||
return |
||||
end |
||||
c------------------------------------------------------------ |
||||
C NOTES: |
||||
c vcarray is the array holding the values for the vertical |
||||
c coordinate. |
||||
c It will always come in with the dimensions of |
||||
c the staggered U and V grid. |
||||
C NCLFORTSTART |
||||
|
||||
subroutine wrf_vintrp(datain,dataout,pres,tk,qvp,ght,terrain, |
||||
& sfp,smsfp,vcarray,interp_levels,numlevels, |
||||
& icase,ew,ns,nz,extrap,vcor,logp,rmsg) |
||||
|
||||
|
||||
implicit none |
||||
integer ew,ns,nz,icase,extrap |
||||
integer vcor,numlevels,logp |
||||
double precision datain(ew,ns,nz),pres(ew,ns,nz),tk(ew,ns,nz) |
||||
double precision ght(ew,ns,nz) |
||||
double precision terrain(ew,ns),sfp(ew,ns),smsfp(ew,ns) |
||||
double precision dataout(ew,ns,numlevels),qvp(ew,ns,nz) |
||||
double precision vcarray(ew,ns,nz) |
||||
double precision interp_levels(numlevels),rmsg |
||||
C NCLEND |
||||
integer njx,niy,nreqlvs,ripk |
||||
integer i,j,k,itriv,kupper |
||||
integer ifound,miy,mjx,isign |
||||
double precision rlevel,vlev,diff |
||||
double precision tempout(ew,ns),tmpvlev |
||||
double precision vcp1,vcp0,valp0,valp1 |
||||
double precision rgas,rgasmd,sclht,ussalr,cvc,eps |
||||
double precision qvlhsl,ttlhsl,vclhsl,vctophsl |
||||
double precision wrf_intrp_value |
||||
double precision plhsl,zlhsl,ezlhsl,tlhsl,psurf,pratio,tlev |
||||
double precision ezsurf,psurfsm,zsurf,qvapor,vt |
||||
double precision rconst,expon,exponi |
||||
double precision ezlev,plev,zlev,ptarget,dpmin,dp |
||||
double precision pbot,zbot,tbotextrap,e |
||||
double precision tlclc1,tlclc2,tlclc3,tlclc4 |
||||
double precision thtecon1,thtecon2,thtecon3 |
||||
double precision tlcl,gamma,cp,cpmd,gammamd,gammam |
||||
character cvcord*1 |
||||
|
||||
rgas = 287.04d0 !J/K/kg |
||||
rgasmd = .608d0 |
||||
ussalr = .0065d0 ! deg C per m |
||||
sclht = rgas*256.d0/9.81d0 |
||||
eps = 0.622d0 |
||||
rconst = -9.81d0/(rgas * ussalr) |
||||
expon = rgas*ussalr/9.81d0 |
||||
exponi = 1./expon |
||||
tlclc1 = 2840.d0 |
||||
tlclc2 = 3.5d0 |
||||
tlclc3 = 4.805d0 |
||||
tlclc4 = 55.d0 |
||||
thtecon1 = 3376.d0 ! K |
||||
thtecon2 = 2.54d0 |
||||
thtecon3 = 0.81d0 |
||||
cp = 1004.d0 |
||||
cpmd = 0.887d0 |
||||
gamma = rgas/cp |
||||
gammamd = rgasmd-cpmd |
||||
|
||||
if(vcor .eq. 1) then |
||||
cvcord = 'p' |
||||
else if((vcor .eq. 2) .or. (vcor .eq. 3)) then |
||||
cvcord = 'z' |
||||
else if((vcor .eq. 4) .or. (vcor .eq. 5)) then |
||||
cvcord = 't' |
||||
end if |
||||
|
||||
|
||||
miy = ns |
||||
mjx = ew |
||||
njx = ew |
||||
niy = ns |
||||
|
||||
|
||||
do j = 1,mjx |
||||
do i = 1,miy |
||||
tempout(j,i) = rmsg |
||||
end do |
||||
end do |
||||
|
||||
|
||||
|
||||
do nreqlvs = 1,numlevels |
||||
if(cvcord .eq. 'z') then |
||||
!Convert rlevel to meters from km |
||||
|
||||
rlevel = interp_levels(nreqlvs) * 1000.d0 |
||||
vlev = exp(-rlevel/sclht) |
||||
else if(cvcord .eq. 'p') then |
||||
vlev = interp_levels(nreqlvs) |
||||
else if(cvcord .eq. 't') then |
||||
vlev = interp_levels(nreqlvs) |
||||
end if |
||||
|
||||
|
||||
do j=1,mjx |
||||
do i=1,miy |
||||
cGet the interpolated value that is within the model domain |
||||
ifound = 0 |
||||
do k = 1,nz-1 |
||||
ripk = nz-k+1 |
||||
vcp1 = vcarray(j,i,ripk-1) |
||||
vcp0 = vcarray(j,i,ripk) |
||||
valp0 = datain(j,i,ripk) |
||||
valp1 = datain(j,i,ripk-1) |
||||
if ((vlev.ge.vcp0.and.vlev.le.vcp1) .or. |
||||
& (vlev.le.vcp0.and.vlev.ge.vcp1)) then |
||||
c print *,i,j,valp0,valp1 |
||||
if((valp0 .eq. rmsg).or.(valp1 .eq. rmsg)) then |
||||
tempout(j,i) = rmsg |
||||
ifound=1 |
||||
else |
||||
if(logp .eq. 1) then |
||||
vcp1 = log(vcp1) |
||||
vcp0 = log(vcp0) |
||||
if(vlev .eq. 0.0d0) then |
||||
print *,"Pressure value = 0" |
||||
print *,"Unable to take log of 0" |
||||
stop |
||||
end if |
||||
tmpvlev = log(vlev) |
||||
else |
||||
tmpvlev = vlev |
||||
end if |
||||
tempout(j,i) = wrf_intrp_value(valp0,valp1, |
||||
& tmpvlev,vcp0,vcp1,icase) |
||||
c print *,"one ",i,j,tempout(j,i) |
||||
ifound=1 |
||||
end if |
||||
goto 115 |
||||
end if |
||||
end do !end for the k loop |
||||
115 continue |
||||
|
||||
|
||||
if (ifound.eq.1) then !Grid point is in the model domain |
||||
goto 333 |
||||
end if |
||||
|
||||
cIf the user has requested no extrapolatin then just assign |
||||
call values above or below the model level to rmsg. |
||||
if(extrap .eq. 0) then |
||||
tempout(j,i) = rmsg |
||||
goto 333 |
||||
end if |
||||
|
||||
|
||||
c The grid point is either above or below the model domain |
||||
c |
||||
c First we will check to see if the grid point is above the |
||||
c model domain. |
||||
vclhsl = vcarray(j,i,1) !lowest model level |
||||
vctophsl = vcarray(j,i,nz)!highest model level |
||||
diff = vctophsl-vclhsl |
||||
isign = nint(diff/abs(diff)) |
||||
C |
||||
if(isign*vlev.ge.isign*vctophsl) then |
||||
C Assign the highest model level to the out array |
||||
tempout(j,i)=datain(j,i,nz) |
||||
C print *,"at warn",j,i,tempout(j,i) |
||||
goto 333 |
||||
endif |
||||
|
||||
|
||||
c |
||||
c Only remaining possibility is that the specified level is below |
||||
c lowest model level. If lowest model level value is missing, |
||||
c set interpolated value to missing. |
||||
c |
||||
if (datain(i,j,1) .eq. rmsg) then |
||||
tempout(j,i) = rmsg |
||||
goto 333 |
||||
endif |
||||
|
||||
c |
||||
c If the field comming in is not a pressure,temperature or height |
||||
C field we can set the output array to the value at the lowest |
||||
c model level. |
||||
c |
||||
tempout(j,i) = datain(j,i,1) |
||||
c |
||||
c For the special cases of pressure on height levels or height on |
||||
c pressure levels, or temperature-related variables on pressure or |
||||
c height levels, perform a special extrapolation based on |
||||
c US Standard Atmosphere. Here we calcualate the surface pressure |
||||
c with the altimeter equation. This is how RIP calculates the |
||||
c surface pressure. |
||||
c |
||||
if (icase.gt.0) then |
||||
plhsl = pres(j,i,1) * 0.01d0 !pressure at lowest model level |
||||
zlhsl = ght(j,i,1) !grid point height a lowest model level |
||||
ezlhsl = exp(-zlhsl/sclht) |
||||
tlhsl = tk(j,i,1) !temperature in K at lowest model level |
||||
zsurf = terrain(j,i) |
||||
qvapor = max((qvp(j,i,1)*.001d0),1.e-15) |
||||
c virtual temperature |
||||
c vt = tlhsl * (eps + qvapor)/(eps*(1.0 + qvapor)) |
||||
c psurf = plhsl * (vt/(vt+ussalr * (zlhsl-zsurf)))**rconst |
||||
psurf = sfp(j,i) |
||||
psurfsm = smsfp(j,i) |
||||
ezsurf = exp(-zsurf/sclht) |
||||
|
||||
cThe if for checking above ground |
||||
if ((cvcord.eq.'z'.and.vlev.lt.ezsurf).or. |
||||
& (cvcord.eq.'p'.and.vlev.lt.psurf)) then |
||||
c |
||||
c We are below the lowest data level but above the ground. |
||||
c Use linear interpolation (linear in prs and exp-height). |
||||
c |
||||
if (cvcord.eq.'p') then |
||||
plev=vlev |
||||
ezlev=((plev-plhsl)*ezsurf+(psurf-plev)*ezlhsl)/ |
||||
& (psurf-plhsl) |
||||
zlev=-sclht*log(ezlev) |
||||
if (icase .eq. 2) then |
||||
tempout(j,i)=zlev |
||||
goto 333 |
||||
endif |
||||
|
||||
elseif (cvcord.eq.'z') then |
||||
ezlev=vlev |
||||
zlev=-sclht*log(ezlev) |
||||
plev=((ezlev-ezlhsl)*psurf+(ezsurf-ezlev)*plhsl)/ |
||||
& (ezsurf-ezlhsl) |
||||
if (icase .eq. 1) then |
||||
tempout(j,i)=plev |
||||
goto 333 |
||||
endif |
||||
endif |
||||
|
||||
else !else for checking above ground |
||||
ptarget=psurfsm-150.d0 |
||||
dpmin=1.e4 |
||||
do k=1,nz |
||||
ripk = nz-k+1 |
||||
dp=abs((pres(j,i,ripk) * 0.01d0)-ptarget) |
||||
if (dp.gt.dpmin) goto 334 |
||||
dpmin=min(dpmin,dp) |
||||
enddo |
||||
334 kupper=k-1 |
||||
|
||||
ripk = nz - kupper + 1 |
||||
pbot = max(plhsl,psurf) |
||||
zbot = min(zlhsl,zsurf) |
||||
pratio = pbot/(pres(j,i,ripk) * 0.01d0) |
||||
tbotextrap = tk(j,i,ripk)*(pratio)**expon |
||||
c virtual temperature |
||||
vt = tbotextrap * (eps + qvapor)/(eps*(1.0d0+qvapor)) |
||||
if (cvcord.eq.'p') then |
||||
plev=vlev |
||||
zlev=zbot+vt/ussalr*(1.-(vlev/pbot)**expon) |
||||
if(icase .eq. 2) then |
||||
tempout(j,i)=zlev |
||||
goto 333 |
||||
endif |
||||
elseif (cvcord.eq.'z') then |
||||
zlev=-sclht*log(vlev) |
||||
plev=pbot*(1.+ussalr/vt*(zbot-zlev))**exponi |
||||
if (icase .eq. 1) then |
||||
tempout(j,i)=plev |
||||
goto 333 |
||||
endif |
||||
endif |
||||
end if !end if for checking above ground |
||||
end if !for icase gt 0 |
||||
|
||||
|
||||
if(icase .gt. 2) then !extrapolation for temperature |
||||
tlev=tlhsl+(zlhsl-zlev)*ussalr |
||||
qvapor = max(qvp(j,i,1),1.e-15) |
||||
gammam = gamma*(1.+gammamd*qvapor) |
||||
if(icase .eq. 3) then |
||||
tempout(j,i) = tlev - 273.16d0 |
||||
else if(icase .eq. 4) then |
||||
tempout(j,i) = tlev |
||||
C Potential temperature - theta |
||||
else if (icase. eq. 5) then |
||||
tempout(j,i)=tlev*(1000.d0/plev)**gammam |
||||
C extraolation for equivalent potential temperature |
||||
else if (icase .eq. 6) then |
||||
e = qvapor*plev/(eps+qvapor) |
||||
tlcl = tlclc1/(log(tlev**tlclc2/e)-tlclc3)+tlclc4 |
||||
tempout(j,i)=tlev*(1000.d0/plev)**(gammam)* |
||||
& exp((thtecon1/tlcl-thtecon2)*qvapor* |
||||
& (1.+thtecon3*qvapor)) |
||||
end if |
||||
end if |
||||
|
||||
333 continue |
||||
|
||||
end do |
||||
end do |
||||
! print *,"----done----",interp_levels(nreqlvs) |
||||
do i = 1,njx |
||||
do j = 1,niy |
||||
dataout(i,j,nreqlvs) = tempout(i,j) |
||||
end do |
||||
end do |
||||
end do !end for the nreqlvs |
||||
return |
||||
end !wrf_vinterp |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue