Subversion Repositories pvinversion.ecmwf

Rev

Rev 3 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed


      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