/*! \file Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 University Corporation for Atmospheric Research/Unidata. See \ref copyright file for more info. */ /* This example program is part of Unidata's netCDF library for scientific data access. This program demonstrates various ways to create netCDF dimensions and variables. We will create a dataset with 4 variables. We'll store a 3D surface temperature (lat x lon x timestep), 4D pressure (lat x lon x height x timestep), a 2D initial temperature (lat x lon) and a 3D initial pressure (lat x lon x height). All variables will be stored as single precision floating point. All variables are intended to share dimensions. For example, the latitude axis is the same for all of them. We'll also include the coordinate axis data for three of the four dimensions, that is, labels for the lat, lon, and height axes. Finally, we'll use some attributes to store some metadata about the variables, the units. Also we'll use a file-level, or global, attribute to record some information about the dataset as a whole. Ed Hartnett, 6/3/4 $Id: met4D.c,v 1.1 2004/07/26 14:04:42 ed Exp $ */ #include #include #include /* This macro handles errors by outputting a message to stdout and then exiting. */ #define NC_EXAMPLE_ERROR 2 /* This is the exit code for failure. */ #define BAIL(e) do { \ printf("Bailing out in file %s, line %d, error:%s.\n", \ __FILE__, __LINE__, nc_strerror(e)); \ return NC_EXAMPLE_ERROR; \ } while (0) #define FILENAME "test.nc" #define NUMDIMS 4 #define NUMVARS 4 /* We'll need to specify the dimensionality of our netCDF variables. These will allow us to do so with less confusion. */ #define NUMDIMS_1D 1 #define NUMDIMS_2D 2 #define NUMDIMS_3D 3 #define NUMDIMS_4D 4 /* The following will be the variable names in the netCDF file. */ #define TEMP_VARNAME "sfc_temp" #define PRES_VARNAME "pressure" #define INIT_TEMP_VARNAME "initial_temp" #define INIT_PRES_VARNAME "initial_pressure" /* These will be names and values of attributes. */ #define UNITS "units" #define CELSIUS "celsius" #define MILIBARS "milibars" #define HISTORY "history" #define HISTSTR "These data were produced by a thousand typing monkeys" /* These will be the names of the dimensions, and also the names of the variables that will hold the coordinate axis labels. */ #define TIME_NAME "timestep" #define LAT_NAME "latitude" #define LON_NAME "longitude" #define HEIGHT_NAME "height" /* These are the lengths of each dimension. */ #define LAT_LEN 7 #define LON_LEN 10 #define HEIGHT_LEN 5 #define TIME_LEN 3 /* These will be used to create some phoney data. */ #define PHONEY_LON_START (-120.) #define PHONEY_LON_MULT (.5) #define PHONEY_LAT_START (40.) #define PHONEY_LAT_MULT (2.5) #define PHONEY_HEIGHT_INC 100 #define PHONEY_TEMP_START (10.5) #define PHONEY_TEMP_DIV 20 #define PHONEY_PRES_START (1013.0) #define PHONEY_PRES_DIV 1 int main() { /* NetCDF IDs for the file, dimensions, and variables. We define three extra varids for the coordinate axis data. */ int ncid, time_dimid, lat_dimid, lon_dimid, height_dimid; int temp_varid, pres_varid, itemp_varid, ipres_varid; int lat_varid, lon_varid, height_varid; /* We'll reuse this array every time we define a variable. */ int dimids[NUMDIMS]; /* Coordinate axis data (ex. what specific longitude values do we have data for?) */ float lat[LAT_LEN], lon[LON_LEN]; int height[HEIGHT_LEN]; /* Phoney variable data. In the real world, the temp and pres variables might be the output of a model or assimilation system, and the itemp and ipres initial values of the temp and pres variables. For temp and pres we will reserve enough memory to store one timestep, and keep using the same timestep's worth of data over and over again. */ float temp[LAT_LEN][LON_LEN]; float itemp[LAT_LEN][LON_LEN]; float pres[LAT_LEN][LON_LEN][HEIGHT_LEN]; float ipres[LAT_LEN][LON_LEN][HEIGHT_LEN]; /* We need these to specify the array subsections we'll be writing in the temp and pres variables. */ size_t start[NUMDIMS], count[NUMDIMS]; float *fp, *ifp; int rec, i, res; /* Create a bunch of phoney data so we have something to write in the example file. */ for (i=0; i function, which can write any array subset of the variable. */ start[0] = rec; /* We want to write *this* record. */ if ((res = nc_put_vara_float(ncid, temp_varid, start, count, (float *)temp))) BAIL(res); if ((res = nc_put_vara_float(ncid, pres_varid, start, count, (float *)pres))) BAIL(res); /* We're done writing one record. */ } /* Close the file. We're done, so we can go out and see the new Harry Potter movie! */ if ((res = nc_close(ncid))) BAIL(res); return 0; }