1 /* This is part of the netCDF package. Copyright 2009 University
2    Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
3    conditions of use.
4 
5    Test netcdf-4 coordinate variables and dimensions.
6 
7    $Id: tst_coords.c,v 1.20 2010/03/30 16:25:41 ed Exp $
8 */
9 
10 #include <nc_tests.h>
11 #include "err_macros.h"
12 #include "netcdf.h"
13 
14 #define FILE_NAME "tst_coords.nc"
15 
16 void
check_err(const int stat,const int line,const char * file)17 check_err(const int stat, const int line, const char *file) {
18     if (stat != NC_NOERR) {
19         (void)fprintf(stderr,"line %d of %s: %s\n", line, file, nc_strerror(stat));
20         fflush(stderr);
21         exit(1);
22     }
23 }
24 
25 #define INST_NAME "institution"
26 #define INSTITUTION "NCAR (National Center for Atmospheric \nResearch, Boulder, CO, USA)"
27 
28 int
main(int argc,char ** argv)29 main(int argc, char **argv)
30 {
31    printf("\n*** Testing netcdf-4 coordinate variables and dimensions.\n");
32 
33    printf("**** testing Jeff Whitakers reported 4.1 bug...");
34    {
35 #define NDIMS 2
36 #define NLAT 10
37 #define NLON 20
38 #define LAT_NAME "lat"
39 #define LON_NAME "lon"
40 #define NVARS 2
41 #define START_LAT 25.0
42 #define START_LON -125.0
43       {
44 	 int ncid, lon_dimid, lat_dimid;
45 	 int lat_varid, lon_varid;
46 	 float lats[NLAT], lons[NLON];
47 	 int lat, lon;
48 	 int nvars, ndims, ngatts, unlimdimid, nvars_in, varids_in[NVARS];
49 	 int ndims_in, natts_in, dimids_in[NDIMS];
50 	 char var_name_in[NC_MAX_NAME + 1];
51 	 nc_type xtype_in;
52 
53 	 /* Initialize coord data. */
54 	 for (lat = 0; lat < NLAT; lat++)
55 	    lats[lat] = START_LAT + 5. * lat;
56 	 for (lon = 0; lon < NLON; lon++)
57 	    lons[lon] = START_LON + 5. * lon;
58 
59 	 /* Create file with two dimensions. */
60 	 if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
61 	 if (nc_def_dim(ncid, LAT_NAME, NLAT, &lat_dimid)) ERR;
62 	 if (nc_def_dim(ncid, LON_NAME, NLON, &lon_dimid)) ERR;
63 
64 	 if (nc_def_var(ncid, LON_NAME, NC_FLOAT, 1, &lon_dimid, &lon_varid)) ERR;
65 
66 	 /* Define and write longitude coord variable. */
67 	 if (nc_put_var_float(ncid, lon_varid, &lons[0])) ERR;
68 
69 	 /* Define and write latitude coord variable. */
70 	 if (nc_def_var(ncid, LAT_NAME, NC_FLOAT, 1, &lat_dimid, &lat_varid)) ERR;
71 	 if (nc_put_var_float(ncid, lat_varid, &lats[0])) ERR;
72 
73 	 if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
74 	 if (nvars != 2 || ndims != 2 || ngatts != 0 || unlimdimid != -1) ERR;
75 	 if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
76 	 if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
77 	 if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
78 	 if (strcmp(var_name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
79 	     dimids_in[0] != 1 || natts_in != 0) ERR;
80 
81 	 /* Close the file. */
82 	 if (nc_close(ncid)) ERR;
83 
84 	 /* Re-open and check the file. */
85 	 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
86 
87 	 if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
88 	 if (nvars != 2 || ndims != 2 || ngatts != 0 || unlimdimid != -1) ERR;
89 	 if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
90 	 if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
91 	 if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
92 	 if (strcmp(var_name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
93 	 dimids_in[0] != 1 || natts_in != 0) ERR;
94 
95 	 if (nc_close(ncid)) ERR;
96       }
97 
98    }
99    SUMMARIZE_ERR;
100    printf("**** testing setting cache values for coordinate variables...");
101    {
102 #define RANK_1 1
103 #define DIM0_NAME "d0"
104 #define CACHE_SIZE 1000000
105 #define CACHE_NELEMS 1009
106 #define CACHE_PREEMPTION .90
107 
108       int ncid, dimid, varid;
109       char name_in[NC_MAX_NAME + 1];
110 
111       /* Create a test file with one dim and coord variable. */
112       if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
113       if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR;
114       if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR;
115       if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
116       if (nc_close(ncid)) ERR;
117 
118       /* Reopen the file and check. */
119       if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
120       if (nc_inq_varname(ncid, 0, name_in)) ERR;
121       if (strcmp(name_in, DIM0_NAME)) ERR;
122       if (nc_set_var_chunk_cache(ncid, 0, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
123       if (nc_inq_dimname(ncid, 0, name_in)) ERR;
124       if (strcmp(name_in, DIM0_NAME)) ERR;
125       if (nc_close(ncid)) ERR;
126    }
127    SUMMARIZE_ERR;
128    printf("**** testing multi-line strings in attributes...");
129    {
130       int ncid_classic, ncid_nc4;
131       /*int attid;*/
132       char att_in_classic[NC_MAX_NAME + 1], att_in_nc4[NC_MAX_NAME + 1];
133 
134 #define FILE_CLASSIC "tst_coords_classic_att.nc"
135 #define FILE_NC4 "tst_coords_nc4_att.nc"
136       /* Create a classic and a netcdf-4 file. */
137       if (nc_create(FILE_CLASSIC, 0, &ncid_classic)) ERR;
138       if (nc_create(FILE_NC4, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid_nc4)) ERR;
139 
140       /* Write an att to both. */
141       if (nc_put_att_text(ncid_classic, NC_GLOBAL, INST_NAME, strlen(INSTITUTION) + 1, INSTITUTION)) ERR;
142       if (nc_put_att_text(ncid_nc4, NC_GLOBAL, INST_NAME, strlen(INSTITUTION) + 1, INSTITUTION)) ERR;
143 
144       /* Close them. */
145       if (nc_close(ncid_classic)) ERR;
146       if (nc_close(ncid_nc4)) ERR;
147 
148       /* Reopen the files. */
149       if (nc_open(FILE_CLASSIC, 0, &ncid_classic)) ERR;
150       if (nc_open(FILE_NC4, 0, &ncid_nc4)) ERR;
151 
152       /* I'll show you mine, if you show me yours... */
153       if (nc_get_att_text(ncid_classic, NC_GLOBAL, INST_NAME, att_in_classic)) ERR;
154       if (nc_get_att_text(ncid_nc4, NC_GLOBAL, INST_NAME, att_in_nc4)) ERR;
155       if (strcmp(att_in_classic, INSTITUTION) || strcmp(att_in_nc4, INSTITUTION) ||
156 	  strcmp(att_in_classic, att_in_nc4)) ERR;
157       if (memcmp(att_in_classic, att_in_nc4, strlen(INSTITUTION) + 1)) ERR;
158 
159       /* Close them. */
160       if (nc_close(ncid_classic)) ERR;
161       if (nc_close(ncid_nc4)) ERR;
162    }
163    SUMMARIZE_ERR;
164    printf("**** testing ar-4 example metadata with ncgen-generated code...");
165    {
166       int  stat;  /* return status */
167       int  ncid;  /* netCDF id */
168 
169       /* group ids */
170       int root_grp;
171 
172       /* dimension ids */
173       int lon_dim;
174       int lat_dim;
175       int bnds_dim;
176       int time_dim;
177 
178       /* dimension lengths */
179       size_t lon_len = 256;
180       size_t lat_len = 128;
181       size_t bnds_len = 2;
182       size_t time_len = NC_UNLIMITED;
183 
184       /* variable ids */
185       int lon_bnds_id;
186       int lat_bnds_id;
187       int time_bnds_id;
188       int time_id;
189       int lat_id;
190       int lon_id;
191       int pr_id;
192 
193       /* rank (number of dimensions) for each variable */
194 #   define RANK_lon_bnds 2
195 #   define RANK_lat_bnds 2
196 #   define RANK_time_bnds 2
197 #   define RANK_time 1
198 #   define RANK_lat 1
199 #   define RANK_lon 1
200 #   define RANK_pr 3
201 
202       /* variable shapes */
203       int lon_bnds_dims[RANK_lon_bnds];
204       int lat_bnds_dims[RANK_lat_bnds];
205       int time_bnds_dims[RANK_time_bnds];
206       int time_dims[RANK_time];
207       int lat_dims[RANK_lat];
208       int lon_dims[RANK_lon];
209       int pr_dims[RANK_pr];
210 
211       /* enter define mode */
212       stat = nc_create(FILE_NAME, NC_NETCDF4 | NC_CLASSIC_MODEL, &ncid);
213       check_err(stat,__LINE__,__FILE__);
214       root_grp = ncid;
215 
216       /* define dimensions */
217       stat = nc_def_dim(root_grp, "lon", lon_len, &lon_dim);
218       check_err(stat,__LINE__,__FILE__);
219       stat = nc_def_dim(root_grp, "lat", lat_len, &lat_dim);
220       check_err(stat,__LINE__,__FILE__);
221       stat = nc_def_dim(root_grp, "bnds", bnds_len, &bnds_dim);
222       check_err(stat,__LINE__,__FILE__);
223       stat = nc_def_dim(root_grp, "time", time_len, &time_dim);
224       check_err(stat,__LINE__,__FILE__);
225 
226       /* define variables */
227 
228       lon_bnds_dims[0] = lon_dim;
229       lon_bnds_dims[1] = bnds_dim;
230       stat = nc_def_var(root_grp, "lon_bnds", NC_DOUBLE, RANK_lon_bnds, lon_bnds_dims, &lon_bnds_id);
231       check_err(stat,__LINE__,__FILE__);
232 
233       lat_bnds_dims[0] = lat_dim;
234       lat_bnds_dims[1] = bnds_dim;
235       stat = nc_def_var(root_grp, "lat_bnds", NC_DOUBLE, RANK_lat_bnds, lat_bnds_dims, &lat_bnds_id);
236       check_err(stat,__LINE__,__FILE__);
237 
238       time_bnds_dims[0] = time_dim;
239       time_bnds_dims[1] = bnds_dim;
240       stat = nc_def_var(root_grp, "time_bnds", NC_DOUBLE, RANK_time_bnds, time_bnds_dims, &time_bnds_id);
241       check_err(stat,__LINE__,__FILE__);
242 
243       time_dims[0] = time_dim;
244       stat = nc_def_var(root_grp, "time", NC_DOUBLE, RANK_time, time_dims, &time_id);
245       check_err(stat,__LINE__,__FILE__);
246 
247       lat_dims[0] = lat_dim;
248       stat = nc_def_var(root_grp, "lat", NC_DOUBLE, RANK_lat, lat_dims, &lat_id);
249       check_err(stat,__LINE__,__FILE__);
250 
251       lon_dims[0] = lon_dim;
252       stat = nc_def_var(root_grp, "lon", NC_DOUBLE, RANK_lon, lon_dims, &lon_id);
253       check_err(stat,__LINE__,__FILE__);
254 
255       pr_dims[0] = time_dim;
256       pr_dims[1] = lat_dim;
257       pr_dims[2] = lon_dim;
258       stat = nc_def_var(root_grp, "pr", NC_FLOAT, RANK_pr, pr_dims, &pr_id);
259       check_err(stat,__LINE__,__FILE__);
260 
261       /* assign global attributes */
262       { /* table_id */
263 	 static const char table_id_att[8] = {"Table A1"} ;
264 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "table_id", 8, table_id_att);
265 	 check_err(stat,__LINE__,__FILE__);
266       }
267       { /* title */
268 	 static const char title_att[34] = {"model output prepared for IPCC AR4"} ;
269 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "title", 34, title_att);
270 	 check_err(stat,__LINE__,__FILE__);
271       }
272       { /* institution */
273 	 static const char institution_att[66] = {INSTITUTION} ;
274 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, INST_NAME, 66, institution_att);
275 	 check_err(stat,__LINE__,__FILE__);
276       }
277       { /* source */
278 	 static const char source_att[153] = {"CCSM3.0, version vector05 (2004): \natmosphere: CAM3.0, T85L26;\nocean     : POP1.4.3 (modified), gx1v3\nsea ice   : CSIM5.0, gx1v3;\nland      : CLM3.0, T85"} ;
279 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "source", 153, source_att);
280 	 check_err(stat,__LINE__,__FILE__);
281       }
282       { /* contact */
283 	 static const char contact_att[13] = {"ccsm@ucar.edu"} ;
284 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "contact", 13, contact_att);
285 	 check_err(stat,__LINE__,__FILE__);
286       }
287       { /* project_id */
288 	 static const char project_id_att[22] = {"IPCC Fourth Assessment"} ;
289 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "project_id", 22, project_id_att);
290 	 check_err(stat,__LINE__,__FILE__);
291       }
292       { /* Conventions */
293 	 static const char Conventions_att[6] = {"CF-1.0"} ;
294 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "Conventions", 6, Conventions_att);
295 	 check_err(stat,__LINE__,__FILE__);
296       }
297       { /* references */
298 	 static const char references_att[137] = {"Collins, W.D., et al., 2005:\n The Community Climate System Model, Version 3\n Journal of Climate\n \n Main website: http://www.ccsm.ucar.edu"} ;
299 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "references", 137, references_att);
300 	 check_err(stat,__LINE__,__FILE__);
301       }
302       { /* acknowledgment */
303 	 static const char acknowledgment_att[847] = {" Any use of CCSM data should acknowledge the contribution\n of the CCSM project and CCSM sponsor agencies with the \n following citation:\n 'This research uses data provided by the Community Climate\n System Model project (www.ccsm.ucar.edu), supported by the\n Directorate for Geosciences of the National Science Foundation\n and the Office of Biological and Environmental Research of\n the U.S. Department of Energy.'\nIn addition, the words 'Community Climate System Model' and\n 'CCSM' should be included as metadata for webpages referencing\n work using CCSM data or as keywords provided to journal or book\npublishers of your manuscripts.\nUsers of CCSM data accept the responsibility of emailing\n citations of publications of research using CCSM data to\n ccsm@ucar.edu.\nAny redistribution of CCSM data must include this data\n acknowledgement statement."} ;
304 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "acknowledgment", 847, acknowledgment_att);
305 	 check_err(stat,__LINE__,__FILE__);
306       }
307       { /* realization */
308 	 static const int realization_att[1] = {8} ;
309 	 stat = nc_put_att_int(root_grp, NC_GLOBAL, "realization", NC_INT, 1, realization_att);
310 	 check_err(stat,__LINE__,__FILE__);
311       }
312       { /* experiment_id */
313 	 static const char experiment_id_att[46] = {"climate of the 20th Century experiment (20C3M)"} ;
314 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "experiment_id", 46, experiment_id_att);
315 	 check_err(stat,__LINE__,__FILE__);
316       }
317       { /* history */
318 	 static const char history_att[139] = {"Created from CCSM3 case b30.030g.ES01\n by strandwg@ucar.edu\n on Wed Sep 10 12:22:06 MDT 2008\n \n For all data, added IPCC requested metadata"} ;
319 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "history", 139, history_att);
320 	 check_err(stat,__LINE__,__FILE__);
321       }
322       { /* comment */
323 	 static const char comment_att[1105] = {"This simulation was initiated from year 460 of \n CCSM3 model run b30.020.ES01 and executed on \n hardware Earth Simulator Center, JAMSTEC. The input external forcings are\nozone forcing    : mozart.o3.128x64_L18_1870-2000_c040515.nc\naerosol optics   : AerosolOptics_c040105.nc\naerosol MMR      : AerosolMass_V_128x256_clim_c031022.nc\ncarbon scaling   : carbonscaling_1870-2000_c040225.nc\nsolar forcing    : scon_lean_1870-2100_c040123.nc\nGHGs             : ghg_1870_2100_c040122.nc\nGHG loss rates   : noaamisc.r8.nc\nvolcanic forcing : VolcanicMass_1870-1999_64x1_L18_c040123.nc\nDMS emissions    : DMS_emissions_128x256_clim_c040122.nc\noxidants         : oxid_128x256_L26_clim_c040112.nc\nSOx emissions    : SOx_emissions_128x256_L2_1850-2000_c040321.nc\n Physical constants used for derived data:\n Lv (latent heat of evaporation): 2.501e6 J kg-1\n Lf (latent heat of fusion     ): 3.337e5 J kg-1\n r[h2o] (density of water      ): 1000 kg m-3\n g2kg   (grams to kilograms    ): 1000 g kg-1\n \n Integrations were performed by NCAR and CRIEPI with support\n and facilities provided by NSF, DOE, MEXT and ESC/JAMSTEC."} ;
324 	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "comment", 1105, comment_att);
325 	 check_err(stat,__LINE__,__FILE__);
326       }
327 
328 
329       /* assign per-variable attributes */
330       { /* calendar */
331 	 static const char time_calendar_att[6] = {"noleap"} ;
332 	 stat = nc_put_att_text(root_grp, time_id, "calendar", 6, time_calendar_att);
333 	 check_err(stat,__LINE__,__FILE__);
334       }
335       { /* standard_name */
336 	 static const char time_standard_name_att[4] = {"time"} ;
337 	 stat = nc_put_att_text(root_grp, time_id, "standard_name", 4, time_standard_name_att);
338 	 check_err(stat,__LINE__,__FILE__);
339       }
340       { /* axis */
341 	 static const char time_axis_att[1] = {"T"} ;
342 	 stat = nc_put_att_text(root_grp, time_id, "axis", 1, time_axis_att);
343 	 check_err(stat,__LINE__,__FILE__);
344       }
345       { /* units */
346 	 static const char time_units_att[19] = {"days since 0000-1-1"} ;
347 	 stat = nc_put_att_text(root_grp, time_id, "units", 19, time_units_att);
348 	 check_err(stat,__LINE__,__FILE__);
349       }
350       { /* bounds */
351 	 static const char time_bounds_att[9] = {"time_bnds"} ;
352 	 stat = nc_put_att_text(root_grp, time_id, "bounds", 9, time_bounds_att);
353 	 check_err(stat,__LINE__,__FILE__);
354       }
355       { /* long_name */
356 	 static const char time_long_name_att[4] = {"time"} ;
357 	 stat = nc_put_att_text(root_grp, time_id, "long_name", 4, time_long_name_att);
358 	 check_err(stat,__LINE__,__FILE__);
359       }
360       { /* axis */
361 	 static const char lat_axis_att[1] = {"Y"} ;
362 	 stat = nc_put_att_text(root_grp, lat_id, "axis", 1, lat_axis_att);
363 	 check_err(stat,__LINE__,__FILE__);
364       }
365       { /* standard_name */
366 	 static const char lat_standard_name_att[8] = {"latitude"} ;
367 	 stat = nc_put_att_text(root_grp, lat_id, "standard_name", 8, lat_standard_name_att);
368 	 check_err(stat,__LINE__,__FILE__);
369       }
370       { /* bounds */
371 	 static const char lat_bounds_att[8] = {"lat_bnds"} ;
372 	 stat = nc_put_att_text(root_grp, lat_id, "bounds", 8, lat_bounds_att);
373 	 check_err(stat,__LINE__,__FILE__);
374       }
375       { /* long_name */
376 	 static const char lat_long_name_att[8] = {"latitude"} ;
377 	 stat = nc_put_att_text(root_grp, lat_id, "long_name", 8, lat_long_name_att);
378 	 check_err(stat,__LINE__,__FILE__);
379       }
380       { /* units */
381 	 static const char lat_units_att[13] = {"degrees_north"} ;
382 	 stat = nc_put_att_text(root_grp, lat_id, "units", 13, lat_units_att);
383 	 check_err(stat,__LINE__,__FILE__);
384       }
385       { /* axis */
386 	 static const char lon_axis_att[1] = {"X"} ;
387 	 stat = nc_put_att_text(root_grp, lon_id, "axis", 1, lon_axis_att);
388 	 check_err(stat,__LINE__,__FILE__);
389       }
390       { /* standard_name */
391 	 static const char lon_standard_name_att[9] = {"longitude"} ;
392 	 stat = nc_put_att_text(root_grp, lon_id, "standard_name", 9, lon_standard_name_att);
393 	 check_err(stat,__LINE__,__FILE__);
394       }
395       { /* bounds */
396 	 static const char lon_bounds_att[8] = {"lon_bnds"} ;
397 	 stat = nc_put_att_text(root_grp, lon_id, "bounds", 8, lon_bounds_att);
398 	 check_err(stat,__LINE__,__FILE__);
399       }
400       { /* long_name */
401 	 static const char lon_long_name_att[9] = {"longitude"} ;
402 	 stat = nc_put_att_text(root_grp, lon_id, "long_name", 9, lon_long_name_att);
403 	 check_err(stat,__LINE__,__FILE__);
404       }
405       { /* units */
406 	 static const char lon_units_att[12] = {"degrees_east"} ;
407 	 stat = nc_put_att_text(root_grp, lon_id, "units", 12, lon_units_att);
408 	 check_err(stat,__LINE__,__FILE__);
409       }
410       { /* comment */
411 	 static const char pr_comment_att[60] = {"Created using NCL code CCSM_atmm_2cf.ncl on\n machine mineral"} ;
412 	 stat = nc_put_att_text(root_grp, pr_id, "comment", 60, pr_comment_att);
413 	 check_err(stat,__LINE__,__FILE__);
414       }
415       { /* missing_value */
416 	 static const float pr_missing_value_att[1] = {1e+20} ;
417 	 stat = nc_put_att_float(root_grp, pr_id, "missing_value", NC_FLOAT, 1, pr_missing_value_att);
418 	 check_err(stat,__LINE__,__FILE__);
419       }
420       { /* _FillValue */
421 	 static const float pr_FillValue_att[1] = {1e+20} ;
422 	 stat = nc_put_att_float(root_grp, pr_id, "_FillValue", NC_FLOAT, 1, pr_FillValue_att);
423 	 check_err(stat,__LINE__,__FILE__);
424       }
425       { /* cell_methods */
426 	 static const char pr_cell_methods_att[30] = {"time: mean (interval: 1 month)"} ;
427 	 stat = nc_put_att_text(root_grp, pr_id, "cell_methods", 30, pr_cell_methods_att);
428 	 check_err(stat,__LINE__,__FILE__);
429       }
430       { /* history */
431 	 static const char pr_history_att[20] = {"(PRECC+PRECL)*r[h2o]"} ;
432 	 stat = nc_put_att_text(root_grp, pr_id, "history", 20, pr_history_att);
433 	 check_err(stat,__LINE__,__FILE__);
434       }
435       { /* original_units */
436 	 static const char pr_original_units_att[7] = {"m-1 s-1"} ;
437 	 stat = nc_put_att_text(root_grp, pr_id, "original_units", 7, pr_original_units_att);
438 	 check_err(stat,__LINE__,__FILE__);
439       }
440       { /* original_name */
441 	 static const char pr_original_name_att[12] = {"PRECC, PRECL"} ;
442 	 stat = nc_put_att_text(root_grp, pr_id, "original_name", 12, pr_original_name_att);
443 	 check_err(stat,__LINE__,__FILE__);
444       }
445       { /* standard_name */
446 	 static const char pr_standard_name_att[18] = {"precipitation_flux"} ;
447 	 stat = nc_put_att_text(root_grp, pr_id, "standard_name", 18, pr_standard_name_att);
448 	 check_err(stat,__LINE__,__FILE__);
449       }
450       { /* units */
451 	 static const char pr_units_att[10] = {"kg m-2 s-1"} ;
452 	 stat = nc_put_att_text(root_grp, pr_id, "units", 10, pr_units_att);
453 	 check_err(stat,__LINE__,__FILE__);
454       }
455       { /* long_name */
456 	 static const char pr_long_name_att[18] = {"precipitation_flux"} ;
457 	 stat = nc_put_att_text(root_grp, pr_id, "long_name", 18, pr_long_name_att);
458 	 check_err(stat,__LINE__,__FILE__);
459       }
460       { /* cell_method */
461 	 static const char pr_cell_method_att[10] = {"time: mean"} ;
462 	 stat = nc_put_att_text(root_grp, pr_id, "cell_method", 10, pr_cell_method_att);
463 	 check_err(stat,__LINE__,__FILE__);
464       }
465 
466       /* don't initialize variables with fill values */
467       stat = nc_set_fill(root_grp, NC_NOFILL, 0);
468       check_err(stat,__LINE__,__FILE__);
469 
470       /* leave define mode */
471       stat = nc_enddef (root_grp);
472       check_err(stat,__LINE__,__FILE__);
473 
474       stat = nc_close(root_grp);
475       check_err(stat,__LINE__,__FILE__);
476 
477       {
478 #define NDIMS4 4
479 	 int ndims, dimids_in[NDIMS4];
480 	 char name_in[NC_MAX_NAME + 1];
481 	 char institution_att_in[NC_MAX_NAME + 1];
482 
483 	 /* Now open this file and check order of dimensions. */
484 	 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
485 
486 	 /* Check dimids. */
487 	 if (nc_inq_dimname(ncid, 0, name_in)) ERR;
488 	 if (strcmp(name_in, "lon")) ERR;
489 	 if (nc_inq_dimname(ncid, 1, name_in)) ERR;
490 	 if (strcmp(name_in, "lat")) ERR;
491 	 if (nc_inq_dimname(ncid, 2, name_in)) ERR;
492 	 if (strcmp(name_in, "bnds")) ERR;
493 	 if (nc_inq_dimname(ncid, 3, name_in)) ERR;
494 	 if (strcmp(name_in, "time")) ERR;
495 
496 	 /* Check inq_dimids function. */
497 	 if (nc_inq_dimids(ncid, &ndims, dimids_in, 0)) ERR;
498 	 if (ndims != NDIMS4 || dimids_in[0] != 0 || dimids_in[1] != 1 ||
499 	     dimids_in[2] != 2 || dimids_in[3] != 3) ERR;
500 
501 	 /* Check attribute with line breaks. */
502 	 if (nc_get_att_text(ncid, NC_GLOBAL, INST_NAME,
503 			     institution_att_in)) ERR;
504 	 if (strncmp(institution_att_in, INSTITUTION, strlen(INSTITUTION))) ERR;
505 
506 	 if (nc_close(ncid)) ERR;
507       }
508 
509    }
510    SUMMARIZE_ERR;
511    printf("**** testing dim order when coord vars are defined in the wrong order...");
512    {
513 #define RANK_2 2
514 #define DIM0 "d0"
515 #define DIM1 "d1"
516       int ncid, dimids[RANK_2], varid[RANK_2];
517       char name_in[NC_MAX_NAME + 1];
518 
519       /* Create a test file. */
520       if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
521 
522       /* Define dimensions in order. */
523       if (nc_def_dim(ncid, DIM0, NC_UNLIMITED, &dimids[0])) ERR;
524       if (nc_def_dim(ncid, DIM1, 4, &dimids[1])) ERR;
525 
526       /* Define coordinate variables in a different order. */
527       if (nc_def_var(ncid, DIM1, NC_DOUBLE, 1, &dimids[1], &varid[1])) ERR;
528       if (nc_def_var(ncid, DIM0, NC_DOUBLE, 1, &dimids[0], &varid[0])) ERR;
529 
530       /* That's it! */
531       if (nc_close(ncid)) ERR;
532 
533       /* Reopen the file and check dimension order. */
534       if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
535 
536       if (nc_inq_dimname(ncid, 0, name_in)) ERR;
537       if (strcmp(name_in, DIM0)) ERR;
538       if (nc_inq_dimname(ncid, 1, name_in)) ERR;
539       if (strcmp(name_in, DIM1)) ERR;
540 
541       if (nc_close(ncid)) ERR;
542    }
543    SUMMARIZE_ERR;
544    printf("**** testing order of coordinate dims...");
545    {
546 #define RANK_3 3
547 #define DIM1_NAME "d1"
548 #define DIM2_NAME "d2"
549 #define DIM3_NAME "d3"
550       int ncid, dimids[RANK_3], varid[RANK_3];
551       char name_in[NC_MAX_NAME + 1];
552 
553       /* Create a 3D test file. */
554       if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
555 
556       /* Define dimensions in order. */
557       if (nc_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimids[0])) ERR;
558       if (nc_def_dim(ncid, DIM2_NAME, 4, &dimids[1])) ERR;
559       if (nc_def_dim(ncid, DIM3_NAME, 3, &dimids[2])) ERR;
560 
561       /* Define coordinate variables in a different order. */
562       if (nc_def_var(ncid, DIM1_NAME, NC_DOUBLE, 1, &dimids[0], &varid[0])) ERR;
563       if (nc_def_var(ncid, DIM2_NAME, NC_DOUBLE, 1, &dimids[1], &varid[1])) ERR;
564       if (nc_def_var(ncid, DIM3_NAME, NC_DOUBLE, 1, &dimids[2], &varid[2])) ERR;
565 
566       /* That's it! */
567       if (nc_close(ncid)) ERR;
568 
569       /* Reopen the file and check dimension order. */
570       if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
571 
572       if (nc_inq_dimname(ncid, 0, name_in)) ERR;
573       if (strcmp(name_in, DIM1_NAME)) ERR;
574       if (nc_inq_dimname(ncid, 1, name_in)) ERR;
575       if (strcmp(name_in, DIM2_NAME)) ERR;
576       if (nc_inq_dimname(ncid, 2, name_in)) ERR;
577       if (strcmp(name_in, DIM3_NAME)) ERR;
578 
579       if (nc_close(ncid)) ERR;
580    }
581    SUMMARIZE_ERR;
582    printf("**** testing coordinate vars...");
583    {
584 #   define RANK_Coordinates_lat 1
585       int ncid;
586       int Coordinates_grp;
587       int lat_dim;
588       size_t lat_len = 3;
589       int Coordinates_lat_id;
590 
591       if(nc_create(FILE_NAME, NC_CLOBBER|NC_NETCDF4, &ncid)) ERR;
592       if (nc_def_grp(ncid, "Coordinates", &Coordinates_grp)) ERR;
593 
594       /* Define dimensions in root group. */
595       if (nc_def_dim(ncid, "lat", lat_len, &lat_dim)) ERR;
596 
597       /* Define coordinate variable in Coordinates group. */
598       if (nc_def_var(Coordinates_grp, "lat", NC_FLOAT,
599 		     1, &lat_dim, &Coordinates_lat_id)) ERR;
600 
601       if (nc_close(ncid)) ERR;
602    }
603    SUMMARIZE_ERR;
604    printf("**** testing 2D non-coordinate variable...");
605    {
606 #define VAR_NAME "Britany"
607 #define NDIMS 2
608 #define TEXT_LEN 15
609 #define D0_NAME "time"
610 #define D1_NAME "tl"
611       int ncid, nvars_in, varids_in[1];
612       int time_dimids[NDIMS], time_id;
613       size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
614       const char ttext[TEXT_LEN]="20051224.150000";
615       int nvars, ndims, ngatts, unlimdimid;
616       int ndims_in, natts_in, dimids_in[NDIMS];
617       char var_name_in[NC_MAX_NAME + 1];
618       nc_type xtype_in;
619 
620       /* Create a netcdf-4 file with 2D coordinate var. */
621       if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
622 
623       if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
624       if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
625       if (nc_def_var(ncid, VAR_NAME, NC_USHORT, NDIMS, time_dimids,
626 		     &time_id) != NC_ESTRICTNC3) ERR;
627       if (nc_def_var(ncid, VAR_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;
628       if (nc_enddef(ncid)) ERR;
629 
630       /* Write one time to the coordinate variable. */
631       time_count[0] = 1;
632       time_count[1] = TEXT_LEN;
633       if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;
634       if (nc_close(ncid)) ERR;
635 
636       /* Open the file and check. */
637       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
638       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
639       if (nvars != 1 || ndims != 2 || ngatts != 0 || unlimdimid != 0) ERR;
640       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
641       if (nvars_in != 1 || varids_in[0] != 0) ERR;
642       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
643       if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_CHAR || ndims_in != 2 ||
644           dimids_in[0] != 0 || dimids_in[1] != 1 || natts_in != 0) ERR;
645       if (nc_close(ncid)) ERR;
646    }
647    SUMMARIZE_ERR;
648    printf("**** testing 2D coordinate variable...");
649    {
650 #define NDIMS 2
651 #define TEXT_LEN 15
652 #define D0_NAME "time"
653 #define D1_NAME "tl"
654       int ncid, nvars_in, varids_in[1];
655       int time_dimids[NDIMS], time_id;
656       size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
657       const char ttext[TEXT_LEN + 1]="20051224.150000";
658       int nvars, ndims, ngatts, unlimdimid;
659       int ndims_in, natts_in, dimids_in[NDIMS];
660       char var_name_in[NC_MAX_NAME + 1];
661       nc_type xtype_in;
662 
663       /* Create a netcdf-4 file with 2D coordinate var. */
664       if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
665       if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
666       if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
667       if (nc_def_var(ncid, D0_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;
668 
669       /* Write one time to the coordinate variable. */
670       time_count[0] = 1;
671       time_count[1] = TEXT_LEN;
672       if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;
673       if (nc_close(ncid)) ERR;
674 
675       /* Open the file and check. */
676       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
677       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
678       if (nvars != 1 || ndims != 2 || ngatts != 0 || unlimdimid != 0) ERR;
679       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
680       if (nvars_in != 1 || varids_in[0] != 0) ERR;
681       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
682       if (strcmp(var_name_in, D0_NAME) || xtype_in != NC_CHAR || ndims_in != 2 ||
683 	dimids_in[0] != 0 || dimids_in[1] != 1 || natts_in != 0) ERR;
684       if (nc_close(ncid)) ERR;
685    }
686    SUMMARIZE_ERR;
687    printf("**** testing new order of doing things with coordinate variable...");
688    {
689       /* In this test:
690            define a dimension
691            define a variable that uses that dimension
692            put values in the variable
693            define coordinate values for the dimension
694       */
695 #define VAR_NAME_BB "The_Birth_of_Britain"
696 #define NDIMS_1 1
697 #define TEXT_LEN 15
698 #define WINSTON_CHURCHILL "Winston_S_Churchill"
699 #define D0_LEN 2
700 #define NUM_VARS_2 2
701       int ncid, nvars_in, varids_in[NUM_VARS_2];
702       int dimid, varid, varid2;
703       int nvars, ndims, ngatts, unlimdimid;
704       int ndims_in, natts_in, dimids_in[NDIMS];
705       char var_name_in[NC_MAX_NAME + 1];
706       nc_type xtype_in;
707       int data[D0_LEN] = {42, -42};
708 
709       /* Create a netcdf-4 file with 2D coordinate var. */
710       if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
711       if (nc_def_dim(ncid, WINSTON_CHURCHILL, NC_UNLIMITED, &dimid)) ERR;
712       if (nc_def_var(ncid, VAR_NAME, NC_INT, NDIMS_1, &dimid, &varid)) ERR;
713       if (nc_put_var_int(ncid, varid, data)) ERR;
714       if (nc_def_var(ncid, WINSTON_CHURCHILL, NC_INT, NDIMS_1, &dimid, &varid2)) ERR;
715       if (nc_put_var_int(ncid, varid2, data)) ERR;
716 
717       /* Check things. */
718       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
719       if (nvars != 2 || ndims != 1 || ngatts != 0 || unlimdimid != 0) ERR;
720       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
721       if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
722       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
723       if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_INT || ndims_in != 1 ||
724 	  dimids_in[0] != 0 || natts_in != 0) ERR;
725 
726       if (nc_close(ncid)) ERR;
727 
728       /* Open the file and check. */
729       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
730       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
731       if (nvars != 2 || ndims != 1 || ngatts != 0 || unlimdimid != 0) ERR;
732       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
733       if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
734       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
735       if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_INT || ndims_in != 1 ||
736 	  dimids_in[0] != 0 || natts_in != 0) ERR;
737       if (nc_close(ncid)) ERR;
738    }
739    SUMMARIZE_ERR;
740    printf("**** testing 2D coordinate variable with dimensions defined in different order...");
741    {
742 #define NDIMS 2
743 #define TEXT_LEN 15
744 #define D0_NAME "time"
745 #define D1_NAME "tl"
746 #define NUM_VARS 2
747       int ncid, nvars_in, varids_in[NUM_VARS];
748       int time_dimids[NDIMS], time_id, tl_id;
749       size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
750       const char ttext[TEXT_LEN + 1]="20051224.150000";
751       char ttext_in[TEXT_LEN + 1];
752       int nvars, ndims, ngatts, unlimdimid;
753       int ndims_in, natts_in, dimids_in[NDIMS];
754       char var_name_in[NC_MAX_NAME + 1], dim_name_in[NC_MAX_NAME + 1];
755       size_t len_in;
756       nc_type xtype_in;
757 
758       /* Create a netcdf-4 file with 2D coordinate var. */
759       if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
760       if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
761       if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
762       if (nc_def_var(ncid, D0_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;
763       if (nc_def_var(ncid, D1_NAME, NC_CHAR, 1, &time_dimids[0], &tl_id)) ERR;
764 
765       /* Write one time to the coordinate variable. */
766       time_count[0] = 1;
767       time_count[1] = TEXT_LEN;
768       if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;
769 
770       /* Check the data. */
771       if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
772       if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;
773 
774       /* Close up. */
775       if (nc_close(ncid)) ERR;
776 
777       /* Open the file and check. */
778       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
779       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
780       if (nvars != NUM_VARS || ndims != NDIMS || ngatts != 0 || unlimdimid != 1) ERR;
781       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
782       if (nvars_in != NUM_VARS || varids_in[0] != 0 || varids_in[1] != 1) ERR;
783       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
784       if (strcmp(var_name_in, D0_NAME) || xtype_in != NC_CHAR || ndims_in != NDIMS ||
785 	dimids_in[0] != 1 || dimids_in[1] != 0 || natts_in != 0) ERR;
786       if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
787       if (ndims_in != NDIMS || dimids_in[0] != 0 || dimids_in[1] != 1) ERR;
788       if (nc_inq_dim(ncid, 0, dim_name_in, &len_in)) ERR;
789       if (strcmp(dim_name_in, D1_NAME) || len_in != TEXT_LEN) ERR;
790       if (nc_inq_dim(ncid, 1, dim_name_in, &len_in)) ERR;
791       if (strcmp(dim_name_in, D0_NAME) || len_in != 1) ERR;
792 
793       /* Check the data. */
794       if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
795       if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;
796 
797       /* Close up. */
798       if (nc_close(ncid)) ERR;
799    }
800    SUMMARIZE_ERR;
801    FINAL_RESULTS;
802 }
803