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


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed