netcdf-cxx4/examples/pres_temp_4D_plugin_wr.cpp
2022-02-23 17:55:53 +00:00

197 lines
6.1 KiB
C++

/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is an example program which writes some 4D pressure and
temperatures. This example demonstrates the netCDF C++ API.
This is part of the netCDF tutorial:
https://docs.unidata.ucar.edu/netcdf-c/current/tutorial_8dox.html
Full documentation of the netCDF C++ API can be found at:
https://docs.unidata.ucar.edu/netcdf-cxx
$Id: pres_temp_4D_wr.cpp,v 1.6 2010/02/11 22:36:42 russ Exp $
*/
#include <netcdf>
#include <iostream>
#include <string>
using namespace std;
using namespace netCDF;
using namespace netCDF::exceptions;
// This is the name of the data file we will create.
#define FILE_NAME "pres_temp_plugin_4D.nc"
// We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
// timesteps of data.
#define NDIMS 4
#define NLVL 2
#define NLAT 6
#define NLON 12
#define NREC 2
// Filter specs.
#define BZIP2_ID 307
#define BZIP2_LEVEL 9
#define BZIP2_NPARAMS 1
unsigned int level = BZIP2_LEVEL;
unsigned int idp = BZIP2_ID;
size_t nparamsp = BZIP2_NPARAMS;
// Names of things.
#define LVL_NAME "level"
#define LAT_NAME "latitude"
#define LON_NAME "longitude"
#define REC_NAME "time"
#define PRES_NAME "pressure"
#define TEMP_NAME "temperature"
#define MAX_ATT_LEN 80
// These are used to construct some example data.
#define SAMPLE_PRESSURE 900
#define SAMPLE_TEMP 9.0
#define START_LAT 25.0
#define START_LON -125.0
string UNITS = "units";
string DEGREES_EAST = "degrees_east";
string DEGREES_NORTH = "degrees_north";
// For the units attributes.
string PRES_UNITS = "hPa";
string TEMP_UNITS = "celsius";
string LAT_UNITS = "degrees_north";
string LON_UNITS = "degrees_east";
// Return this code to the OS in case of failure.
#define NC_ERR 2
int main()
{
nc_set_log_level(5);
// We will write latitude and longitude fields.
float lats[NLAT],lons[NLON];
// Program variables to hold the data we will write out. We will
// only need enough space to hold one timestep of data; one record.
float pres_out[NLVL][NLAT][NLON];
float temp_out[NLVL][NLAT][NLON];
int i=0; //used in the data generation loop
// create some pretend data. If this wasn't an example program, we
// would have some real data to write for example, model output.
for (int lat = 0; lat < NLAT; lat++)
lats[lat] = START_LAT + 5. * lat;
for (int lon = 0; lon < NLON; lon++)
lons[lon] = START_LON + 5. * lon;
for (int lvl = 0; lvl < NLVL; lvl++)
for (int lat = 0; lat < NLAT; lat++)
for (int lon = 0; lon < NLON; lon++)
{
pres_out[lvl][lat][lon] =(float) (SAMPLE_PRESSURE + i);
temp_out[lvl][lat][lon] = (float)(SAMPLE_TEMP + i++);
}
try
{
// Create the file.
NcFile test(FILE_NAME, NcFile::replace);
nc_set_log_level(5);
// Define the dimensions. NetCDF will hand back an ncDim object for
// each.
NcDim lvlDim = test.addDim(LVL_NAME, NLVL);
NcDim latDim = test.addDim(LAT_NAME, NLAT);
NcDim lonDim = test.addDim(LON_NAME, NLON);
NcDim recDim = test.addDim(REC_NAME); //adds an unlimited dimension
// Define the coordinate variables.
NcVar latVar = test.addVar(LAT_NAME, ncFloat, latDim);
NcVar lonVar = test.addVar(LON_NAME, ncFloat, lonDim);
// Define units attributes for coordinate vars. This attaches a
// text attribute to each of the coordinate variables, containing
// the units.
latVar.putAtt(UNITS, DEGREES_NORTH);
lonVar.putAtt(UNITS, DEGREES_EAST);
// Define the netCDF variables for the pressure and temperature
// data.
vector<NcDim> dimVector;
dimVector.push_back(recDim);
dimVector.push_back(lvlDim);
dimVector.push_back(latDim);
dimVector.push_back(lonDim);
NcVar pressVar = test.addVar(PRES_NAME, ncFloat, dimVector);
NcVar tempVar = test.addVar(TEMP_NAME, ncFloat, dimVector);
// Define units attributes for coordinate vars. This attaches a
// text attribute to each of the coordinate variables, containing
// the units.
pressVar.putAtt(UNITS, PRES_UNITS);
tempVar.putAtt(UNITS, TEMP_UNITS);
// Write the coordinate variable data to the file.
//latVar.putVar(lats);
//lonVar.putVar(lons);
vector<size_t> chunks;
for(int i = 0; i < NDIMS; i++) {
chunks.push_back(4);
}
latVar.setChunking(NcVar::nc_CHUNKED,chunks);
//Testing the filter ability in a write function
cout<<"BZIP2_ID: " << BZIP2_ID <<"BZIP2_NPARAMS: "<< BZIP2_NPARAMS << " level: "<< level;
latVar.setFilter(BZIP2_ID,BZIP2_NPARAMS,&level);
latVar.getFilter(&idp,&nparamsp, &level);
latVar.putVar(lats);
lonVar.putVar(lons);
// Write the pretend data. This will write our surface pressure and
// surface temperature data. The arrays only hold one timestep
// worth of data. We will just rewrite the same data for each
// timestep. In a real application, the data would change between
// timesteps.
vector<size_t> startp,countp;
startp.push_back(0);
startp.push_back(0);
startp.push_back(0);
startp.push_back(0);
countp.push_back(1);
countp.push_back(NLVL);
countp.push_back(NLAT);
countp.push_back(NLON);
for (size_t rec = 0; rec < NREC; rec++)
{
startp[0]=rec;
pressVar.putVar(startp,countp,pres_out);
tempVar.putVar(startp,countp,temp_out);
}
// The file is automatically closed by the destructor. This frees
// up any internal netCDF resources associated with the file, and
// flushes any buffers.
//cout << "*** SUCCESS writing example file " << FILE_NAME << "!" << endl;
test.close();
return 0;
}
catch(NcException& e)
{
cout<<"FAILURE**************************\n";
cout << e.what() << endl;
return NC_ERR;
}
}