Subversion Repositories pvinversion.ecmwf

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

      PROGRAM modify_anomaly

c     ******************************************************************************
c     * Read the modified and unmodified PV from the R file and                  *
c     * perform some non-standard modifications: (a) Change of amplitude,          *
c     * (b) Stretching and shrinking along an axis, (c) rotation, or               *
c     * (d) change in position.     
c     *                                                                            
c     # modify_anomaly.sh R_20060116_18 shifty=-10,rot=10,stretchy=1.5,rot=-10,shifty=10
c     # modify_anomaly.sh R_20060116_18 fac=2
c     # modify_anomaly.sh R_20060116_18 cex=-30,cey=-30,rot=20
c     *                                                                            *
c     * Michael Sprenger / Spring, Summer 2007                                     *
c     ******************************************************************************

      implicit none

c     -----------------------------------------------------------------------------
c     Declaration of parameters and variables
c     -----------------------------------------------------------------------------

c     Input/output file and command string
      character*80   pvsrcfile
      character*80   commandstr

c     Grid parameters
      integer        nx,ny,nz
      real           xmin,ymin,zmin,xmax,ymax,zmax
      real           dx,dy,dz
      real           mdv

c     3d fields for calculation of qgPV and Ertel's PV
      real,allocatable,dimension (:,:,:) :: pv1,pv2,ano

c     Numerical epsilon
      real           eps
      parameter      (eps=0.01)

c     Parameters for the transformations
      real           cex,cey              ! Centre point for rotation
      real           angle                ! Rotation angle

c     Auxiliary variables
      real           zpos
      integer        i,j,k
      integer        stat
      character*80   varname
      integer        n
      real           par
      character*80   com

c     -----------------------------------------------------------------------------
c     Preparations
c     -----------------------------------------------------------------------------

      print*,'********************************************************'
      print*,'* MODIFY_ANOMALY                                       *'
      print*,'********************************************************'

c     Read parameter file
      open(10,file='fort.10')
       read(10,*) pvsrcfile
       read(10,*) commandstr
      close(10)
      print*
      print*,'Input file : ',trim(pvsrcfile)
      print*,'Command    : ',trim(commandstr)
      print*

c     Get lat/lon gid parameters from input file
      call read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
     >               pvsrcfile)
      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 modified and non-modified PV
      allocate(pv1 (0:nx,0:ny,0:nz),STAT=stat)
      if (stat.ne.0) print*,'error allocating pv1'
      allocate(pv2 (0:nx,0:ny,0:nz),STAT=stat)
      if (stat.ne.0) print*,'error allocating pv2'
      allocate(ano  (0:nx,0:ny,0:nz),STAT=stat)
      if (stat.ne.0) print*,'error allocating ano'   
   
c     Read data from file
      varname='PV'
      call read_inp (pv1,varname,pvsrcfile,
     >               nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
      varname='PV_FILT'
      call read_inp (pv2,varname,pvsrcfile,
     >               nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)

c     Define the anomaly
      do i=0,nx
         do j=0,ny
            do k=0,nz
               if ( (abs(pv1(i,j,k)-mdv).gt.eps).and.
     >              (abs(pv2(i,j,k)-mdv).gt.eps) ) then
                  ano(i,j,k)=pv1(i,j,k)-pv2(i,j,k)
               else
                  ano(i,j,k)=0.
               endif
            enddo
         enddo
      enddo


c     -------------------------------------------------------------------------------
c     Modifications
c     -------------------------------------------------------------------------------

c     Set the default values for parameters
      cex   = 0.
      cey   = 0.
      angle = 0.

c     Set the counter for the command string
      n=1

c     Loop over all commands
 100  continue

c     Extract new command/parameter pair; exit if no new command
      call next_command(commandstr,n,com,par)
      if (com.eq.'nil') goto 200
      print*,trim(com),par

c     Multiply the anomaly by a constant factor
      if (com.eq.'fac') then
         call mod_factor (ano,par,nx,ny,nz,mdv)
      endif

c     Set the centre point (needed for rotations)
      if (com.eq.'cex') then
         cex=par
      endif
      if (com.eq.'cey') then
         cey=par
      endif

c     Rotation around the centrre point
      if (com.eq.'rot') then
         call mod_rotation (ano,par,cex,cey,
     >                       nx,ny,nz,xmin,ymin,dx,dy,mdv)
      endif

c     Shift in x or in y direction
      if (com.eq.'shiftx') then
         call  mod_shift (ano,par,0.,
     >                    nx,ny,nz,xmin,ymin,dx,dy,mdv)
      endif
      if (com.eq.'shifty') then
         call  mod_shift (ano,0.,par,
     >                    nx,ny,nz,xmin,ymin,dx,dy,mdv)
      endif      

c     Stretch/shrink in x or in y direction
      if (com.eq.'stretchx') then
         call  mod_stretch (ano,par,1.,
     >                      nx,ny,nz,xmin,ymin,dx,dy,mdv)
      endif
      if (com.eq.'stretchy') then
         call  mod_stretch (ano,1.,par,
     >                      nx,ny,nz,xmin,ymin,dx,dy,mdv)
      endif      


c     Goto next command/parameter pair
      goto 100

c     All commands handled
 200  continue

c     --------------------------------------------------------------------------------
c     Write modified fields
c     --------------------------------------------------------------------------------

c     Build the modified PV distribution from the anomaly
      do i=0,nx
         do j=0,ny
            do k=0,nz
               if ( (abs(pv1(i,j,k)-mdv).gt.eps).and.
     >              (abs(ano(i,j,k)-mdv).gt.eps) ) then
                  pv2(i,j,k)=pv1(i,j,k)-ano(i,j,k)
               else
                  pv2(i,j,k)=mdv
               endif
            enddo
         enddo
      enddo

c     Write result to netcdf file
      varname='PV_FILT'
      call write_inp (pv2,varname,pvsrcfile,nx,ny,nz)

c     Write the modified anomaly also to the file
      varname='PV_ANOM'
      call write_inp (ano,varname,pvsrcfile,nx,ny,nz)

      end

c     ********************************************************************************
c     * Command handling and transformations                                         *
c     ********************************************************************************

c     --------------------------------------------------------------------------------
c     Extract next command from command string
c     --------------------------------------------------------------------------------
      
      subroutine next_command (commandstr,n,com,par)
      
c     Given the command string <commandstr>, extract the next command/parameter pair
c     <com,par> starting at position <n> of the command string.

      implicit none
      
c     Declaration of subroutine parameters
      character*80 commandstr
      character*80 com
      real         par
      integer      n

c     Auxiliary variables
      integer      i,j,k

c     Check whether end of command line reached
      if (n.ge.80) then
         com='nil'
         par=0.
         goto 120
      endif

c     Set indices to next next command/parameter pair
      i=n
      j=n
 100  if ( (commandstr(j:j).ne.'=').and.(j.lt.80) ) then
        j=j+1
        goto 100
      endif
      k=j+1
 110  if ( (commandstr(k:k).ne.',' ).and.
     >     (commandstr(k:k).ne.';' ).and.
     >     (commandstr(k:k).ne.' ' ).and.
     >     (k              .lt.80  ) ) then
        k=k+1
        goto 110
      endif

c     Check whether this is a valid command/parameter pair
      if ( ((j-1).lt.i).or.((k-1).lt.(j+1)) ) then
         com='nil'
         par=0.
         goto 120
      endif

c     Extract tzhe command and the parameter
      com=commandstr(i:j-1)
      read(commandstr(j+1:k-1),*) par

c     Set the counter to the next command/parameter pair
      n=k+1

c     Exit point
 120  continue

      end

c     --------------------------------------------------------------------------------
c     Multiply the anomaly by a factor
c     --------------------------------------------------------------------------------
 
      subroutine mod_factor (field,factor,nx,ny,nz,mdv)
      
c     Multiply the anomaly <field>  by a constant factor <factor>. The grid and the
c     missing data value are given by <nx,ny,nz,mdv>.
      
      implicit none
 
c     Declaration of subroutine parameters
      integer    nx,ny,nz
      real       field(0:nx,0:ny,0:nz)
      real       mdv
      real       factor
      
c     Parameters
      real       eps
      parameter  (eps=0.01)

c     Auxiliary variables
      integer    i,j,k

c     Do the transformation
      do i=0,nx
         do j=0,ny
            do k=0,nz
               if ( (abs(field(i,j,k)-mdv).gt.eps) ) then 
                  field(i,j,k)=factor*field(i,j,k)
               endif
            enddo
         enddo
      enddo
      
      end

c     --------------------------------------------------------------------------------
c     Rotate the anomaly
c     --------------------------------------------------------------------------------

      subroutine mod_rotation (field,angle,cex,cey,
     >                         nx,ny,nz,xmin,ymin,dx,dy,mdv)

c     Rotate the anomaly <field> in the horizontal by the angle <angle>. The centre
c     for the rotation is given by <cex,cey>, expressed in rotated longitude, latitude.
c     The grid and the missing data value are given by <nx,ny,nz,xmin,ymin,dx,dy,mdv>.
      
      
      implicit none
 
c     Declaration of subroutine parameters
      integer    nx,ny,nz
      real       field(0:nx,0:ny,0:nz)
      real       xmin,ymin,dx,dy
      real       mdv
      real       angle
      real       cex,cey
      
c     Parameters
      real       eps
      parameter  (eps=0.01)
      real       pi180
      parameter  (pi180=3.14159/180.)

c     Auxiliary variables
      integer    i,j,k
      real       lon,lat,rlon,rlat
      real       xmax,ymax
      real       tmp1(0:nx,0:ny),tmp2(0:nx,0:ny)

c     Externals 
      real       int2d
      external   int2d

c     Maximal grid extension
      xmax=xmin+real(nx-1)*dx
      ymax=ymin+real(ny-1)*dy

c     Do the Transformation
      do k=0,nz

c        Copy level to 2d array
         do i=0,nx
            do j=0,ny
               tmp1(i,j)=field(i,j,k)
            enddo
         enddo

c        Rotate each grid point
         do i=0,nx
            do j=0,ny
               
c              Lon/lat coordinates of grid point
               lon=xmin+real(i)*dx-cex
               lat=ymin+real(j)*dy-cey

c              Rotation
               rlon = cex + lon*cos(angle*pi180) + lat*sin(angle*pi180)
               rlat = cey - lon*sin(angle*pi180) + lat*cos(angle*pi180)

c              Do the interpolation
               if ( (rlon.gt.xmin).and.(rlon.lt.xmax).and.
     >              (rlat.gt.ymin).and.(rlat.lt.ymax) ) 
     >         then
                  tmp2(i,j)=int2d(tmp1,rlon,rlat,
     >                            dx,dy,xmin,ymin,nx,ny,mdv)
               else
                  tmp2(i,j)=0.
               endif
               
            enddo
         enddo
         
c        Copy 2d array to level
         do i=0,nx
            do j=0,ny
               field(i,j,k)=tmp2(i,j)
            enddo
         enddo
         
      enddo

      end

c     --------------------------------------------------------------------------------
c     Shift the anomaly in x and y direction
c     --------------------------------------------------------------------------------

      subroutine mod_shift (field,shiftx,shifty,
     >                      nx,ny,nz,xmin,ymin,dx,dy,mdv)

c     Shift the anomaly <field> in the horizontal by the vector <shiftx,shifty>. 
c     The grid and the missing data value are given by <nx,ny,nz,xmin,ymin,dx,dy,mdv>.
      
      
      implicit none
 
c     Declaration of subroutine parameters
      integer    nx,ny,nz
      real       field(0:nx,0:ny,0:nz)
      real       xmin,ymin,dx,dy
      real       mdv
      real       shiftx,shifty
      
c     Parameters
      real       eps
      parameter  (eps=0.01)

c     Auxiliary variables
      integer    i,j,k
      real       lon,lat,rlon,rlat
      real       xmax,ymax
      real       tmp1(0:nx,0:ny),tmp2(0:nx,0:ny)

c     Externals 
      real       int2d
      external   int2d

c     Maximal grid extension
      xmax=xmin+real(nx-1)*dx
      ymax=ymin+real(ny-1)*dy

c     Do the Transformation
      do k=0,nz

c        Copy level to 2d array
         do i=0,nx
            do j=0,ny
               tmp1(i,j)=field(i,j,k)
            enddo
         enddo

c        Rotate each grid point
         do i=0,nx
            do j=0,ny
               
c              Lon/lat coordinates of grid point
               lon=xmin+real(i)*dx
               lat=ymin+real(j)*dy

c              shifted coordinates
               rlon = lon - shiftx
               rlat = lat - shifty

c              Do the interpolation
               if ( (rlon.gt.xmin).and.(rlon.lt.xmax).and.
     >              (rlat.gt.ymin).and.(rlat.lt.ymax) ) 
     >         then
                  tmp2(i,j)=int2d(tmp1,rlon,rlat,
     >                            dx,dy,xmin,ymin,nx,ny,mdv)
               else
                  tmp2(i,j)=0.
               endif
               
            enddo
         enddo
         
c        Copy 2d array to level
         do i=0,nx
            do j=0,ny
               field(i,j,k)=tmp2(i,j)
            enddo
         enddo
         
      enddo

      end

c     --------------------------------------------------------------------------------
c     Stretch/shrink the anomaly in x and y direction
c     --------------------------------------------------------------------------------

      subroutine mod_stretch (field,stretchx,stretchy,
     >                        nx,ny,nz,xmin,ymin,dx,dy,mdv)

c     Stretch the anomaly <field> in the horizontal by the fatcors <stretchx,stretchy>. 
c     The grid and the missing data value are given by <nx,ny,nz,xmin,ymin,dx,dy,mdv>.
      
      
      implicit none
 
c     Declaration of subroutine parameters
      integer    nx,ny,nz
      real       field(0:nx,0:ny,0:nz)
      real       xmin,ymin,dx,dy
      real       mdv
      real       stretchx,stretchy
      
c     Parameters
      real       eps
      parameter  (eps=0.01)

c     Auxiliary variables
      integer    i,j,k
      real       lon,lat,rlon,rlat
      real       xmax,ymax
      real       tmp1(0:nx,0:ny),tmp2(0:nx,0:ny)

c     Externals 
      real       int2d
      external   int2d

c     Maximal grid extension
      xmax=xmin+real(nx-1)*dx
      ymax=ymin+real(ny-1)*dy

c     Do the Transformation
      do k=0,nz

c        Copy level to 2d array
         do i=0,nx
            do j=0,ny
               tmp1(i,j)=field(i,j,k)
            enddo
         enddo

c        Rotate each grid point
         do i=0,nx
            do j=0,ny
               
c              Lon/lat coordinates of grid point
               lon=xmin+real(i)*dx
               lat=ymin+real(j)*dy

c              shifted coordinates
               rlon = 1./stretchx * lon
               rlat = 1./stretchy * lat

c              Do the interpolation
               if ( (rlon.gt.xmin).and.(rlon.lt.xmax).and.
     >              (rlat.gt.ymin).and.(rlat.lt.ymax) ) 
     >         then
                  tmp2(i,j)=int2d(tmp1,rlon,rlat,
     >                            dx,dy,xmin,ymin,nx,ny,mdv)
               else
                  tmp2(i,j)=0.
               endif
               
            enddo
         enddo
         
c        Copy 2d array to level
         do i=0,nx
            do j=0,ny
               field(i,j,k)=tmp2(i,j)
            enddo
         enddo
         
      enddo

      end

c     ------------------------------------------------------------------------
c     Two-dimensional interpolation         
c     ------------------------------------------------------------------------

      real function int2d(ar,lon,lat,
     >                    dx,dy,xmin,ymin,nx,ny,mdv)

c     Interpolate the field <ar(nx,ny)> to the position <lon,lat>. The
c     grid is specified by <dx,dy,xmin,ymin,nx,ny>.

      implicit none

c     Declaration of subroutine paramters
      integer   nx,ny
      real      ar(0:nx,0:ny)
      real      lon,lat
      real      dx,dy,xmin,ymin
      real      mdv

c     Parameters
      real      eps
      parameter (eps=0.01)

c     Auxiliary variables
      real      ri,rj
      integer   i,j,ir,ju     
      real      frac0i,frac0j,frac1i,frac1j
      real      tmp,nor

c     Get index
      ri=(lon-xmin)/dx
      rj=(lat-ymin)/dy
      i=int(ri)
      j=int(rj)
      if ((i.lt.0).or.(i.gt.nx).or.
     >    (j.lt.0).or.(j.gt.ny)) then
         print*,'lat/lon interpolation not possible....'
         stop
      endif
      
c     Get inidices of left and upper neighbours
      ir=i+1
      if (ir.gt.nx) ir=nx
      ju=j+1
      if (ju.gt.ny) ju=ny

c     Get the weights for the bilinear interpolation
      frac0i=ri-float(i)
      frac0j=rj-float(j)
      frac1i=1.-frac0i
      frac1j=1.-frac0j

c     Bilinear interpolation with missing data check
      tmp=0.
      nor=0.
      if ( (abs(ar(i ,j )-mdv).gt.eps) ) then
         tmp = tmp + ar(i ,j ) * frac1i * frac1j
         nor = nor + frac1i * frac1j
      endif
      if ( (abs(ar(i ,ju)-mdv).gt.eps) ) then
         tmp = tmp + ar(i ,ju) * frac1i * frac0j
         nor = nor + frac1i * frac0j
      endif
      if ( (abs(ar(ir,j )-mdv).gt.eps) ) then
         tmp = tmp + ar(ir,j ) * frac0i * frac1j
         nor = nor + frac0i * frac1j
      endif
      if ( (abs(ar(ir,ju)-mdv).gt.eps) ) then
         tmp = tmp + ar(ir,ju) * frac0i * frac0j
         nor = nor + frac0i * frac0j
      endif

c     Return result
      int2d=tmp/nor

      end

c     ********************************************************************************
c     * NETCDF INPUT AND 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                 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 PV
      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='PV'
      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 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                 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='PV'
      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