| 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 |