Subversion Repositories pvinversion.ecmwf

Compare Revisions

No changes between revisions

Ignore whitespace Rev 2 → Rev 3

/trunk/diag/calc_qgpv.f
0,0 → 1,819
PROGRAM main_calc_qgpv
 
c ********************************************************************************
c * CALCULATE QUASI-GEOSTROPHIC PV ACCORDING TO ITS DEFINITION *
c * Michael Sprenger / Summer, Autumn 2006 *
c ********************************************************************************
 
c --------------------------------------------------------------------------------
c Declaration of variables, parameters, externals and common blocks
c --------------------------------------------------------------------------------
 
implicit none
 
c Input and output file
character*80 diagfile
character*80 referfile
 
c Grid parameters
integer nx,ny,nz
real xmin,ymin,zmin,xmax,ymax,zmax
real dx,dy,dz
real deltax,deltay,deltaz
real mdv
real, allocatable,dimension (:,:) :: coriol
 
c Reference state
real, allocatable,dimension (:) :: nsqref
real, allocatable,dimension (:) :: thetaref
real, allocatable,dimension (:) :: rhoref
real, allocatable,dimension (:) :: pressref
real, allocatable,dimension (:) :: zref
 
c 3d fields for calculation of qgPV
real,allocatable,dimension (:,:,:) :: qgpv,th,uu,vv
 
c Auxiliary variables
integer i,j,k
integer stat
character*80 varname
 
c --------------------------------------------------------------------------------
c Input
c --------------------------------------------------------------------------------
 
print*,'********************************************************'
print*,'* CALC_QGPV *'
print*,'********************************************************'
 
c Read parameter file
open(10,file='fort.10')
read(10,*) diagfile
read(10,*) referfile
close(10)
print*
print*,trim(diagfile)
print*,trim(referfile)
print*
 
c Get lat/lon gid parameters from input file
call read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
> diagfile)
print*,'Read_Dim: nx,ny,nz = ',nx,ny,nz
print*,' dx,dy,dz = ',dx,dy,dz
print*,' xmin,ymin,zmin = ',xmin,ymin,zmin
print*,' mdv = ',mdv
print*
 
c Count from 0, not from 1: consistent with <inv_cart.f>.
nx=nx-1
ny=ny-1
nz=nz-1
 
c Allocate memory for Coriolis parameters
allocate(coriol(0:nx,0:ny),STAT=stat)
if (stat.ne.0) print*,'error allocating coriol'
 
c Allocate memory for reference profile
allocate(rhoref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating rhoref'
allocate(pressref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating pressref'
allocate(thetaref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating thetaref'
allocate(nsqref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating nsqref'
allocate(zref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating zref'
c Allocate memory for 3d fields
allocate(qgpv(0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating qgpv'
allocate(uu(0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating uu'
allocate(vv(0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating vv'
allocate(th(0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating th'
 
c --------------------------------------------------------------------------------
c Calculate the qgPV from definition and put it onto file
c --------------------------------------------------------------------------------
 
c Read data from file
varname='U'
call read_inp (uu,varname,diagfile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
varname='V'
call read_inp (vv,varname,diagfile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
varname='TH'
call read_inp (th,varname,diagfile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
 
c Read reference profile and grid parameters
call read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,coriol,
> referfile)
deltax=1000.*deltax
deltay=1000.*deltay
print*,'Deltax,deltay,deltaz =',deltax,deltay,deltaz
 
c Calculate qgPV
print*,'C qgPV'
call calc_qgpv (qgpv,uu,vv,th,
> rhoref,pressref,nsqref,thetaref,coriol,
> nx,ny,nz,deltax,deltay,deltaz,mdv)
 
c Write result to netcdf file
varname='QGPV_DIA'
call write_inp (qgpv,varname,diagfile,nx,ny,nz)
 
end
 
c ********************************************************************************
c * NETCDF OUTPUT *
c ********************************************************************************
 
c --------------------------------------------------------------------------------
c Write input field to netcdf
c --------------------------------------------------------------------------------
 
SUBROUTINE write_inp (field,fieldname,pvsrcfile,nx,ny,nz)
 
c Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specified
c by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the input
c files are consitent with this grid.
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real field (0:nx,0:ny,0:nz)
character*80 fieldname
character*80 pvsrcfile
 
c Auxiliary variables
integer cdfid,stat
integer vardim(4)
real misdat
real varmin(4),varmax(4),stag(4)
integer ndimin,outid,i,j,k
real max_th
real tmp(0:nx,0:ny,0:nz)
integer ntimes
real time(200)
integer nvars
character*80 vnam(100),varname
integer isok
 
c Get grid parameters from THETA
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 998
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 998
isok=0
varname='TH'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 998
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 998
call clscdf(cdfid,stat)
if (stat.ne.0) goto 998
 
c Save variables (write definition, if necessary)
call cdfwopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 998
isok=0
varname=fieldname
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
endif
call putdat(cdfid,varname,time(1),0,field,stat)
print*,'W ',trim(varname),' ',trim(pvsrcfile)
if (stat.ne.0) goto 998
 
c Close input netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 998
return
 
c Exception handling
998 print*,'Write_Inp: Problem with input netcdf file... Stop'
stop
 
end
 
c --------------------------------------------------------------------------------
c Read input fields
c --------------------------------------------------------------------------------
 
SUBROUTINE read_inp (field,fieldname,pvsrcfile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
 
c Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specified
c by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the input
c files are consitent with this grid. The missing data value is set to <mdv>.
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real field(0:nx,0:ny,0:nz)
character*80 fieldname
character*80 pvsrcfile
real dx,dy,dz,xmin,ymin,zmin
real mdv
 
c Numerical and physical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,stat,cdfid99
integer vardim(4)
real misdat
real varmin(4),varmax(4),stag(4)
integer ndimin,outid,i,j,k
real max_th
real tmp(nx,ny,nz)
integer ntimes
real time(200)
integer nvars
character*80 vnam(100),varname
integer isok
 
c Open the input netcdf file
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 998
 
c Check whether needed variables are on file
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 998
isok=0
varname=trim(fieldname)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 998
 
c Get the grid parameters from theta
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 998
 
c Check whether grid parameters are consistent
if ( (vardim(1).ne.(nx+1)).or.
> (vardim(2).ne.(ny+1)).or.
> (vardim(3).ne.(nz+1)).or.
> (abs(varmin(1)-xmin).gt.eps).or.
> (abs(varmin(2)-ymin).gt.eps).or.
> (abs(varmin(3)-zmin).gt.eps).or.
> (abs((varmax(1)-varmin(1))/real(vardim(1)-1)-dx).gt.eps).or.
> (abs((varmax(2)-varmin(2))/real(vardim(2)-1)-dy).gt.eps).or.
> (abs((varmax(3)-varmin(3))/real(vardim(3)-1)-dz).gt.eps) )
>then
print*,'Input grid inconsitency...'
print*,' Nx = ',vardim(1),nx+1
print*,' Ny = ',vardim(2),ny+1
print*,' Nz = ',vardim(3),nz+1
print*,' Varminx = ',varmin(1),xmin
print*,' Varminy = ',varmin(2),ymin
print*,' Varminz = ',varmin(3),zmin
print*,' Dx = ',(varmax(1)-varmin(1))/real(nx-1),dx
print*,' Dy = ',(varmax(2)-varmin(2))/real(ny-1),dy
print*,' Dz = ',(varmax(3)-varmin(3))/real(nz-1),dz
goto 998
endif
 
c Load variables
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
call getdat(cdfid,varname,time(1),0,field,stat)
print*, 'R ',trim(varname),' ',trim(pvsrcfile)
if (stat.ne.0) goto 998
 
c Close input netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 998
 
c Set missing data value to <mdv>
do i=1,nx
do j=1,ny
do k=1,nz
if (abs(field(i,j,k)-misdat).lt.eps) then
field(i,j,k)=mdv
endif
enddo
enddo
enddo
 
return
 
c Exception handling
998 print*,'Read_Inp: Problem with input netcdf file... Stop'
stop
 
end
 
c --------------------------------------------------------------------------------
c Read refernece profile from netcdf
c --------------------------------------------------------------------------------
 
SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,coriol,
> pvsrcfile)
 
c Read the reference profile from file
c
c thetaref : Reference potential temperature (K)
c pressref : Reference pressure (Pa)
c rhoref : Reference density (kg/m^3)
c nsqref : Stratification (s^-1)
c zref : Reference height (m)
c nx,nny,nz : Grid dimension in x,y,z direction
c deltax,deltay,deltaz : Grid spacings used for calculations (m)
c coriol : Coriolis parameter (s^-1)
c pvsrcfile : Input file
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real nsqref (0:2*nz)
real thetaref(0:2*nz)
real rhoref (0:2*nz)
real pressref(0:2*nz)
real zref (0:2*nz)
real deltax,deltay,deltaz
real coriol (0:nx,0:ny)
character*80 pvsrcfile
 
c Numerical and physical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,stat
integer vardim(4)
real misdat
integer ndimin
real varmin(4),varmax(4),stag(4)
integer i,j,k,nf1
integer ntimes
real time(200)
character*80 vnam(100),varname
integer nvars
integer isok,ierr
real x(0:nx,0:ny),y(0:nx,0:ny)
real mean,count
 
c Get grid description from topography
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
isok=0
varname='ORO'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 997
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 997
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Open output netcdf file
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
c Create the variable if necessary
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
 
c Read data from netcdf file
isok=0
varname='NSQREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,nsqref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='RHOREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,rhoref,stat)
if (stat.ne.0) goto 997
isok=0
varname='THETAREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,thetaref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='PREREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,pressref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='ZREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,zref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='CORIOL'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,coriol,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='X'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,x,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='Y'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,y,stat)
if (stat.ne.0) goto 997
 
c Close netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Determine the grid spacings <deltax, deltay, deltaz>
mean=0.
count=0.
do i=1,nx
do j=0,ny
mean=mean+abs(x(i,j)-x(i-1,j))
count=count+1.
enddo
enddo
deltax=mean/count
 
mean=0.
count=0.
do j=1,ny
do i=0,nx
mean=mean+abs(y(i,j)-y(i,j-1))
count=count+1.
enddo
enddo
deltay=mean/count
 
mean=0.
count=0.
do k=1,nz-1
mean=mean+abs(zref(k+1)-zref(k-1))
count=count+1.
enddo
deltaz=mean/count
 
return
 
c Exception handling
997 print*,'Read_Ref: Problem with input netcdf file... Stop'
stop
 
end
 
 
c --------------------------------------------------------------------------------
c Check whether variable is found on netcdf file
c --------------------------------------------------------------------------------
 
subroutine check_varok (isok,varname,varlist,nvars)
 
c Check whether the variable <varname> is in the list <varlist(nvars)>. If this is
C the case, <isok> is incremented by 1. Otherwise <isok> keeps its value.
 
implicit none
 
c Declaraion of subroutine parameters
integer isok
integer nvars
character*80 varname
character*80 varlist(nvars)
 
c Auxiliary variables
integer i
 
c Main
do i=1,nvars
if (trim(varname).eq.trim(varlist(i))) isok=isok+1
enddo
 
end
 
c --------------------------------------------------------------------------------
c Get grid parameters
c --------------------------------------------------------------------------------
 
subroutine read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
> pvsrcfile)
 
c Get the grid parameters from the variable <THETA> on the input file <pvsrcfile>.
c The grid parameters are
c nx,ny,nz : Number of grid points in x, y and z direction
c xmin,ymin,zmin : Minimum domain coordinates in x, y and z direction
c xmax,ymax,zmax : Maximal domain coordinates in x, y and z direction
c dx,dy,dz : Horizontal and vertical resolution
c Additionally, it is checked whether the vertical grid is equally spaced. If ok,
c the grid paramters are transformed from lon/lat to distance (in meters)
 
implicit none
 
c Declaration of subroutine parameters
character*80 pvsrcfile
integer nx,ny,nz
real dx,dy,dz
real xmin,ymin,zmin,xmax,ymax,zmax
real mdv
 
c Numerical epsilon and other physical/geoemtrical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,cstid
integer ierr
character*80 vnam(100),varname
integer nvars
integer isok
integer vardim(4)
real misdat
real varmin(4),varmax(4),stag(4)
real aklev(1000),bklev(1000),aklay(1000),bklay(1000)
real dh
character*80 csn
integer ndim
integer i
 
c Get all grid parameters
call cdfopn(pvsrcfile,cdfid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,nvars,vnam,ierr)
if (ierr.ne.0) goto 998
isok=0
varname='TH'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 998
call getcfn(cdfid,csn,ierr)
if (ierr.ne.0) goto 998
call cdfopn(csn,cstid,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,varname,ndim,misdat,vardim,varmin,varmax,
> stag,ierr)
if (ierr.ne.0) goto 998
nx=vardim(1)
ny=vardim(2)
nz=vardim(3)
xmin=varmin(1)
ymin=varmin(2)
zmin=varmin(3)
call getlevs(cstid,nz,aklev,bklev,aklay,bklay,ierr)
if (ierr.ne.0) goto 998
call getgrid(cstid,dx,dy,ierr)
if (ierr.ne.0) goto 998
xmax=varmax(1)
ymax=varmax(2)
zmax=varmax(3)
dz=(zmax-zmin)/real(nz-1)
call clscdf(cstid,ierr)
if (ierr.ne.0) goto 998
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Check whether the grid is equallay spaced in the vertical
do i=1,nz-1
dh=aklev(i+1)-aklev(i)
if (abs(dh-dz).gt.eps) then
print*,'Aklev: Vertical grid must be equally spaced... Stop'
print*,(aklev(i),i=1,nz)
stop
endif
dh=aklay(i+1)-aklay(i)
if (abs(dh-dz).gt.eps) then
print*,'Aklay: Vertical grid must be equally spaced... Stop'
print*,(aklay(i),i=1,nz)
stop
endif
enddo
 
c Set missing data value
mdv=misdat
 
return
 
c Exception handling
998 print*,'Read_Dim: Problem with input netcdf file... Stop'
stop
 
end
 
 
 
c --------------------------------------------------------------------------------
c Calculate qgPV from wind and theta
c --------------------------------------------------------------------------------
 
subroutine calc_qgpv (qgpv,uu,vv,th,
> rhoref,pressref,nsqref,thetaref,coriol,
> nx,ny,nz,deltax,deltay,deltaz,mdv)
 
c Calculate qgPV from wind and potential temperature according to
c equation 2.9 p 16 Thesis Rene Fehlmann. Note a cartesian grid with
c equidistant grid spacings <deltax,deltay,deltaz> is assumend. No
c 'correction' is made for spherical geoemtry.
 
implicit none
c Declaration of subroutine parameters
integer nx,ny,nz
real qgpv(0:nx,0:ny,0:nz)
real uu(0:nx,0:ny,0:nz)
real vv(0:nx,0:ny,0:nz)
real th(0:nx,0:ny,0:nz)
real rhoref(0:2*nz)
real nsqref(0:2*nz)
real thetaref(0:2*nz)
real pressref(0:2*nz)
real deltax,deltay,deltaz
real mdv
real coriol(0:nx,0:ny)
 
c Numerical epsilon and physical constants
real g
parameter (g=9.81)
real eps
parameter (eps=0.01)
real scale
parameter (scale=1e6)
 
c Auxiliary variables
integer i,j,k
integer kk,jj
real dvdx(0:nx,0:ny,0:nz)
real dudy(0:nx,0:ny,0:nz)
real dtdz(0:nx,0:ny,0:nz)
real t1,t2
c Calculate horizontal derivatives dudy and dvdx of velocity
do k=0,nz
do j=0,ny
do i=0,nx
c Calculate dudy
if (j.eq.0) then
if ( (abs(uu(i,1,k)-mdv).gt.eps).and.
> (abs(uu(i,0,k)-mdv).gt.eps)) then
dudy(i,0,k)=(uu(i,1,k)-uu(i,0,k))/deltay
else
dudy(i,0,k)=mdv
endif
elseif (j.eq.ny) then
if ( (abs(uu(i,ny, k)-mdv).gt.eps).and.
> (abs(uu(i,ny-1,k)-mdv).gt.eps)) then
dudy(i,ny,k)=(uu(i,ny,k)-uu(i,ny-1,k))/deltay
else
dudy(i,ny,k)=mdv
endif
else
if ( (abs(uu(i,j+1,k)-mdv).gt.eps).and.
> (abs(uu(i,j-1,k)-mdv).gt.eps)) then
dudy(i,j,k)=(uu(i,j+1,k)-uu(i,j-1,k))/(2.*deltay)
else
dudy(i,j,k)=mdv
endif
endif
 
c Calculate dvdx
if (i.eq.0) then
if ((abs(vv(1,j,k)-mdv).gt.eps).and.
> (abs(vv(0,j,k)-mdv).gt.eps)) then
dvdx(0,j,k)=(vv(1,j,k)-vv(0,j,k))/deltax
else
dvdx(0,j,k)=mdv
endif
elseif (i.eq.nx) then
if ((abs(vv(nx, j,k)-mdv).gt.eps).and.
> (abs(vv(nx-1,j,k)-mdv).gt.eps)) then
dvdx(nx,j,k)=(vv(nx,j,k)-vv(nx-1,j,k))/deltax
else
dvdx(nx,j,k)=mdv
endif
else
if ((abs(vv(i+1,j,k)-mdv).gt.eps).and.
> (abs(vv(i-1,j,k)-mdv).gt.eps)) then
dvdx(i,j,k)=(vv(i+1,j,k)-vv(i-1,j,k))/(2.*deltax)
else
dvdx(i,j,k)=mdv
endif
endif
 
enddo
enddo
enddo
 
c Calculate vertical derivative of potential temperature
do i=0,nx
do j=0,ny
do k=0,nz
 
if (k.eq.0) then
if ((abs(th(i,j,2)-mdv).gt.eps).and.
> (abs(th(i,j,1)-mdv).gt.eps)) then
t1=rhoref(2)*th(i,j,1)/thetaref(2)/nsqref(2)*g
t2=rhoref(0)*th(i,j,0)/thetaref(0)/nsqref(0)*g
dtdz(i,j,0)=(t1-t2)/deltaz
else
dtdz(i,j,0)=mdv
endif
else if (k.eq.nz) then
if ((abs(th(i,j,nz )-mdv).gt.eps).and.
> (abs(th(i,j,nz-1)-mdv).gt.eps)) then
kk=2*nz
t1=rhoref(kk )*th(i,j,nz )/
> thetaref(kk)/nsqref(kk)*g
t2=rhoref(kk-2)*th(i,j,nz-1)/
> thetaref(kk-2)/nsqref(kk-2)*9.8
dtdz(i,j,nz)=(t1-t2)/deltaz
else
dtdz(i,j,nz)=mdv
endif
else
if ((abs(th(i,j,k+1)-mdv).gt.eps).and.
> (abs(th(i,j,k )-mdv).gt.eps).and.
> (abs(th(i,j,k-1)-mdv).gt.eps)) then
kk=2*k
t1=rhoref(kk+1)*(th(i,j,k)+th(i,j,k+1))/2.
> /thetaref(kk+1)/nsqref(kk+1)*g
t2=rhoref(kk-1)*(th(i,j,k)+th(i,j,k-1))/2.
> /thetaref(kk-1)/nsqref(kk-1)*g
dtdz(i,j,k)=(t1-t2)/deltaz
else
dtdz(i,j,k)=mdv
endif
endif
enddo
enddo
enddo
c Calculate qgPV
do i=0,nx
do j=0,ny
do k=0,nz
kk=2*k
 
if ((abs(dudy(i,j,k)-mdv).gt.eps).and.
> (abs(dvdx(i,j,k)-mdv).gt.eps).and.
> (abs(dtdz(i,j,k)-mdv).gt.eps)) then
qgpv(i,j,k)=-dudy(i,j,k)+dvdx(i,j,k)+
> coriol(i,j)*dtdz(i,j,k)/rhoref(kk)
else
qgpv(i,j,k)=mdv
endif
enddo
enddo
enddo
 
end
 
Property changes:
Added: svn:executable
/trunk/diag/check_boundcon.f
0,0 → 1,871
 
PROGRAM set_boundcon
 
c ************************************************************************
c * Set boundary conditions for inversion; lower and upper boundary *
c * conditions for potential temperature; lateral boundary conditions *
c * for zonal and meridional wind; in particular, missing data values *
c * are removed. *
c * *
c * Michael Sprenger / Summer 2006 *
c ************************************************************************
 
c --------------------------------------------------------------------------------
c Declaration of variables, parameters, externals and common blocks
c --------------------------------------------------------------------------------
 
implicit none
 
c Input and output file
character*80 anomafile
character*80 referfile
 
c Grid parameters
integer nx,ny,nz
real xmin,ymin,zmin,xmax,ymax,zmax
real dx,dy,dz
real mdv
real deltax,deltay,deltaz
real, allocatable,dimension (:,:) :: coriol
 
c Reference state
real, allocatable,dimension (:) :: nsqref
real, allocatable,dimension (:) :: thetaref
real, allocatable,dimension (:) :: rhoref
real, allocatable,dimension (:) :: pressref
real, allocatable,dimension (:) :: zref
 
C Boundary conditions
real, allocatable,dimension (:,:) :: thetatop
real, allocatable,dimension (:,:) :: thetabot
real, allocatable,dimension (:,:) :: ua
real, allocatable,dimension (:,:) :: ub
real, allocatable,dimension (:,:) :: va
real, allocatable,dimension (:,:) :: vb
 
c 3d arrays
real,allocatable,dimension (:,:,:) :: th_anom,pv_anom
real,allocatable,dimension (:,:,:) :: uu_anom,vv_anom
 
c Auxiliary variables
integer i,j,k,kk
integer stat
character*80 varname
integer n1,n2
c --------------------------------------------------------------------------------
c Input
c --------------------------------------------------------------------------------
 
print*,'********************************************************'
print*,'* CHECK_BOUNDCON *'
print*,'********************************************************'
 
c Read parameter file
open(10,file='fort.10')
read(10,*) anomafile
read(10,*) referfile
close(10)
print*
print*,trim(anomafile)
print*,trim(referfile)
print*
 
c Get lat/lon gid parameters from input file
call read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
> anomafile)
print*,'Read_Dim: nx,ny,nz = ',nx,ny,nz
print*,' dx,dy,dz = ',dx,dy,dz
print*,' xmin,ymin,zmin = ',xmin,ymin,zmin
print*,' mdv = ',mdv
print*
 
c Count from 0, not from 1: consistent with <inv_cart.f>.
nx=nx-1
ny=ny-1
nz=nz-1
 
c Allocate memory for 3d arrays
allocate(pv_anom (0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating pv_anom'
allocate(th_anom (0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating th_anom'
allocate(uu_anom (0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating uu_anom'
allocate(vv_anom (0:nx,0:ny,0:nz),STAT=stat)
if (stat.ne.0) print*,'error allocating vv_anom'
 
c Allocate memory for reference profile
allocate(rhoref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating rhoref'
allocate(pressref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating pressref'
allocate(thetaref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating thetaref'
allocate(nsqref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating nsqref'
allocate(zref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating zref'
 
c Allocate memory for Coriolis parameter
allocate(coriol(0:nx,0:ny),STAT=stat)
if (stat.ne.0) print*,'error allocating f'
 
c Allocate memory for boundary conditions
allocate(thetatop(0:nx,0:ny),stat=stat)
if (stat.ne.0) print*,'*** error allocating array thetatop ***'
allocate(thetabot(0:nx,0:ny),stat=stat)
if (stat.ne.0) print*,'*** error allocating array thetabot ***'
allocate(ua(0:nx,0:nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ua ***'
allocate(ub(0:nx,0:nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ub ***'
allocate(va(0:ny,0:nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array va ***'
allocate(vb(0:ny,0:nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array vb ***'
 
c Read reference profile and ngrid parameters
call read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,coriol,
> referfile)
deltax=1000.*deltax
deltay=1000.*deltay
print*,'Deltax,deltay,deltaz =',deltax,deltay,deltaz
c Read data from MOD file
varname='QGPV'
call read_inp (pv_anom,varname,anomafile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
varname='TH'
call read_inp (th_anom,varname,anomafile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
varname='U'
call read_inp (uu_anom,varname,anomafile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
varname='V'
call read_inp (vv_anom,varname,anomafile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
 
 
c --------------------------------------------------------------------------------
c Consistency check for boundary conditions and adaptions
c --------------------------------------------------------------------------------
 
c Copy 3d to boundary conditions
do i=0,nx
do j=0,ny
thetatop(i,j)=th_anom(i,j,nz)
thetabot(i,j)=th_anom(i,j,0)
enddo
enddo
do i=0,nx
do k=0,nz
ua(i,k)=uu_anom(i, 0,k)
ub(i,k)=uu_anom(i,ny,k)
enddo
enddo
do j=0,ny
do k=0,nz
va(j,k)=vv_anom( 0,j,k)
vb(j,k)=vv_anom(nx,j,k)
enddo
enddo
 
c Check the lower and upper boundary condition for consistency check
print*
call combouncon(pv_anom,nsqref,rhoref,thetatop,
> thetabot,thetaref,coriol,ua,ub,va,vb,
> nx,ny,nz,deltax,deltay,deltaz)
print*
 
 
end
 
 
c ********************************************************************************
c * NETCDF INPUT AND OUTPUT *
c ********************************************************************************
 
c --------------------------------------------------------------------------------
c Read input fields for reference profile
c --------------------------------------------------------------------------------
 
SUBROUTINE read_inp (field,fieldname,pvsrcfile,
> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
 
c Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specified
c by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the input
c files are consitent with this grid. The missing data value is set to <mdv>.
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real field(0:nx,0:ny,0:nz)
character*80 fieldname
character*80 pvsrcfile
real dx,dy,dz,xmin,ymin,zmin
real mdv
 
c Numerical and physical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,stat,cdfid99
integer vardim(4)
real misdat
real varmin(4),varmax(4),stag(4)
integer ndimin,outid,i,j,k
real max_th
real tmp(nx,ny,nz)
integer ntimes
real time(200)
integer nvars
character*80 vnam(100),varname
integer isok
 
c Open the input netcdf file
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 998
 
c Check whether needed variables are on file
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 998
isok=0
varname=trim(fieldname)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 998
 
c Get the grid parameters from theta
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 998
 
c Check whether grid parameters are consistent
if ( (vardim(1).ne.(nx+1)).or.
> (vardim(2).ne.(ny+1)).or.
> (vardim(3).ne.(nz+1)).or.
> (abs(varmin(1)-xmin).gt.eps).or.
> (abs(varmin(2)-ymin).gt.eps).or.
> (abs(varmin(3)-zmin).gt.eps).or.
> (abs((varmax(1)-varmin(1))/real(vardim(1)-1)-dx).gt.eps).or.
> (abs((varmax(2)-varmin(2))/real(vardim(2)-1)-dy).gt.eps).or.
> (abs((varmax(3)-varmin(3))/real(vardim(3)-1)-dz).gt.eps) )
>then
print*,'Input grid inconsitency...'
print*,' Nx = ',vardim(1),nx+1
print*,' Ny = ',vardim(2),ny+1
print*,' Nz = ',vardim(3),nz+1
print*,' Varminx = ',varmin(1),xmin
print*,' Varminy = ',varmin(2),ymin
print*,' Varminz = ',varmin(3),zmin
print*,' Dx = ',(varmax(1)-varmin(1))/real(nx-1),dx
print*,' Dy = ',(varmax(2)-varmin(2))/real(ny-1),dy
print*,' Dz = ',(varmax(3)-varmin(3))/real(nz-1),dz
goto 998
endif
 
c Load variables
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 998
call getdat(cdfid,varname,time(1),0,field,stat)
print*, 'R ',trim(varname),' ',trim(pvsrcfile)
if (stat.ne.0) goto 998
 
c Close input netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 998
 
c Set missing data value to <mdv>
do i=1,nx
do j=1,ny
do k=1,nz
if (abs(field(i,j,k)-misdat).lt.eps) then
field(i,j,k)=mdv
endif
enddo
enddo
enddo
 
return
 
c Exception handling
998 print*,'Read_Inp: Problem with input netcdf file... Stop'
stop
 
end
 
c --------------------------------------------------------------------------------
c Check whether variable is found on netcdf file
c --------------------------------------------------------------------------------
 
subroutine check_varok (isok,varname,varlist,nvars)
 
c Check whether the variable <varname> is in the list <varlist(nvars)>. If this is
C the case, <isok> is incremented by 1. Otherwise <isok> keeps its value.
 
implicit none
 
c Declaraion of subroutine parameters
integer isok
integer nvars
character*80 varname
character*80 varlist(nvars)
 
c Auxiliary variables
integer i
 
c Main
do i=1,nvars
if (trim(varname).eq.trim(varlist(i))) isok=isok+1
enddo
 
end
 
c --------------------------------------------------------------------------------
c Get grid parameters
c --------------------------------------------------------------------------------
 
subroutine read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
> pvsrcfile)
 
c Get the grid parameters from the variable <THETA> on the input file <pvsrcfile>.
c The grid parameters are
c nx,ny,nz : Number of grid points in x, y and z direction
c xmin,ymin,zmin : Minimum domain coordinates in x, y and z direction
c xmax,ymax,zmax : Maximal domain coordinates in x, y and z direction
c dx,dy,dz : Horizontal and vertical resolution
c Additionally, it is checked whether the vertical grid is equally spaced. If ok,
c the grid paramters are transformed from lon/lat to distance (in meters)
 
implicit none
 
c Declaration of subroutine parameters
character*80 pvsrcfile
integer nx,ny,nz
real dx,dy,dz
real xmin,ymin,zmin,xmax,ymax,zmax
real mdv
 
c Numerical epsilon and other physical/geoemtrical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,cstid
integer ierr
character*80 vnam(100),varname
integer nvars
integer isok
integer vardim(4)
real misdat
real varmin(4),varmax(4),stag(4)
real aklev(1000),bklev(1000),aklay(1000),bklay(1000)
real dh
character*80 csn
integer ndim
integer i
 
c Get all grid parameters
call cdfopn(pvsrcfile,cdfid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,nvars,vnam,ierr)
if (ierr.ne.0) goto 998
isok=0
varname='QGPV'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 998
call getcfn(cdfid,csn,ierr)
if (ierr.ne.0) goto 998
call cdfopn(csn,cstid,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,varname,ndim,misdat,vardim,varmin,varmax,
> stag,ierr)
if (ierr.ne.0) goto 998
nx=vardim(1)
ny=vardim(2)
nz=vardim(3)
xmin=varmin(1)
ymin=varmin(2)
zmin=varmin(3)
call getlevs(cstid,nz,aklev,bklev,aklay,bklay,ierr)
if (ierr.ne.0) goto 998
call getgrid(cstid,dx,dy,ierr)
if (ierr.ne.0) goto 998
xmax=varmax(1)
ymax=varmax(2)
zmax=varmax(3)
dz=(zmax-zmin)/real(nz-1)
call clscdf(cstid,ierr)
if (ierr.ne.0) goto 998
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Check whether the grid is equallay spaced in the vertical
do i=1,nz-1
dh=aklev(i+1)-aklev(i)
if (abs(dh-dz).gt.eps) then
print*,'Aklev: Vertical grid must be equally spaced... Stop'
print*,(aklev(i),i=1,nz)
stop
endif
dh=aklay(i+1)-aklay(i)
if (abs(dh-dz).gt.eps) then
print*,'Aklay: Vertical grid must be equally spaced... Stop'
print*,(aklay(i),i=1,nz)
stop
endif
enddo
 
c Set missing data value
mdv=misdat
 
return
 
c Exception handling
998 print*,'Read_Dim: Problem with input netcdf file... Stop'
stop
 
end
 
 
c --------------------------------------------------------------------------------
c Read refernece profile from netcdf
c --------------------------------------------------------------------------------
 
SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,coriol,
> pvsrcfile)
 
c Read the reference profile from file
c
c thetaref : Reference potential temperature (K)
c pressref : Reference pressure (Pa)
c rhoref : Reference density (kg/m^3)
c nsqref : Stratification (s^-1)
c zref : Reference height (m)
c nx,nny,nz : Grid dimension in x,y,z direction
c deltax,deltay,deltaz : Grid spacings used for calculations (m)
c coriol : Coriolis parameter (s^-1)
c pvsrcfile : Input file
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real nsqref (0:2*nz)
real thetaref(0:2*nz)
real rhoref (0:2*nz)
real pressref(0:2*nz)
real zref (0:2*nz)
real deltax,deltay,deltaz
real coriol (0:nx,0:ny)
character*80 pvsrcfile
 
c Numerical and physical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,stat
integer vardim(4)
real misdat
integer ndimin
real varmin(4),varmax(4),stag(4)
integer i,j,k,nf1
integer ntimes
real time(200)
character*80 vnam(100),varname
integer nvars
integer isok,ierr
real x(0:nx,0:ny),y(0:nx,0:ny)
real mean,count
 
c Get grid description from topography
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
isok=0
varname='ORO'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 997
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 997
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Open output netcdf file
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
c Create the variable if necessary
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
 
c Read data from netcdf file
isok=0
varname='NSQREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,nsqref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='RHOREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,rhoref,stat)
if (stat.ne.0) goto 997
isok=0
varname='THETAREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,thetaref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='PREREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,pressref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='ZREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,zref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='CORIOL'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,coriol,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='X'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,x,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='Y'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,y,stat)
if (stat.ne.0) goto 997
 
c Close netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Determine the grid spacings <deltax, deltay, deltaz>
mean=0.
count=0.
do i=1,nx
do j=0,ny
mean=mean+abs(x(i,j)-x(i-1,j))
count=count+1.
enddo
enddo
deltax=mean/count
 
mean=0.
count=0.
do j=1,ny
do i=0,nx
mean=mean+abs(y(i,j)-y(i,j-1))
count=count+1.
enddo
enddo
deltay=mean/count
 
mean=0.
count=0.
do k=1,nz-1
mean=mean+abs(zref(k+1)-zref(k-1))
count=count+1.
enddo
deltaz=mean/count
 
return
 
c Exception handling
997 print*,'Read_Ref: Problem with input netcdf file... Stop'
stop
 
end
 
 
c ********************************************************************************
c * BOUNDARY CONDITIONS - CONSISTENCY CHECK AND ADAPTIONS *
c ********************************************************************************
 
c --------------------------------------------------------------------------------
c Boundary condition
c --------------------------------------------------------------------------------
 
subroutine combouncon(pv,nsq,rhoref,thetatop,
> thetabot,thetaref,coriol,
> ua,ub,va,vb,nx,ny,nz,dx,dy,dz)
 
c Evaluate the consistency integrals A.7 from Rene's dissertation. This inegral
c is a necessary condition that the von Neumann problem has a unique solution.
c Adjust the upper and lower boundary conditions on <thetabot> and <thetatop>, so
c that the consitency check is ok.
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real dx,dy,dz
real pv(0:nx,0:ny,0:nz)
real nsq(0:2*nz)
real rhoref(0:2*nz)
real thetatop(0:nx,0:ny)
real thetabot(0:nx,0:ny)
real thetaref(0:2*nz)
real coriol(0:nx,0:ny)
real ua(0:nx,0:nz)
real ub(0:nx,0:nz)
real va(0:ny,0:nz)
real vb(0:ny,0:nz)
 
c Numerical and physical parameters
real g
parameter (g=9.81)
 
c Auxiliary variables
integer i,j,k
real dxy,dxz,dyz,dxyz
real integr,denombot,denomtop,denom
real shifttop,shiftbot
 
c Set the area and volume infinitesimals for integration
dxy =dx*dy
dxz =dx*dz
dyz =dy*dz
dxyz=dx*dy*dz
 
c Init integration variables
integr=0.
 
c Inner
do k=1,nz-1
do i=1,nx-1
do j=1,ny-1
integr=integr+dxyz*rhoref(2*k)*pv(i,j,k)
enddo
enddo
enddo
 
c ZY plane
do k=1,nz-1
do j=1,ny-1
integr=integr+dyz*
> rhoref(2*k)*(dx*pv(0, j,k)+va(j,k))
c
integr=integr+dyz*
> rhoref(2*k)*(dx*pv(nx,j,k)-vb(j,k))
enddo
enddo
 
c ZX plane
do k=1,nz-1
do i=1,nx-1
integr=integr+dxz*
> rhoref(2*k)*(dy*pv(i,0,k)-ua(i,k))
c
integr=integr+dxz*
> rhoref(2*k)*(dy*pv(i,ny,k)+ub(i,k))
enddo
enddo
 
c XY plane
do i=1,nx-1
do j=1,ny-1
integr=integr+dxy*rhoref(0)*(
> dz*pv(i,j,0)+coriol(i,j)*g*thetabot(i,j)/
> (nsq(0)*thetaref(0)))
c
integr=integr+dxy*rhoref(2*nz)*(
> dz*pv(i,j,nz)-coriol(i,j)*g*thetatop(i,j)/
> (nsq(2*nz)*thetaref(2*nz)))
c
enddo
enddo
 
c X edges
do i=1,nx-1
integr=integr+dx*
> rhoref(0)*(dyz*pv(i,0,0)-
> dz*ua(i,0)+dy*coriol(i,0)*g*thetabot(i,0)/
> (nsq(0)*thetaref(0)))
c
integr=integr+dx*
> rhoref(0)*(dyz*pv(i,ny,0)+
> dz*ub(i,0)+dy*coriol(i,ny)*g*thetabot(i,ny)/
> (nsq(0)*thetaref(0)))
c
integr=integr+dx*
> rhoref(2*nz)*(dyz*pv(i,0,nz)-
> dz*ua(i,nz)-dy*coriol(i,0)*g*thetatop(i,0)/
> (nsq(2*nz)*thetaref(2*nz)))
 
integr=integr+dx*
> rhoref(2*nz)*(dyz*pv(i,ny,nz)+
> dz*ub(i,nz)-dy*coriol(i,ny)*g*thetatop(i,ny)/
> (nsq(2*nz)*thetaref(2*nz)))
c
enddo
 
c Y edges
do j=1,ny-1
integr=integr+dy*
> rhoref(0)*(dxz*pv(0,j,0)+
> dz*va(j,0)+dx*coriol(0,j)*g*thetabot(0,j)/
> (nsq(0)*thetaref(0)))
c
integr=integr+dy*
> rhoref(0)*(dxz*pv(nx,j,0)-
> dz*vb(j,0)+dx*coriol(nx,j)*g*thetabot(nx,j)/
> (nsq(0)*thetaref(0)))
c
integr=integr+dy*
> rhoref(2*nz)*(dxz*pv(0,j,nz)+
> dz*va(j,nz)-dx*coriol(0,j)*g*thetatop(0,j)/
> (nsq(2*nz)*thetaref(2*nz)))
c
integr=integr+dy*
> rhoref(2*nz)*(dxz*pv(nx,j,nz)-
> dz*vb(j,nz)-dx*coriol(nx,j)*g*thetatop(nx,j)/
> (nsq(2*nz)*thetaref(2*nz)))
c
enddo
 
c Z edges
do k=1,nz-1
integr=integr+dz*
> rhoref(2*k)*(dxy*pv(0,0,k)+
> dy*va(0,k)-dx*ua(0,k))
c
integr=integr+dz*
> rhoref(2*k)*(dxy*pv(nx,0,k)-
> dy*vb(0,k)-dx*ua(nx,k))
c
integr=integr+dz*
> rhoref(2*k)*(dxy*pv(0,ny,k)+
> dy*va(ny,k)+dx*ub(0,k))
c
integr=integr+dz*
> rhoref(2*k)*(dxy*pv(nx,ny,k)-
> dy*vb(ny,k)+dx*ub(nx,k))
enddo
 
c Points
integr=integr+rhoref(0)*(dxyz*pv(0,0,0)+
> dyz*va(0,0)-dxz*ua(0,0)+
> dxy*coriol(0,0)*g*thetabot(0,0)/
> (nsq(0)*thetaref(0)))
c
integr=integr+rhoref(0)*(dxyz*pv(nx,0,0)-
> dyz*vb(0,0)-dxz*ua(nx,0)+
> dxy*coriol(nx,0)*g*thetabot(nx,0)/
> (nsq(0)*thetaref(0)))
c
integr=integr+rhoref(0)*(dxyz*pv(0,ny,0)+
> dyz*va(ny,0)+dxz*ub(0,0)+
> dxy*coriol(0,ny)*g*thetabot(0,ny)/
> (nsq(0)*thetaref(0)))
c
integr=integr+rhoref(0)*(dxyz*pv(nx,ny,0)-
> dyz*vb(ny,0)+dxz*ub(nx,0)+
> dxy*coriol(nx,ny)*g*thetabot(nx,ny)/
> (nsq(0)*thetaref(0)))
c
integr=integr+rhoref(2*nz)*(dxyz*pv(0,0,nz)+
> dyz*va(0,nz)-dxz*ua(0,nz)-
> dxy*coriol(0,0)*g*thetatop(0,0)/
> (nsq(2*nz)*thetaref(2*nz)))
c
integr=integr+rhoref(2*nz)*(dxyz*pv(nx,0,nz)-
> dyz*vb(0,nz)-dxz*ua(nx,nz)-
> dxy*coriol(nx,0)*g*thetatop(nx,0)/
> (nsq(2*nz)*thetaref(2*nz)))
c
integr=integr+rhoref(2*nz)*(dxyz*pv(0,ny,nz)+
> dyz*va(ny,nz)+dxz*ub(0,nz)-
> dxy*coriol(0,ny)*g*thetatop(0,ny)/
> (nsq(2*nz)*thetaref(2*nz)))
c
integr=integr+rhoref(2*nz)*(dxyz*pv(nx,ny,nz)-
> dyz*vb(ny,nz)+dxz*ub(nx,nz)-
> dxy*coriol(nx,ny)*g*thetatop(nx,ny)/
> (nsq(2*nz)*thetaref(2*nz)))
c
 
c Get the integrals from the reference state at bottom and top
denombot=0.
denomtop=0.
do i=0,nx
do j=0,ny
denombot=denombot+dxy*
> rhoref(0)*coriol(i,j)*g/
> (nsq(0)*thetaref(0))
c
denomtop=denomtop+dxy*
> rhoref(2*nz)*coriol(i,j)*g/
> (nsq(2*nz)*thetaref(2*nz))
enddo
enddo
denom=denomtop-denombot
c Determine the deviation of potential temperature from reference profile
shiftbot=0.
shifttop=0.
do i=0,nx
do j=0,ny
shifttop=shifttop+thetatop(i,j)
shiftbot=shiftbot+thetabot(i,j)
enddo
enddo
shifttop=shifttop/real((nx+1)*(ny+1))
shiftbot=shiftbot/real((nx+1)*(ny+1))
 
c Write some information about the consitency integrals
print*,'Consistency Check for boundary'
print*,' integ = ', integr
print*,' denombot = ', denombot
print*,' denomtop = ', denomtop
print*,' denom = ', denom
print*,' theta adjustment = ', integr/denom
print*,' theta shift @ top = ', shifttop,
> thetaref(2*nz)
print*,' theta shift @ bot = ', shiftbot,
> thetaref(0)
 
end
Property changes:
Added: svn:executable
/trunk/diag/check_boundcon.m
0,0 → 1,267
% -------------------------------------------------------------------------
% Load files
% -------------------------------------------------------------------------
 
% Base directory and filename
base = '/net/rossby/lhome/sprenger/PV_Inversion_Tool/';
folder = base;
filename = 'Z1_20060115_18';
disp([folder filename])
 
% First image (otherwise first image is not correctly written)
figname = [base '/test.eps'];
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
% Load variables from file (on model levels)
z_th = cdf_loadV(folder,filename,'TH');
z_uu = cdf_loadV(folder,filename,'U');
z_vv = cdf_loadV(folder,filename,'V');
 
% -------------------------------------------------------------------------
% Lower boundary condition for potential temperature
% -------------------------------------------------------------------------
 
ilev=1;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Set projection
load coast
h=axesm('MapProjection','eqdcylin');
setm(gca,'FLatLimit',[z_th.latmin z_th.latmax],'FLonLimit',[z_th.lonmin z_th.lonmax]);
h=plotm(lat,long);
gridm;
 
% Scale the plotting field for color map
fld=squeeze(z_th.var(ilev,:,:));
c_map = scale_col(230:5:310,fld);
 
% Plot TH
lat=z_th.ymin + (0:z_th.ny-1) * z_th.dy;
lon=z_th.xmin + (0:z_th.nx-1) * z_th.dx;
[C,h]=contourfm(lat,lon,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Lower Boundary Condition : Potential Temperature @' num2str(z_th.aklay(ilev)) ' m ASL' ]);
 
% Save figure
figname = [ base '/bound_lower_th_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
% -------------------------------------------------------------------------
% Upper boundary condition for potential temperature
% -------------------------------------------------------------------------
 
ilev=z_th.nz;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Set projection
load coast
h=axesm('MapProjection','eqdcylin');
setm(gca,'FLatLimit',[z_th.latmin z_th.latmax],'FLonLimit',[z_th.lonmin z_th.lonmax]);
h=plotm(lat,long);
gridm;
 
% Scale the plotting field for color map
fld=squeeze(z_th.var(ilev,:,:));
c_map = scale_col(450:10:550,fld);
 
% Plot TH
lat=z_th.ymin + (0:z_th.ny-1) * z_th.dy;
lon=z_th.xmin + (0:z_th.nx-1) * z_th.dx;
[C,h]=contourfm(lat,lon,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Upper Boundary Condition : Potential Temperature @ ' num2str(z_th.aklay(ilev)) ' m ASL' ]);
 
% Save figure
figname = [ base '/bound_upper_th_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
 
% -------------------------------------------------------------------------
% Southern lateral boundary condition for zonal wind
% -------------------------------------------------------------------------
 
ilev=1;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Scale the plotting field for color map
fld=squeeze(z_uu.var(:,ilev,:));
c_map = scale_col(-50:10:50,fld);
 
% Plot
lev=z_uu.aklev/10000;
lon=z_uu.xmin + (0:z_uu.nx-1) * z_uu.dx;
[C,h]=contourf(lon,lev,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Southern lateral Boundary Condition : Zonal Wind @ ' num2str(z_uu.ymin) '^\circ N' ]);
xlabel('Longitude');
ylabel('Height [km]');
 
% Save figure
figname = [ base '/bound_south_uu_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
 
% -------------------------------------------------------------------------
% Northern lateral boundary condition for zonal wind
% -------------------------------------------------------------------------
 
ilev=z_uu.ny;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Scale the plotting field for color map
fld=squeeze(z_uu.var(:,ilev,:));
c_map = scale_col(-50:10:50,fld);
 
% Plot
lev=z_uu.aklev/10000;
lon=z_uu.xmin + (0:z_uu.nx-1) * z_uu.dx;
[C,h]=contourf(lon,lev,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Northern lateral Boundary Condition : Zonal Wind @ ' num2str(z_uu.ymax) '^\circ N' ]);
xlabel('Longitude');
ylabel('Height [km]');
 
% Save figure
figname = [ base '/bound_north_uu_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
% -------------------------------------------------------------------------
% Western lateral boundary condition for meridional wind
% -------------------------------------------------------------------------
 
ilev=1;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Scale the plotting field for color map
fld=squeeze(z_vv.var(:,:,ilev));
c_map = scale_col(-50:10:50,fld);
 
% Plot
lev=z_vv.aklev/10000;
lat=z_vv.ymin + (0:z_vv.ny-1) * z_vv.dy;
[C,h]=contourf(lat,lev,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Western lateral Boundary Condition : Meridional Wind @ ' num2str(z_vv.xmin) '^\circ E' ]);
xlabel('Latitude');
ylabel('Height [km]');
 
% Save figure
figname = [ base '/bound_west_vv_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
 
% -------------------------------------------------------------------------
% Eastern lateral boundary condition for meridional wind
% -------------------------------------------------------------------------
 
ilev=z_vv.nx;
 
% Create a new figure
close;
fh=figure('Units','pixels','Position',[100 100 900 900])
 
% Scale the plotting field for color map
fld=squeeze(z_vv.var(:,:,ilev));
c_map = scale_col(-50:10:50,fld);
 
% Plot
lev=z_vv.aklev/10000;
lat=z_vv.ymin + (0:z_vv.ny-1) * z_vv.dy;
[C,h]=contourf(lat,lev,c_map.data,c_map.xtick);
for icnt = 1: length(h)
set( h(icnt), 'EdgeColor', 'none' )
end
 
% Add color bar
colormap('default');
ctb(['/home/sprenger/ECFC_STE_Forecast/ctb_isen'],c_map.xtick,2);
caxis(c_map.caxis);
q=colorbar('vert');
set(q,'ytick',c_map.xtick,'YTickLabel',c_map.label);
 
% Add the grid and the coast lines to the plot
title([ 'Eastern lateral Boundary Condition : Meridional Wind @ ' num2str(z_vv.xmax) '^\circ E' ]);
xlabel('Latitude');
ylabel('Height [km]');
 
% Save figure
figname = [ base '/bound_east_vv_' filename '.eps' ];
set(gcf, 'PaperPosition', [2 1 15 10]);
print('-depsc2','-r0',figname);
Property changes:
Added: svn:executable
/trunk/diag/difference.f
0,0 → 1,241
PROGRAM difference
 
c **************************************************************************
c * Get the difference between two runs *
c * Michael Sprenger / Autumn 2006 *
c **************************************************************************
 
implicit none
 
c --------------------------------------------------------------------------
c Declaration of subroutine parameters
c --------------------------------------------------------------------------
 
c Physical and numerical parameters
real eps
parameter (eps=0.01)
integer nmax
parameter (nmax=300*300*200)
 
c Variables for input file 1
character*80 i1_filename
real i1_varmin(4),i1_varmax(4),i1_stag(4)
integer i1_vardim(4)
real i1_mdv
integer i1_ndim
integer i1_nx,i1_ny,i1_nz
real i1_time
integer i1_nvars
character*80 i1_vnam(100)
real i1_field(nmax)
 
c Variables for input file 2
character*80 i2_filename
real i2_varmin(4),i2_varmax(4),i2_stag(4)
integer i2_vardim(4)
real i2_mdv
integer i2_ndim
integer i2_nx,i2_ny,i2_nz
real i2_time
integer i2_nvars
character*80 i2_vnam(100)
real i2_field(nmax)
 
c Variables for output file
character*80 o_filename
real o_varmin(4),o_varmax(4),o_stag(4)
integer o_vardim(4)
real o_mdv
integer o_ndim
integer o_nx,o_ny,o_nz
real o_time
real o_field(nmax)
 
c Auxiliary variables
integer i,j,k
integer cdfid,ierr
integer isok
character*80 cfn,varname
 
c --------------------------------------------------------------------------------
c Input
c --------------------------------------------------------------------------------
 
print*,'********************************************************'
print*,'* DIFFERENCE *'
print*,'********************************************************'
 
c Read parameter file
open(10,file='fort.10')
read(10,*) i1_filename
read(10,*) i2_filename
read(10,*) o_filename
close(10)
print*
print*,trim(i1_filename)
print*,trim(i2_filename)
print*,trim(o_filename)
print*
 
c Get a list of all variables on the two input files
call cdfopn(i1_filename,cdfid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,i1_nvars,i1_vnam,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,i1_vnam(i1_nvars),i1_ndim,i1_mdv,i1_vardim,
> i1_varmin,i1_varmax,i1_stag,ierr)
call clscdf(cdfid,ierr)
print*,(trim(i1_vnam(i))//' ',i=1,i1_nvars)
 
call cdfopn(i2_filename,cdfid,ierr)
if (ierr.ne.0) goto 997
call getvars(cdfid,i2_nvars,i2_vnam,ierr)
if (ierr.ne.0) goto 997
call clscdf(cdfid,ierr)
print*,(trim(i2_vnam(i))//' ',i=1,i2_nvars)
print*
 
c Create the output file
o_ndim=i1_ndim
do i=1,i1_ndim
o_varmin(i)=i1_varmin(i)
o_varmax(i)=i1_varmax(i)
enddo
cfn=trim(o_filename)//'_cst'
call crecdf(trim(o_filename),cdfid,o_varmin,o_varmax,
> o_ndim,trim(cfn),ierr)
if (ierr.ne.0) goto 996
call clscdf(cdfid,ierr)
 
c --------------------------------------------------------------------------------
c Loop through all variables
c --------------------------------------------------------------------------------
 
do i=1,i1_nvars
 
c Check wether the variable is available on both files
varname=i1_vnam(i)
if (varname.eq.'time') goto 100
isok=0
call check_varok (isok,varname,i2_vnam,i2_nvars)
if (isok.eq.0) goto 100
 
c Read first input file
call cdfopn(i1_filename,cdfid,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,varname,i1_ndim,i1_mdv,i1_vardim,
> i1_varmin,i1_varmax,i1_stag,ierr)
if (ierr.ne.0) goto 998
call getdat(cdfid,varname,0.,0,i1_field,ierr)
if (ierr.ne.0) goto 998
call clscdf(cdfid,ierr)
c Read second input file
call cdfopn(i2_filename,cdfid,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,varname,i2_ndim,i2_mdv,i2_vardim,
> i2_varmin,i2_varmax,i2_stag,ierr)
if (ierr.ne.0) goto 998
call getdat(cdfid,varname,0.,0,i2_field,ierr)
if (ierr.ne.0) goto 998
call clscdf(cdfid,ierr)
 
c Consistency check
if (i1_ndim.ne.i2_ndim) then
print*,'Inconsistent input files... Stop',i1_ndim,i2_ndim
stop
endif
do j=1,3
if ( (i1_vardim(j).ne.i2_vardim(j)).or.
> (abs(i1_varmin(j)-i2_varmin(j)).gt.eps).or.
> (abs(i1_varmax(j)-i2_varmax(j)).gt.eps).or.
> (abs(i1_stag(j)-i2_stag(j)).gt.eps)) then
print*,'Inconsistent input files... Stop'
print*,j,i1_varmin(j),i2_varmin(j)
print*,j,i1_varmax(j),i2_varmax(j)
print*,j,i1_vardim(j),i2_vardim(j)
print*,j,i1_stag(j), i2_stag(j)
stop
endif
enddo
c Get the difference
do j=1,i1_vardim(1)*i1_vardim(2)*i1_vardim(3)
if ( (abs(i1_field(j)-i1_mdv).gt.eps).and.
> (abs(i2_field(j)-i2_mdv).gt.eps) ) then
o_field(j)=i1_field(j)-i2_field(j)
else
o_field(j)=i1_mdv
endif
enddo
 
c Write to output file
o_ndim=i1_ndim
o_mdv =i1_mdv
do j=1,i1_ndim
o_vardim(j)=i1_vardim(j)
o_varmin(j)=i1_varmin(j)
o_varmax(j)=i1_varmax(j)
o_stag(j) =i1_stag(j)
enddo
call cdfwopn(o_filename,cdfid,ierr)
if (ierr.ne.0) goto 996
call putdef(cdfid,varname,o_ndim,o_mdv,o_vardim,
> o_varmin,o_varmax,o_stag,ierr)
if (ierr.ne.0) goto 996
call putdat(cdfid,varname,0.,0,o_field,ierr)
if (ierr.ne.0) goto 996
print*,'W ',trim(varname),' ',trim(o_filename)
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 996
 
c Next
100 continue
 
enddo
 
c -----------------------------------------------------------------
c Exception handling and format specs
c -----------------------------------------------------------------
 
stop
 
998 print*,'Problems with input file 1 ',trim(i1_filename)
stop
 
997 print*,'Problems with input file 2 ',trim(i2_filename)
stop
 
996 print*,'Problems with output file ',trim(o_filename)
stop
 
end
 
 
c --------------------------------------------------------------------------------
c Check whether variable is found on netcdf file
c --------------------------------------------------------------------------------
 
subroutine check_varok (isok,varname,varlist,nvars)
 
c Check whether the variable <varname> is in the list <varlist(nvars)>. If this is
C the case, <isok> is incremented by 1. Otherwise <isok> keeps its value.
 
implicit none
 
c Declaraion of subroutine parameters
integer isok
integer nvars
character*80 varname
character*80 varlist(nvars)
 
c Auxiliary variables
integer i
 
c Main
do i=1,nvars
if (trim(varname).eq.trim(varlist(i))) isok=isok+1
enddo
 
end
 
Property changes:
Added: svn:executable
/trunk/diag/hydrostatic.f
0,0 → 1,542
PROGRAM hydrostatic
 
c Calculate the geopotential and add it to the P file
c Michael Sprenger / Spring 2006
 
implicit none
 
c ---------------------------------------------------------------
c Declaration of variables
c ---------------------------------------------------------------
 
c Variables for input P file : model level
character*80 ml_pfn
real ml_varmin(4),ml_varmax(4),ml_stag(4)
integer ml_vardim(4)
real ml_mdv
integer ml_ndim
integer ml_nx,ml_ny,ml_nz
real ml_xmin,ml_xmax,ml_ymin,ml_ymax,ml_dx,ml_dy
integer ml_ntimes
real ml_aklev(500),ml_bklev(500)
real ml_aklay(500),ml_bklay(500)
real ml_time
real ml_pollon,ml_pollat
integer ml_nvars
character*80 ml_vnam(100)
integer ml_idate(5)
real,allocatable, dimension (:,:) :: ml_ps,ml_zb
real,allocatable, dimension (:,:,:) :: ml_t3,ml_q3,ml_p3,ml_tv3
real,allocatable, dimension (:,:,:) :: ml_zlay3
 
c Variables for input Z file : pressure level
character*80 pl_zfn
real pl_varmin(4),pl_varmax(4),pl_stag(4)
integer pl_vardim(4)
real pl_mdv
integer pl_ndim
integer pl_nx,pl_ny,pl_nz
real pl_xmin,pl_xmax,pl_ymin,pl_ymax,pl_dx,pl_dy
integer pl_ntimes
real pl_aklev(500),pl_bklev(500)
real pl_aklay(500),pl_bklay(500)
real pl_time
real pl_pollon,pl_pollat
integer pl_nvars
character*80 pl_vnam(100)
integer pl_idate(5)
real,allocatable, dimension (:,:,:) :: pl_z3,pl_p3
 
c Physical and numerical parameters
real g
parameter (g=9.80665)
real eps
parameter (eps=0.01)
real tzero
parameter (tzero=273.15)
real kappa
parameter (kappa=0.6078)
real zerodiv
parameter (zerodiv=0.0000000001)
real dpmin
parameter (dpmin=10.)
real rdg
parameter (rdg=29.271)
 
c Auxiliary variables
integer ierr
integer cdfid,cstid
character*80 cfn
integer stat
real time
real tv1(1000),z1(1000),p1(1000),f1(1000)
real spline_tv1(1000),spline_f1(1000),spline_z1(1000)
real pu,po,zu,zo,p,z,dp,p0,tvu,tvo,ff
integer i,j,k,l
integer lmin,n
character*80 varname,cdfname
integer isok
integer mode
 
c -----------------------------------------------------------------
c Read input fields
c -----------------------------------------------------------------
 
print*,'*********************************************************'
print*,'* hydrostatic *'
print*,'*********************************************************'
 
c Read in the parameter file
open(10,file='fort.10')
read(10,*) ml_pfn
read(10,*) pl_zfn
close(10)
 
c Decide which mode is used (1: reference from Z, 2: reference from ORO/PS)
if ( trim(ml_pfn).ne.trim(pl_zfn) ) then
mode=1
print*,'Taking reference from Z ',trim(pl_zfn)
else
mode=2
print*,'Taking reference from ORO/PS ',trim(pl_zfn)
endif
 
print*,trim(ml_pfn)
print*,trim(pl_zfn)
c Get grid description for P file : model level
call cdfopn(ml_pfn,cdfid,ierr)
if (ierr.ne.0) goto 998
call getcfn(cdfid,cfn,ierr)
if (ierr.ne.0) goto 998
call cdfopn(cfn,cstid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,ml_nvars,ml_vnam,ierr)
varname='T'
isok=0
call check_varok (isok,varname,ml_vnam,ml_nvars)
if (isok.ne.1) goto 998
call getdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,
> ml_varmin,ml_varmax,ml_stag,ierr)
if (ierr.ne.0) goto 998
ml_nx =ml_vardim(1)
ml_ny =ml_vardim(2)
ml_nz =ml_vardim(3)
ml_xmin=ml_varmin(1)
ml_ymin=ml_varmin(2)
call getlevs(cstid,ml_nz,ml_aklev,ml_bklev,ml_aklay,ml_bklay,ierr)
call getgrid(cstid,ml_dx,ml_dy,ierr)
ml_xmax=ml_xmin+real(ml_nx-1)*ml_dx
ml_ymax=ml_ymin+real(ml_ny-1)*ml_dy
call gettimes(cdfid,ml_time,ml_ntimes,ierr)
call getstart(cstid,ml_idate,ierr)
call getpole(cstid,ml_pollon,ml_pollat,ierr)
call clscdf(cstid,ierr)
call clscdf(cdfid,ierr)
 
c Get grid description reference: either ORO(P) or Z(Z)
call cdfopn(pl_zfn,cdfid,ierr)
if (ierr.ne.0) goto 998
call getcfn(cdfid,cfn,ierr)
if (ierr.ne.0) goto 998
call cdfopn(cfn,cstid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,pl_nvars,pl_vnam,ierr)
if (mode.eq.1) then
varname='Z'
isok=0
call check_varok (isok,varname,pl_vnam,pl_nvars)
if (isok.ne.1) goto 998
call getdef(cdfid,varname,pl_ndim,pl_mdv,pl_vardim,
> pl_varmin,pl_varmax,pl_stag,ierr)
if (ierr.ne.0) goto 998
call getlevs(cstid,pl_nz,pl_aklev,pl_bklev,
> pl_aklay,pl_bklay,ierr)
call getgrid(cstid,pl_dx,pl_dy,ierr)
call gettimes(cdfid,pl_time,pl_ntimes,ierr)
call getstart(cstid,pl_idate,ierr)
call getpole(cstid,pl_pollon,pl_pollat,ierr)
 
else if (mode.eq.2) then
varname='ORO'
isok=0
call check_varok (isok,varname,pl_vnam,pl_nvars)
if (isok.ne.1) goto 998
call getdef(cdfid,varname,pl_ndim,pl_mdv,pl_vardim,
> pl_varmin,pl_varmax,pl_stag,ierr)
if (ierr.ne.0) goto 998
call getgrid(cstid,pl_dx,pl_dy,ierr)
call gettimes(cdfid,pl_time,pl_ntimes,ierr)
call getstart(cstid,pl_idate,ierr)
call getpole(cstid,pl_pollon,pl_pollat,ierr)
endif
pl_nx =pl_vardim(1)
pl_ny =pl_vardim(2)
pl_nz =pl_vardim(3)
pl_xmin=pl_varmin(1)
pl_ymin=pl_varmin(2)
pl_xmax=pl_xmin+real(pl_nx-1)*pl_dx
pl_ymax=pl_ymin+real(pl_ny-1)*pl_dy
call clscdf(cstid,ierr)
call clscdf(cdfid,ierr)
 
c Consitency check for the grids
if ( (ml_nx.ne.pl_nx).or.
> (ml_ny.ne.pl_ny).or.
> (abs(ml_xmin-pl_xmin ).gt.eps).or.
> (abs(ml_ymin-pl_ymin ).gt.eps).or.
> (abs(ml_xmax-pl_xmax ).gt.eps).or.
> (abs(ml_ymax-pl_ymax ).gt.eps).or.
> (abs(ml_dx -pl_dx ).gt.eps).or.
> (abs(ml_dy -pl_dy ).gt.eps).or.
> (abs(ml_time-pl_time ).gt.eps).or.
> (abs(ml_pollon-pl_pollon).gt.eps).or.
> (abs(ml_pollat-pl_pollat).gt.eps)) then
print*,'Input P and Z grids are not consistent... Stop'
print*,'Xmin ',ml_xmin ,pl_xmin
print*,'Ymin ',ml_ymin ,pl_ymin
print*,'Xmax ',ml_xmax ,pl_xmax
print*,'Ymax ',ml_ymax ,pl_ymax
print*,'Dx ',ml_dx ,pl_dx
print*,'Dy ',ml_dy ,pl_dy
print*,'Pollon ',ml_pollon ,pl_pollon
print*,'Pollat ',ml_pollat ,pl_pollat
print*,'Time ',ml_time ,pl_time
stop
endif
 
c Allocate memory for all fields
allocate(ml_ps(ml_nx,ml_ny),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_ps ***'
allocate(ml_zb(ml_nx,ml_ny),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_zb ***'
allocate(ml_p3(ml_nx,ml_ny,ml_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_p3 ***'
allocate(ml_t3(ml_nx,ml_ny,ml_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_t3 ***'
allocate(ml_q3(ml_nx,ml_ny,ml_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_q3 ***'
allocate(ml_tv3(ml_nx,ml_ny,ml_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_tv3 ***'
allocate(ml_zlay3(ml_nx,ml_ny,ml_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array ml_zlay3 ***'
 
allocate(pl_z3(pl_nx,pl_ny,pl_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array pl_z3 ***'
allocate(pl_p3(pl_nx,pl_ny,pl_nz),stat=stat)
if (stat.ne.0) print*,'*** error allocating array pl_p3 ***'
 
c Read T, Q, PS from P file
call cdfopn(ml_pfn,cdfid,ierr)
if (ierr.ne.0) goto 998
isok=0
varname='T'
call check_varok (isok,varname, ml_vnam,ml_nvars)
varname='Q'
call check_varok (isok,varname, ml_vnam,ml_nvars)
varname='PS'
call check_varok (isok,varname,ml_vnam,ml_nvars)
if (isok.ne.3) goto 998
print*,'R T ',trim(ml_pfn)
call getdat(cdfid,'T',ml_time,0,ml_t3,ierr)
print*,'R Q ',trim(ml_pfn)
call getdat(cdfid,'Q',ml_time,0,ml_q3,ierr)
print*,'R PS ',trim(ml_pfn)
call getdat(cdfid,'PS',ml_time,1,ml_ps,ierr)
call clscdf(cdfid,ierr)
 
c Read ORO from P or Z from Z file
call cdfopn(pl_zfn,cdfid,ierr)
if (ierr.ne.0) goto 998
if (mode.eq.1) then
isok=0
varname='Z'
call check_varok (isok,varname,pl_vnam,pl_nvars)
if (isok.ne.1) goto 998
print*,'R Z ',trim(pl_zfn)
call getdat(cdfid,varname,pl_time,0,pl_z3,ierr)
else if (mode.eq.2) then
isok=0
varname='ORO'
call check_varok (isok,varname,pl_vnam,pl_nvars)
if (isok.ne.1) goto 998
print*,'R ORO ',trim(pl_zfn)
call getdat(cdfid,varname,pl_time,1,pl_z3,ierr)
endif
call clscdf(cdfid,ierr)
 
c Set the values for the pressure on the pressure levels
do i=1,pl_nx
do j=1,pl_ny
do k=1,pl_nz
if (mode.eq.1) then
pl_p3(i,j,k)=pl_aklay(k)
else if (mode.eq.2) then
pl_p3(i,j,k)=ml_ps(i,j)
endif
enddo
enddo
enddo
 
c Calculate 3d pressure field
print*,'C P'
do k=1,ml_nz
do i=1,ml_nx
do j=1,ml_ny
ml_p3(i,j,k)=ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)
enddo
enddo
enddo
 
c Calculate 3d virtual temperature
print*,'C TV'
do k=1,ml_nz
do i=1,ml_nx
do j=1,ml_ny
ml_tv3(i,j,k) = (ml_t3(i,j,k)+tzero)*
> (1.+kappa*ml_q3(i,j,k))
enddo
enddo
enddo
 
c -----------------------------------------------------------------
c Calculate geopotential
c -----------------------------------------------------------------
 
c Integrate hydrostatic equation towards layers
print*,'C HYDROSTATIC EQUATION (LAYERS)'
do i=1,ml_nx
do j=1,ml_ny
 
c Make the virtual temperature profile available
do k=1,ml_nz
p1 (ml_nz-k+1)=ml_p3 (i,j,k)
tv1(ml_nz-k+1)=ml_tv3(i,j,k)
enddo
call spline (p1,tv1,ml_nz,1.e30,1.e30,spline_tv1)
 
c Loop over all model levels
do k=1,ml_nz
 
c Get pressure at the grid point
p = ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)
 
c Find nearest pressure level which is above topography
if (mode.eq.1) then
lmin=pl_nz
do l=1,pl_nz
if ((abs(p-pl_p3(i,j,l))).lt.
> (abs(p-pl_p3(i,j,lmin)))
> .and.
> (pl_p3(i,j,l).lt.ml_ps(i,j)) ) then
lmin=l
endif
enddo
else if (mode.eq.2) then
lmin=1
endif
 
c Integrate hydrostatic equation from this level to the grid point
p0 = pl_p3(i,j,lmin)
n = nint(abs(p-p0)/dpmin)
if (n.lt.1) n=1
dp = (p-p0)/real(n)
 
pu = p0
z = pl_z3(i,j,lmin)
call splint(p1,tv1,spline_tv1,ml_nz,pu,tvu)
do l=1,n
po = pu+dp
call splint(p1,tv1,spline_tv1,ml_nz,po,tvo)
z = z + rdg*0.5*(tvu+tvo)*alog(pu/po)
tvu = tvo
pu = po
enddo
c Set the geopotential at the grid point
ml_zlay3(i,j,k) = z
enddo
 
enddo
 
enddo
 
c -----------------------------------------------------------------
c Calculate height of topography
c -----------------------------------------------------------------
 
if (mode.eq.1) then
print*,'C TOPOGRAPHY'
do i=1,ml_nx
do j=1,ml_ny
c Make the z/p profile available
do k=1,ml_nz
p1(ml_nz-k+1)=ml_p3(i,j,k)
z1(ml_nz-k+1)=ml_zlay3(i,j,k)
enddo
 
c Cubic spline interpolation
call spline (p1,z1,ml_nz,1.e30,1.e30,spline_z1)
call splint (p1,z1,spline_z1,ml_nz,ml_ps(i,j),ml_zb(i,j))
enddo
enddo
endif
 
c -----------------------------------------------------------------
c Write the topography and geopotential to P file
c -----------------------------------------------------------------
 
c Open P file
call cdfwopn(trim(ml_pfn),cdfid,ierr)
 
c Write orography (levels)
if (mode.eq.1) then
varname='ORO'
print*,'W ',trim(varname),' ',trim(ml_pfn)
isok=0
call check_varok (isok,varname,ml_vnam,ml_nvars)
if (isok.eq.0) then
ml_vardim(3)=1
call putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,
> ml_varmin,ml_varmax,ml_stag,ierr)
ml_vardim(3)=ml_nz
if (ierr.ne.0) goto 997
endif
call putdat(cdfid,varname,ml_time,1,ml_zb,ierr)
if (ierr.ne.0) goto 997
endif
 
c Write geopotential on layers
varname='Z_DIA'
print*,'W ',trim(varname),' ',trim(ml_pfn)
isok=0
call check_varok (isok,varname,ml_vnam,ml_nvars)
if (isok.eq.0) then
ml_stag(3)=-0.5
call putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,
> ml_varmin,ml_varmax,ml_stag,ierr)
if (ierr.ne.0) goto 997
endif
call putdat(cdfid,varname,ml_time,0,ml_zlay3,ierr)
if (ierr.ne.0) goto 997
 
c Close P file
call clscdf(cdfid,ierr)
 
c -----------------------------------------------------------------
c Exception handling and format specs
c -----------------------------------------------------------------
 
stop
 
998 print*,'Z: Problems with input from m level'
stop
 
997 print*,'Z: Problems with output on m level'
stop
 
996 print*,'F: Problems with input from m level'
stop
 
995 print*,'F: Problems with output on z level'
stop
 
 
end
 
c -------------------------------------------------------------
c Natural cubic spline
c -------------------------------------------------------------
 
SUBROUTINE spline(x,y,n,yp1,ypn,y2)
INTEGER n,NMAX
REAL yp1,ypn,x(n),y(n),y2(n)
PARAMETER (NMAX=500)
INTEGER i,k
REAL p,qn,sig,un,u(NMAX)
if (yp1.gt..99e30) then
y2(1)=0.
u(1)=0.
else
y2(1)=-0.5
u(1)=(3./(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1)
endif
do 11 i=2,n-1
sig=(x(i)-x(i-1))/(x(i+1)-x(i-1))
p=sig*y2(i-1)+2.
y2(i)=(sig-1.)/p
u(i)=(6.*((y(i+1)-y(i))/(x(i+
*1)-x(i))-(y(i)-y(i-1))/(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig*
*u(i-1))/p
11 continue
if (ypn.gt..99e30) then
qn=0.
un=0.
else
qn=0.5
un=(3./(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1)))
endif
y2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.)
do 12 k=n-1,1,-1
y2(k)=y2(k)*y2(k+1)+u(k)
12 continue
return
END
 
 
SUBROUTINE splint(xa,ya,y2a,n,x,y)
INTEGER n
REAL x,y,xa(n),y2a(n),ya(n)
INTEGER k,khi,klo
REAL a,b,h
klo=1
khi=n
1 if (khi-klo.gt.1) then
k=(khi+klo)/2
if(xa(k).gt.x)then
khi=k
else
klo=k
endif
goto 1
endif
h=xa(khi)-xa(klo)
if (h.eq.0.) pause 'bad xa input in splint'
a=(xa(khi)-x)/h
b=(x-xa(klo))/h
y=a*ya(klo)+b*ya(khi)+((a**3-a)*y2a(klo)+(b**3-b)*y2a(khi))*(h**
*2)/6.
return
END
 
c ----------------------------------------------------------------
c Check whether variable is found on netcdf file
c ----------------------------------------------------------------
 
subroutine check_varok (isok,varname,varlist,nvars)
 
c Check whether the variable <varname> is in the list <varlist(nvars)>.
c If this is the case, <isok> is incremented by 1. Otherwise <isok>
c keeps its value.
 
implicit none
 
c Declaraion of subroutine parameters
integer isok
integer nvars
character*80 varname
character*80 varlist(nvars)
 
c Auxiliary variables
integer i
 
c Main
do i=1,nvars
if (trim(varname).eq.trim(varlist(i))) isok=isok+1
enddo
 
end
Property changes:
Added: svn:executable
/trunk/diag/qvec_analysis.f
0,0 → 1,1468
PROGRAM z2s
 
c Calculate secondary fields on z levels
c Michael Sprenger / Summer 2006
 
implicit none
 
c ---------------------------------------------------------------
c Declaration of parameters
c ---------------------------------------------------------------
 
real tzero
parameter (tzero=273.15)
real kappa
parameter (kappa=0.6078)
real rd
parameter (rd=287.)
 
c ---------------------------------------------------------------
c Declaration of variables
c ---------------------------------------------------------------
 
c Variables for output Z file : height level
character*80 cfn
real varmin(4),varmax(4),stag(4)
integer vardim(4)
real mdv
integer ndim
integer nx,ny,nz
real xmin,xmax,ymin,ymax,dx,dy
integer ntimes
real aklev(1000),bklev(1000)
real aklay(1000),bklay(1000)
real time
real pollon,pollat
integer idate(5)
integer nfields
character*80 field_nam(100)
real,allocatable, dimension (:,:,:,:) :: field_dat
real,allocatable, dimension (:,:,:) :: z3
real,allocatable, dimension (:,:) :: x2,y2,f2,oro
real,allocatable, dimension (:,:,:) :: out1,out2
real,allocatable, dimension (:,:,:) :: inp
real,allocatable,dimension (:) :: nsqref
real,allocatable,dimension (:) :: thetaref
real,allocatable,dimension (:) :: tref
real,allocatable,dimension (:) :: rhoref
real,allocatable,dimension (:) :: pressref
real,allocatable,dimension (:) :: zref
real deltax,deltay,deltaz
integer nvars
character*80 vnam(100),varname
integer isok
integer cdfid,cstid
character*3 mode
 
c Parameter file
character*80 fieldname
integer nfilt
character*80 ofn,gri
 
c Auxiliary variables
integer ierr,stat
integer i,j,k,n
real,allocatable, dimension (:,:) :: tmp
character*80 vnam2(100)
integer nvars2
 
c ---------------------------------------------------------------
c Preparations
c ---------------------------------------------------------------
 
print*,'*********************************************************'
print*,'* qvec_analysis *'
print*,'*********************************************************'
 
c Read parameter file
open(10,file='fort.10')
read(10,*) fieldname
read(10,*) ofn
read(10,*) gri
read(10,*) nfilt
close(10)
 
c Decide whether to enter ANO or MOD/ORG mode
mode = ofn(1:3)
if ( (mode.ne.'ANO').and.
> (mode.ne.'MOD').and.
> (mode.ne.'ORG') )
>then
print*,'Unsupported mode ',trim(mode)
stop
endif
 
c Get grid description for Z file : height level
call cdfopn(ofn,cdfid,ierr)
if (ierr.ne.0) goto 998
call getcfn(cdfid,cfn,ierr)
if (ierr.ne.0) goto 998
call cdfopn(cfn,cstid,ierr)
if (ierr.ne.0) goto 998
call getdef(cdfid,'T',ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
nx =vardim(1)
ny =vardim(2)
nz =vardim(3)
xmin=varmin(1)
ymin=varmin(2)
call getlevs(cstid,nz,aklev,bklev,aklay,bklay,ierr)
if (ierr.ne.0) goto 998
call getgrid(cstid,dx,dy,ierr)
if (ierr.ne.0) goto 998
xmax=xmin+real(nx-1)*dx
ymax=ymin+real(ny-1)*dy
call gettimes(cdfid,time,ntimes,ierr)
if (ierr.ne.0) goto 998
call getstart(cstid,idate,ierr)
if (ierr.ne.0) goto 998
call getpole(cstid,pollon,pollat,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,nvars,vnam,ierr)
if (ierr.ne.0) goto 998
call clscdf(cstid,ierr)
if (ierr.ne.0) goto 998
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Get a list of all variables on the GRID file
if (trim(gri).ne.trim(ofn)) then
call cdfopn(gri,cdfid,ierr)
if (ierr.ne.0) goto 998
call getvars(cdfid,nvars2,vnam2,ierr)
if (ierr.ne.0) goto 998
do i=1,nvars2
vnam(nvars+i)=vnam2(i)
enddo
nvars=nvars+nvars2
endif
 
c Check whether calculation of <fieldname> is supported
if ( (fieldname.ne.'GEO' ).and.
> (fieldname.ne.'AGEO' ).and.
> (fieldname.ne.'DIV_UV' ).and.
> (fieldname.ne.'QVEC' ).and.
> (fieldname.ne.'DIV_Q' ) ) then
print*,'Variable not supported ',trim(fieldname)
stop
endif
c Set dependencies
if (fieldname.eq.'GEO') then
nfields=2
field_nam(1)='T'
field_nam(2)='P'
elseif (fieldname.eq.'AGEO') then
nfields=4
field_nam(1)='U'
field_nam(2)='UG'
field_nam(3)='V'
field_nam(4)='VG'
else if (fieldname.eq.'DIV_UV') then
nfields=2
field_nam(1)='U'
field_nam(2)='V'
else if (fieldname.eq.'QVEC') then
nfields=3
field_nam(1)='UG'
field_nam(2)='VG'
field_nam(3)='TH'
else if (fieldname.eq.'DIV_Q') then
nfields=2
field_nam(1)='QX'
field_nam(2)='QY'
endif
 
c Allocate memory
allocate(field_dat(nfields,nx,ny,nz),stat=stat)
if (stat.ne.0) print*,'error allocating field_dat'
allocate(out1(nx,ny,nz),stat=stat)
if (stat.ne.0) print*,'error allocating out1'
allocate(out2(nx,ny,nz),stat=stat)
if (stat.ne.0) print*,'error allocating out2'
allocate(inp(nx,ny,nz),stat=stat)
if (stat.ne.0) print*,'error allocating inp'
allocate(z3(nx,ny,nz),stat=stat)
if (stat.ne.0) print*,'error allocating z3'
allocate(x2(nx,ny),stat=stat)
if (stat.ne.0) print*,'error allocating x2'
allocate(y2(nx,ny),stat=stat)
if (stat.ne.0) print*,'error allocating y2'
allocate(f2(nx,ny),stat=stat)
if (stat.ne.0) print*,'error allocating f2'
allocate(oro(nx,ny),stat=stat)
if (stat.ne.0) print*,'error allocating oro'
 
C Allocate memory for reference profile
allocate(rhoref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating rhoref'
allocate(pressref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating pressref'
allocate(thetaref(0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating thetaref'
allocate(nsqref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating nsqref'
allocate(zref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating zref'
allocate(tref (0:2*nz),STAT=stat)
if (stat.ne.0) print*,'error allocating tref'
 
c Allocate auxiliary fields
allocate(tmp(nx,ny),stat=stat)
if (stat.ne.0) print*,'error allocating tmp'
c Read reference profile and grid parameters
call read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,f2,oro,gri)
 
c Read X grid
varname='X'
isok=0
call check_varok (isok,varname,vnam,nvars)
if (isok.eq.0) then
print*,'Variable ',trim(varname),' missing... Stop'
stop
endif
call cdfopn(gri,cdfid,ierr)
if (ierr.ne.0) goto 998
call getdat(cdfid,varname,time,0,x2,ierr)
if (ierr.ne.0) goto 998
print*,'R ',trim(varname),' ',trim(gri)
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Read Y grid
varname='Y'
isok=0
call check_varok (isok,varname,vnam,nvars)
if (isok.eq.0) then
print*,'Variable ',trim(varname),' missing... Stop'
stop
endif
call cdfopn(gri,cdfid,ierr)
if (ierr.ne.0) goto 998
call getdat(cdfid,varname,time,0,y2,ierr)
if (ierr.ne.0) goto 998
print*,'R ',trim(varname),' ',trim(gri)
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Calculate reference profile of temperature
print*,'C T_ref = TH_ref * ( P_ref/1000)^kappa'
do i=0,2*nz
tref(i) = thetaref(i) * ( pressref(i)/1000. ) ** kappa
enddo
 
c Init height levels
do i=1,nx
do j=1,ny
do k=1,nz
z3(i,j,k)=zref(2*k-1)
enddo
enddo
enddo
 
c Load needed variables
do n=1,nfields
 
c Check whether variable is available on file
varname=field_nam(n)
isok=0
call check_varok (isok,varname,vnam,nvars)
 
c Variable is available on file
if (isok.eq.1) then
 
call cdfopn(ofn,cdfid,ierr)
if (ierr.ne.0) goto 998
call getdat(cdfid,varname,time,0,inp,ierr)
if (ierr.ne.0) goto 998
print*,'R ',trim(varname),' ',trim(ofn)
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
do i=1,nx
do j=1,ny
do k=1,nz
field_dat(n,i,j,k)=inp(i,j,k)
enddo
enddo
enddo
else
print*,'Variable missing : ',trim(varname)
stop
endif
 
enddo
 
c Add reference profile if ANO file is provided
if ( mode.eq.'ANO' ) then
 
print*,'C T -> T_ano + T_ref'
n=0
do i=1,nfields
if (field_nam(i).eq.'T') n=i
enddo
if (n.ne.0) then
do i=1,nx
do j=1,ny
do k=1,nz
field_dat(n,i,j,k) = field_dat(n,i,j,k) + tref(2*k-1)
enddo
enddo
enddo
endif
 
print*,'C TH -> TH_ano + TH_ref'
n=0
do i=1,nfields
if (field_nam(i).eq.'TH') n=i
enddo
if (n.ne.0) then
do i=1,nx
do j=1,ny
do k=1,nz
field_dat(n,i,j,k) = field_dat(n,i,j,k)+thetaref(2*k-1)
enddo
enddo
enddo
endif
 
print*,'C P -> P_ano + P_ref'
n=0
do i=1,nfields
if (field_nam(i).eq.'P') n=i
enddo
if (n.ne.0) then
do i=1,nx
do j=1,ny
do k=1,nz
field_dat(n,i,j,k) = field_dat(n,i,j,k)+pressref(2*k-1)
enddo
enddo
enddo
endif
 
endif
 
c Change units: P (hPa -> Pa), T(K -> degC)
n=0
do i=1,nfields
if (field_nam(i).eq.'P') n=i
enddo
if (n.ne.0) then
do i=1,nx
do j=1,ny
do k=1,nz
field_dat(n,i,j,k)=100.*field_dat(n,i,j,k)
enddo
enddo
enddo
endif
 
n=0
do i=1,nfields
if (field_nam(i).eq.'T') n=i
enddo
if (n.ne.0) then
do i=1,nx
do j=1,ny
do k=1,nz
if ( field_dat(n,i,j,1).gt.100. ) then
field_dat(n,i,j,k)=field_dat(n,i,j,k) - tzero
endif
enddo
enddo
enddo
endif
 
c ----------------------------------------------------------------
c Calculations
c ----------------------------------------------------------------
 
c Geostrophic wind (GEO)
if (fieldname.eq.'GEO') then
 
print*,'C ',trim(fieldname)
field_nam(1)='RHO'
do i=1,nx
do j=1,ny
do k=1,nz
if ( mode.eq.'ANO' ) then
field_dat(1,i,j,k)=rhoref(2*k-1)
else
field_dat(1,i,j,k)=
> 1./rd*field_dat(2,i,j,k)/(field_dat(1,i,j,k)+tzero)
endif
enddo
enddo
enddo
call calc_geo (out1,out2, ! (Ug,Vg)
> field_dat(1,:,:,:), ! RHO
> field_dat(2,:,:,:), ! P
> z3,x2,y2,f2, ! Z,X,Y,CORIOL
> nx,ny,nz,mdv)
 
c Ageostrophic wind (AGEO)
elseif (fieldname.eq.'AGEO') then
 
print*,'C ',trim(fieldname)
call calc_ageo (out1,out2, ! (Ua,Va)
> field_dat(1,:,:,:), ! U
> field_dat(2,:,:,:), ! UG
> field_dat(3,:,:,:), ! V
> field_dat(4,:,:,:), ! VG
> nx,ny,nz,mdv)
 
c Divergence of wind (DIV_UV)
else if (fieldname.eq.'DIV_UV') then
 
print*,'C ',trim(fieldname)
call calc_div_uv (out1, ! Div(U,V))
> field_dat(1,:,:,:), ! U
> field_dat(2,:,:,:), ! V
> z3,x2,y2,f2, ! Z,X,Y,CORIOL
> nx,ny,nz,mdv)
 
c Q vector (QVEC)
else if (fieldname.eq.'QVEC') then
 
print*,'C ',trim(fieldname)
call calc_qvec (out1,out2, ! (Qx,Qy)
> field_dat(1,:,:,:), ! UG
> field_dat(2,:,:,:), ! VG
> field_dat(3,:,:,:), ! TH
> z3,x2,y2,f2, ! Z,X,Y,CORIOL
> nx,ny,nz,mdv)
 
c Divergence of Q vector (DIV_Q)
else if (fieldname.eq.'DIV_Q') then
print*,'C ',trim(fieldname)
call calc_div_q (out1, ! Div(U,V))
> field_dat(1,:,:,:), ! QX
> field_dat(2,:,:,:), ! QY
> z3,x2,y2,f2, ! Z,X,Y,CORIOL
> nx,ny,nz,mdv)
 
endif
 
c Horizontal filtering of the resulting fields
print*,'F ',trim(fieldname)
do k=1,nz
do i=1,nx
do j=1,ny
tmp(i,j)=out1(i,j,k)
enddo
enddo
do n=1,nfilt
call filt2d (tmp,tmp,nx,ny,1.,mdv,0,0,0,0)
enddo
do i=1,nx
do j=1,ny
out1(i,j,k)=tmp(i,j)
enddo
enddo
 
do i=1,nx
do j=1,ny
tmp(i,j)=out2(i,j,k)
enddo
enddo
do n=1,nfilt
call filt2d (tmp,tmp,nx,ny,1.,mdv,0,0,0,0)
enddo
do i=1,nx
do j=1,ny
out2(i,j,k)=tmp(i,j)
enddo
enddo
enddo
 
c ----------------------------------------------------------------
c Save result onto netcdf file
c ----------------------------------------------------------------
 
c Open output file
call cdfwopn(ofn,cdfid,ierr)
if (ierr.ne.0) goto 998
 
c Save geostrophic wind
if (fieldname.eq.'GEO') then
isok=0
varname='UG'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out1,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
isok=0
varname='VG'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out2,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
 
c Save ageostrophic wind
elseif (fieldname.eq.'AGEO') then
isok=0
varname='UA'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out1,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
isok=0
varname='VA'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out2,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
 
c Save divergence of wind field
else if (fieldname.eq.'DIV_UV') then
isok=0
varname='DIV_UV'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out1,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
 
c Save components of Q vector
else if (fieldname.eq.'QVEC') then
isok=0
varname='QX'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out1,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
isok=0
varname='QY'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out2,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
 
c Save divergence of wind field
else if (fieldname.eq.'DIV_Q') then
isok=0
varname='DIV_Q'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) then
call putdef(cdfid,varname,ndim,mdv,vardim,
> varmin,varmax,stag,ierr)
if (ierr.ne.0) goto 998
endif
call putdat(cdfid,varname,time,0,out1,ierr)
if (ierr.ne.0) goto 998
print*,'W ',trim(varname),' ',trim(ofn)
 
endif
 
c Close output file
call clscdf(cdfid,ierr)
if (ierr.ne.0) goto 998
 
 
c ----------------------------------------------------------------
c Exception handling
c ----------------------------------------------------------------
stop
 
998 print*,'Problem with netcdf file'
stop
 
end
 
 
c ****************************************************************
c * SUBROUTINE SECTION: AUXILIARY ROUTINES *
c ****************************************************************
 
c ----------------------------------------------------------------
c Check whether variable is found on netcdf file
c ----------------------------------------------------------------
 
subroutine check_varok (isok,varname,varlist,nvars)
 
c Check whether the variable <varname> is in the list <varlist(nvars)>.
c If this is the case, <isok> is incremented by 1. Otherwise <isok>
c keeps its value.
 
implicit none
 
c Declaraion of subroutine parameters
integer isok
integer nvars
character*80 varname
character*80 varlist(nvars)
 
c Auxiliary variables
integer i
 
c Main
do i=1,nvars
if (trim(varname).eq.trim(varlist(i))) isok=isok+1
enddo
 
end
 
 
c ****************************************************************
c * SUBROUTINE SECTION: CALCULATE SECONDARY FIELDS *
c ****************************************************************
 
c ----------------------------------------------------------------
c Calculate geostrophic wind components
c ----------------------------------------------------------------
 
subroutine calc_geo (ug,vg,rho,p,
> z3,x2,y2,f2,nx,ny,nz,mdv)
 
c Calculate the geostrophic wind components (ug,vg) if the temperature
c (t) and the pressure (p) are given. The grid and the missing data
c value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real ug (nx,ny,nz)
real vg (nx,ny,nz)
real rho(nx,ny,nz)
real p (nx,ny,nz)
real z3 (nx,ny,nz)
real x2 (nx,ny)
real y2 (nx,ny)
real f2 (nx,ny)
real mdv
 
c Physical parameters and numerical constants
real eps
parameter (eps=0.01)
real g
parameter (g=9.80616)
 
 
c Auxiliray variables
integer i,j,k
real dpdx(nx,ny,nz)
real dpdy(nx,ny,nz)
 
c Calculate horizontal derivatives of pressure
call deriv(dpdx,p,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv(dpdy,p,'y',z3,x2,y2,nx,ny,nz,mdv)
 
c Calculation
do i=1,nx
do j=1,ny
do k=1,nz
 
if ((abs(rho (i,j,k)-mdv).gt.eps).and.
> (abs(dpdx(i,j,k)-mdv).gt.eps).and.
> (abs(dpdy(i,j,k)-mdv).gt.eps)) then
 
ug(i,j,k)=-1./(rho(i,j,k)*f2(i,j))*dpdy(i,j,k)
vg(i,j,k)= 1./(rho(i,j,k)*f2(i,j))*dpdx(i,j,k)
endif
 
enddo
enddo
enddo
 
end
 
c ----------------------------------------------------------------
c Calculate ageostrophic wind components
c ----------------------------------------------------------------
 
subroutine calc_ageo (ua,va,u,ug,v,vg,nx,ny,nz,mdv)
 
c Calculate the geostrophic wind components (ug,vg) if the temperature
c (t) and the pressure (p) are given. The grid and the missing data
c value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real ua (nx,ny,nz)
real va (nx,ny,nz)
real u (nx,ny,nz)
real ug (nx,ny,nz)
real v (nx,ny,nz)
real vg (nx,ny,nz)
real mdv
 
c Parameters
real eps
parameter (eps=0.01)
 
c Auxiliray variables
integer i,j,k
 
c Calculation
do i=1,nx
do j=1,ny
do k=1,nz
 
if ((abs(u (i,j,k)-mdv).gt.eps).and.
> (abs(ug(i,j,k)-mdv).gt.eps).and.
> (abs(v (i,j,k)-mdv).gt.eps).and.
> (abs(vg(i,j,k)-mdv).gt.eps)) then
 
ua(i,j,k)=u(i,j,k) - ug(i,j,k)
va(i,j,k)=v(i,j,k) - vg(i,j,k)
 
endif
 
enddo
enddo
enddo
 
end
 
c ----------------------------------------------------------------
c Calculate divergence of wind field
c ----------------------------------------------------------------
 
subroutine calc_div_uv (div_uv,u,v,
> z3,x2,y2,f2,nx,ny,nz,mdv)
 
c Calculate the divergence (div_uv) of the horizontal wind field if+
c the wind components (u,v) are given. The grid and the missing data
c value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real div_uv(nx,ny,nz)
real u (nx,ny,nz)
real v (nx,ny,nz)
real z3 (nx,ny,nz)
real x2 (nx,ny)
real y2 (nx,ny)
real f2 (nx,ny)
real mdv
 
c Physical parameters and numerical constants
real eps
parameter (eps=0.01)
 
c Auxiliray variables
integer i,j,k
real rho
real dudx(nx,ny,nz)
real dvdy(nx,ny,nz)
 
c Calculate horizontal derivatives of pressure
call deriv(dudx,u,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv(dvdy,v,'y',z3,x2,y2,nx,ny,nz,mdv)
 
c Calculation
do i=1,nx
do j=1,ny
do k=1,nz
 
if ((abs(dudx(i,j,k)-mdv).gt.eps).and.
> (abs(dvdy(i,j,k)-mdv).gt.eps)) then
 
div_uv(i,j,k)=dudx(i,j,k)+dvdy(i,j,k)
endif
 
enddo
enddo
enddo
 
end
 
c ----------------------------------------------------------------
c Calculate Q vector
c ----------------------------------------------------------------
 
subroutine calc_qvec (qx3,qy3,
> th3,u3,v3,
> z3,x2,y2,f2,nx,ny,nz,mdv)
 
c Calculate teh Q vector components <qx3> and <qy3>, as well as the divergence
c of the Q vector <divq3> on the model grid. The grid is specified in the horizontal
c by <xmin,ymin,dx,dy,nx,ny>. The number of vertical levels is <nz>. The input field
c are: potential temperature <th3>, horizontal wind <u3> and <v3>, pressure <p3>.
c The calculation follows the one described in "Weather Analysis, Dusan Djuric"
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real qx3(nx,ny,nz)
real qy3(nx,ny,nz)
real th3(nx,ny,nz)
real u3 (nx,ny,nz)
real v3 (nx,ny,nz)
real z3 (nx,ny,nz)
real x2 (nx,ny)
real y2 (nx,ny)
real f2 (nx,ny)
real mdv
 
c Physical and numerical parameters
real scale1,scale2
parameter (scale1=1.E10,scale2=1.E14)
real eps
parameter (eps=0.01)
real g
parameter (g=9.80616)
real tzero
parameter (tzero=273.16)
 
c Auxiliary variables
real dudx(nx,ny,nz)
real dudy(nx,ny,nz)
real dvdx(nx,ny,nz)
real dvdy(nx,ny,nz)
real dtdx(nx,ny,nz)
real dtdy(nx,ny,nz)
integer i,j,k
 
c Needed derivatives
call deriv (dudx, u3,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv (dudy, u3,'y',z3,x2,y2,nx,ny,nz,mdv)
call deriv (dvdx, v3,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv (dvdy, v3,'y',z3,x2,y2,nx,ny,nz,mdv)
call deriv (dtdx,th3,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv (dtdy,th3,'y',z3,x2,y2,nx,ny,nz,mdv)
 
c Calculate vector components of the Q vector
do i=1,nx
do j=1,ny
do k=1,nz
 
c Evaluate Q vector formula with missing data check
if ((abs(dudx(i,j,k)-mdv).gt.eps).and.
> (abs(dudy(i,j,k)-mdv).gt.eps).and.
> (abs(dvdx(i,j,k)-mdv).gt.eps).and.
> (abs(dvdy(i,j,k)-mdv).gt.eps).and.
> (abs(dtdx(i,j,k)-mdv).gt.eps).and.
> (abs(dtdy(i,j,k)-mdv).gt.eps)) then
 
qx3(i,j,k) = -g/tzero * (dudx(i,j,k)*dtdx(i,j,k)
> +dvdx(i,j,k)*dtdy(i,j,k))
qy3(i,j,k) = -g/tzero * (dudy(i,j,k)*dtdx(i,j,k)
> +dvdy(i,j,k)*dtdy(i,j,k))
 
else
qx3(i,j,k)=mdv
qy3(i,j,k)=mdv
endif
 
enddo
enddo
enddo
 
c Scale the output
do i=1,nx
do j=1,ny
do k=1,nz
if (abs(qx3(i,j,k)-mdv).gt.eps) then
qx3(i,j,k)=scale1*qx3(i,j,k)
endif
if (abs(qy3(i,j,k)-mdv).gt.eps) then
qy3(i,j,k)=scale1*qy3(i,j,k)
endif
enddo
enddo
enddo
 
end
 
c ----------------------------------------------------------------
c Calculate divergence of wind field
c ----------------------------------------------------------------
 
subroutine calc_div_q (div_q,qx,qy,
> z3,x2,y2,f2,nx,ny,nz,mdv)
 
c Calculate the divergence (div_q) of the Q vector field if
c the components (qx,qy) are given. The grid and the missing data
c value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real div_q(nx,ny,nz)
real qx (nx,ny,nz)
real qy (nx,ny,nz)
real z3 (nx,ny,nz)
real x2 (nx,ny)
real y2 (nx,ny)
real f2 (nx,ny)
real mdv
 
c Physical parameters and numerical constants
real eps
parameter (eps=0.01)
 
c Auxiliray variables
integer i,j,k
real rho
real dqxdx(nx,ny,nz)
real dqydy(nx,ny,nz)
 
c Calculate horizontal derivatives of pressure
call deriv(dqxdx,qx,'x',z3,x2,y2,nx,ny,nz,mdv)
call deriv(dqydy,qy,'y',z3,x2,y2,nx,ny,nz,mdv)
 
c Calculation
do i=1,nx
do j=1,ny
do k=1,nz
 
if ((abs(dqxdx(i,j,k)-mdv).gt.eps).and.
> (abs(dqydy(i,j,k)-mdv).gt.eps)) then
 
div_q(i,j,k)=dqxdx(i,j,k)+dqydy(i,j,k)
endif
 
enddo
enddo
enddo
 
end
 
 
c ****************************************************************
c * SUBROUTINE SECTION: GRID HANDLING *
c ****************************************************************
 
c -----------------------------------------------------------------
c Horizontal and vertical derivatives for 3d fields
c -----------------------------------------------------------------
 
subroutine deriv (df,f,direction,
> z3,x2,y2,nx,ny,nz,mdv)
 
c Calculate horizontal and vertical derivatives of the 3d field <f>.
c The direction of the derivative is specified in <direction>
c 'x','y' : Horizontal derivative in x and y direction
c 'p','z','t','m' : Vertical derivative (pressure, height, theta, model)
c The 3d field <z3> specifies the isosurfaces along which the horizontal
c derivatives are calculated or the levels for the vertical derivatives.
 
implicit none
 
c Input and output parameters
integer nx,ny,nz
real df (nx,ny,nz)
real f (nx,ny,nz)
real z3 (nx,ny,nz)
real x2 (nx,ny)
real y2 (nx,ny)
character direction
real mdv
c Numerical and physical parameters
real pi180
parameter (pi180=3.141592654/180.)
real deltay
parameter (deltay=111.1775E3)
real zerodiv
parameter (zerodiv=0.00000001)
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer i,j,k
real vmin,vmax
real scale,lat
real vu,vl,vuvl,vlvu
integer o,u,w,e,n,s
 
c Vertical derivative
if ((direction.eq.'z').or.
> (direction.eq.'th').or.
> (direction.eq.'p').or.
> (direction.eq.'m').and.
> (nz.gt.1)) then
 
do i=1,nx
do j=1,ny
do k=1,nz
o=k+1
if (o.gt.nz) o=nz
u=k-1
if (u.lt.1) u=1
 
if ((abs(f(i,j,o)-mdv).gt.eps).and.
> (abs(f(i,j,u)-mdv).gt.eps).and.
> (abs(f(i,j,k)-mdv).gt.eps)) then
 
vu = z3(i,j,k)-z3(i,j,o)
vl = z3(i,j,u)-z3(i,j,k)
vuvl = vu/(vl+zerodiv)
vlvu = 1./(vuvl+zerodiv)
 
df(i,j,k) = 1./(vu+vl)
> * (vuvl*(f(i,j,u)-f(i,j,k))
> + vlvu*(f(i,j,k)-f(i,j,o)))
 
else
df(i,j,k) = mdv
endif
 
enddo
enddo
enddo
c Horizontal derivative in the y direction: 3d
elseif (direction.eq.'y') then
do i=1,nx
do j=1,ny
do k=1,nz
s=j-1
if (s.lt.1) s=1
n=j+1
if (n.gt.ny) n=ny
 
if ((abs(f(i,n,k)-mdv).gt.eps).and.
> (abs(f(i,j,k)-mdv).gt.eps).and.
> (abs(f(i,s,k)-mdv).gt.eps)) then
vu = 1000.*(y2(i,j)-y2(i,n))
vl = 1000.*(y2(i,s)-y2(i,j))
vuvl = vu/(vl+zerodiv)
vlvu = 1./(vuvl+zerodiv)
df(i,j,k) = 1./(vu+vl)
> * (vuvl*(f(i,s,k)-f(i,j,k))
> + vlvu*(f(i,j,k)-f(i,n,k)))
 
else
df(i,j,k) = mdv
endif
 
enddo
enddo
enddo
 
c Horizontal derivative in the x direction: 3d
elseif (direction.eq.'x') then
 
do i=1,nx
do j=1,ny
do k=1,nz
w=i-1
if (w.lt.1) w=1
e=i+1
if (e.gt.nx) e=nx
 
if ((abs(f(w,j,k)-mdv).gt.eps).and.
> (abs(f(i,j,k)-mdv).gt.eps).and.
> (abs(f(e,j,k)-mdv).gt.eps)) then
vu = 1000.*(x2(i,j)-x2(e,j))
vl = 1000.*(x2(w,j)-x2(i,j))
vuvl = vu/(vl+zerodiv)
vlvu = 1./(vuvl+zerodiv)
 
df(i,j,k) = 1./(vu+vl)
> * (vuvl*(f(w,j,k)-f(i,j,k))
> + vlvu*(f(i,j,k)-f(e,j,k)))
 
else
df(i,j,k) = mdv
endif
 
enddo
enddo
enddo
c Undefined direction for derivative
else
print*,'Invalid direction of derivative... Stop'
stop
endif
 
end
 
c -----------------------------------------------------------------
c Horizontal filter
c -----------------------------------------------------------------
 
subroutine filt2d (a,af,nx,ny,fil,misdat,
& iperx,ipery,ispol,inpol)
 
c Apply a conservative diffusion operator onto the 2d field a,
c with full missing data checking.
c
c a real inp array to be filtered, dimensioned (nx,ny)
c af real out filtered array, dimensioned (nx,ny), can be
c equivalenced with array a in the calling routine
c f1 real workarray, dimensioned (nx+1,ny)
c f2 real workarray, dimensioned (nx,ny+1)
c fil real inp filter-coeff., 0<afil<=1. Maximum filtering with afil=1
c corresponds to one application of the linear filter.
c misdat real inp missing-data value, a(i,j)=misdat indicates that
c the corresponding value is not available. The
c misdat-checking can be switched off with with misdat=0.
c iperx int inp periodic boundaries in the x-direction (1=yes,0=no)
c ipery int inp periodic boundaries in the y-direction (1=yes,0=no)
c inpol int inp northpole at j=ny (1=yes,0=no)
c ispol int inp southpole at j=1 (1=yes,0=no)
c
c Christoph Schaer, 1993
 
c argument declaration
integer nx,ny
real a(nx,ny),af(nx,ny),fil,misdat
integer iperx,ipery,inpol,ispol
 
c local variable declaration
integer i,j,is
real fh
real f1(nx+1,ny),f2(nx,ny+1)
 
c compute constant fh
fh=0.125*fil
 
c compute fluxes in x-direction
if (misdat.eq.0.) then
do j=1,ny
do i=2,nx
f1(i,j)=a(i-1,j)-a(i,j)
enddo
enddo
else
do j=1,ny
do i=2,nx
if ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) then
f1(i,j)=0.
else
f1(i,j)=a(i-1,j)-a(i,j)
endif
enddo
enddo
endif
if (iperx.eq.1) then
c do periodic boundaries in the x-direction
do j=1,ny
f1(1,j)=f1(nx,j)
f1(nx+1,j)=f1(2,j)
enddo
else
c set boundary-fluxes to zero
do j=1,ny
f1(1,j)=0.
f1(nx+1,j)=0.
enddo
endif
 
c compute fluxes in y-direction
if (misdat.eq.0.) then
do j=2,ny
do i=1,nx
f2(i,j)=a(i,j-1)-a(i,j)
enddo
enddo
else
do j=2,ny
do i=1,nx
if ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) then
f2(i,j)=0.
else
f2(i,j)=a(i,j-1)-a(i,j)
endif
enddo
enddo
endif
c set boundary-fluxes to zero
do i=1,nx
f2(i,1)=0.
f2(i,ny+1)=0.
enddo
if (ipery.eq.1) then
c do periodic boundaries in the x-direction
do i=1,nx
f2(i,1)=f2(i,ny)
f2(i,ny+1)=f2(i,2)
enddo
endif
if (iperx.eq.1) then
if (ispol.eq.1) then
c do south-pole
is=(nx-1)/2
do i=1,nx
f2(i,1)=-f2(mod(i-1+is,nx)+1,2)
enddo
endif
if (inpol.eq.1) then
c do north-pole
is=(nx-1)/2
do i=1,nx
f2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)
enddo
endif
endif
 
c compute flux-convergence -> filter
if (misdat.eq.0.) then
do j=1,ny
do i=1,nx
af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
enddo
enddo
else
do j=1,ny
do i=1,nx
if (a(i,j).eq.misdat) then
af(i,j)=misdat
else
af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
endif
enddo
enddo
endif
end
 
c --------------------------------------------------------------------------------
c Read refernece profile from netcdf
c --------------------------------------------------------------------------------
 
SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,
> nx,ny,nz,deltax,deltay,deltaz,coriol,oro,
> pvsrcfile)
 
c Read the reference profile from file
c
c thetaref : Reference potential temperature (K)
c pressref : Reference pressure (Pa)
c rhoref : Reference density (kg/m^3)
c nsqref : Stratification (s^-1)
c zref : Reference height (m)
c nx,nny,nz : Grid dimension in x,y,z direction
c deltax,deltay,deltaz : Grid spacings used for calculations (m)
c coriol : Coriolis parameter (s^-1)
c oro : Height of orography (m)
c pvsrcfile : Input file
 
implicit none
 
c Declaration of subroutine parameters
integer nx,ny,nz
real nsqref (0:2*nz)
real thetaref(0:2*nz)
real rhoref (0:2*nz)
real pressref(0:2*nz)
real zref (0:2*nz)
real deltax,deltay,deltaz
real coriol (0:nx,0:ny)
real oro (0:nx,0:ny)
character*80 pvsrcfile
 
c Numerical and physical parameters
real eps
parameter (eps=0.01)
 
c Auxiliary variables
integer cdfid,stat
integer vardim(4)
real misdat
integer ndimin
real varmin(4),varmax(4),stag(4)
integer i,j,k,nf1
integer ntimes
real time(200)
character*80 vnam(100),varname
integer nvars
integer isok,ierr
real x(0:nx,0:ny),y(0:nx,0:ny)
real mean,count
 
c Get grid description from topography
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
isok=0
varname='ORO'
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdef(cdfid,varname,ndimin,misdat,vardim,
> varmin,varmax,stag,stat)
if (stat.ne.0) goto 997
time(1)=0.
call gettimes(cdfid,time,ntimes,stat)
if (stat.ne.0) goto 997
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Open output netcdf file
call cdfopn(pvsrcfile,cdfid,stat)
if (stat.ne.0) goto 997
 
c Create the variable if necessary
call getvars(cdfid,nvars,vnam,stat)
if (stat.ne.0) goto 997
 
c Read data from netcdf file
isok=0
varname='NSQREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,nsqref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='RHOREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,rhoref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='THETAREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,thetaref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='PREREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,pressref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='ZREF'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,zref,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='CORIOL'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,coriol,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='ORO'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,oro,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='X'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,x,stat)
if (stat.ne.0) goto 997
 
isok=0
varname='Y'
print*,'R ',trim(varname),' ',trim(pvsrcfile)
call check_varok(isok,varname,vnam,nvars)
if (isok.eq.0) goto 997
call getdat(cdfid,varname,time(1),0,y,stat)
if (stat.ne.0) goto 997
 
c Close netcdf file
call clscdf(cdfid,stat)
if (stat.ne.0) goto 997
 
c Determine the grid spacings <deltax, deltay, deltaz>
mean=0.
count=0.
do i=1,nx
do j=0,ny
mean=mean+abs(x(i)-x(i-1))
count=count+1.
enddo
enddo
deltax=mean/count
 
mean=0.
count=0.
do j=1,ny
do i=0,nx
mean=mean+abs(y(j)-y(j-1))
count=count+1.
enddo
enddo
deltay=mean/count
 
mean=0.
count=0.
do k=1,nz-1
mean=mean+abs(zref(k+1)-zref(k-1))
count=count+1.
enddo
deltaz=mean/count
 
return
 
c Exception handling
997 print*,'Read_Ref: Problem with input netcdf file... Stop'
stop
 
end
Property changes:
Added: svn:executable