This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
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