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: