NetCDF  4.9.2
pres_temp_4D_wr.c
Go to the documentation of this file.
1 /* Copyright 2019 University Corporation for Atmospheric
2  Research/Unidata. See COPYRIGHT file for conditions of use. */
16 #include <stdio.h>
17 #include <string.h>
18 #include <netcdf.h>
19 
20 /* This is the name of the data file we will create. */
21 #define FILE_NAME "pres_temp_4D.nc"
22 
23 /* We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
24  timesteps of data. */
25 #define NDIMS 4
26 #define NLAT 6
27 #define NLON 12
28 #define LAT_NAME "latitude"
29 #define LON_NAME "longitude"
30 #define NREC 2
31 #define REC_NAME "time"
32 #define LVL_NAME "level"
33 #define NLVL 2
34 
35 /* Names of things. */
36 #define PRES_NAME "pressure"
37 #define TEMP_NAME "temperature"
38 #define UNITS "units"
39 #define DEGREES_EAST "degrees_east"
40 #define DEGREES_NORTH "degrees_north"
41 
42 /* These are used to construct some example data. */
43 #define SAMPLE_PRESSURE 900
44 #define SAMPLE_TEMP 9.0
45 #define START_LAT 25.0
46 #define START_LON -125.0
47 
48 /* For the units attributes. */
49 #define UNITS "units"
50 #define PRES_UNITS "hPa"
51 #define TEMP_UNITS "celsius"
52 #define LAT_UNITS "degrees_north"
53 #define LON_UNITS "degrees_east"
54 #define MAX_ATT_LEN 80
55 
56 /* Handle errors by printing an error message and exiting with a
57  * non-zero status. */
58 #define ERR(e) {printf("Error: %s\n", nc_strerror(e)); return 2;}
59 
60 int
61 main()
62 {
63  /* IDs for the netCDF file, dimensions, and variables. */
64  int ncid, lon_dimid, lat_dimid, lvl_dimid, rec_dimid;
65  int lat_varid, lon_varid, pres_varid, temp_varid;
66  int dimids[NDIMS];
67 
68  /* The start and count arrays will tell the netCDF library where to
69  write our data. */
70  size_t start[NDIMS], count[NDIMS];
71 
72  /* Program variables to hold the data we will write out. We will only
73  need enough space to hold one timestep of data; one record. */
74  float pres_out[NLVL][NLAT][NLON];
75  float temp_out[NLVL][NLAT][NLON];
76 
77  /* These program variables hold the latitudes and longitudes. */
78  float lats[NLAT], lons[NLON];
79 
80  /* Loop indexes. */
81  int lvl, lat, lon, rec, i = 0;
82 
83  /* Error handling. */
84  int retval;
85 
86  /* Create some pretend data. If this wasn't an example program, we
87  * would have some real data to write, for example, model
88  * output. */
89  for (lat = 0; lat < NLAT; lat++)
90  lats[lat] = START_LAT + 5.*lat;
91  for (lon = 0; lon < NLON; lon++)
92  lons[lon] = START_LON + 5.*lon;
93 
94  for (lvl = 0; lvl < NLVL; lvl++)
95  for (lat = 0; lat < NLAT; lat++)
96  for (lon = 0; lon < NLON; lon++)
97  {
98  pres_out[lvl][lat][lon] = SAMPLE_PRESSURE + i;
99  temp_out[lvl][lat][lon] = SAMPLE_TEMP + i++;
100  }
101 
102  /* Create the file. */
103  if ((retval = nc_create(FILE_NAME, NC_CLOBBER, &ncid)))
104  ERR(retval);
105 
106  /* Define the dimensions. The record dimension is defined to have
107  * unlimited length - it can grow as needed. In this example it is
108  * the time dimension.*/
109  if ((retval = nc_def_dim(ncid, LVL_NAME, NLVL, &lvl_dimid)))
110  ERR(retval);
111  if ((retval = nc_def_dim(ncid, LAT_NAME, NLAT, &lat_dimid)))
112  ERR(retval);
113  if ((retval = nc_def_dim(ncid, LON_NAME, NLON, &lon_dimid)))
114  ERR(retval);
115  if ((retval = nc_def_dim(ncid, REC_NAME, NC_UNLIMITED, &rec_dimid)))
116  ERR(retval);
117 
118  /* Define the coordinate variables. We will only define coordinate
119  variables for lat and lon. Ordinarily we would need to provide
120  an array of dimension IDs for each variable's dimensions, but
121  since coordinate variables only have one dimension, we can
122  simply provide the address of that dimension ID (&lat_dimid) and
123  similarly for (&lon_dimid). */
124  if ((retval = nc_def_var(ncid, LAT_NAME, NC_FLOAT, 1, &lat_dimid,
125  &lat_varid)))
126  ERR(retval);
127  if ((retval = nc_def_var(ncid, LON_NAME, NC_FLOAT, 1, &lon_dimid,
128  &lon_varid)))
129  ERR(retval);
130 
131  /* Assign units attributes to coordinate variables. */
132  if ((retval = nc_put_att_text(ncid, lat_varid, UNITS,
133  strlen(DEGREES_NORTH), DEGREES_NORTH)))
134  ERR(retval);
135  if ((retval = nc_put_att_text(ncid, lon_varid, UNITS,
136  strlen(DEGREES_EAST), DEGREES_EAST)))
137  ERR(retval);
138 
139  /* The dimids array is used to pass the dimids of the dimensions of
140  the netCDF variables. Both of the netCDF variables we are
141  creating share the same four dimensions. In C, the
142  unlimited dimension must come first on the list of dimids. */
143  dimids[0] = rec_dimid;
144  dimids[1] = lvl_dimid;
145  dimids[2] = lat_dimid;
146  dimids[3] = lon_dimid;
147 
148  /* Define the netCDF variables for the pressure and temperature
149  * data. */
150  if ((retval = nc_def_var(ncid, PRES_NAME, NC_FLOAT, NDIMS,
151  dimids, &pres_varid)))
152  ERR(retval);
153  if ((retval = nc_def_var(ncid, TEMP_NAME, NC_FLOAT, NDIMS,
154  dimids, &temp_varid)))
155  ERR(retval);
156 
157  /* Assign units attributes to the netCDF variables. */
158  if ((retval = nc_put_att_text(ncid, pres_varid, UNITS,
159  strlen(PRES_UNITS), PRES_UNITS)))
160  ERR(retval);
161  if ((retval = nc_put_att_text(ncid, temp_varid, UNITS,
162  strlen(TEMP_UNITS), TEMP_UNITS)))
163  ERR(retval);
164 
165  /* End define mode. */
166  if ((retval = nc_enddef(ncid)))
167  ERR(retval);
168 
169  /* Write the coordinate variable data. This will put the latitudes
170  and longitudes of our data grid into the netCDF file. */
171  if ((retval = nc_put_var_float(ncid, lat_varid, &lats[0])))
172  ERR(retval);
173  if ((retval = nc_put_var_float(ncid, lon_varid, &lons[0])))
174  ERR(retval);
175 
176  /* These settings tell netcdf to write one timestep of data. (The
177  setting of start[0] inside the loop below tells netCDF which
178  timestep to write.) */
179  count[0] = 1;
180  count[1] = NLVL;
181  count[2] = NLAT;
182  count[3] = NLON;
183  start[1] = 0;
184  start[2] = 0;
185  start[3] = 0;
186 
187  /* Write the pretend data. This will write our surface pressure and
188  surface temperature data. The arrays only hold one timestep worth
189  of data. We will just rewrite the same data for each timestep. In
190  a real application, the data would change between timesteps. */
191  for (rec = 0; rec < NREC; rec++)
192  {
193  start[0] = rec;
194  if ((retval = nc_put_vara_float(ncid, pres_varid, start, count,
195  &pres_out[0][0][0])))
196  ERR(retval);
197  if ((retval = nc_put_vara_float(ncid, temp_varid, start, count,
198  &temp_out[0][0][0])))
199  ERR(retval);
200  }
201 
202  /* Close the file. */
203  if ((retval = nc_close(ncid)))
204  ERR(retval);
205 
206  printf("*** SUCCESS writing example file %s!\n", FILE_NAME);
207  return 0;
208 }
EXTERNL int nc_put_att_text(int ncid, int varid, const char *name, size_t len, const char *op)
Write a text attribute.
Definition: dattput.c:153
EXTERNL int nc_close(int ncid)
Close an open netCDF dataset.
Definition: dfile.c:1302
EXTERNL int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
Definition: dfile.c:400
EXTERNL int nc_enddef(int ncid)
Leave define mode.
Definition: dfile.c:1029
EXTERNL int nc_def_dim(int ncid, const char *name, size_t len, int *idp)
Define a new dimension.
Definition: ddim.c:121
int nc_put_vara_float(int ncid, int varid, const size_t *startp, const size_t *countp, const float *op)
Write an array of values to a variable.
Definition: dvarput.c:692
int nc_put_var_float(int ncid, int varid, const float *op)
Write an entire variable with one call.
Definition: dvarput.c:962
EXTERNL int nc_def_var(int ncid, const char *name, nc_type xtype, int ndims, const int *dimidsp, int *varidp)
Define a new variable.
Definition: dvar.c:214
Main header file for the C API.
#define NC_UNLIMITED
Size argument to nc_def_dim() for an unlimited dimension.
Definition: netcdf.h:251
#define NC_CLOBBER
Destroy existing file.
Definition: netcdf.h:129
#define NC_FLOAT
single precision floating point number
Definition: netcdf.h:40