Blame | Last modification | View Log | Download | RSS feed
PROGRAM inv_cartc ********************************************************************************c * CALCULATES FOR A PV AND THETA DISTRIBUTION OTHER PROGNOSTIC FIELDS BY *c * MEANS OF A PV INVERSION *c * *c * Rene Fehlmann 1994 / Code re-organization: Michael Sprenger, 2006 *c ********************************************************************************c --------------------------------------------------------------------------------c Declaration of variables, parameters, externals and common blocksc --------------------------------------------------------------------------------implicit nonec Grid parametersinteger nx,ny,nzreal xmin,ymin,zmin,xmax,ymax,zmaxreal dx,dy,dzreal deltax,deltay,deltazreal mdvreal, allocatable,dimension (:,:) :: coriolc Reference statereal, allocatable,dimension (:) :: nsqrefreal, allocatable,dimension (:) :: thetarefreal, allocatable,dimension (:) :: rhorefreal, allocatable,dimension (:) :: pressrefreal, allocatable,dimension (:) :: zrefC Boundary conditionsreal, allocatable,dimension (:,:) :: thetatopreal, allocatable,dimension (:,:) :: thetabotreal, allocatable,dimension (:,:) :: uareal, allocatable,dimension (:,:) :: ubreal, allocatable,dimension (:,:) :: vareal, allocatable,dimension (:,:) :: vbc Potentiual vorticity and stream functionreal, allocatable,dimension (:,:,:) :: psireal, allocatable,dimension (:,:,:) :: pvc Auxiliary arrays for numericsreal, allocatable,dimension (:,:,:) :: areal, allocatable,dimension (:,:,:) :: breal, allocatable,dimension (:,:,:) :: cc Input parameterscharacter*80 pvsrcfilecharacter*80 referfilec Auxiliary variablesinteger i,j,kinteger statc --------------------------------------------------------------------------------c Preparationsc --------------------------------------------------------------------------------print*,'********************************************************'print*,'* INV_CART *'print*,'********************************************************'c Read parameter fileopen(10,file='fort.10')read(10,*) pvsrcfileread(10,*) referfileclose(10)print*print*,trim(pvsrcfile)c Get lat/lon gid parameters from input filecall read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,> pvsrcfile)print*print*,'Read_Dim: nx,ny,nz = ',nx,ny,nzprint*,' dx,dy,dz = ',dx,dy,dzprint*,' xmin,ymin,zmin = ',xmin,ymin,zminprint*,' mdv = ',mdvprint*c Count from 0, not from 1nx=nx-1ny=ny-1nz=nz-1c Allocate memory for boundary conditionsallocate(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 Allocate memory for 3d PV and stream functionallocate(psi(0:nx,0:ny,0:nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array psi ***'allocate(pv(0:nx,0:ny,0:nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array pv ***'c Alllocate memory for matrix elements for inversion operatorallocate(a(0:nx,0:ny,0:nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array a ***'allocate(b(0:nx,0:ny,0:nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array b ***'allocate(c(0:nx,0:ny,0:nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array c ***'c Allocate memory for reference profileallocate(nsqref(0:2*nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array nsqref ***'allocate(thetaref(0:2*nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array thetaref ***'allocate(rhoref(0:2*nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array rhoref ***'allocate(pressref(0:2*nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array pressref ***'allocate(zref(0:2*nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array zref ***'c Allocate memory for Coriolis parameterallocate(coriol(0:nx,0:ny),STAT=stat)if (stat.ne.0) print*,'error allocating coriol'c --------------------------------------------------------------------------------c Inputc --------------------------------------------------------------------------------c Read reference profile and grid parameterscall read_ref (nsqref,rhoref,thetaref,pressref,zref,> nx,ny,nz,deltax,deltay,deltaz,coriol,> referfile)deltax=1000.*deltaxdeltay=1000.*deltayc Read input fields from netcdfcall read_inp (pv,thetabot,thetatop,ua,ub,va,vb,> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,> pvsrcfile)c --------------------------------------------------------------------------------c Perform the inversionc --------------------------------------------------------------------------------C Init matrix elements for inversioncall matrixel(a,b,c,coriol,nx,ny,nz,nsqref,rhoref,> deltax,deltay,deltaz)c Inversioncall sor(psi,nsqref,thetatop,thetabot,thetaref,rhoref,coriol,> pv,ua,ub,va,vb,a,b,c,nx,ny,nz,deltax,deltay,deltaz)c --------------------------------------------------------------------------------c Outputc --------------------------------------------------------------------------------c Write output to netcdfprint*call write_out (psi,thetabot,thetatop,ua,ub,va,vb,> nx,ny,nz,deltax,deltay,deltaz,> coriol,thetaref,rhoref,pressref,pvsrcfile)ENDc ********************************************************************************c * NETCDF AND ASCII INPUT AND OUTPUT *c ********************************************************************************c --------------------------------------------------------------------------------c Output to netcdf filec --------------------------------------------------------------------------------SUBROUTINE write_out (psi,thetabot,thetatop,ua,ub,va,vb,nx,ny,nz,> dx,dy,dz,coriol,thetaref,rhoref,pref,> pvsrcfile)c Write the result of the inversion to output netcdfcc psi : streamm function as calculated from inversionc thetabot,thetatop : potential temperature at lower and upper boundaryc ua,ub : Zonal wind at western and eastern boundaryc va,vb : Meridional wind at southern and northern boundaryc nx,ny,nz : Grid dimension in x, y and z directionc dx,dy,dz : Grid resolutionc coriol : Coriolis parameterc thetaref : Reference profile of potential temperaturec rhoref : Reference profile of densityc pref : Reference profile of pressurec pvsrcfile : Name of the output netcdf fileimplicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal psi(0:nx,0:ny,0:nz)real thetatop(0:nx,0:ny)real thetabot(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)character*(30) pvsrcfilereal dx,dy,dzreal thetaref(0:2*nz)real rhoref(0:2*nz)real pref(0:2*nz)real coriol(0:nx,0:ny)c Numerical and physical parametersreal epsparameter (eps=0.01)real gparameter (g=9.81)real preunitparameter (preunit=0.01)real kappaparameter (kappa=0.286)c Auxiliary variablesinteger cdfid,statinteger vardim(4)real misdatinteger ndiminreal varmin(4),varmax(4),stag(4)integer i,j,k,nf1,jj,kkreal tmp(0:nx,0:ny,0:nz)real pr (0:nx,0:ny,0:nz)real th (0:nx,0:ny,0:nz)integer ntimesreal time(200)character*80 vnam(100),varnameinteger nvarsinteger isok,ierrreal meanpsi,meancntc Get grid descriptioncall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997call getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997isok=0varname='QGPV'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 997call clscdf(cdfid,stat)if (stat.ne.0) goto 997c Open output netcdf filecall cdfwopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997c Create the variable if necessarycall getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997isok=0varname='PSI'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifisok=0varname='U'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifisok=0varname='V'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifisok=0varname='TH'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifisok=0varname='T'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifisok=0varname='P'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997endifc Write stream functionvarname='PSI'call putdat(cdfid,varname,time(1),0,psi,ierr)if (stat.ne.0) goto 997print*,'W PSI ',trim(pvsrcfile)c Calculate and write velocity U: keep southern and northern boundarydo k=0,nzdo i=0,nxdo j=1,ny-1tmp(i,j,k)=(psi(i,j-1,k)-psi(i,j+1,k))/> (2.*dy*coriol(i,j))enddotmp(i,0,k) =ua(i,k)tmp(i,ny,k)=ub(i,k)enddoenddovarname='U'call putdat(cdfid,varname,time(1),0,tmp,ierr)if (stat.ne.0) goto 997print*,'W U ',trim(pvsrcfile)C Calculate and write velocity V: keep western and eastern boundarydo k=0,nzdo j=0,nydo i=1,nx-1tmp(i,j,k)=(psi(i+1,j,k)-psi(i-1,j,k))/> (2.*dx*coriol(i,j))enddotmp(0,j,k)=va(j,k)tmp(nx,j,k)=vb(j,k)enddoenddovarname='V'call putdat(cdfid,varname,time(1),0,tmp,ierr)if (stat.ne.0) goto 997print*,'W V ',trim(pvsrcfile)c Calculate and write potential temperature: keep lower and upper boundaryc Potential temperature is needed for calculation of temperature: keep itdo i=0,nxdo j=0,nyth(i,j,0)=thetabot(i,j)do k=1,nz-1th(i,j,k)=thetaref(2*k)*> (psi(i,j,k+1)-psi(i,j,k-1))/(2.*dz*g)enddoth(i,j,nz)=thetatop(i,j)enddoenddovarname='TH'call putdat(cdfid,varname,time(1),0,th,ierr)if (stat.ne.0) goto 997print*,'W TH ',trim(pvsrcfile)c Calculate and write pressure: The pressure is directly proportional to thec streamfunction. But the streamfunction is determined only up to an additivec constant. Shift the streamfunction in such a way that it vanish in the meanc on the boundaries. Pressure is needed for calculation of temperature: keep itmeanpsi=0.meancnt=0.do i=0,nxdo j=0,nymeanpsi=meanpsi+psi(i,j,0)+psi(i,j,nz)meancnt=meancnt+2enddoenddodo i=0,nxdo k=0,nzmeanpsi=meanpsi+psi(i,0,k)+psi(i,ny,k)meancnt=meancnt+2enddoenddodo j=0,nydo k=0,nzmeanpsi=meanpsi+psi(0,j,k)+psi(nx,j,k)meancnt=meancnt+2enddoenddomeanpsi=meanpsi/meancntdo i=0,nxdo j=0,nydo k=0,nzkk=2*kpr(i,j,k)=preunit*rhoref(kk)*(psi(i,j,k)-meanpsi)enddoenddoenddovarname='P'call putdat(cdfid,varname,time(1),0,pr,ierr)if (stat.ne.0) goto 997print*,'W P ',trim(pvsrcfile)c Calculate and write temperaturedo i=0,nxdo j=0,nydo k=0,nzkk=2*ktmp(i,j,k)=((pref(kk)/1000.)**kappa) *> (th(i,j,k)+kappa*thetaref(kk)*pr(i,j,k)/pref(kk))enddoenddoenddovarname='T'call putdat(cdfid,varname,time(1),0,tmp,ierr)if (stat.ne.0) goto 997print*,'W T ',trim(pvsrcfile)c Close output netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 997returnc Exception handling997 print*,'Problem with output netcdf file... Stop'stopendc --------------------------------------------------------------------------------c Read the reference filec --------------------------------------------------------------------------------SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,> nx,ny,nz,deltax,deltay,deltaz,coriol,> pvsrcfile)c Read the reference profile from filecc 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 directionc deltax,deltay,deltaz : Grid spacings used for calculations (m)c coriol : Coriolis parameter (s^-1)c pvsrcfile : Input fileimplicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal 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,deltazreal coriol (0:nx,0:ny)character*80 pvsrcfilec Numerical and physical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,statinteger vardim(4)real misdatinteger ndiminreal varmin(4),varmax(4),stag(4)integer i,j,k,nf1integer ntimesreal time(200)character*80 vnam(100),varnameinteger nvarsinteger isok,ierrreal x(0:nx,0:ny),y(0:nx,0:ny)real mean,countc Get grid description from topographycall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997call getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997isok=0varname='ORO'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 997call clscdf(cdfid,stat)if (stat.ne.0) goto 997c Open output netcdf filecall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997c Create the variable if necessarycall getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997c Read data from netcdf fileisok=0varname='NSQREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,nsqref,stat)if (stat.ne.0) goto 997isok=0varname='RHOREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,rhoref,stat)if (stat.ne.0) goto 997isok=0varname='THETAREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,thetaref,stat)if (stat.ne.0) goto 997isok=0varname='PREREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,pressref,stat)if (stat.ne.0) goto 997isok=0varname='ZREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,zref,stat)if (stat.ne.0) goto 997isok=0varname='CORIOL'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,coriol,stat)if (stat.ne.0) goto 997isok=0varname='X'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,x,stat)if (stat.ne.0) goto 997isok=0varname='Y'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,y,stat)if (stat.ne.0) goto 997c Close netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 997c Determine the grid spacings <deltax, deltay, deltaz>mean=0.count=0.do i=1,nxdo j=0,nymean=mean+abs(x(i,j)-x(i-1,j))count=count+1.enddoenddodeltax=mean/countmean=0.count=0.do j=1,nydo i=0,nxmean=mean+abs(y(i,j)-y(i,j-1))count=count+1.enddoenddodeltay=mean/countmean=0.count=0.do k=1,nz-1mean=mean+abs(zref(k+1)-zref(k-1))count=count+1.enddodeltaz=mean/countreturnc Exception handling997 print*,'Read_Ref: Problem with input netcdf file... Stop'stopendc --------------------------------------------------------------------------------c Get grid parametersc --------------------------------------------------------------------------------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 arec nx,ny,nz : Number of grid points in x, y and z directionc xmin,ymin,zmin : Minimum domain coordinates in x, y and z directionc xmax,ymax,zmax : Maximal domain coordinates in x, y and z directionc dx,dy,dz : Horizontal and vertical resolutionc 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 nonec Declaration of subroutine parameterscharacter*80 pvsrcfileinteger nx,ny,nzreal dx,dy,dzreal xmin,ymin,zmin,xmax,ymax,zmaxreal mdvc Numerical epsilon and other physical/geoemtrical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,cstidinteger ierrcharacter*80 vnam(100),varnameinteger nvarsinteger isokinteger vardim(4)real misdatreal varmin(4),varmax(4),stag(4)real aklev(1000),bklev(1000),aklay(1000),bklay(1000)real dhcharacter*80 csninteger ndiminteger ic Get all grid parameterscall cdfopn(pvsrcfile,cdfid,ierr)if (ierr.ne.0) goto 998call getvars(cdfid,nvars,vnam,ierr)if (ierr.ne.0) goto 998isok=0varname='QGPV'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 998call getcfn(cdfid,csn,ierr)if (ierr.ne.0) goto 998call cdfopn(csn,cstid,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,varname,ndim,misdat,vardim,varmin,varmax,> stag,ierr)if (ierr.ne.0) goto 998nx=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 998call getgrid(cstid,dx,dy,ierr)if (ierr.ne.0) goto 998xmax=varmax(1)ymax=varmax(2)zmax=varmax(3)dz=(zmax-zmin)/real(nz-1)call clscdf(cstid,ierr)if (ierr.ne.0) goto 998call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Check whether the grid is equallay spaced in the verticaldo i=1,nz-1dh=aklev(i+1)-aklev(i)if (abs(dh-dz).gt.eps) thenprint*,'Aklev: Vertical grid must be equally spaced... Stop'print*,(aklev(i),i=1,nz)stopendifdh=aklay(i+1)-aklay(i)if (abs(dh-dz).gt.eps) thenprint*,'Aklay: Vertical grid must be equally spaced... Stop'print*,(aklay(i),i=1,nz)stopendifenddoc Set missing data valuemdv=misdatreturnc Exception handling998 print*,'Read_Dim: Problem with input netcdf file... Stop'stopendc -------------------------------------------------------------------------------c Read the input netcdf filec --------------------------------------------------------------------------------SUBROUTINE read_inp (pv,thetabot,thetatop,ua,ub,va,vb,> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,> pvsrcfile)c Read all needed field from netcdf file <pvsrcfile>. The input fields are:c pv : quasigeostrophic potential vorticityc thetabot,thetatop : potential temperature at lower and upper boundaryc ua,ub : Zonal wind at western and eastern boundaryc va,vb : Meridional wind at southern and northern boundaryc The grid is specified by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performedc whether the input files are consitent with this grid. The input netcdf file mustc contain the variables <QGPV,THETA,U,V>. If the netcdf file also contains the fieldsc <DQGPV,DTHETA,DU,DV>, these increments are added to <QGPV,THETA,U,V>.implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal pv(0:nx,0:ny,0:nz)real thetatop(0:nx,0:ny)real thetabot(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)character*(30) pvsrcfilereal dx,dy,dz,xmin,ymin,zminc Numerical and physical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,statinteger vardim(4)real misdatreal varmin(4),varmax(4),stag(4)integer ndimin,outid,i,j,kreal max_threal tmp(0:nx,0:ny,0:nz)integer ntimesreal time(200)integer nvarscharacter*80 vnam(100),varnameinteger isokc Open the input netcdf filecall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 998c Check whether needed variables are on filecall getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 998isok=0varname='TH'call check_varok(isok,varname,vnam,nvars)varname='U'call check_varok(isok,varname,vnam,nvars)varname='V'call check_varok(isok,varname,vnam,nvars)varname='QGPV'call check_varok(isok,varname,vnam,nvars)if (isok.ne.4) goto 998c Get the grid parametersvarname='QGPV'call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 998c Check whether grid parameters are consitentif ( (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(nx)-dx).gt.eps).or.> (abs((varmax(2)-varmin(2))/real(ny)-dy).gt.eps).or.> (abs((varmax(3)-varmin(3))/real(nz)-dz).gt.eps) ) thenprint*,'Input grid inconsitency...'print*,'xmin : ',xmin,varmin(1)print*,'ymin : ',ymin,varmin(2)print*,'zmin : ',zmin,varmin(3)print*,'dx : ',dx,(varmax(1)-varmin(1))/real(nx)print*,'dy : ',dy,(varmax(2)-varmin(2))/real(ny)print*,'dz : ',dz,(varmax(3)-varmin(3))/real(nz)print*,'nx : ',nxprint*,'ny : ',nyprint*,'nz : ',nzgoto 998endifc THETA: Load upper and lower boundary valuesvarname='TH'call getdat(cdfid,varname,time(1),0,tmp,stat)print*,'R TH ',trim(pvsrcfile)if (stat.ne.0) goto 998do i=0,nxdo j=0,nyif ( abs(tmp(i,j,0)-misdat).lt.eps ) thenthetabot(i,j)=0.elsethetabot(i,j)=tmp(i,j,0)endifif ( abs(tmp(i,j,nz)-misdat).lt.eps ) thenthetatop(i,j)=0.elsethetatop(i,j)=tmp(i,j,nz)endifenddoenddoc U: Load zonal velocity at southern and northern boundaryvarname='U'call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998call getdat(cdfid,varname,time(1),0,tmp,stat)print*,'R U ',trim(pvsrcfile)if (stat.ne.0) goto 998do i=0,nxdo k=0,nzif ( abs(tmp(i,0,k)-misdat).lt.eps ) thenua(i,k)=0.elseua(i,k)=tmp(i,0,k)endifif ( abs(tmp(i,ny,k)-misdat).lt.eps ) thenub(i,k)=0.elseub(i,k)=tmp(i,ny,k)endifenddoenddoc Load meridional velocity at western and eastern boundaryvarname='V'call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998call getdat(cdfid,varname,time(1),0,tmp,stat)print*,'R V ',trim(pvsrcfile)if (stat.ne.0) goto 998do j=0,nydo k=0,nzif ( abs(tmp(0,j,k)-misdat).lt.eps ) thenva(j,k)=0.elseva(j,k)=tmp(0,j,k)endifif ( abs(tmp(nx,j,k)-misdat).lt.eps ) thenvb(j,k)=0.elsevb(j,k)=tmp(nx,j,k)endifenddoenddoc Load qgPVvarname='QGPV'call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998call getdat(cdfid,varname,time(1),0,tmp,stat)print*,'R QGPV ',trim(pvsrcfile)if (stat.ne.0) goto 998do i=0,nxdo j=0,nydo k=0,nzif ( abs(tmp(i,j,k)-misdat).lt.eps ) thenpv(i,j,k)=0.elsepv(i,j,k)=tmp(i,j,k)endifenddoenddoenddoc Close input netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 998returnc Exception handling998 print*,'Problem with input netcdf file... Stop'stopendc --------------------------------------------------------------------------------c Check whether variable is found on netcdf filec --------------------------------------------------------------------------------subroutine check_varok (isok,varname,varlist,nvars)c Check whether the variable <varname> is in the list <varlist(nvars)>. If this isC the case, <isok> is incremented by 1. Otherwise <isok> keeps its value.implicit nonec Declaraion of subroutine parametersinteger isokinteger nvarscharacter*80 varnamecharacter*80 varlist(nvars)c Auxiliary variablesinteger ic Maindo i=1,nvarsif (trim(varname).eq.trim(varlist(i))) isok=isok+1enddoendc ********************************************************************************c * INVERSION ROUTINES *c ********************************************************************************c --------------------------------------------------------------------------------c SOR algorithm (successive over relaxation)c --------------------------------------------------------------------------------SUBROUTINE sor(psi,nsq,thetatop,thetabot,thetaref,rhoref,> coriol,pv,ua,ub,va,vb,a,b,c,nx,ny,nz,dx,dy,dz)c Solve the qgPV equation by succesive over relaxation (SOR). The subroutinec parameters are:cc psi : Streamfunction, i.e. result of the PV inversionc nsq,rhoref,thetaref : Reference profilec thetatop,thetabot : Upper and lower boundary conditionc pv : quasigeostrophic potential vorticity (qgPV)c ua,ub,va,vb : lateral boundary condition for windc a,b,c : Matrices for the inversion operatorc nx,ny,nz,dx,dy,dz : Grid specificationc coriol : Coriolis parameterimplicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal dx,dy,dzreal psi (0:nx,0:ny,0:nz)real nsq (0:2*nz)real thetatop(0:nx,0:ny)real thetabot(0:nx,0:ny)real thetaref(0:2*nz)real rhoref (0:2*nz)real pv (0:nx,0:ny,0:nz)real ua (0:nx,0:nz)real ub (0:nx,0:nz)real va (0:ny,0:nz)real vb (0:ny,0:nz)real a (0:nx,0:ny,0:nz)real b (0:nx,0:ny,0:nz)real c (0:nx,0:ny,0:nz)real coriol (0:nx,0:ny)c Numerical and physical parametersreal maxspecparameter (maxspec=2.0)integer nofiterparameter (nofiter=500)real omegaparameter (omega=1.81)c Auxiliary variablesinteger counterinteger i,j,kreal deltasq,psigaugereal specx,specy,speczreal helpx,helpy,helpzc Init the output arraydo i=0,nxdo j=0,nydo k=0,nzpsi(i,j,k)=0.enddoenddoenddoc Calculate the spectrum of the matrixi=nx/2specx=4.*a(i,0,0)/> (2.*a(i,0,0)+b(i,0,0)+b(i,1,0)+c(i,0,0)+c(i,0,1))specy=2.*(b(i,0,0)+b(i,1,0))/> (2.*a(i,0,0)+b(i,0,0)+b(i,1,0)+c(i,0,0)+c(i,0,1))specz=2.*(c(i,0,0)+c(i,0,1))/> (2.*a(i,0,0)+b(i,0,0)+b(i,1,0)+c(i,0,0)+c(i,0,1))do k=1,nz-2do j=1,ny-2helpx=4.*a(i,j,k)/> (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k)+c(i,j,k-1))if (helpx.gt.specx) specx=helpxhelpy=2.*(b(i,j,k)+b(i,j+1,k))/> (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k)+c(i,j,k-1))if (helpy.gt.specy) specy=helpyhelpz=2.*(c(i,j,k)+c(i,j,k+1))/> (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k)+c(i,j,k-1))if (helpz.gt.specz) specz=helpzenddoenddoc Check whether the dimensions of the grid are sufficientprint *print *, 'Spectrum of the matrix in each direction 'print *, 'Spectrum = ', specx, specy, speczprint *if ((maxspec*specx.lt.specy).or.(maxspec*specx.lt.specz)) thenprint*,' Nx too small... Stop'stopendifif ((maxspec*specy.lt.specx).or.(maxspec*specy.lt.specz)) thenprint*,'Ny too small... Stop'stopendifif ((maxspec*specz.lt.specx).or.(maxspec*specz.lt.specy)) thenprint*,'Nz too small... Stop'stopendifc Calculate error: control variable for the iterationpsigauge=0.deltasq=0.do k=1,nz-1do i=1,nx-1do j=1,ny-1deltasq=deltasq+(-pv(i,j,k)+(> a(i,j,k)*(psi(i+1,j,k)+psi(i-1,j,k)-> 2.*psi(i,j,k)) +> b(i,j,k)*(psi(i,j+1,k)-psi(i,j,k))-> b(i,j-1,k)*(psi(i,j,k)-psi(i,j-1,k))+> c(i,j,k)*(psi(i,j,k+1)-psi(i,j,k))-> c(i,j,k-1)*(psi(i,j,k)-psi(i,j,k-1))> )/(dx*dy*dz*rhoref(2*k)))**2.enddoenddoenddoprint 102, 'psigauge', psigauge, 'deltasq',> deltasq/(real(nx)*real(ny)*real(nz))c Iterationsdo counter=1,nofiterC Perform one iteration stepcall psiappsor(omega,pv,psi,nsq,rhoref,thetatop,> thetabot,thetaref,coriol,ua,ub,va,vb,> a,b,c,nx,ny,nz,dx,dy,dz)c Adjustmentif (mod(counter,100).eq.0) thenpsigauge=0.do i=0,nxdo j=0,nyif (psi(i,j,0).lt.psigauge) thenpsigauge=psi(i,j,0)endifenddoenddodo k=0,nzdo i=0,nxdo j=0,nypsi(i,j,k)=psi(i,j,k)-psigaugeenddoenddoenddoendifc Calculate error: control variable for the iterationif (mod(counter,nofiter/10).eq.0) thendeltasq=0.do k=1,nz-1do i=1,nx-1do j=1,ny-1deltasq=deltasq+(-pv(i,j,k)+(> a(i,j,k)*(psi(i+1,j,k)+psi(i-1,j,k)-> 2.*psi(i,j,k)) +> b(i,j,k)*(psi(i,j+1,k)-psi(i,j,k))-> b(i,j-1,k)*(psi(i,j,k)-psi(i,j-1,k))+> c(i,j,k)*(psi(i,j,k+1)-psi(i,j,k))-> c(i,j,k-1)*(psi(i,j,k)-psi(i,j,k-1))> )/(dx*dy*dz*rhoref(2*k)))**2.enddoenddoenddoprint 102, 'psigauge', psigauge, 'deltasq',> deltasq/(real(nx)*real(ny)*real(nz))endifenddoreturnc Format specifications102 format (a11, ' = ',e10.3,a11, ' = ',e10.3)endc --------------------------------------------------------------------------------c SOR algorithm (successive over relaxation)c --------------------------------------------------------------------------------subroutine psiappsor(omega,pv,psi,nsq,rhoref,thetatop,> thetabot,thetaref,coriol,ua,ub,va,vb,> a,b,c,nx,ny,nz,dx,dy,dz)c Perform one relaxation stepcc psi : Streamfunction, i.e. result of the PV inversionc nsq,rhoref,thetaref : Reference profilec thetatop,thetabot : Upper and lower boundary conditionc pv : quasigeostrophic potential vorticity (qgPV)c ua,ub,va,vb : lateral boundary condition for windc a,b,c : Matrices for the inversion operatorc nx,ny,nz,dx,dy,dz : Grid specificationc nofiter : Number of iterationsc omega : Relaxation parameterc coriol : Coriolis parameterimplicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal pv(0:nx,0:ny,0:nz)real psi(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 ua(0:nx,0:nz)real ub(0:nx,0:nz)real va(0:ny,0:nz)real vb(0:ny,0:nz)real a(0:nx,0:ny,0:nz)real b(0:nx,0:ny,0:nz)real c(0:nx,0:ny,0:nz)real coriol(0:nx,0:ny)real dx,dy,dzreal omegac Numerical and physical parametersreal gparameter (g=9.81)c Auxiliary variablesinteger i,j,kreal dxy,dxz,dyz,dxyzc Set the area and volume infinitesimals for integrationdxy=dx*dydxz=dx*dzdyz=dy*dzdxyz=dx*dy*dzc Innerdo k=1,nz-1do i=1,nx-1do j=1,ny-1psi(i,j,k)=omega*(-dxyz*> rhoref(2*k)*pv(i,j,k)+a(i,j,k)*> (psi(i+1,j,k)+psi(i-1,j,k))+b(i,j,k)*> psi(i,j+1,k)+b(i,j-1,k)*psi(i,j-1,k)+c(i,j,k)*> psi(i,j,k+1)+c(i,j,k-1)*psi(i,j,k-1))/> (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k-1)+> c(i,j,k))+(1.-omega)*psi(i,j,k)enddoenddoenddoc ZY planedo k=1,nz-1do j=1,ny-1psi(0,j,k)=omega*(-dyz*> rhoref(2*k)*(dx*pv(0,j,k)+va(j,k))+> a(0,j,k)*psi(1,j,k)+> b(0,j,k)*psi(0,j+1,k)+b(0,j-1,k)*psi(0,j-1,k)+> c(0,j,k)*psi(0,j,k+1)+c(0,j,k-1)*psi(0,j,k-1))/> (a(0,j,k)+b(0,j,k)+b(0,j-1,k)+c(0,j,k-1)+c(0,j,k))> +(1.-omega)*psi(0,j,k)cpsi(nx,j,k)=omega*(-dyz*> rhoref(2*k)*(dx*pv(nx,j,k)-vb(j,k))+> a(nx,j,k)*psi(nx-1,j,k)+> b(nx,j,k)*psi(nx,j+1,k)+b(nx,j-1,k)*psi(nx,j-1,k)+> c(nx,j,k)*psi(nx,j,k+1)+c(nx,j,k-1)*psi(nx,j,k-1))/> (a(nx,j,k)+b(nx,j-1,k)+b(nx,j,k)+c(nx,j,k-1)+c(nx,j,k))> +(1.-omega)*psi(nx,j,k)enddoenddoc ZX planedo k=1,nz-1do i=1,nx-1psi(i,0,k)=omega*(-dxz*> rhoref(2*k)*(dy*pv(i,0,k)-ua(i,k))+> a(i,0,k)*(psi(i+1,0,k)+psi(i-1,0,k))+> b(i,0,k)*psi(i,1,k)+> c(i,0,k)*psi(i,0,k+1)+c(i,0,k-1)*psi(i,0,k-1))/> (2.*a(i,0,k)+b(i,0,k)+c(i,0,k-1)+c(i,0,k))> +(1.-omega)*psi(i,0,k)cpsi(i,ny,k)=omega*(-dxz*> rhoref(2*k)*(dy*pv(i,ny,k)+ub(i,k))+> a(i,ny-1,k)*(psi(i+1,ny,k)+psi(i-1,ny,k))+> b(i,ny-1,k)*psi(i,ny-1,k)+> c(i,ny-1,k)*psi(i,ny,k+1)+c(i,ny-1,k-1)*> psi(i,ny,k-1))/(2.*a(i,ny-1,k)+b(i,ny-1,k)+> c(i,ny-1,k-1)+c(i,ny-1,k))> +(1.-omega)*psi(i,ny,k)enddoenddoc XY planedo i=1,nx-1do j=1,ny-1psi(i,j,0)=omega*(-dxy*rhoref(0)*(> dz*pv(i,j,0)+g*coriol(i,j)*thetabot(i,j)/> (nsq(0)*thetaref(0)))+> a(i,j,0)*(psi(i+1,j,0)+psi(i-1,j,0))+> b(i,j,0)*psi(i,j+1,0)+b(i,j-1,0)*psi(i,j-1,0)+> c(i,j,0)*psi(i,j,1))/> (2.*a(i,j,0)+b(i,j-1,0)+b(i,j,0)+c(i,j,0))> +(1.-omega)*psi(i,j,0)cpsi(i,j,nz)=omega*(-dxy*rhoref(2*nz)*(> dz*pv(i,j,nz)-g*coriol(i,j)*thetatop(i,j)/> (nsq(2*nz)*thetaref(2*nz)))+> a(i,j,nz)*(psi(i+1,j,nz)+psi(i-1,j,nz))+> b(i,j,nz)*psi(i,j+1,nz)+b(i,j-1,nz)*psi(i,j-1,nz)+> c(i,j,nz-1)*psi(i,j,nz-1))/> (2.*a(i,j,nz)+b(i,j-1,nz)+b(i,j,nz)+c(i,j,nz-1))> +(1.-omega)*psi(i,j,nz)enddoenddoc Y edgesdo j=1,ny-1psi(0,j,0)=omega*(-dy*rhoref(0)*(dxz*pv(0,j,0)+> dz*va(j,0)+dx*g*coriol(0,j)*thetabot(0,j)/> (nsq(0)*thetaref(0)))+> a(0,j,0)*psi(1,j,0)+> b(0,j,0)*psi(0,j+1,0)+b(0,j-1,0)*psi(0,j-1,0)+> c(0,j,0)*psi(0,j,1))/> (a(0,j,0)+b(0,j-1,0)+b(0,j,0)+c(0,j,0))> +(1.-omega)*psi(0,j,0)cpsi(nx,j,0)=omega*(-dy*rhoref(0)*(dxz*pv(nx,j,0)-> dz*vb(j,0)+dx*g*coriol(nx,j)*thetabot(nx,j)/> (nsq(0)*thetaref(0)))+> a(nx,j,0)*psi(nx-1,j,0)+> b(nx,j,0)*psi(nx,j+1,0)+b(nx,j-1,0)*psi(nx,j-1,0)+> c(nx,j,0)*psi(nx,j,1))/> (a(nx,j,0)+b(nx,j-1,0)+b(nx,j,0)+c(nx,j,0))> +(1.-omega)*psi(nx,j,0)cpsi(0,j,nz)=omega*(-dy*rhoref(2*nz)*(dxz*pv(0,j,nz)+> dz*va(j,nz)-dx*g*coriol(0,j)*thetatop(0,j)/> (nsq(2*nz)*thetaref(2*nz)))+> a(0,j,nz)*psi(1,j,nz)+> b(0,j,nz)*psi(0,j+1,nz)+b(0,j-1,nz)*psi(0,j-1,nz)+> c(0,j,nz-1)*psi(0,j,nz-1))/> (a(0,j,nz)+b(0,j-1,nz)+b(0,j,nz)+c(0,j,nz-1))> +(1.-omega)*psi(0,j,nz)cpsi(nx,j,nz)=omega*(-dy*rhoref(2*nz)*(dxz*pv(nx,j,nz)-> dz*vb(j,nz)-dx*g*coriol(nx,j)*thetatop(nx,j)/> (nsq(2*nz)*thetaref(2*nz)))+> a(nx,j,nz)*psi(nx-1,j,nz)+> b(nx,j,nz)*psi(nx,j+1,nz)+b(nx,j-1,nz)*psi(nx,j-1,nz)+> c(nx,j,nz-1)*psi(nx,j,nz-1))/> (a(nx,j,nz)+b(nx,j-1,nz)+b(nx,j,nz)+c(nx,j,nz-1))> +(1.-omega)*psi(nx,j,nz)enddoc X edgesdo i=1,nx-1psi(i,0,0)=omega*(-dx*rhoref(0)*(dyz*pv(i,0,0)-> dz*ua(i,0)+dy*g*coriol(i,0)*thetabot(i,0)/> (nsq(0)*thetaref(0)))+> a(i,0,0)*(psi(i+1,0,0)+psi(i-1,0,0))+> b(i,0,0)*psi(i,1,0)+> c(i,0,0)*psi(i,0,1))/> (2.*a(i,0,0)+b(i,0,0)+c(i,0,0))> +(1.-omega)*psi(i,0,0)cpsi(i,ny,0)=omega*(-dx*rhoref(0)*(dyz*pv(i,ny,0)+> dz*ub(i,0)+dy*g*coriol(i,ny)*thetabot(i,ny)/> (nsq(0)*thetaref(0)))+> a(i,ny,0)*(psi(i+1,ny,0)+psi(i-1,ny,0))+> b(i,ny-1,0)*psi(i,ny-1,0)+> c(i,ny,0)*psi(i,ny,1))/> (2.*a(i,ny,0)+b(i,ny-1,0)+c(i,ny,0))> +(1.-omega)*psi(i,ny,0)cpsi(i,0,nz)=omega*(-dx*rhoref(2*nz)*(dyz*pv(i,0,nz)-> dz*ua(i,nz)-dy*g*coriol(i,0)*thetatop(i,0)/> (nsq(2*nz)*thetaref(2*nz)))+> a(i,0,nz)*(psi(i+1,0,nz)+psi(i-1,0,nz))+> b(i,0,nz)*psi(i,1,nz)+> c(i,0,nz-1)*psi(i,0,nz-1))/> (2.*a(i,0,nz)+b(i,0,nz)+c(i,0,nz-1))> +(1.-omega)*psi(i,0,nz)cpsi(i,ny,nz)=omega*(-dx*rhoref(2*nz)*(dyz*pv(i,ny,nz)+> dz*ub(i,nz)-dy*g*coriol(i,ny)*thetatop(i,ny)/> (nsq(2*nz)*thetaref(2*nz)))+> a(i,ny,nz)*(psi(i+1,ny,nz)+psi(i-1,ny,nz))+> b(i,ny-1,nz)*psi(i,ny-1,nz)+> c(i,ny,nz-1)*psi(i,ny,nz-1))/> (2.*a(i,ny,nz)+b(i,ny-1,nz)+c(i,ny,nz-1))> +(1.-omega)*psi(i,ny,nz)enddoc Z edgesdo k=1,nz-1psi(0,0,k)=omega*(-dz*rhoref(2*k)*(dxy*pv(0,0,k)+> dy*va(0,k)-dx*ua(0,k))+> a(0,0,k)*psi(1,0,k)+> b(0,0,k)*psi(0,1,k)+> c(0,0,k)*psi(0,0,k+1)+c(0,0,k-1)*psi(0,0,k-1))/> (a(0,0,k)+b(0,0,k)+c(0,0,k-1)+c(0,0,k))> +(1.-omega)*psi(0,0,k)cpsi(nx,0,k)=omega*(-dz*rhoref(2*k)*(dxy*pv(nx,0,k)-> dy*vb(0,k)-dx*ua(nx,k))+> a(nx,0,k)*psi(nx-1,0,k)+> b(nx,0,k)*psi(nx,1,k)+> c(nx,0,k)*psi(nx,0,k+1)+c(nx,0,k-1)*psi(nx,0,k-1))/> (a(nx,0,k)+b(nx,0,k)+c(nx,0,k-1)+c(nx,0,k))> +(1.-omega)*psi(nx,0,k)cpsi(0,ny,k)=omega*(-dz*rhoref(2*k)*(dxy*pv(0,ny,k)+> dy*va(ny,k)+dx*ub(0,k))+> a(0,ny,k)*psi(1,ny,k)+> b(0,ny-1,k)*psi(0,ny-1,k)+> c(0,ny,k)*psi(0,ny,k+1)+c(0,ny,k-1)*psi(0,ny,k-1))/> (a(0,ny,k)+b(0,ny-1,k)+c(0,ny,k-1)+c(0,ny,k))> +(1.-omega)*psi(0,ny,k)cpsi(nx,ny,k)=omega*(-dz*rhoref(2*k)*(dxy*pv(nx,ny,k)-> dy*vb(ny,k)+dx*ub(nx,k))+> a(nx,ny,k)*psi(nx-1,ny,k)+> b(nx,ny-1,k)*psi(nx,ny-1,k)+> c(nx,ny,k)*psi(nx,ny,k+1)+c(nx,ny,k-1)*psi(nx,ny,k-1))/> (a(nx,ny,k)+b(nx,ny-1,k)+c(nx,ny,k-1)+c(nx,ny,k))> +(1.-omega)*psi(nx,ny,k)enddoc Pointspsi(0,0,0)=omega*(-rhoref(0)*(dxyz*pv(0,0,0)+dyz*va(0,0)-> dxz*ua(0,0)+dxy*g*coriol(0,0)*thetabot(0,0)/> (nsq(0)*thetaref(0)))+> a(0,0,0)*psi(1,0,0)+> b(0,0,0)*psi(0,1,0)+> c(0,0,0)*psi(0,0,1))/> (a(0,0,0)+b(0,0,0)+c(0,0,0))+> (1.-omega)*psi(0,0,0)cpsi(nx,0,0)=omega*(-rhoref(0)*(dxyz*pv(nx,0,0)-dyz*vb(0,0)-> dxz*ua(nx,0)+dxy*g*coriol(nx,0)*thetabot(nx,0)/> (nsq(0)*thetaref(0)))+> a(nx,0,0)*psi(nx-1,0,0)+> b(nx,0,0)*psi(nx,1,0)+> c(nx,0,0)*psi(nx,0,1))/> (a(nx,0,0)+b(nx,0,0)+c(nx,0,0))+> (1.-omega)*psi(nx,0,0)cpsi(0,ny,0)=omega*(-rhoref(0)*(dxyz*pv(0,ny,0)+dyz*va(ny,0)+> dxz*ub(0,0)+dxy*g*coriol(0,ny)*thetabot(0,ny)/> (nsq(0)*thetaref(0)))+> a(0,ny,0)*psi(1,ny,0)+> b(0,ny-1,0)*psi(0,ny-1,0)+> c(0,ny,0)*psi(0,ny,1))/> (a(0,ny,0)+b(0,ny-1,0)+c(0,ny,0))+> (1.-omega)*psi(0,ny,0)cpsi(nx,ny,0)=omega*(-rhoref(0)*(dxyz*pv(nx,ny,0)-dyz*vb(ny,0)+> dxz*ub(nx,0)+dxy*g*coriol(nx,ny)*thetabot(nx,ny)/> (nsq(0)*thetaref(0)))+> a(nx,ny,0)*psi(nx-1,ny,0)+> b(nx,ny-1,0)*psi(nx,ny-1,0)+> c(nx,ny,0)*psi(nx,ny,1))/> (a(nx,ny,0)+b(nx,ny-1,0)+c(nx,ny,0))+> (1.-omega)*psi(nx,ny,0)cpsi(0,0,nz)=omega*(-rhoref(2*nz)*(dxyz*pv(0,0,nz)+dyz*va(0,nz)-> dxz*ua(0,nz)-dxy*g*coriol(0,0)*thetatop(0,0)/> (nsq(2*nz)*thetaref(2*nz)))+> a(0,0,nz)*psi(1,0,nz)+> b(0,0,nz)*psi(0,1,nz)+> c(0,0,nz-1)*psi(0,0,nz-1))/> (a(0,0,nz)+b(0,0,nz)+c(0,0,nz-1))+> (1.-omega)*psi(0,0,nz)cpsi(nx,0,nz)=omega*(-rhoref(2*nz)*(dxyz*pv(nx,0,nz)-dyz*vb(0,nz)> -dxz*ua(nx,nz)-dxy*g*coriol(nx,0)*thetatop(nx,0)/> (nsq(2*nz)*thetaref(2*nz)))+> a(nx,0,nz)*psi(nx-1,0,nz)+> b(nx,0,nz)*psi(nx,1,nz)+> c(nx,0,nz-1)*psi(nx,0,nz-1))/> (a(nx,0,nz)+b(nx,0,nz)+c(nx,0,nz-1))+> (1.-omega)*psi(nx,0,nz)cpsi(0,ny,nz)=omega*(-rhoref(2*nz)*(dxyz*pv(0,ny,nz)+> dyz*va(ny,nz)+dxz*ub(0,nz)-> dxy*g*coriol(0,ny)*thetatop(0,ny)/> (nsq(2*nz)*thetaref(2*nz)))+> a(0,ny,nz)*psi(1,ny,nz)+> b(0,ny-1,nz)*psi(0,ny-1,nz)+> c(0,ny,nz-1)*psi(0,ny,nz-1))/> (a(0,ny,nz)+b(0,ny-1,nz)+c(0,ny,nz-1))+> (1.-omega)*psi(0,ny,nz)cpsi(nx,ny,nz)=omega*(-rhoref(2*nz)*(dxyz*pv(nx,ny,nz)-> dyz*vb(ny,nz)+dxz*ub(nx,nz)-> dxy*g*coriol(nx,ny)*thetatop(nx,ny)/> (nsq(2*nz)*thetaref(2*nz)))+> a(nx,ny,nz)*psi(nx-1,ny,nz)+> b(nx,ny-1,nz)*psi(nx,ny-1,nz)+> c(nx,ny,nz-1)*psi(nx,ny,nz-1))/> (a(nx,ny,nz)+b(nx,ny-1,nz)+c(nx,ny,nz-1))+> (1.-omega)*psi(nx,ny,nz)cendc --------------------------------------------------------------------------------c Init matrix elements for the inversionc --------------------------------------------------------------------------------subroutine matrixel(a,b,c,coriol,nx,ny,nz,nsq,rhoref,dx,dy,dz)c Define the coefficients for the inversion problem (see page 119ff in Rene'sc dissertation).implicit nonec Declaration of subroutine parametersinteger nx,nz,nyreal a (0:nx,0:ny,0:nz)real b (0:nx,0:ny,0:nz)real c (0:nx,0:ny,0:nz)real coriol(0:nx,0:ny)real nsq (0:2*nz)real rhoref(0:2*nz)real dx,dy,dzc Auxiliary variablesinteger i,j,kc Calculate coefficientsdo i=0,nxdo j=0,nydo k=0,nza(i,j,k)=dy*dz*rhoref(2*k)/(dx*coriol(i,j))if (j.lt.ny) thenb(i,j,k)=dx*dz*rhoref(2*k)/> (dy*0.5*(coriol(i,j)+coriol(i,j+1)))elseb(i,j,k)=0.endifif (k.lt.nz) thenc(i,j,k)=dx*dy*rhoref(2*k+1)*coriol(i,j)/> (dz*nsq(2*k+1))elsec(i,j,k)=0.endifenddoenddoenddoend