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.
>From: Jiye Zeng <address@hidden> >Organization: Center For Global Environmental Research, Japan >Keywords: 200502021439.j12Edlsi019750 netCDF C example Jiya, > I tried nc_put_vara_xxx(...) function, but I still missed something. When the > time > dimension and variable are created like > > nc_def_dim(ncid, "time", NC_UNLIMITED, &varid); > nc_def_var(ncid, "time", nctype, 1, time_dimid, &varid); > > The dimemsion of time is zero. I am not able to write to time(time) variable > or P(time, > lat, lon). For example > > static int P_start[] = {0, 0, 0}; > static int P_edges[] = {1, nlat, nlon}; > status = nc_put_vara_xxx(ncid, P_id, P_start, P_edges, P); > > does not work. That should work fine. Are you calling nc_close(ncid) before exiting the program, to make sure the buffers get flushed and the in-memory metadata, such as number of records, is synchronized to disk? If your program calls nc_close() after the above call and you look at the resulting file with something like "ncdump -h", it should show that one record was written, because the time dimension will appear like: time = UNLIMITED ; // (1 currently) > My question is how to extend the time? > > Could you give me a rather complete example? (Without any attribute IO is OK). Sure, and I'll also tell you how to generate your own example with the "ncgen" program. Just create a small text CDL file, say "example.cdl", for some data you want to write, for example here is one, with a few attributes: //----------------------- example.cdl -------------------- netcdf example { // A small example netCDF file dimensions: lat = 2, lon = 3, time = unlimited; variables: float P(time, lat, lon); P:long_name = "pressure"; P:units = "hectopascals"; float lat(lat); lat:long_name = "latitude"; lat:units = "degrees_north"; float lon(lon); lon:long_name = "longitude"; lon:units = "degrees_east"; float time(time); time:units = "hours since 1992-1-1"; data: P = 1000, 1001, 1002, 1003, 1004, 1005, 1010, 1011, 1012, 1013, 1014, 1015; } //----------------------- end of example.cdl -------------- Then to generate a C program that will create the corresponding netCDF file, invoke ncgen with the "-c" option to tell it that you want to generate C output: ncgen -c example.cdl > example.c Now the C program, which I've attached, can be compiled and linked with the netCDF library, and when run, it should produce the netCDF file corresponding to the CDL above. The part that writes the first two records looks like this: static size_t P_start[RANK_P]; static size_t P_count[RANK_P]; static float P[] = {1000, 1001, 1002, 1003, 1004, 1005, 1010, 1011, 1012, 1013, 1014, 1015}; time_len = 2; /* number of records of P data */ P_start[0] = 0; P_start[1] = 0; P_start[2] = 0; P_count[0] = time_len; P_count[1] = lat_len; P_count[2] = lon_len; stat = nc_put_vara_float(ncid, P_id, P_start, P_count, P); and if you only wanted to store 1 record, all that would change is setting P_count[0] to 1 instead of 2. By the way, you don't have to write the records in order; fill values are provided for unwritten data. > By the way, it seems that global attributes must be created right after a > file creation. Is > that true? No, you can later enter define mode and define new attributes, but this may cause the whole file to be rewritten if there was not enough space in the "file header" to store the new attributes. It's possible to allocate extra space in the file header when you create the file to prevent the expense of later copying it when you add new attributes, using the nc__enddef() function: http://www.unidata.ucar.edu/packages/netcdf/docs/netcdf-c/nc_005f_005fenddef.ht ml#nc_005f_005fenddef But that's advanced usage for large files. For small files, you probably don't need to worry about it. --Russ
#include <stdio.h> #include <stdlib.h> #include <netcdf.h> void check_err(const int stat, const int line, const char *file) { if (stat != NC_NOERR) { (void) fprintf(stderr, "line %d of %s: %s\n", line, file, nc_strerror(stat)); exit(1); } } int main() { /* create example.nc */ int stat; /* return status */ int ncid; /* netCDF id */ /* dimension ids */ int lat_dim; int lon_dim; int time_dim; /* dimension lengths */ size_t lat_len = 2; size_t lon_len = 3; size_t time_len = NC_UNLIMITED; /* variable ids */ int P_id; int lat_id; int lon_id; int time_id; /* rank (number of dimensions) for each variable */ # define RANK_P 3 # define RANK_lat 1 # define RANK_lon 1 # define RANK_time 1 /* variable shapes */ int P_dims[RANK_P]; int lat_dims[RANK_lat]; int lon_dims[RANK_lon]; int time_dims[RANK_time]; /* enter define mode */ stat = nc_create("example.nc", NC_CLOBBER, &ncid); check_err(stat,__LINE__,__FILE__); /* define dimensions */ stat = nc_def_dim(ncid, "lat", lat_len, &lat_dim); check_err(stat,__LINE__,__FILE__); stat = nc_def_dim(ncid, "lon", lon_len, &lon_dim); check_err(stat,__LINE__,__FILE__); stat = nc_def_dim(ncid, "time", time_len, &time_dim); check_err(stat,__LINE__,__FILE__); /* define variables */ P_dims[0] = time_dim; P_dims[1] = lat_dim; P_dims[2] = lon_dim; stat = nc_def_var(ncid, "P", NC_FLOAT, RANK_P, P_dims, &P_id); check_err(stat,__LINE__,__FILE__); lat_dims[0] = lat_dim; stat = nc_def_var(ncid, "lat", NC_FLOAT, RANK_lat, lat_dims, &lat_id); check_err(stat,__LINE__,__FILE__); lon_dims[0] = lon_dim; stat = nc_def_var(ncid, "lon", NC_FLOAT, RANK_lon, lon_dims, &lon_id); check_err(stat,__LINE__,__FILE__); time_dims[0] = time_dim; stat = nc_def_var(ncid, "time", NC_FLOAT, RANK_time, time_dims, &time_id); check_err(stat,__LINE__,__FILE__); /* assign attributes */ stat = nc_put_att_text(ncid, P_id, "long_name", 8, "pressure"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, P_id, "units", 12, "hectopascals"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, lat_id, "long_name", 8, "latitude"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, lat_id, "units", 13, "degrees_north"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, lon_id, "long_name", 9, "longitude"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, lon_id, "units", 12, "degrees_east"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, time_id, "units", 20, "hours since 1992-1-1"); check_err(stat,__LINE__,__FILE__); /* leave define mode */ stat = nc_enddef (ncid); check_err(stat,__LINE__,__FILE__); { /* store P */ static size_t P_start[RANK_P]; static size_t P_count[RANK_P]; static float P[] = {1000, 1001, 1002, 1003, 1004, 1005, 1010, 1011, 1012, 1013, 1014, 1015}; time_len = 2; /* number of records of P data */ P_start[0] = 0; P_start[1] = 0; P_start[2] = 0; P_count[0] = time_len; P_count[1] = lat_len; P_count[2] = lon_len; stat = nc_put_vara_float(ncid, P_id, P_start, P_count, P); check_err(stat,__LINE__,__FILE__); } stat = nc_close(ncid); check_err(stat,__LINE__,__FILE__); return 0; }