NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.

Problems with readgeneral.f

Hello,
I'm a student at the Philipps-University Marburg (Germany) and want to work 
with the NCEP/NCAR Reanalysis Data but I've got problems compiling 
'readgeneral.f' from CDC, which is for reading netcdf format files from CDC.

I have installed netcdf-3.5.1 and udunits-1.11.7 from source on this system:
Linux linux 2.4.21-99-athlon #1 Wed Sep 24 13:34:32 UTC 2003 i686 athlon i386 
GNU/Linux

I set following environments:
setenv CPPFLAGS "-DNDEBUG -Df2cFortran"
setenv FC g77
setenv LD_MATH "-lm"

I tried to compile readgeneral.f with the following command:

g77 readgeneral.F -lnetcdf -ludunits 

and get this output:

/usr/local/udunits/include/udunits.inc: In subroutine `gridread':
In file included from readgeneral.F:174:
/usr/local/udunits/include/udunits.inc:27: error: undefined or invalid # 
directive
/usr/local/udunits/include/udunits.inc:36:
         PTR utmake
         1         2
Unrecognized statement name at (1) and invalid form for assignment or 
statement-function definition at (2)
readgeneral.F:217: warning:
         call ncagt(inet,ivar,'scale_factor',xscale,icode1)
              1
readgeneral.F:219: (continued):
....

/usr/local/udunits/include/udunits.inc:36:
         PTR utmake
         1         2
Unrecognized statement name at (1) and invalid form for assignment or 
statement-function definition at (2)
 
Attached is 'udunits.inc' and 'readgeneral.F'


Thank you very much for your help!
Regards 
Katja Trachte
__________________________________________________________
Mit WEB.DE FreePhone mit hoechster Qualitaet ab 0 Ct./Min.
weltweit telefonieren! http://freephone.web.de/?mc=021201
      integer   UT_EOF, UT_ENOFILE, UT_ESYNTAX, UT_EUNKNOWN
      integer   UT_EIO, UT_EINVALID, UT_ENOINIT, UT_ECONVERT
      integer   UT_EALLOC, UT_ENOROOM, UT_ENOTTIME

      parameter (UT_EOF         = 1)
      parameter (UT_ENOFILE     = -1)
      parameter (UT_ESYNTAX     = -2)
      parameter (UT_EUNKNOWN    = -3)
      parameter (UT_EIO         = -4)
      parameter (UT_EINVALID    = -5)
      parameter (UT_ENOINIT     = -6)
      parameter (UT_ECONVERT    = -7)
      parameter (UT_EALLOC      = -8)
      parameter (UT_ENOROOM     = -9)
      parameter (UT_ENOTTIME    = -10)

      integer   UT_MAXNUM_BASE_QUANTITIES
      parameter (UT_MAXNUM_BASE_QUANTITIES = 10)

C The FORTRAN API:
C
C NB: `PTR in the following stands for whatever FORTRAN type is
C appropriate for storing a pointer to a structure.  Because this is
C necessarily platform-dependent, IT IS UP TO THE USER TO DECLARE AND USE
C THE CORRECT TYPE.

#ifndef PTR
#   define PTR  integer
#endif

C
C   Initialize the units package:
      integer utopen
C       (character*(*) fpath)

C   Create a new unit:
      PTR utmake
C       ()

C   Is a unit a temporal one?
      integer uttime
C       (PTR unit)

C   Indicate whether or not a unit has a non-zero origin (0=>no, 1=>yes).
      integer utorigin
C         (PTR unit)

C   Clear a unit:
C     utclr
C       (PTR unit)

C   Copy a unit:
C     utcpy
C       (PTR source,
C       PTR dest)

C   Shift the origin of a unit:
C     utorig
C       (PTR source, 
C       doubleprecision amount, 
C       PTR result)

C   Scale a unit:
C     utscal
C       (PTR source, 
C       doubleprecision factor, 
C       PTR result)

C   Multiply two units:
C     utmult
C       (PTR term1,
C       PTR term2, 
C       PTR result)

C   Invert a unit:
C     utinv
C       (PTR source,
C       PTR result)

C   Divide one unit by another:
C     utdiv
C       (PTR numer,
C       PTR denom, 
C       PTR result)

C   Raise a unit to a power:
C     utexp
C       (PTR source,
C       PTR power, 
C       PTR result)

C   Decode a formatted specification into a unit:
      integer utdec
C       (character*(*) fspec,
C       PTR unit)

C   Convert a temporal value into a UTC Gregorian date and time:
      integer utcaltime
C       (real    value,
C       PTR unit,
C       integer year
C       integer month,
C       integer day,
C       integer hour,
C       integer minute,
C       real    second)

C   Convert a Gregorian/Julian date and time into a temporal value:
      integer uticaltime
C       (integer year,
C       integer  month,
C       integer  day,
C       integer  hour,
C       integer  minute,
C       real     second,
C       PTR      unit,
C       doubleprecision value)

C   Encode a unit into a formatted specification:
      integer utenc
C       (PTR unit,
C       char fspec)

C   Convert from one unit to another:
      integer utcvt
C       (PTR from,
C       PTR to, 
C       doubleprecision slope, 
C       doubleprecision intercept)

C   Free a unit thingy created by utmake():
C     utfree
C       (PTR unit)

C   Close the units package:
C     utcls
C       ()
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C      
C       This is a sample program that will read netCDF data files
C       from the NOAA-CIRES Climate Diagnostics Center.
C
C       In order to run the code you must have the netCDF and UDUNITS
C       libraries installed from UniData.
C
C               netCDF can be found at
C               http://www.unidata.ucar.edu/packages/netcdf/index.html
C
C               UDUNITS can be found at
C               http://www.unidata.ucar.edu/packages/udunits/index.html
C
C       Don't forget to add them -lnetcdf and -ludunits options to the compile
C       or load command line.
C
C       There are four things that you must change to use this code
C       at your site.  Each place where you must make a change is
C       indicated with a comment of the form like the line below.
C
C STEP 1.
C       Change the location of the netcdf.inc and udunits.inc include files
C       to match your installation. (Occurs in 4 places.)
C
C STEP 2.
C       Change the location of the udunits.dat file to match your system
C       installation.
C
C STEP 3.
C       Change PARAMETER values for ilon and jlat to match your file.
C       You can find out the sizes of the lon and lat dimensions by looking
C       at the output of ncdump -h <your_file>.
C
C STEP 4.
C    Change the name of the input file to match the data file you want to read.
C
C STEP 5.
C    Choose among the three different ways to read data and remove the comments
C       to get the code you need to do your job.
C
C NOTES:
C       Data is read in one 2D grid at a time in the same lat/lon order
C       it was stored.
C   The gridread subroutine returns the date of the grid read.
C
C     Code written 10/9/96 by Cathy Smith
C
C     NOAA-CIRES Climate Diagnostics Center, Boulder, CO.
C     based on code writen by Tom Baltzer, Roland Schweitzer and
C     Cathy Smtih
C     For help, contact Roland Schweitzer or Cathy Smith
C                                 Roland.Schweitzer@xxxxxxxx or 
cathy.smith@xxxxxxxx
C     :)
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C    MAIN CODE

c
c This is the latitude, longitude dimension of the grid to be read.
c This corresponds to the lat and lon dimension variables in the netCDF file.
c
C STEP 3.
      parameter (ilon =360)
      parameter (jlat=180)

c
c The data are packed into short integers (INTEGER*2).  The array work
c will be used to hold the packed integers.  The array 'x' will contain
c the unpacked data.
c
C    DATA ARRAY AND WORK ARRAY
      real x(ilon,jlat)
      integer*2 work(ilon,jlat)

c
c Initialize the UDUNITS package.  You may need to change the location
c of the udunits.dat file to match your system.
c
C STEP 2.

       retcode=utopen('/usr/local/udunits/etc/udunits.dat')
C STEP 4.
c
c Below in the ncopen call is the file name of the netCDF file.
c You may want to add code to read in the file name and the variable name.
c
c The variable name is the netCDF variable name.  At CDC we name our files
c after the variable name.  If you follow that convention the variable name
c is the same as the first few letters of the file name (the letters up to
c but not including the first '.'.
C
C    OPEN FILE AND GET FILES ID AND VARIABLE ID(S)

      inet=ncopn('sst.mnmean.nc',0,icode)
      ivar=ncvid(inet,'sst',icode)
C STEP 5.
C Pick one of the following scenarios to match your needs.
C
C Comment out this section and remove the comment from one of
C the sections below.

        print*, 'Pick one of the three scenarios for your data.'
        print*, 'See STEP 5 in the comments.'
        stop 'Pick a scenario'
c
C SCENARIO 1.
c USE THIS LOOP TO READ THE FIRST 'NTIME' TIME STEPS FROM A FILE
c WITH ONLY ONE LEVEL.  IF THE FILE ONLY HAS ONE LEVEL SET ILEV TO 0.
c
       ntime = 5
       ilev = 0
       do it=1,ntime
          call gridread(inet,ivar,it,x,jlat,ilon,ilev,ny,nm,nd,nh,work)
          print*,x(2,2),x(72,36),ny,nm,nd,nh
       enddo
c
C SCENARIO 2.
c USE THIS LOOP TO READ THE FIRST 'NTIME' TIME STEPS FROM A FILE
c WITH 'NLEV' LEVELS IN IT.  EACH PASS THROUGH THE LOOP WILL RESULT
c IN A GRID AT LEVEL ILEV, AND TIME STEP NTIME.
c

c     ntime = 5
c     nlev = 17
c
c     do it=1,ntime
c       do ilev = 1, nlev
c          call gridread(inet,ivar,it,x,jlat,ilon,ilev,ny,nm,nd,nh,work)
c          print*,x(1,1),ny,nm,nd,nh
c       enddo
c     enddo

c
C SCENARIO 3.
c THIS CODE BLOCK WILL READ A SPECIFIC TIME AND DATE FROM THE FILE.
c

c
c Set the time of the grid to be read.
c

      ny = 1995
      nm = 3
      nd = 6
      nh = 12

c
c Set this to 0 for a file with one level, loop over it to get all levels,
c or set it to the index of a specific level.
c
c     ilev = 5

c     call timeindex(inet,ny,nm,nd,nh,it)
c     call gridread(inet,ivar,it,x,jlat,ilon,ilev,ny,nm,nd,nh,work)

c
c The value of ny, nm, nd, and nh have been overwritten with the
c values for the grid just read.
c
c     print*,x(1,1),ny,nm,nd,nh

      stop
      end

********************************************************************
********************************************************************
C     MAIN SUBROUTINE TO READ GRID

      subroutine gridread(inet,ivar,nt,x,jlat,ilon,ilev,iyear,imonth,
     &   iday,ihour,idata)

C STEP 1.
      include '/usr/local/udunits/include/udunits.inc'
      include '/usr/local/netcdf/include/netcdf.inc'

********************************************************************
C     UDUNITS STUFF TO UNPACK TIME:
********************************************************************
C     declare udunits function calls

      integer*4 UTMAKE
c      integer UTDEC,uttime

C     declare everything else

      integer*4 iyear,imonth,iday,ihour,retcode,itimeid
      integer*4 unitptr
      character*1024 unitstrin
      character*1024 unitstr

      integer*2 idata(ilon,jlat)
      real*4 x(ilon,jlat)
      integer count(3),start(3)
      integer countl(4),startl(4)
      integer icount2(1),istart2(1)
      integer*2 miss


c      unitptr=utmake()
      retcode=utdec(unitstr,unitptr)
      retcode=uttime(unitptr)
      isave=1
      itimeid=NCVID(inet,'time',icode)
      call ncainq(inet,itimeid,'units',iNCCHAR,mlen,i)
      call ncagtc(inet,itimeid,'units',unitstrin,mlen,icode)
      unitstr=unitstrin(1:nblen(unitstrin))
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

C     TEST AND SEE OF FILE HAS LEVELS
C     ALSO SEE IF PACKED

C     GET SCALE FACTOR AND MISSING VALUE IF NECESSARY
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC


      call NCPOPT(0)    !Turn off netCDF error reaction
      call ncagt(inet,ivar,'scale_factor',xscale,icode1)
      call ncagt(inet,ivar,'add_offset',xoff,icode2)
      call ncagt(inet,ivar,'missing_value',miss,icode3)
C     you need to get level or else use integer level
C     SLAB INFO FOR DATA ARRAY

C     see if packed or not
      ipack=0
      if((icode1.eq.0).and.(icode2.eq.0))then
        if((xscale.eq.1).and.(xoff.eq.0))then
         ipack=0
        else
         ipack=1
        endif
      endif

        start(3)=nt
        if(ilev.eq.0)then
          start(1)=1
          start(2)=1
          start(3)=nt

          count(1)=ilon
          count(2)=jlat
          count(3)=1

C     LOOP THROUGH 1 YEAR OF DATA, UNPACK ARRAY, UNPACK TIME
C     AND READ HEADER


         if(ipack.eq.1)then
           call ncvgt(inet,ivar,start,count,idata,icode)
           call unpack(idata,x,xscale,xoff,miss,ilon,jlat)
         else
           call ncvgt(inet,ivar,start,count,x,icode)
         endif
         call ncvgt(inet,itimeid,nt,1,xtime,icode)
         istart2(1)=nt
         icount2(1)=1
         call ncvgt(inet,itimeid,istart2,icount2,xtime,iercode)
         call udparse(unitstrin,xtime,iyear,imonth,iday,ihour)
      else
          startl(1)=1
          startl(2)=1
          startl(3)=ilev
          startl(4)=nt

          countl(1)=ilon
          countl(2)=jlat
          countl(3)=1
          countl(4)=1

C     LOOP THROUGH 1 YEAR OF DATA, UNPACK ARRAY, UNPACK TIME
C     AND READ HEADER

          if(ipack.eq.1)then
            call ncvgt(inet,ivar,startl,countl,idata,icode)
            call unpack(idata,x,xscale,xoff,miss,ilon,jlat)
          else
            call ncvgt(inet,ivar,startl,countl,x,icode)
          endif
          call ncvgt(inet,itimeid,nt,1,xtime,icode)
          istart2(1)=nt
          icount2(1)=1
          call ncvgt(inet,itimeid,istart2,icount2,xtime,iercode)
          call udparse(unitstrin,xtime,iyear,imonth,iday,ihour)
      endif

      return
      end

********************************************************************
      subroutine unpack(x,y,xscale,xadd,miss,ilon,jlat)
      parameter (zmiss=1e30)

      integer*2 x(ilon,jlat),miss
      real y(ilon,jlat)

      do i=1,ilon
         do j=1,jlat
            if(x(i,j).eq.miss)then
               y(i,j)=zmiss
            else
              y(i,j)=(x(i,j)*xscale)+xadd
           endif
         enddo
      enddo

      return
      end
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C     This routine (part of the netopen package for CDC netCDF file
C     handling) takes a netCDF file id, a year, month, day and hour
C     and converts it to the time index for that time in the file
C     and returns that index
C
C     NOTE: WILL NOT HANDLE LESS THAN HOURLY DATA!  Prints error message
C               and terminates.
C
C     Written by Cathy Smith of CDC on ???
C     Modified by Tom Baltzer of CDC on 2/14/95
C               - Broke out into own file and added comments
C     Modified by Tom Baltzer of CDC on 2/27/95
C                 added declarations comments and made to work with
C                 reanalysis.
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      subroutine timeindex(netid,nyr,nmn,ndy,nhr,itime)
C STEP 1.
      include '/usr/local/netcdf/include/netcdf.inc'
      include '/usr/local/udunits/include/udunits.inc'

      integer netid                     ! NetCDF file id
      integer nyr,nmn,ndy,nhr           ! Input year,month,day & hour
      integer itime                     ! Return time index

      integer inyr2d                    ! 2 digit in year (used throughout)
      integer inyr4d                    ! 4 digit input year
      real*8  xtime(10)                 ! Holds 10 time values from file
      real*8  inxtime                   ! Input time in netCDF file form
      character*25 cdeltat              ! delta_t attribute from file
      integer timevid                   ! Time variable id
      integer timedid                   ! Time dimension id
      character*100 timeunit            ! unit attribute for time variable
      integer*4 unitptr                 ! pointer to udunits unit
      integer*4 UTMAKE                  ! Declare the function.  It's in the
                                        ! udunits.inc at our site, but
                                        ! may not be at others.
      integer yr1,mn1,dy1,hr1           ! First time value in file
      integer yr2,mn2,dy2,hr2           ! Second time value in file
      integer*4 xhour1,xhour2,xhourin   ! results of xhour calls
      integer*4 hourinc                 ! delta time in hours
      integer monthly                   ! 1 if data is monthly
      integer daily                     ! 1 if data is daily
      integer found                     ! 0 if not found 1 if found

      integer ltm                       ! Used to identify a LTM file
      integer equalinc                  ! Identify non-equal time increments

      integer ercode                    ! To get netCDF error codes
c      integer UTDEC                    ! Declare the functions.
c      integer UTICALTIME
      integer istart(1),icount(1)       ! Used in netCDF calls
      character*15 cname                ! Place holder

C     Initialize
c
c I added the condition to find values less that 100.  We assume that such
c a year is a 2 digit year in the 20th century.
c
c The other else if block gets set up for other years, like 1851 the beginning
c of the DOE data set.
c
      if (nyr.gt.1900.and.nyr.lt.3000) then
         inyr2d = nyr - 1900
         inyr4d = nyr
      else if ( nyr.lt.100 ) then       ! Between 0-99, it's a 2 digit year.
         inyr2d = nyr
         inyr4d = nyr + 1900
      else if ( nyr .ge. 100 .and. nyr .lt. 2000) then  ! Some other year
         inyr2d = nyr   !Not really, but it's non-zero which is inportant.
         inyr4d = nyr   !What ever they gave us was the year we want.
      endif

      ltm = 0
      equalinc = 0
      monthly = 0
      daily = 0

C     Get all the time variable information including the first 10 or
C     (if < 10) total available values and convert 1st 3 to yr,mn,dy, & hr

      timedid=NCDID(netid,'time',ercode)
      call NCDINQ(netid,timedid,cname,idimt,ercode)
      istart(1)=1
      if (idimt.ge.10) then
         icount(1)=10
      else
         icount(1)=idimt
      endif
      timevid=NCVID(netid,'time',ercode)
      call NCVGT(netid,timevid,istart,icount,xtime,ercode)
      call NCAGTC (netid,timevid, 'units', timeunit, 100, ercode)

      if (idimt.ge.3) then
         call udparse(timeunit, xtime(1), yr1,mn1,dy1,hr1)
         call udparse(timeunit, xtime(2), yr2,mn2,dy2,hr2)
      elseif (idimt.eq.1) then
         write(0,*) "Only one time increment in the file - returning it"
         itime = 1
         found = 1
         return
      else
         equalinc = 1
         call udparse(timeunit, xtime(1), yr1,mn1,dy1,hr1)
         call udparse(timeunit, xtime(2), yr2,mn2,dy2,hr2)
      endif


C     Turn off error checking and see if this is a CDC data file, and
C     if so, check time increment < hourly and check for ltm file.
C     Also do first check for equal increment.

      call NCPOPT(0)
      call NCAGTC(netid,timevid,'delta_t',cdeltat,25,ercode)
      if (ercode.eq.0) then
         equalinc = 1
c
c Previously, this was called with variable id hard coded to 1.
c This won't work for multiple variables in the same run.
c
c        call NCAGTC(netid,1,'statistic',cstat,25,ercode)
c
c We will detect long term means from the ltm_range attribute.
c That way we don't need the variable id at all.
c
        call NCAGT(netid,timevid,'ltm_range',ltm_range,ercode)

c
c Ugly kludge to handle different spellings of LTM.  Probably
c should do this as a caseless comparison.  rhs 1/8/96
c Using ltm range gets rid of this ugly kludge.
c
c        if(cstat(1:14).eq.'Long Term Mean' .or.
c    &      cstat(1:14).eq.'Long term mean' .or.
c    &      cstat(1:14).eq.'long term mean') then
c
c If the return code from the above is zero then we have
c and LTM file.
        if (ercode .eq. 0) then
c
c Looking for daily long term means as well as monthly.
c
c           if(inyr2d.ne.0.or.ndy.ne.0.or.nhr.ne.0) then
c              write(0,*) 'timeindex: Warning - non-monthly value ',
c    &                  'requested for monthly LTM file'
c              write(0,*) 'Using month value ',nmn,' to get index'
c           endif
c
c Detect both monthly and daily long term mean.
c
            if(inyr2d.ne.0.or.nhr.ne.0) then
               write(0,*) 'timeindex: Warning - non-zero hourly value ',
     &                  'requested for a LTM file.',
     &                  'Do not know how do deal with hourly LTM.  ',
     &                  'Quiting...'
                stop 'LTM'
            endif
            ltm = 1
         endif
         if (cdeltat(15:16).ne.'00'.or.cdeltat(18:19).ne.'00') then
            write(0,*) 'timeindex: Error: Time increment is < hourly -'
            write(0,*) ' cannot be handled. -Terminating.'
            stop
         endif
         if (cdeltat(7:7).eq.'1') monthly = 1
         if (cdeltat(10:10).eq.'1') daily = 1
      endif
      call NCPOPT(NCVERBOS+NCFATAL)

C     Get the time index.

      if (ltm.eq.1 .and. monthly.eq.1) then
         itime=(nmn-mn1)+1
         found = 1
      elseif ( ltm.eq.1 .and. daily.eq.1) then
         call xhour(yr1,mn1,dy1,hr1,xhour1)
         call xhour(yr2,mn2,dy2,hr2,xhour2)
         hourinc = xhour2 - xhour1
c
c Well, this looks ugly.
c Previously, these xhour values were computed from the year 0.
c xhour turns the year 0 into 1900 and all the calculations are
c done relative to 1900.  1900 is a leap year, which pushes the
c ltm values off by a day.  Instead, since we know it's a ltm
c already from the statistic attribute, we use year 1 for
c the xhour calculations.  rhs 1/8/95
c
         if (daily.eq.1.or.hourinc.eq.24) then
c           call xhour(yr1,mn1,dy1,0,xhour1)
c           call xhour(yr2,mn2,dy2,0,xhour2)
c           call xhour(inyr4d,nmn,ndy,0,xhourin)
            call xhour(1,mn1,dy1,0,xhour1)
            call xhour(1,mn2,dy2,0,xhour2)
            call xhour(1,nmn,ndy,0,xhourin)
         else
            call xhour(inyr4d,nmn,ndy,nhr,xhourin)
         endif
         itime = INT(((xhourin - xhour1)/hourinc) + 0.5)
         itime = itime + 1
         found = 1
      elseif (monthly.eq.1) then
         itime=(((inyr4d*12)+nmn)-((yr1*12)+mn1))
         itime=itime+1
         found = 1
      elseif (equalinc.eq.1) then
         call xhour(yr1,mn1,dy1,hr1,xhour1)
         call xhour(yr2,mn2,dy2,hr2,xhour2)
         hourinc = xhour2 - xhour1
         if (daily.eq.1.or.hourinc.eq.24) then
            call xhour(yr1,mn1,dy1,0,xhour1)
            call xhour(yr2,mn2,dy2,0,xhour2)
            call xhour(inyr4d,nmn,ndy,0,xhourin)
         else
            call xhour(inyr4d,nmn,ndy,nhr,xhourin)
         endif
         itime = INT(((xhourin - xhour1)/hourinc) + 0.5)
         itime = itime + 1
         found = 1
      else
         write(0,*) 'Cannot assume consistant delta time for ',
     &                  'finding index (no delta_t attribute)'
         write(0,*) 'This may take a while ...'
         found = 0

C        Inverse parse the date for comparisons - and move through the
C        time values searching for the one we want.

         if (timeunit(1:1).eq.'y'.or.timeunit(1:1).eq.'Y') then
            inxtime = inyr4d*10000000000.d0 + nmn*100000000.d0 +
     &                ndy*1000000. + nhr*10000.
         else
            unitptr = UTMAKE()
            ercode = UTDEC(timeunit(1:nblen(timeunit)),unitptr)
            if (ercode.ne.0) then
               call uduerr(ercode,'UTDEC','')
               write(0,*) ''
               write(0,*) 'NOTE: You must call netop_init to use
     &                          gridread,'
               write(0,*) '      gridreadx, dayread, and dayreadx'
               stop
            endif
            ercode = UTICALTIME(inyr4d,nmn,ndy,nhr,0,0.,unitptr,inxtime)
            if (ercode.ne.0) then
               call uduerr(ercode,'UTICALTIME','')
               write(0,*) ' '
               write(0,*) 'Something wrong with finding time increment'
               write(0,*) 'Terminating'
               stop
            endif
            call UTFREE(unitptr)
         endif

C        See if time is in first group of time values gotten from file

         do i = 1,icount(1)
            if (xtime(i).eq.inxtime) then
               itime = i
               found = 1
            endif
         enddo
         if (icount(1).eq.idimt) then
            write(0,*) 'Could not find desired time increment'
            write(0,*) ' - Terminating'
            stop
         endif

C        Step through file getting groups of values and seeing if it's in there

         istart(1) = istart(1) + icount(1)
         do while (found.eq.0.and.istart(1)+icount(1).le.idimt)
            call NCVGT(netid,timevid,istart,icount,xtime,ercode)
            do i = 1,icount(1)
               if (xtime(i).eq.inxtime) then
                  itime = (istart(1) + i) - 1
                  found = 1
               endif
            enddo
         enddo

C        Check the last group of time values in the file
         if (found.eq.0) then
            icount(1) = (idimt - istart(1)) + 1
            call NCVGT(netid,timevid,istart,icount,xtime,ercode)
            do i = 1,icount(1)
               if (xtime(i).eq.inxtime) then
                  itime = (istart(1) + i) - 1
                  found = 1
               endif
            enddo
         endif

         if (found.eq.0) then
            write(0,*) 'Could not find desired time increment'
            write(0,*) ' - Terminating'
            stop
         endif

      endif

      if(itime.gt.idimt)then
         write(0,*)'You are requesting a time past the end of the file'
         istart(1)=idimt
         icount(1)=1
         call NCVGT(netid,timevid,istart,icount,xtime,ercode)
         call udparse(timeunit,xtime(1),iyear,imonth,iday,ihour)
         write(0,*)' last day of file is: ',iyear,imonth,iday,ihour
      endif
      if(itime.le.0)then
        print*,'you asked for a time before first day of the dataset'
        print*,iyear,imonth,iday,ihour,' is first day of data'
        itime=0
      endif

      return
      end
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C  This subroutine is part of the netopen/read set of Fortran callable
C  routines for reading CDC netCDF files and returning grids.
C
C  This routine takes in a year, month, day and hour and calculates
C  the number of hours since a date before all our data (year 1 month 1
C  day 1) - this gives a referece value from which differences between
C  dates can be derived.
C
C  Note that this routine will take a 4 or a 2 digit date, if it
C  receives a 2 digit date it assumes that it is in the range 1900 -
C  1999.
C
C  Written by Cathy Smith of CDC on ???
C  Modified by Tom Baltzer of CDC on Feb 28, 1995
C       - converted from days to hours so that hourly data can be
C         accounted for, and made starting date 1-1-1 from 1-1-1920.
C
C  File: xhour.f (to be included in netopen.subr.f)
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      subroutine xhour(iy,im,id,ih,xhours)

      integer iy,im,id,ih       ! The input year, month, day and hour
      integer*4 xhours          ! OUT # of hours between in and 1-1-1

      integer*4 xdays           ! Used in calculating hours
      integer   inyear          ! Used to work with input year

      integer imonth(12)        ! Used in calculating # days in this year
      integer imonthl(12)       ! "                                     "

      data imonth/31,28,31,30,31,30,31,31,30,31,30,31/
      data imonthl/31,29,31,30,31,30,31,31,30,31,30,31/

C     See if date is in 1900s but given as 2 digit.

      if (iy.lt.100) then
         inyear = iy + 1900
      else
         inyear = iy
      endif

C     CALCULATE DAYS FROM JAN 1 Year 1

      xdays=0
      xhours=0

      xdays = INT((inyear-1)*365.25)

      if(im.gt.1)then
        do imm=1,im-1
           if((mod(inyear,4).eq.0).and.(inyear.ne.0))then
             xdays=xdays+imonthl(imm)
           else
             xdays=xdays+imonth(imm)
           endif
        enddo
      endif

      xdays=xdays+id

      xhours = xdays*24

      xhours = xhours + ih

      return
      end

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C     This subroutine is part of the netopen Fortran callable CDC
C     group of routines for reading generic netCDF files in the new
C     cooperative standard as presented in:
C       http://ferret.wrc.noaa.gov/noaa_coop/coop_cdf_profile.html
C
C     This routine takes a time value pulled from the netCDF file,
C     determines if it is in the new or old time format (by using the
C     udunits function) and then returns the representative year,
C     month, day and hour represented by the time value.
C
C     Written by Cathy Smith of CDC on ???
C     Modified by Tom Baltzer of CDC on Feb. 8, 1995
C       - To determine if time is old or new format and parse
C               accordingly
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      subroutine udparse(timeunit,intime,oyear,omonth,oday,ohour)

C STEP 1.
      include '/usr/local/udunits/include/udunits.inc'

C     Note: POINTER type is integer*4 on the CDC SparcCenter 2000
c     system running SunOS 5.3
c      integer UTMAKE,UTDEC,utcaltime

      integer*4 unitptr ! Pointer to udunits "unit" type

      character*100 timeunit
                        ! The unit attribute for time in the netCDF file
      real*8 intime,xx  ! The input time value and var to work with it
      integer oyear,omonth,oday,ohour
                        ! The output year,month,day and hour
      integer tmin      ! Temporary storage for minutes value
      real    tsec      ! Temporary storage for seconds value
      integer ercode    ! For determining udunits result

      unitptr = UTMAKE()
      ercode = UTDEC(timeunit(1:nblen(timeunit)),unitptr)
      if (ercode.ne.0) then

C        Assume old CDC standard if time unit is unknown

         if (ercode.eq.UT_EUNKNOWN.and.(timeunit(1:1).eq.'y'.or.
     &          timeunit(1:1).eq.'Y')) then
            xx=0.
            oyear=int(intime/10000000000.d0)
            xx=oyear*10000000000.d0
            omonth=int((intime-xx)/100000000.d0)
            xx=xx+omonth*100000000.
            oday=int((intime-xx)/1000000.)
            xx=xx+oday*1000000.
            ohour=int((intime-xx)/10000.)
         else
            call uduerr(ercode,'UTDEC','')
            write(0,*) ''
            write(0,*) 'NOTE: You must call netop_init to use gridread,'
            write(0,*) '      gridreadx, dayread, and dayreadx'
            stop
         endif
      else
         ercode = UTCALTIME(intime,unitptr,oyear,omonth,oday,ohour,
     &                      tmin,tsec)
         if (ercode.ne.0) then
            call uduerr(ercode,'UTCALTIME','')
            stop
         endif
      endif

C     Free up the pointer
      call UTFREE(unitptr)

      return
      end
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C  This function is intended to handle all possible error conditions
C  for the Udunits package  (Version 1.7.1) from Unidata, it takes the
C  error code returned from a udunits function, the function name and
C  the filename the function was accessing (applicable only for utopen
C  function).  It prints an indication to the user of the error and
C  function in which it occurred.
C
C  Written by: Tom Baltzer of CDC  February 10, 1995
C
C  File:  uduerr.f  (To be added to netopen.subr.f)
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      subroutine uduerr(ercode, funcname, filename)

C STEP 1.
      include '/usr/local/udunits/include/udunits.inc'

      integer ercode            ! The Udunits Error number
      character* (*) funcname   ! Function name which returned error
      character* (*) filename   ! Name of file on which funct operates
      character*1024 path       ! Path to file on which funct really works

      if (filename.eq.'') then
         call getenv('UDUNITS_PATH',path)
         if (path.eq.'') then
            path = '/usr/local/udunits'
         endif
      else
         path = filename
      endif

      write(0,*) 'Error in udunits function: ',funcname
      if (ercode.eq.UT_ENOFILE) then
         write(0,*) 'File: ',path(1:nblen(path))
         write(0,*) 'Does not exist!'
      elseif (ercode.eq.UT_ESYNTAX) then
         write(0,*) 'A Udunits syntax error was detected'
         if (path.ne.'') then
            write(0,*) 'Possibly in the file: ',
     &                  path(1:nblen(path))
         endif
      elseif (ercode.eq.UT_EUNKNOWN) then
         write(0,*) 'Udunits unknown specification found'
         if (path.ne.'') then
            write(0,*) 'Possibly in the file: ',
     &                  path(1:nblen(path))
         endif
      elseif (ercode.eq.UT_EIO) then
         write(0,*) 'I/O Error detected'
         if (path.ne.'') then
            write(0,*) 'Possibly in the file: ',
     &                  path(1:nblen(path))
         endif
      elseif (ercode.eq.UT_EINVALID) then
         write(0,*) 'An invalid udunits structure was found'
         write(0,*) ' Note: probably a temporal struct'
      elseif (ercode.eq.UT_ENOINIT) then
         write(0,*) 'Udunits package has not been initialized'
      elseif (ercode.eq.UT_ECONVERT) then
         write(0,*) 'No conversion between the two units is possible'
      elseif (ercode.eq.UT_ENOROOM) then
         write(0,*) 'Not enough room in character string for conversion'
      elseif (ercode.eq.UT_EALLOC) then
         write(0,*) 'Memory allocation falure'
      else
         write(0,*) 'UTOPEN: Unknown error: ',ercode
      endif

      return
      end
      integer function nblen (string)
c
c     given a character string, nblen returns the length of the string
c     to the last non-blank character, presuming the string is left-
c     justified, i.e. if string = '   xs  j   ', nblen = 8.
c
c     called non-library routines: none
c     language: standard fortran 77
c
      integer ls,i
      character*(*) string, blank*1, null*1
      data blank /' '/
c
      null = char(0)
      nblen = 0
      ls = len(string)
      if (ls .eq. 0) return
      do 1 i = ls, 1, -1
         if (string(i:i) .ne. blank .and. string(i:i) .ne. null) go to 2
    1    continue
      return
    2 nblen = i
      return
      end
  • 2004 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: