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.
>To: address@hidden >cc: address@hidden >From: David Han <address@hidden> >Subject: Need Help with Compilation >Organization: NASA/GSFC >Keywords: 200209091724.g89HOSj19603 Hi David, > Below is my test program which has a compilation problem on the following > line: > > status = nc_put_var_double(ncid, my3d_id, my3d_data); > > Can you tell me why this is a problem? Thanks for your help. [Note added later: parts of this answer are wrong. These are marked with the tags <WRONG> ... </WRONG> below. A more detailed explanation appears at the end of the reply.] Yes, there are two problems with the above statement: first you need to give the address of the first element of the array instead of the name of the array <WRONG>(in C these are not the same for multidimensional arrays with more than 1 dimension)</WRONG> and second you are writing a record variable, so you need to use the interface that lets you specify how many records to write. Just fixing the first problem would change the statement to the following: status = nc_put_var_double(ncid, my3d_id, &my3d_data[0][0][0]); That will compile without error, but it won't work as you intend, because the nc_put_var_double() interface is for writing a whole array at once, where the size of the array is determined by how large it is in the netCDF file on disk. Since this is a record variable (uses the NC_UNLIMITED dimension) and there are no records on disk yet, the size of the array on disk is 0x5x10, so no data will be written. You need to use the interface that permits you to say how many records will be written. If you want to write 3 records at once, you would use the nc_put_vara_double interface: http://www.unidata.ucar.edu/packages/netcdf/guidec/guidec-12.html#HEADING12-480 providing a start array specifying the starting indices and a count array specifying how far along each dimension you want to write: static size_t start[] = {0, 0, 0}; static size_t count[] = {TIMES, LATS, LONS}; ... status = nc_put_vara_double(ncid, rh_id, start, count, &my3d_data[0][0][0]); > It seems that the only way to make a scalar variable is to create a > 1-D variable with one element in it. Is this correct? No, you make a scalar variable by specifying a rank of 0 when you create it. That's not the same as a 1-D variable with 1 element (which has a rank of 1). For example, here's code to create a scalar variable: int scalar_id; ... status = nc_def_var(ncid, "scalar", NC_DOUBLE, 0, 0, &scalar_id); > David > ----------------------------------------------------------------- > > #include <stdio.h> > #include "netcdf.h" > > #define TIMES 3 > #define LATS 5 > #define LONS 10 > > void handle_error(int); > > main () > { > int status, i, j, k, ncid, rhid, tempid, my3d_id; > int lat_dim, lon_dim, time_dim, scalar_dim; > int rh_dimids[3]; > double rh_val; > double my3d_data[TIMES][LATS][LONS]; > size_t rh_index[] = {1, 0, 0}; > double rh_data[TIMES*LATS*LONS]; > > status = nc_create("test.nc", NC_NOCLOBBER, &ncid); > if (status != NC_NOERR) handle_error(status); > > status = nc_def_dim(ncid, "scalar", 1L, &scalar_dim); > if (status != NC_NOERR) handle_error(status); > > status = nc_def_dim(ncid, "lat", 5L, &lat_dim); > if (status != NC_NOERR) handle_error(status); > > status = nc_def_dim(ncid, "lon", 10L, &lon_dim); > if (status != NC_NOERR) handle_error(status); > > status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim); > if (status != NC_NOERR) handle_error(status); > > rh_dimids[0] = time_dim; > rh_dimids[1] = lat_dim; > rh_dimids[2] = lon_dim; > status = nc_def_var(ncid, "my3d", NC_DOUBLE, 3, rh_dimids, &my3d_id); > if (status != NC_NOERR) handle_error(status); > > status = nc_enddef(ncid); > if (status != NC_NOERR) handle_error(status); > > rh_val = 0.5; > > for (i=0; i < TIMES; i++) > for (j=0; j < LATS; j++) > for (k=0; k < LONS; k++) { > my3d_data[i][j][k] = rh_val; > rh_val += 0.5; > } > > status = nc_put_var_double(ncid, my3d_id, my3d_data); > if (status != NC_NOERR) handle_error(status); > > status = nc_close(ncid); > if (status != NC_NOERR) handle_error(status); > } > > void handle_error(int status) { > fprintf(stderr, "%s\n", nc_strerror(status)); > } [Note about wrong part of answer above: while it's true for dynamically allocated multidimensional arrays that "my3d_data" is not the same as "&my3d_data[0][0][0]", these actually are the same for statically allocated multidimensional arrays, as my3d_data is declared to be in the example above.]