Subversion Repositories lagranto.ocean

Rev

Blame | Last modification | View Log | Download | RSS feed

c***********************************************************************
c CF-netCDF / Reading
c***********************************************************************

c     -------------------------------------------------------------------
c     cdfopn
c     -------------------------------------------------------------------

      subroutine cdfopn(filnam,cdfid,ierror)

      use netcdf
      
      character*(*) filnam
      integer       cdfid
      integer       ierror

      ierror = NF90_OPEN(TRIM(filnam),nf90_nowrite, cdfid)
      IF ( ierror /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierror)

      return
      end


c     -------------------------------------------------------------------
c     clscdf
c     -------------------------------------------------------------------

      subroutine clscdf (cdfid, ierror)

      use netcdf
      
      integer      cdfid
      integer      ierror

      ierror = NF90_CLOSE(cdfid)
      IF( ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      end


c     -------------------------------------------------------------------
c     getdef
c     -------------------------------------------------------------------

      subroutine getdef (cdfid, varnam, ndim, misdat, 
     &                      vardim, varmin, varmax, stag, ierror)

      use netcdf

      integer        cdfid
      character *(*) varnam
      integer        ndim
      real           misdat
      integer        vardim(4)
      real           varmin(4)
      real           varmax(4)
      real           stag(4)
      integer        ierror

      real           lat(5000)
      real           lon(5000)
      real           lev(5000)
      real           tim(5000)
      integer        varid
      integer        lonid
      integer        latid
      integer        timid
      integer        dimids (nf90_max_var_dims)
      character*80   dimname(nf90_max_var_dims)
      integer        nlon
      integer        nlat
      integer        nlev
      integer        ntim
      character*(80) attname
      integer        i

c     Get <varid>
      ierror = NF90_INQ_VARID(cdfid,varnam,varid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Get <ndim>, <dimids> and <dimname>
      ierror = nf90_inquire_variable(cdfid, varid, ndims  = ndim)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_variable(cdfid, varid, 
     >                                   dimids = dimids(1:ndim))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      do i=1,ndim
         ierror = nf90_inquire_dimension(cdfid, dimids(i), 
     >                               name = dimname(i) )
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      enddo

      if ( (ndim.ne.3).and.(ndim.ne.4).and.(ndim.ne.1) ) then
          print*,' ERROR: getdef only support 3d, 4d and 1d level arrays'
         print*,'1D=lev (ORA); 3D=time,lat,lon; 4D=time,level,lat,lon'
          stop
      endif

c     Get the ID for <longitude>, <latitude>, <level> and <time>
      if (ndim.eq.4) then
        ierror = nf90_inq_dimid(cdfid,dimname(1), lonid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = nf90_inq_dimid(cdfid,dimname(2), latid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = nf90_inq_dimid(cdfid,dimname(3), levid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = nf90_inq_dimid(cdfid,dimname(4), timid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      else if ( ndim.eq.3 ) then
        ierror = nf90_inq_dimid(cdfid,dimname(1), lonid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = nf90_inq_dimid(cdfid,dimname(2), latid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = nf90_inq_dimid(cdfid,dimname(3), timid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      else if ( ndim.eq.1 ) then
        ierror = nf90_inq_dimid(cdfid,dimname(1), levid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      endif

c     Read lon and set <vardim(1)>, <varmin(1)>, <varmax(1)>, <stag(1)>
      if ( ndim.eq.4 .or. ndim.eq.3 ) then
        ierror = nf90_inquire_dimension(cdfid, lonid, len = nlon)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_INQ_VARID(cdfid,dimname(1),lonid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_GET_VAR(cdfid,lonid,lon(1:nlon))
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
        vardim(1) = nlon
        varmin(1) = lon( 1    )
        varmax(1) = lon( nlon )
        stag  (1) = 0.
      else if ( ndim.eq.1 ) then
        vardim(1) = 1
        varmin(1) = 1
        varmax(1) = 1
        stag  (1) = 0.
      end if

c     Read lat and set <vardim2(2)>, <varmin(2)>, <varmax(2)>, <stag(2)>
      if ( ndim.eq.4 .or. ndim.eq.3 ) then
        ierror = nf90_inquire_dimension(cdfid, latid, len = nlat)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_INQ_VARID(cdfid,dimname(2),latid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_GET_VAR(cdfid,latid,lat(1:nlat))
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
        vardim(2) = nlat
        varmin(2) = lat( 1    )
        varmax(2) = lat( nlat )
        stag  (2) = 0. 
      else if ( ndim.eq.1 ) then
        vardim(2) = 1
        varmin(2) = 1
        varmax(2) = 1
        stag  (2) = 0.
      end if
      
c     Read lev and set <vardim2(3)>, <varmin(3)>, <varmax(3)>, <stag(3)>
      if ( ndim.eq.4 ) then
         ierror = nf90_inquire_dimension(cdfid, levid, len = nlev)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_INQ_VARID(cdfid,dimname(3),levid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_GET_VAR(cdfid,levid,lev(1:nlev))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
         vardim(3) = nlev
         varmin(3) = 1050.
         varmax(3) = 0.
         stag  (3) = -0.5
      else if (ndim.eq.3) then
         vardim(3) = 1
         varmin(3) = 1
         varmax(3) = 1
         stag  (3) = 0.
      else if ( ndim.eq.1 ) then ! valid for 1d lev array
         ierror = nf90_inquire_dimension(cdfid, levid, len = nlev)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_INQ_VARID(cdfid,dimname(1),levid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_GET_VAR(cdfid,levid,lev(1:nlev))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        vardim(3) = nlev
        varmin(3) = lev(1)
        varmax(3) = lev(nlev)
        stag  (3) = 0.
      endif 

c     Read time and set <vardim2(4)>, <varmin(4)>, <varmax(4)>, <stag(4)>
      if ( ndim.eq.4 ) then
         ierror = nf90_inquire_dimension(cdfid, timid, len = ntim)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_INQ_VARID(cdfid,dimname(4),timid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_GET_VAR(cdfid,timid,tim(1:ntim))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
         vardim(4) = ntim
         varmin(4) = tim( 1    )
         varmax(4) = tim( ntim )
         stag  (4) = 0.0
      else if ( ndim.eq.3 ) then 
        ierror = nf90_inquire_dimension(cdfid, timid, len = ntim)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_INQ_VARID(cdfid,dimname(3),timid)
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
        ierror = NF90_GET_VAR(cdfid,timid,tim(1:ntim))
        IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
        vardim(4) = ntim
        varmin(4) = tim( 1    )
        varmax(4) = tim( ntim )
        stag  (4) = 0.0
      else if ( ndim.eq.1 ) then
        vardim(4) = 1
        varmin(4) = 1
        varmax(4) = 1
        stag  (4) = 0.     
      endif
      
c     Read missing data value <misdat>
      ierror  = nf90_get_att(cdfid, varid, "_FillValue", misdat)
      IF (ierror /= nf90_NoErr) THEN
         misdat = -999.99
         ierror = nf90_NoErr
      ENDIF

c     Do some checks
      if ( varmax(1).lt.varmin(1) ) then
         print*,' Error: Wrong order of longitudes'
         ierror = 1
         return
      endif
      if ( varmax(2).lt.varmin(2) ) then
         print*,' Error: Wrong order of latitudes'
         ierror = 1
         return
      endif

         
      end


c     -------------------------------------------------------------------
c     getgrid
c     -------------------------------------------------------------------

      subroutine getgrid(cdfid,dx,dy,ierror)

      use netcdf

      integer   cdfid
      real      dx
      real      dy
      integer   ierror

      integer   lonid
      integer   latid
      real      lat(5000)
      real      lon(5000)
      integer   nlon
      integer   nlat

c     Get length of lon and lat fields
      ierror = nf90_inq_dimid(cdfid,'lon', lonid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inq_dimid(cdfid,'lat', latid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, lonid, len = nlon)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, latid, len = nlat)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Read lon and calculate <dx>
      ierror = nf90_inq_varid(cdfid,'lon', lonid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_GET_VAR(cdfid,lonid,lon(1:nlon))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      dx = ( lon(nlon) - lon(1) ) / ( real(nlon) - 1.)

c     Read lat and calculate <dy>
      ierror = nf90_inq_varid(cdfid,'lat', latid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_GET_VAR(cdfid,latid,lat(1:nlat))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      dy = ( lat(nlat) - lat(1) ) / ( real(nlat) - 1.)

      end


c     -------------------------------------------------------------------
c     getpole
c     -------------------------------------------------------------------

      subroutine getpole(cdfid,pollon,pollat,ierror)

      use netcdf

      integer   cdfid
      real      pollon
      real      pollat
      integer   ierror

      integer   varid
      integer   ncvid

      ierror  = nf90_get_att(cdfid,nf90_global, "pollon", pollon)
      IF(ierror /= nf90_NoErr) pollon = 0.
      ierror  = nf90_get_att(cdfid,nf90_global, "pollat", pollat)
      IF(ierror /= nf90_NoErr) pollat = 90.

      end


c     -------------------------------------------------------------------
c     getcfn
c     -------------------------------------------------------------------

      subroutine getcfn(cdfid,cfn,ierror)
      
      use netcdf

      integer      cdfid
      character*80 cfn
      integer      ierror

      ierror  = nf90_get_att(cdfid,nf90_global,
     >                    "constants_file_name ", cfn(1:80) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      end


c     -------------------------------------------------------------------
c     getdat
c     -------------------------------------------------------------------

      subroutine getdat(cdfid, varnam, time, level, dat, ierror)

      use netcdf

      integer       cdfid
      character*(*) varnam
      real          time
      integer       level
      real          dat(*)
      integer       ierror

      integer       varid
      integer       ndim
      real          misdat
      integer       vardim(4)
      real          varmin(4)
      real          varmax(4)
      real          stag(4)
      integer       timid
      integer       lonid
      integer       latid
      integer       ntim
      real          tim(5000)
      integer       dimids (nf90_max_var_dims)
      character*80  dimname(nf90_max_var_dims)
      integer       itime
      integer       corner(4)
      integer       count (4)
      real,allocatable, dimension (:,:,:,:) :: tmp
      real,allocatable, dimension (:,:,:)   :: tmp3
      real,allocatable, dimension (:,:)     :: tmp2
      real,allocatable, dimension (:)       :: tmp1
      integer       stat
      integer       i,j,k
      character*80  dir

c     Get variable definition
      call getdef (cdfid, varnam, ndim, misdat, 
     &                vardim, varmin, varmax, stag, ierror)

      if ( (ndim.ne.3).and.(ndim.ne.4).and.(ndim.ne.1) ) then
         print*,' ERROR: getdat only support 1d, 3d and 4d arraysd'
         print*,' 1D=lev (ORA); 3D=time,lat,lon; 4D=time,level,lat,lon'
         stop
      endif

c     Get <varid>
      ierror = NF90_INQ_VARID(cdfid,varnam,varid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Get <dimids> and <dimname>
      ierror = nf90_inquire_variable(cdfid, varid, 
     >                                   dimids = dimids(1:ndim))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      do i=1,ndim
         ierror = nf90_inquire_dimension(cdfid, dimids(i), 
     >                               name = dimname(i) )
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      enddo

c     Get the ID for <longitude>, <latitude>, <level> and <time>
      if ( ndim.eq.4) then 
         ierror = nf90_inq_dimid(cdfid,dimname(1), lonid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_inq_dimid(cdfid,dimname(2), latid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_inq_dimid(cdfid,dimname(3), levid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_inq_dimid(cdfid,dimname(4), timid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      else if (ndim.eq.3)then
         ierror = nf90_inq_dimid(cdfid,dimname(1), lonid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_inq_dimid(cdfid,dimname(2), latid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_inq_dimid(cdfid,dimname(3), timid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      else if (ndim.eq.1)then
         ierror = nf90_inq_dimid(cdfid,dimname(1), levid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      endif

c     Get all times for variable
      if ( ndim.eq.4 )  then
         ierror = nf90_inquire_dimension(cdfid, timid, len = ntim)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_INQ_VARID(cdfid,dimname(4),timid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_GET_VAR(cdfid,timid,tim(1:ntim))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      elseif ( ndim.eq.3 ) then
         ierror = nf90_inquire_dimension(cdfid, timid, len = ntim)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_INQ_VARID(cdfid,dimname(3),timid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = NF90_GET_VAR(cdfid,timid,tim(1:ntim))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
         
      elseif ( ndim.eq.1 ) then         
         ntim=1
         tim(1:ntim)=time         
      endif
      
c     Find the appropriate time index
      itime = 0
      do i=1,ntim
         if ( tim(i).eq.time) itime = i
      enddo
      if ( itime.eq.0 ) then
         ierror = 1
         print*,'Error: Unknown time in getdat'
         return
      endif
      

c     Define the data volume to be read
      if ( ndim.eq.4 .or. ndim.eq.3) then

      corner(1) = 1
      count (1) = vardim(1)
      
      corner(2) = 1
      count (2) = vardim(2)
      
      end if
      
      if ( ndim.eq.4 ) then
         if (level.eq.0) then
            corner(3) = 1
            count (3) = vardim(3)
         elseif ( (level.ge.1).and.(level.le.vardim(3)) ) then
            corner(3) = vardim(3)-level+1
            count (3) = 1
         else
            ierror = 1
            return
         endif

         corner(4) = itime
         count (4) = 1

      elseif ( ndim.eq.3 ) then
         
         corner(3) = itime
         count (3) = 1
         
      elseif (ndim.eq.1) then
      
        corner(3)  = 1
        count(3)   = vardim(3)
      
      endif

c     Read data
       if ( ndim.eq.4 ) then
        allocate(tmp(count(1),count(2),count(3),count(4)),stat=stat)
        ierror = nf90_get_var(cdfid,varid,tmp,
     >           start = (/ corner(1),corner(2),corner(3),corner(4) /),
     >           count = (/ count (1),count (2),count (3),count (4) /) ) 

      else if ( ndim.eq.3 ) then
        allocate(tmp3(count(1),count(2),count(3)),stat=stat)
        allocate(tmp(count(1),count(2),1,count(3)),stat=stat)
        ierror = nf90_get_var(cdfid,varid,tmp3,
     >           start = (/ corner(1),corner(2),corner(3) /),
     >           count = (/ count (1),count (2),count (3) /) )
               do j = 1, count(2)
            do i = 1, count(1)
               tmp(i,j,1,1) = tmp3(i,j,1)
            enddo
           enddo
        count(4) = count(3)
        count(3) = 1 
        
       else if ( ndim.eq.1 ) then
       
        allocate(tmp1(count(3)),stat=stat)
        ierror = nf90_get_var(cdfid,varid,tmp1,
     >         start = (/ corner(3) /),
     >         count = (/ count (3)/) ) 
     


      endif

c     Copy data to output array: change orientation of vertical axis
c      if ( ndim.eq.4 .or. ndim.eq.3) then

c      do i=1,count(1)
c         do j=1,count(2)
c            if ( count(3).gt.1) then

c               do k=1,count(3)
c                     dat(i+count(1)*(j-1)+count(1)*count(2)*(k-1)) = 
c     >                                      tmp(i,j,count(3)-k+1,1)
c               enddo

c            else 
c               dat(i+count(1)*(j-1)) = tmp(i,j,1,1)
c            endif
c
c         enddo
c        enddo

c     Copy data to output array: don't change orientation of vertical axis
      if ( ndim.eq.4 .or. ndim.eq.3) then

      do i=1,count(1)
         do j=1,count(2)
            if ( count(3).gt.1) then

               do k=1,count(3)
                     dat(i+count(1)*(j-1)+count(1)*count(2)*(k-1)) = 
     >                                      tmp(i,j,k,1)
               enddo

            else 
               dat(i+count(1)*(j-1)) = tmp(i,j,1,1)
            endif

         enddo
       enddo
          
      else if  (ndim.eq.1) then ! for ORA
        do i=1,count(3)
            dat(i) = tmp1(i)
        end do     
      
      end if
               
c     Deallocate memory
      deallocate(tmp,stat=stat)

      end

c     -------------------------------------------------------------------
c     gettimes
c     -------------------------------------------------------------------

      subroutine gettimes(cdfid,times,ntimes,ierror)

      use netcdf
      
      integer cdfid
      real    times(*)
      integer ntimes
      integer ierror
      
      integer timid

c     Get all times 
      ierror = nf90_inq_dimid(cdfid,'time', timid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, timid, len = ntimes)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_INQ_VARID(cdfid,'time',timid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_GET_VAR(cdfid,timid,times(1:ntimes))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

      end

c     -------------------------------------------------------------------
c     getlevs
c     -------------------------------------------------------------------

      subroutine getlevs(cdfid,nlev,aklev,bklev,aklay,bklay,ierror)

      use netcdf
      
      integer     cdfid
      integer     nlev
      real        aklev(nlev)
      real        bklev(nlev)
      real        aklay(nlev)
      real        bklay(nlev)
      integer     ierror

      integer      aklayid
      integer      bklayid
      integer      aklevid
      integer      bklevid
      integer      dimids (1)
      character*80 dimname(1)
      integer      nz
      integer      nz1
      integer      dimid
      real         aklev1(nlev+1)
      real         bklev1(nlev+1)
      character*80 dir
      real         lev0,lev1
      character*80 unit
      real         tmp(nlev)

c     Get <varid>
      ierror = NF90_INQ_VARID(cdfid,'hyam',aklayid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_INQ_VARID(cdfid,'hybm',bklayid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_INQ_VARID(cdfid,'hyai',aklevid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_INQ_VARID(cdfid,'hybi',bklevid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Get dimension of the two arrays
      ierror = nf90_inquire_variable(cdfid, aklayid, dimids = dimids)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, dimids(1),name =dimname(1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inq_dimid(cdfid,dimname(1), dimid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, dimid, len = nz)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      ierror = nf90_inquire_variable(cdfid, aklevid, dimids = dimids)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, dimids(1),name =dimname(1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inq_dimid(cdfid,dimname(1), dimid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, dimid, len = nz1)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Check dimensions
      if ( (nz.ne.nlev).or.(nz1.ne.(nlev+1)) ) then
         print*,' Error: incompatible number of levels (getlevs)'
         ierror = 1
         return
      endif
      
c     Get levels
      ierror = NF90_GET_VAR(cdfid,aklayid,aklay(1:nz))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      ierror = NF90_GET_VAR(cdfid,bklayid,bklay(1:nz))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      ierror = NF90_GET_VAR(cdfid,aklevid,aklev1(1:nz1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      ierror = NF90_GET_VAR(cdfid,bklevid,bklev1(1:nz1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

c     Set the appropriate levels
      do i=1,nz
         aklev(i) = aklev1(i)
         bklev(i) = bklev1(i)
      enddo

c     Adjust unit (in hPa)
      ierror = NF90_INQ_VARID(cdfid,'hyam',aklayid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_get_att(cdfid, aklayid, "units", unit)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      if ( unit.eq.'Pa' ) then
         do i=1,nz
            aklay(i) = 0.01 * aklay(i)
         enddo
      endif

      ierror = NF90_INQ_VARID(cdfid,'hyai',aklevid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_get_att(cdfid, aklevid, "units", unit)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      if ( unit.eq.'Pa' ) then
         do i=1,nz
            aklev(i) = 0.01 * aklev(i)
         enddo
      endif

c     Adjust index order (up)
      do i=1,nz
         tmp(i) = aklev(i)
      enddo
      do i=1,nz
         aklev(i) = tmp(nz-i+1)
      enddo
      
      do i=1,nz
         tmp(i) = aklay(i)
      enddo
      do i=1,nz
         aklay(i) = tmp(nz-i+1)
      enddo
      
      do i=1,nz
         tmp(i) = bklev(i)
      enddo
      do i=1,nz
         bklev(i) = tmp(nz-i+1)
      enddo
         
      do i=1,nz
         tmp(i) = bklay(i)
      enddo
      do i=1,nz
         bklay(i) = tmp(nz-i+1)
      enddo
         
      end


c     -------------------------------------------------------------------
c     getvars
c     -------------------------------------------------------------------

      subroutine getvars(cdfid,nvars,vnam,ierror)

      use netcdf
      
      integer           cdfid
      integer           nvars
      character*80      vnam(*)
      integer           ierror

      integer           i

c     Get number of variables
      ierror = nf90_inquire(cdfid, nVariables = nvars)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      
c     Get variable names
      do i=1,nvars
          ierror = nf90_inquire_variable(cdfid, i, name = vnam(i) )
          IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      enddo

      return
      end


c     -------------------------------------------------------------------
c     getstart
c     -------------------------------------------------------------------

      subroutine getstart(cdfid,idate,ierror)
      
      use netcdf
      
      integer cdfid
      integer idate(5)
      integer ierror

      integer varid

c     Read data      
      ierror  = nf90_get_att(cdfid,nf90_global, "starty", idate(1))
      IF(ierror /= nf90_NoErr) idate(1) = 0
      ierror  = nf90_get_att(cdfid,nf90_global, "startm", idate(2))
      IF(ierror /= nf90_NoErr) idate(2) = 0
      ierror  = nf90_get_att(cdfid,nf90_global, "startd", idate(3))
      IF(ierror /= nf90_NoErr) idate(3) = 0
      ierror  = nf90_get_att(cdfid,nf90_global, "starth", idate(4))
      IF(ierror /= nf90_NoErr) idate(4) = 0
      ierror  = nf90_get_att(cdfid,nf90_global, "starts", idate(5))
      IF(ierror /= nf90_NoErr) idate(5) = 0

      end


c***********************************************************************
c CF-netCDF / Writing
c***********************************************************************

c     -------------------------------------------------------------------
c     crecdf
c     -------------------------------------------------------------------

      subroutine crecdf (filnam, cdfid, phymin, phymax, ndim, cfn, 
     &                      ierror) 
      
      use netcdf
      
      character*(* ) filnam
      integer        cdfid
      real           phymin(4)
      real           phymax(4)
      integer        ndim
      character*(*)  cfn
      integer        ierror

c     Create the netCDF file
      ierror = nf90_create(path  = filnam, 
     >                     cmode = nf90_clobber, 
     >                     ncid  = cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Global attributes
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                            "Conventions", "CF")
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "constants_file_name", trim(cfn))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "institution", 'IACETH')
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "lonmin", real(phymin(1)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "lonmax", real(phymax(1)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "latmin", real(phymin(2)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "latmax", real(phymax(2)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "levmin", real(phymin(3)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                             "levmax", real(phymax(3)))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     End definition mode
      ierror = nf90_enddef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      end


c     -------------------------------------------------------------------
c     putdef
c     -------------------------------------------------------------------

      subroutine putdef (cdfid, newvar, ndimension, misdat, 
     &                      vardim, varmin, varmax, stag, ierror)

      use netcdf
      
      integer        cdfid
      character*(*)  newvar
      integer        ndimension
      real           misdat
      integer        vardim(4)
      real           varmin(4)
      real           varmax(4)
      real           stag(4)
      integer        ierror

      real          eps
      parameter     (eps=0.0001)
      
      integer       ndim
      integer       nvar
      character*80  dimname(100)
      character*80  varname(100)
      integer       dimid
      integer       dimids(4)
      integer       nval
      real          val(1000)
      integer       varid
      integer       varids(4)
      integer       writelon,writelat,writelev,writetim
      character*80  lonname,latname,levname,timname

c     Unit/name table
      character*80  tablefile
      parameter     (tablefile='nil')
      character*80  table_varname (1000)
      character*80  table_longname(1000)
      character*80  table_unit    (1000)
      integer       fid
      integer       ntable

c     Read table information
      if ( tablefile.ne.'nil' ) then
         ntable = 0
         fid    = 10
         open(fid,file=tablefile)
 100      ntable = ntable + 1
          read(fid,*) table_varname (ntable),
     >                        table_longname(ntable),
     >                        table_unit    (ntable)

          print*,table_varname(ntable),table_longname(ntable),
     >             table_unit(ntable)
          
          goto 100
 101     close(fid)
      endif

c     Set the default names for dimensions
      lonname = 'lon'
      latname = 'lat'
      levname = 'lev'
      timname = 'time'

c     Get number of dimensions and of variables
      ierror = nf90_inquire(cdfid, nDimensions    = ndim,
     >                             nVariables     = nvar )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Get a list of all dimensions
      if ( ndim.gt.0 ) then
         do i=1,ndim
            ierror = nf90_inquire_dimension(cdfid,i,name = dimname(i))
            IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         enddo
      endif

c     Get a list of all variables
      if ( nvar.gt.0 ) then
         do i=1,nvar
            ierror = nf90_inquire_variable(cdfid,i,name = varname(i))
            IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         enddo
      endif

c     Check whether the new variable name is in conflict with the others
      do i=1,nvar
         if ( newvar.eq.varname(i) ) then
            print*,trim(newvar),' already exists on the file'
            stop
         endif
      enddo

c     Set IDs for dimensions 
      do i=1,4
         dimids(i) = -1
      enddo
      writelon = 0
      writelat = 0
      writelev = 0
      writetim = 0

c     Check whether there is already a time dimension (tim)
      ierror = nf90_inquire(cdfid, unlimitedDimId = dimids(4) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Check whether existing dimensions can be used
      do i=1,ndim

         if (i.ne.dimids(4)) then

c        Read dimension values
         ierror = nf90_inquire_dimension(cdfid,i,len = nval)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)         
         ierror = NF90_INQ_VARID(cdfid,dimname(i),varid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
         ierror = NF90_GET_VAR(cdfid,varid,val(1:nval))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

c        Check whether it can be used for the first dimension (lon)
         if ( (vardim(1).eq.nval).and.
     >        (abs(varmin(1)-val(1)   ).lt.eps).and.
     >        (abs(varmax(1)-val(nval)).lt.eps) )
     >   then
            dimids(1) = i
         endif

c        Check whether it can be used for the second dimension (lat)
         if ( (vardim(2).eq.nval).and.
     >        (abs(varmin(2)-val(1)   ).lt.eps).and.
     >        (abs(varmax(2)-val(nval)).lt.eps) )
     >   then
            dimids(2) = i
         endif
         
c        Check whether it can be used for the third dimension (lev)
         if ( (vardim(3).eq.nval) ) then
            dimids(3) = i
         endif
         
         endif

      enddo

c     Decide what dimension names to use
      if ( dimids(1).eq.-1 ) then
         do i=1,ndim
            if ( dimname(i).eq.lonname ) then
               lonname = trim(lonname)//'_'//trim(newvar)
            endif
         enddo
      endif
      if ( dimids(2).eq.-1 ) then
         do i=1,ndim
            if ( dimname(i).eq.latname ) then
               latname = trim(latname)//'_'//trim(newvar)
            endif
         enddo
      endif
      if ( dimids(3).eq.-1 ) then
         do i=1,ndim
            if ( dimname(i).eq.levname ) then
               levname = trim(levname)//'_'//trim(newvar)
            endif
         enddo
      endif

c     Enter definition mode
      ierror = nf90_redef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Define dimensions and corresponding variables if necessary
      if ( dimids(1).eq.-1 ) then
         dimid = ndim + 1
         ndim  = ndim + 1
         ierror = nf90_def_dim(cdfid, lonname, vardim(1), dimids(1))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_var(cdfid, lonname,
     >                                 NF90_FLOAT,dimids(1),varids(1))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(1), 
     >                               "long_name", "longitude") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(1), 
     >                               "units", "degrees_east") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(1), 
     >                               "standard_name", "longitude") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(1), 
     >                               "axis", "X") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         writelon = 1
      endif
      if ( dimids(2).eq.-1 ) then
         dimid = ndim + 1
         ndim  = ndim + 1
         ierror = nf90_def_dim(cdfid, latname, vardim(2), dimids(2))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_var(cdfid, latname,
     >                                NF90_FLOAT,dimids(2),varids(2))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(2), 
     >                               "long_name", "latitude") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(2), 
     >                               "units", "degrees_north") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(2), 
     >                               "standard_name", "latitude") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(2), 
     >                               "axis", "Y") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         writelat = 1
      endif
      if ( dimids(3).eq.-1 ) then
         dimid = ndim + 1
         ndim  = ndim + 1
         ierror = nf90_def_dim(cdfid, levname, vardim(3), dimids(3))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_var(cdfid, levname,
     >                                NF90_FLOAT,dimids(3),varids(3))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "long_name", "hybrid level at layer midpoints") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "units", "level") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "standard_name", "hybrid_sigma_pressure") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "positive", "down") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "formula", "hyam hybm (mlev=hyam+hybm*aps)") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(3), 
     >                 "formula_terms", "ap: hyam b: hybm ps: aps") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         writelev = 1
      endif
      if ( dimids(4).eq.-1 ) then
         dimid = ndim + 1
         ndim  = ndim + 1
         ierror = nf90_def_dim(cdfid,timname, nf90_unlimited, dimids(4))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_var(cdfid, timname,
     >                                NF90_FLOAT,dimids(4),varids(4))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(4), 
     >                 "units", "hours") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_att(cdfid, varids(4), 
     >                 "calendar", "proleptic_gregorian") 
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         
         writetim = 1
      endif

c     Define the variable
      ierror = nf90_def_var(cdfid,newvar,
     >                      NF90_FLOAT,dimids,varid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Write variable attributes
      ierror = nf90_put_att(cdfid, varid, 
     >                 "long_name", "unknown (please add with NCO)") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varid, 
     >                 "units", "unknown (please add with NCO)") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varid, 
     >                 "_FillValue", real(-999.99) ) 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)


c     Leave definition mode
      ierror = nf90_enddef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Write dimension arrays
      if ( writelon.eq.1 ) then
         do i=1,vardim(1)
            val(i) = varmin(1) + real(i-1) *
     >                 ( varmax(1) - varmin(1) ) / real(vardim(1)-1)
         enddo
         ierror = nf90_inq_varid(cdfid,lonname,varid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_var(cdfid, varid, val(1:vardim(1)))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      endif
      if ( writelat.eq.1 ) then
         do i=1,vardim(2)
            val(i) = varmin(2) + real(i-1) *
     >                 ( varmax(2) - varmin(2) ) / real(vardim(2)-1)
         enddo
         ierror = nf90_inq_varid(cdfid,latname,varid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_var(cdfid, varid, val(1:vardim(2)))
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      endif

      if ( writelev.eq.1 ) then
         do i=1,vardim(3)
            val(i) = real(i)
         enddo
         ierror = nf90_inq_varid(cdfid,levname,varid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_put_var(cdfid, varid, val(1:vardim(3)) )
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      endif

      end


c     -------------------------------------------------------------------
c     puttimes
c     -------------------------------------------------------------------

      subroutine puttimes(cdfid,times,ntimes,ierror)

      use netcdf
      
      integer   cdfid
      real      times(*)
      integer   ntimes
      integer   ierror

      integer   timid
      integer   otimes

c     Get number of times 
      ierror = nf90_inq_dimid(cdfid,'time', timid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_inquire_dimension(cdfid, timid, len = otimes)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      
      if (otimes.lt.ntimes) then
         print *,'Warning: puttimes is extending times-array'
      else if (nfiltim.gt.ntimes) then
         print *,'Warning: puttimes does not cover range of times-array'
      endif

c     Write times
      ierror = NF90_INQ_VARID(cdfid,'time',timid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = NF90_PUT_VAR(cdfid,timid,times(1:ntimes))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

c     Sync
      ierror = nf90_sync(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

      end


c     -------------------------------------------------------------------
c     putstart
c     -------------------------------------------------------------------

      subroutine putstart(cdfid,idate,ierror)

      use netcdf

      integer      cdfid
      integer      idate(5)
      integer      ierror

c     Enter definition mode
      ierror = nf90_redef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Write data      
      ierror  = nf90_put_att(cdfid,nf90_global, "starty", idate(1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_put_att(cdfid,nf90_global, "startm", idate(2))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_put_att(cdfid,nf90_global, "startd", idate(3))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_put_att(cdfid,nf90_global, "starth", idate(4))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror  = nf90_put_att(cdfid,nf90_global, "starts", idate(5))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Exit definition mode
      ierror = nf90_enddef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Sync
      ierror = nf90_sync(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

      end


c     -------------------------------------------------------------------
c     cdfwopn
c     -------------------------------------------------------------------

      subroutine cdfwopn(filnam,cdfid,ierror)
      
      use netcdf
      
      character*(*) filnam
      integer       cdfid
      integer       ierror

      ierror = NF90_OPEN(TRIM(filnam),nf90_write, cdfid)
      IF ( ierror /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierror)

      return
      end


c     -------------------------------------------------------------------
c     putdat
c     -------------------------------------------------------------------

      subroutine putdat(cdfid, varnam, time, level, dat, ierror)

      use netcdf
      
      integer        cdfid
      character*(*)  varnam
      real           time
      integer        level
      real           dat(*)
      integer        ierror

      real           eps
      parameter      (eps=0.0001)

      integer        ndims
      real           misdat
      integer        vardim(4)
      real           varmin(4)
      real           varmax(4)
      real           stag(4)
      integer        varid
      integer        ntimes
      real           times(100)
      integer        itime
      integer        corner(4)
      integer        count(4)
      integer        stat
      real,allocatable, dimension (:,:,:,:) :: tmp

c     Get definitions of data
      call getdef (cdfid, trim(varnam), ndims, misdat, 
     &                vardim, varmin, varmax, stag, ierr)
      if (ierr.ne.0)  print *,'*ERROR* in getdef in putdat'

c     Get id of the variable
      ierror = NF90_INQ_VARID(cdfid,varnam,varid)
      IF (ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Get a list of all times 
      call gettimes(cdfid,times,ntimes,ierror)

c     Get the time index
      itime = -1
      do i=1,ntimes
         if ( abs(time-times(i)).lt.eps) itime = i
      enddo

c     Start a new time step, if necessary
      if ( itime.eq.-1 ) then
         ntimes        = ntimes + 1
         times(ntimes) = time
         itime         = ntimes
         call puttimes(cdfid,times,ntimes,ierror)
      endif

C     Define data volume to write on the NetCDF file in index space
      corner(1) = 1               
      corner(2) = 1
      count(1)  = vardim(1)       
      count(2)  = vardim(2)
      if (level.eq.0) then
        corner(3) = 1
        count(3)  = vardim(3)
      else
        corner(3) = vardim(3)-level+1
        count(3)  = 1
      endif
      corner(4) = itime
      count(4)  = 1

c     Allocate temporary array
      allocate(tmp(count(1),count(2),count(3),count(4)),stat=stat)

c     Copy data to output array: change orientation of vertical axis
      if ( count(3).gt.1 ) then
         do i=1,count(1)
            do j=1,count(2)
               do k=1,count(3)
                  tmp(i,j,count(3)-k+1,1) =
     >               dat(i+count(1)*(j-1)+count(1)*count(2)*(k-1)) 
               enddo
            enddo
         enddo
      else
         do i=1,count(1)
            do j=1,count(2)
               tmp(i,j,1,1) = dat(i+count(1)*(j-1)) 
            enddo
         enddo
      endif
               
c     Write data
      ierror = nf90_put_var(cdfid, varid, tmp,
     >           start = (/ corner(1),corner(2),corner(3),corner(4) /),
     >           count = (/ count (1),count (2),count (3),count (4) /) ) 

c     Deallocate memory
      deallocate(tmp,stat=stat)

c     Sync
      ierror = nf90_sync(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

      end


c     -------------------------------------------------------------------
c     wricst
c     -------------------------------------------------------------------

      subroutine wricst(cstnam,datar,aklev,bklev,aklay,bklay,stdate)

      use netcdf
      
      character*80  cstnam
      integer       datar(14)
      real          aklev(1000)
      real          bklev(1000)
      real          aklay(1000)
      real          bklay(1000)
      integer       stdate(5)

      integer       writeakbk
      parameter     (writeakbk=0)

      integer       ierror
      integer       cdfid
      real          phymin(4),phymax(4)
      integer       ndim
      character*80  cfn
      real          pollon,pollatq
      real          dellon,dellat
      integer       dimid
      integer       dimids(4)
      integer       varids(4)

      goto 200

c     Get the number of levels
      nz = datar(9)                     

c     Try to open the netCDF file - create it, if necesarry
      ierror = NF90_OPEN(TRIM(cstnam),nf90_write, cdfid)
      IF ( ierror /= nf90_NoErr ) then      
         phymin(1) = real(datar(4))/1000.
         phymin(2) = max(real(datar(5))/1000.,-90.)
         phymin(3) = 1
         phymax(1) = real(datar(6))/1000.
         phymax(2) = min(real(datar(3))/1000.,90.)
         phymax(3) = nz
         ndim      = 4
         cfn       = cstnam
         call crecdf (cstnam, cdfid, phymin, phymax, ndim, cfn, 
     &               ierror ) 
         call putstart (cdfid,stdate,ierror)         
         ierror = nf90_def_dim(cdfid,'nx', datar(1), dimid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_dim(cdfid,'ny', datar(2), dimid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
         ierror = nf90_def_dim(cdfid,'ny', datar(3), dimid)
         IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 
      endif

c     Enter definition mode
      ierror = nf90_redef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Write pole longitude and latitude
      pollon = real(datar(13))/1000
      if (datar(14).gt.0) then
        pollat=min(real(datar(14))/1000.,90.)
      else
        pollat=max(real(datar(14))/1000.,-90.)
      endif

      ierror = nf90_put_att(cdfid, nf90_global, 
     >                               "pollon", real(pollon))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                               "pollat", real(pollat))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

C     Write grid resolution
      dellon = real(datar(7))/1000.
      dellat = real(datar(8))/1000.

      ierror = nf90_put_att(cdfid, nf90_global, 
     >                               "dellon", real(dellon))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, nf90_global, 
     >                               "dellat", real(dellat))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Skip ak,bk definition if writing ot requested
      if (writeakbk.eq.0) goto 100

c     Define dimensions for nhym, nhym
      ierror = nf90_def_dim(cdfid,'nhyi', nz, dimids(1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_def_dim(cdfid,'nhym', nz, dimids(2))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Define variables hyai,hyam,hybi,hybm
      ierror = nf90_def_var(cdfid, 'hyai',
     >                       NF90_FLOAT,dimids(1),varids(1))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(1), 
     >         "long_name", "hybrid A coefficient at layer interfaces") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(1), 
     >          "units", "hPa") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      ierror = nf90_def_var(cdfid, 'hybi',
     >                       NF90_FLOAT,dimids(1),varids(2))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(2), 
     >         "long_name", "hybrid B coefficient at layer interfaces") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(2), 
     >          "units", "1") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      ierror = nf90_def_var(cdfid, 'hyam',
     >                       NF90_FLOAT,dimids(2),varids(3))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(3), 
     >         "long_name", "hybrid A coefficient at layer midpoints") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(3), 
     >          "units", "hPa") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

      ierror = nf90_def_var(cdfid, 'hybm',
     >                       NF90_FLOAT,dimids(2),varids(4))
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(4), 
     >         "long_name", "hybrid B coefficient at layer midpoints") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_att(cdfid, varids(4), 
     >          "units", "1") 
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Exit definition mode
      ierror = nf90_enddef(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Write ak,bk
      ierror = nf90_put_var(cdfid, varids(1), aklay(1:nz) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_var(cdfid, varids(2), bklay(1:nz) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_var(cdfid, varids(3), aklev(1:nz) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)
      ierror = nf90_put_var(cdfid, varids(4), bklev(1:nz) )
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Continue
 100  continue

c     Sync
      ierror = nf90_sync(cdfid)
      IF(ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror) 

c     Close netCDF
      call clscdf(cdfid,ierror)
      IF (ierror /= nf90_NoErr) PRINT *,NF90_STRERROR(ierror)

c     Exit
 200  continue

      end