[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[netCDF #DXD-376053]: [netcdfgroup] Very strange problem with Fortran



Ian,

First, if you are willing to just use the default type-specific fill
value for a variable, it's not necessary to explicitly define the
_FillValue attribute, and not defining it makes sure it is of the
right type for the variable.  So you only need to define the
time:_FillValue attribute if you want to use a particular non-default
value for missing times.

Second, if time is supposed to be a coordinate variable, it should not
have missing values.  This is not a requirement enforced by the
library, just a "best practice", as listed here:

 
http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Coordinate%20Systems

 A coordinate variable is a one-dimensional variable with the same
 name as a dimension, which names the coordinate values of the
 dimension. It must not have any missing data (for example, no
 _FillValue or missing_value attributes) and must be strictly
 monotonic (values increasing or decreasing).

Third, I tried using NF_FILL_DOUBLE as a fill value for a time
coordinate associated with the unlimited dimension, and it worked
fine.  I've attached an example program, mostly generated by ncgen -f,
that demonstrates this.

Finally, in response to your last question, the fill value type has to
match the type of the variable that the fill value is associated with.
In your case that's the double precision time variable, not the
single-precision data variable, right?

I hope this helps.  I still haven't figure out why the error isn't
generated when the attribute is defined rather than when the data is
written, but I hope you can just delete the attribute definition for
the time _FillValue, since it shouldn't have such an attribute or the
default value is adequate.

--Russ

Russ Rew                                         UCAR Unidata Program
address@hidden                     http://www.unidata.ucar.edu



Ticket Details
===================
Ticket ID: DXD-376053
Department: Support netCDF
Priority: Normal
Status: Closed
      program fgennc
      include 'netcdf.inc'
* error status return
      integer  iret
* netCDF id
      integer  ncid
* dimension ids
      integer  lat_dim
      integer  lon_dim
      integer  time_dim
* dimension lengths
      integer  lat_len
      integer  lon_len
      integer  time_len
      parameter (lat_len = 2)
      parameter (lon_len = 3)
      parameter (time_len = NF_UNLIMITED)
* variable ids
      integer  lat_id
      integer  lon_id
      integer  time_id
      integer  rh_id
* rank (number of dimensions) for each variable
      integer  lat_rank
      integer  lon_rank
      integer  time_rank
      integer  rh_rank
      parameter (lat_rank = 1)
      parameter (lon_rank = 1)
      parameter (time_rank = 1)
      parameter (rh_rank = 3)
* variable shapes
      integer  lat_dims(lat_rank)
      integer  lon_dims(lon_rank)
      integer  time_dims(time_rank)
      integer  rh_dims(rh_rank)
* data variables
      real  lat(lat_len)
      real  lon(lon_len)
* attribute vectors
      double precision  doubleval(1)
* enter define mode
      iret = nf_create('ih.nc', NF_CLOBBER, ncid)
      call check_err(iret)
* define dimensions
      iret = nf_def_dim(ncid, 'lat', 2, lat_dim)
      call check_err(iret)
      iret = nf_def_dim(ncid, 'lon', 3, lon_dim)
      call check_err(iret)
      iret = nf_def_dim(ncid, 'time', NF_UNLIMITED, time_dim)
      call check_err(iret)
* define variables
      lat_dims(1) = lat_dim
      iret = nf_def_var(ncid, 'lat', NF_REAL, lat_rank, lat_dims, lat_id
     1)
      call check_err(iret)
      lon_dims(1) = lon_dim
      iret = nf_def_var(ncid, 'lon', NF_REAL, lon_rank, lon_dims, lon_id
     1)
      call check_err(iret)
      time_dims(1) = time_dim
      iret = nf_def_var(ncid, 'time', NF_DOUBLE, time_rank, time_dims, t
     1ime_id)
      call check_err(iret)
      rh_dims(3) = time_dim
      rh_dims(2) = lat_dim
      rh_dims(1) = lon_dim
      iret = nf_def_var(ncid, 'rh', NF_REAL, rh_rank, rh_dims, rh_id)
      call check_err(iret)
* assign attributes
      doubleval(1) = 0
*      iret = nf_put_att_double(ncid, time_id, '_FillValue', NF_DOUBLE, 1
*     1, doubleval)
      call check_err(iret)
*      print *, "about to define fill value attribute"
* This causes error later when time value written
*      iret = nf_put_att_real(ncid, time_id, '_FillValue', NF_REAL, 1
*     1, 0.0)
* This works OK
*      iret = nf_put_att_double(ncid, time_id, '_FillValue', NF_DOUBLE, 1
*     1, 0.0d0)
      iret = nf_put_att_double(ncid, time_id, '_FillValue', NF_DOUBLE, 1
     1, NF_FILL_DOUBLE)
      call check_err(iret)
* leave define mode
      iret = nf_enddef(ncid)
      call check_err(iret)
       
* Write record variables
      call writerecs(ncid,time_id,rh_id)
       
      iret = nf_close(ncid)
      call check_err(iret)
      end
       
      subroutine writerecs(ncid,time_id,rh_id)
       
* netCDF id
      integer  ncid
* variable ids
      integer  time_id
      integer  rh_id
       
      include 'netcdf.inc'
* error status return
      integer  iret
       
* netCDF dimension sizes for dimensions used with record variables
      integer  lat_len
      parameter (lat_len = 2)
      integer  lon_len
      parameter (lon_len = 3)
       
* rank (number of dimensions) for each variable
      integer  time_rank
      integer  rh_rank
      parameter (time_rank = 1)
      parameter (rh_rank = 3)
* starts and counts for array sections of record variables
      integer  time_start(time_rank), time_count(time_rank)
      integer  rh_start(rh_rank), rh_count(rh_rank)
       
* data variables
       
      integer  time_nr
      parameter (time_nr = 2)
      double precision  time(time_nr)
       
      integer  rh_nr
      parameter (rh_nr = 2)
      real  rh(lon_len, lat_len, rh_nr)
       
      data time /2., 3./
      data rh /4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15/
       
* store time
      time_start(1) = 1
      time_count(1) = time_nr
      iret = nf_put_vara_double(ncid, time_id, time_start, time_count, t
     1ime)
      call check_err(iret)
*      iret = nf_put_var1_double(ncid, time_id, 1, 2.0d0)
*      print *, "about to put time value 1"
*      iret = nf_put_var1_double(ncid, time_id, 1, time(1))
*      print *, "iret = ", iret
*      call check_err(iret)
*      print *, "about to put time value 2"
*      iret = nf_put_var1_double(ncid, time_id, 2, time(2))
*      print *, "iret = ", iret
*      call check_err(iret)
* store rh
      rh_start(1) = 1
      rh_start(2) = 1
      rh_start(3) = 1
      rh_count(1) = lon_len
      rh_count(2) = lat_len
      rh_count(3) = rh_nr
      iret = nf_put_vara_real(ncid, rh_id, rh_start, rh_count, rh)
      call check_err(iret)
       
      end
       
      subroutine check_err(iret)
      integer iret
      include 'netcdf.inc'
      if (iret .ne. NF_NOERR) then
      print *, nf_strerror(iret)
      stop
      endif
      end