alex-robinson / ncio

Simple Fortran interface to NetCDF reading and writing.
23 stars 9 forks source link

Writing plain integer yields an error #16

Closed dmr-dj closed 5 months ago

dmr-dj commented 8 months ago

I was trying to write a plain integer (one value) into a netCDF file. Using nc_write. According to the API:

filename        name of the NetCDF file in which to write data
name            name of the variable in NetCDF file to be written
dat             Fortran data type of data to be written
dims            vector of dimension names of the variable in NetCDF file (optional)
dim1,...,dim6   individual dimension names of the variable in NetCDF file (optional)
start           vector of values specifying starting indices for reading data from each dimension (optional)
count           vector of values specifying how many values to read in each dimension (optional)
long_name       NetCDF attribute, a long descriptive name of variable (optional)
standard_name   NetCDF attribute specifying the CF convention standard name of the variable (optional)
grid_mapping    name of the grid this variable is mapped on (optional)
units           NetCDF attribute of the units of the variable (optional)
missing_value   Value of missing data to be written to file (optional)
ncid            File ID for a file that remains open for various NCIO calls (optional) 

... the only thing to provide are the first three arguments.

Thus using the simplest test possible:

program test
   use ncio

   call nc_create("test.nc",overwrite=.true.,netcdf4=.true.)
   call nc_write("test.nc","int_var",1)

end program test

But this example compiles fine but do not run, error message is:

ncio:: nc_create   :: test.nc
 ncio:: error: NetCDF: Invalid dimension ID or name
STOP stopped by ncio.

Within the module it should be caught by nc_write_int_pt that calls nc4_write_internal, but I could not find the case where ndims=0 in the latter. I guess it defaults to ndims=1 and then crashes since none exist/specified.

alex-robinson commented 8 months ago

Yes, I see the test case would give an error because the dimension of the integer variable must be defined first with a call to nc_write_dim, and then that dimension should be used with the nc_write of the integer itself. For example, this would look something like this:

program test
   use ncio

   call nc_create("test.nc",overwrite=.true.,netcdf4=.true.)
   call nc_write_dim("test.nc","point",x=1,units="-")
   call nc_write("test.nc","int_var",1,dim1="point")

end program test

It does seem a bit like overkill to have to write a dimension for an integer variable of length 1, but this is required by NetCDF.

So, is the issue though, that a better error message should be provided in this case? Or do you think some functionality could be improved?

dmr-dj commented 8 months ago

I am not sure that netCDF do need a dimension for this. If you look at what ncio does for the "crs" variable, it indeed writes a integer without an axis associated:

call nc_check( nf90_def_var(nc_id, trim(crs_name), NF90_INT, varid) )

I guess one option would be to add a special case when dims = 0 and process it in a similar fashion as above ... or am I missing something?

dmr-dj commented 8 months ago

(or at least it defines a variable without an axis, more properly said)

alex-robinson commented 5 months ago

Ok, I have made some changes within the code, and now it looks like your test works. I have also made a new test program from your code just to check:

make nodim
./test_nodim.x

I think it works as expected. Please let me know if you encounter any trouble, and thanks for the suggestion!