0,0 → 1,978 |
PROGRAM z2s |
|
c Calculate secondary fields on z levels |
c Michael Sprenger / Summer 2006 |
|
implicit none |
|
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 |
real,allocatable, dimension (:,:,:) :: out |
real,allocatable, dimension (:,:,:) :: inp |
integer nvars |
character*80 vnam(100),varname |
integer isok |
integer cdfid,cstid |
|
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 (:,:) :: out2 |
character*80 vnam2(100) |
integer nvars2 |
|
c --------------------------------------------------------------- |
c Preparations |
c --------------------------------------------------------------- |
|
print*,'*********************************************************' |
print*,'* z2s *' |
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 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.'TH' ).and. |
> (fieldname.ne.'NSQ') .and. |
> (fieldname.ne.'PV' ) .and. |
> (fieldname.ne.'RHO')) then |
print*,'Variable not supported ',trim(fieldname) |
stop |
endif |
|
c Set dependencies |
if (fieldname.eq.'TH') then |
nfields=2 |
field_nam(1)='T' |
field_nam(2)='P' |
else if (fieldname.eq.'RHO') then |
nfields=2 |
field_nam(1)='T' |
field_nam(2)='P' |
else if (fieldname.eq.'NSQ') then |
nfields=2 |
field_nam(1)='T' |
field_nam(2)='Q' |
else if (fieldname.eq.'PV') then |
nfields=4 |
field_nam(1)='T' |
field_nam(2)='P' |
field_nam(3)='U' |
field_nam(4)='V' |
endif |
|
c Allocate memory |
allocate(field_dat(nfields,nx,ny,nz),stat=stat) |
if (stat.ne.0) print*,'error allocating field_dat' |
allocate(out(nx,ny,nz),stat=stat) |
if (stat.ne.0) print*,'error allocating out' |
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' |
|
c Allocate auxiliary fields |
allocate(out2(nx,ny),stat=stat) |
if (stat.ne.0) print*,'error allocating out2' |
|
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 Read Coriolis parametzer |
varname='CORIOL' |
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,f2,ierr) |
if (ierr.ne.0) goto 998 |
print*,'R ',trim(varname),' ',trim(gri) |
call clscdf(cdfid,ierr) |
if (ierr.ne.0) goto 998 |
|
c Init height levels |
do i=1,nx |
do j=1,ny |
do k=1,nz |
z3(i,j,k)=aklay(k) |
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 Change unit of pressure from hPa to Pa |
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 |
|
c ---------------------------------------------------------------- |
c Calculations |
c ---------------------------------------------------------------- |
|
c Call to the defining routines |
if (fieldname.eq.'RHO') then |
|
print*,'C ',trim(fieldname) |
call calc_rho (out, ! RHO |
> field_dat(1,:,:,:), ! T |
> field_dat(2,:,:,:), ! P |
> nx,ny,nz,mdv) |
|
else if (fieldname.eq.'TH') then |
|
print*,'C ',trim(fieldname) |
call calc_theta (out, ! TH |
> field_dat(1,:,:,:), ! T |
> field_dat(2,:,:,:), ! P |
> nx,ny,nz,mdv) |
|
else if (fieldname.eq.'NSQ') then |
|
print*,'C ',trim(fieldname) |
call calc_nsq (out, ! NSQ |
> field_dat(1,:,:,:), ! T |
> field_dat(2,:,:,:), ! Q |
> z3, ! Z |
> nx,ny,nz,mdv) |
|
else if (fieldname.eq.'PV') then |
|
print*,'C ',trim(fieldname) |
call calc_pv (out, ! PV |
> field_dat(1,:,:,:), ! T |
> field_dat(2,:,:,:), ! P |
> field_dat(3,:,:,:), ! U |
> field_dat(4,:,:,:), ! V |
> 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 |
out2(i,j)=out(i,j,k) |
enddo |
enddo |
do n=1,nfilt |
call filt2d (out2,out2,nx,ny,1.,mdv,0,0,0,0) |
enddo |
|
do i=1,nx |
do j=1,ny |
out(i,j,k)=out2(i,j) |
enddo |
enddo |
|
enddo |
|
c ---------------------------------------------------------------- |
c Save result onto netcdf file |
c ---------------------------------------------------------------- |
|
call cdfwopn(ofn,cdfid,ierr) |
if (ierr.ne.0) goto 998 |
isok=0 |
varname=fieldname |
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,out,ierr) |
if (ierr.ne.0) goto 998 |
print*,'W ',trim(varname),' ',trim(ofn) |
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 density |
c ----------------------------------------------------------------- |
|
subroutine calc_rho (rho3,t3,p3, |
> nx,ny,nz,mdv) |
|
c Calculate the density <rho3> (in kg/m^3) from temperature <t3> |
c (in deg C) and pressure <p3> (in hPa). |
|
implicit none |
|
c Declaration of subroutine parameters |
integer nx,ny,nz |
real mdv |
real rho3(nx,ny,nz) |
real t3 (nx,ny,nz) |
real p3 (nx,ny,nz) |
|
c Declaration of physical constants |
real eps |
parameter (eps=0.01) |
real rd |
parameter (rd=287.) |
real tzero |
parameter (tzero=273.15) |
|
c Auxiliary variables |
integer i,j,k |
|
c Calculation |
do i=1,nx |
do j=1,ny |
do k=1,nz |
|
if ((abs(t3(i,j,k)-mdv).gt.eps).and. |
> (abs(p3(i,j,k)-mdv).gt.eps)) then |
|
rho3(i,j,k)=1./rd*p3(i,j,k)/(t3(i,j,k)+tzero) |
|
else |
rho3(i,j,k)=mdv |
endif |
|
enddo |
enddo |
enddo |
|
end |
|
|
c ----------------------------------------------------------------- |
c Calculate potential temperature |
c ----------------------------------------------------------------- |
|
subroutine calc_theta (th3,t3,p3, |
> nx,ny,nz,mdv) |
|
c Calculate potential temperature <th3> (in K) from temperature <t3> |
c (in deg C) and pressure <p3> (in hPa). |
|
implicit none |
|
c Declaration of subroutine parameters |
integer nx,ny,nz |
real mdv |
real th3(nx,ny,nz) |
real t3 (nx,ny,nz) |
real p3 (nx,ny,nz) |
|
c Declaration of physical constants |
real rdcp,tzero,p0 |
parameter (rdcp=0.286) |
parameter (tzero=273.15) |
parameter (p0=100000.) |
real eps |
parameter (eps=0.01) |
|
c Auxiliary variables |
integer i,j,k |
|
c Calculation |
do i=1,nx |
do j=1,ny |
do k=1,nz |
|
if ((abs(t3(i,j,k)-mdv).gt.eps).and. |
> (abs(p3(i,j,k)-mdv).gt.eps)) then |
|
th3(i,j,k)=(t3(i,j,k)+tzero)*( (p0/p3(i,j,k))**rdcp ) |
|
else |
th3(i,j,k)=mdv |
endif |
|
enddo |
enddo |
enddo |
|
end |
|
c ----------------------------------------------------------------- |
c Calculate stratification |
c ----------------------------------------------------------------- |
|
subroutine calc_nsq (nsq3,t3,q3, |
> z3,nx,ny,nz,mdv) |
|
c Calculate stratification <nsq3> on the model grid. The grid is |
c specified in the horizontal by <xmin,ymin,dx,dy,nx,ny>. The number |
c of vertical levels is <nz>. The input field are: temperature <t3>, |
c specific humidity <q3>, height <z3> and horizontal grid <x2>, <y2>. |
|
implicit none |
|
c Declaration of subroutine parameters |
integer nx,ny,nz |
real nsq3(nx,ny,nz) |
real t3 (nx,ny,nz) |
real q3 (nx,ny,nz) |
real z3 (nx,ny,nz) |
real x2 (nx,ny) |
real y2 (nx,ny) |
real mdv |
|
c Physical and numerical parameters |
real scale |
parameter (scale=1.) |
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 cp |
parameter (cp=1005.) |
real zerodiv |
parameter (zerodiv=0.0000000001) |
real R |
parameter (R=287.) |
|
c Auxiliary variables |
real tv (nx,ny,nz) |
real dtvdz(nx,ny,nz) |
integer i,j,k |
real scaledz |
|
c Calculate 3d virtual temperature |
do k=1,nz |
do i=1,nx |
do j=1,ny |
if ((abs(t3(i,j,k)-mdv).gt.eps).and. |
> (abs(q3(i,j,k)-mdv).gt.eps)) |
> then |
tv(i,j,k) = (t3(i,j,k)+tzero)*(1.+kappa*q3(i,j,k)) |
else |
tv(i,j,k) = mdv |
endif |
enddo |
enddo |
enddo |
|
c Vertical derivative of virtual temperature |
call deriv (dtvdz,tv,'z',z3,x2,y2,nx,ny,nz,mdv) |
|
c Stratification |
do i=1,nx |
do j=1,ny |
do k=1,nz |
if ((abs(dtvdz(i,j,k)-mdv).gt.eps).and. |
> (abs(tv (i,j,k)-mdv).gt.eps)) |
> then |
nsq3(i,j,k) = g/tv(i,j,k) * (dtvdz(i,j,k) + g/cp) |
else |
nsq3(i,j,k) = mdv |
endif |
enddo |
enddo |
enddo |
|
end |
|
c ----------------------------------------------------------------- |
c Calculate potential vorticity |
c ----------------------------------------------------------------- |
|
subroutine calc_pv (pv3,t3,p3,u3,v3, |
> z3,x2,y2,f2,nx,ny,nz,mdv) |
|
c Calculate potential vorticity <pv3> on the model grid. The grid is |
c specified in the horizontal by <xmin,ymin,dx,dy,nx,ny>. The number |
c of vertical levels is <nz>. The input field are: potential temperature |
c <th3>, horizontal wind <u3> and <v3>, density <rho3>, height <z3>. |
c The terms including the vertical velocity are neglected in the calculation |
c of the PV. |
|
implicit none |
|
c Declaration of subroutine parameters |
integer nx,ny,nz |
real pv3 (nx,ny,nz) |
real t3 (nx,ny,nz) |
real p3 (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 scale |
parameter (scale=1.E6) |
real omega |
parameter (omega=7.292E-5) |
real pi180 |
parameter (pi180=3.141592654/180.) |
real eps |
parameter (eps=0.01) |
|
c Auxiliary variables |
real dtdz(nx,ny,nz) |
real dtdx(nx,ny,nz) |
real dtdy(nx,ny,nz) |
real dudz(nx,ny,nz) |
real dvdz(nx,ny,nz) |
real dvdx(nx,ny,nz) |
real dudy(nx,ny,nz) |
real rho3(nx,ny,nz) |
real th3 (nx,ny,nz) |
|
integer i,j,k |
|
c Calculate density and potential temperature |
call calc_rho (rho3,t3,p3,nx,ny,nz,mdv) |
call calc_theta (th3 ,t3,p3,nx,ny,nz,mdv) |
|
c Calculate needed derivatives |
call deriv (dudz, u3,'z',z3,x2,y2,nx,ny,nz,mdv) |
call deriv (dvdz, v3,'z',z3,x2,y2,nx,ny,nz,mdv) |
call deriv (dtdz,th3,'z',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) |
call deriv (dvdx, v3,'x',z3,x2,y2,nx,ny,nz,mdv) |
call deriv (dudy, u3,'y',z3,x2,y2,nx,ny,nz,mdv) |
|
c Calculate potential vorticity |
do j=1,ny |
do i=1,nx |
do k=1,nz |
|
c Evaluate PV formula with missing data check |
if ((abs(dtdz(i,j,k)-mdv).gt.eps).and. |
> (abs(dudz(i,j,k)-mdv).gt.eps).and. |
> (abs(dtdy(i,j,k)-mdv).gt.eps).and. |
> (abs(dvdz(i,j,k)-mdv).gt.eps).and. |
> (abs(rho3(i,j,k)-mdv).gt.eps).and. |
> (abs(dtdx(i,j,k)-mdv).gt.eps).and. |
> (abs(dvdx(i,j,k)-mdv).gt.eps).and. |
> (abs(dudy(i,j,k)-mdv).gt.eps)) then |
|
pv3(i,j,k)=scale*1./rho3(i,j,k)* |
> ((dvdx(i,j,k)-dudy(i,j,k)+f2(i,j))*dtdz(i,j,k) |
> +dudz(i,j,k)*dtdy(i,j,k) |
> -dvdz(i,j,k)*dtdx(i,j,k)) |
else |
pv3(i,j,k)=mdv |
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 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 |
Property changes: |
Added: svn:executable |