initial upload

This commit is contained in:
张壹 2021-04-19 09:02:09 +08:00
parent e1b16f2e3f
commit df80d03bd7
14 changed files with 3629 additions and 0 deletions

10
CMakeLists.txt Normal file
View File

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.15.2)
#
project(NETCDF_CXX)
message(STATUS "Platform: " ${CMAKE_HOST_SYSTEM_NAME})
set(CMAKE_INSTALL_PREFIX "D:/Library")
#
add_subdirectory(src/)

1
src/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

61
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,61 @@
#
aux_source_directory(lib/ NETCDF_SRC)
# netcdf c
set(LIB_NETCDF_INC C:/Program\ Files/netCDF\ 4.8.0/include)
set(LIB_NETCDF_LIB C:/Program\ Files/netCDF\ 4.8.0/lib)
# netcdf cmakeVS
# gctl->->->netcdf
#set(LIB_NETCDF_BIN C:/Program\ Files/netCDF\ 4.8.0/bin)
include_directories(${LIB_NETCDF_INC})
#
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
#
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
#
#
# libcmake
add_library(netcdf_c++ SHARED ${NETCDF_SRC})
#
add_library(netcdf_c++_static STATIC ${NETCDF_SRC})
#
set_target_properties(netcdf_c++_static PROPERTIES OUTPUT_NAME "netcdf_c++")
#
set_target_properties(netcdf_c++ PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(netcdf_c++_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
#
set_target_properties(netcdf_c++ PROPERTIES VERSION 1.0 SOVERSION 1.0)
find_library(NETCDF_LIBRARY netcdf ${LIB_NETCDF_LIB})
target_link_libraries(netcdf_c++ PUBLIC ${NETCDF_LIBRARY})
target_link_libraries(netcdf_c++_static ${NETCDF_LIBRARY})
#
install(TARGETS netcdf_c++ DESTINATION lib)
install(TARGETS netcdf_c++_static DESTINATION lib)
#
install(FILES lib/netcdfcpp.h DESTINATION include)
install(FILES lib/ncvalues.h DESTINATION include)
#
#
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
#
macro(add_sample name)
#
add_executable(${name} example/${name}.cpp)
# Windows
set_target_properties(${name} PROPERTIES INSTALL_RPATH D:/Library/lib)
#
target_link_libraries(${name} PUBLIC netcdf_c++)
endmacro()
add_sample(pres_temp_4D_rd)
add_sample(pres_temp_4D_wr)
add_sample(sfc_pres_temp_rd)
add_sample(sfc_pres_temp_wr)
add_sample(simple_xy_rd)
add_sample(simple_xy_wr)

View File

@ -0,0 +1,126 @@
/* 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 which reads some 4D pressure and temperature
values. The data file read by this program is produced by the
companion program pres_temp_4D_wr.cpp. It is intended to illustrate
the use of the netCDF C++ API.
This program is part of the netCDF tutorial:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: pres_temp_4D_rd.cpp,v 1.13 2007/02/14 20:59:21 ed Exp $
*/
#include <iostream>
#include <netcdfcpp.h>
using namespace std;
// We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
// timesteps of data.
static const int NLVL = 2;
static const int NLAT = 6;
static const int NLON = 12;
static const int NREC = 2;
// These are used to construct some example data.
static const float SAMPLE_PRESSURE = 900.0;
static const float SAMPLE_TEMP = 9.0;
static const float START_LAT = 25.0;
static const float START_LON = -125.0;
// Return this code to the OS in case of failure.
static const int NC_ERR = 2;
int main()
{
// These arrays will store the latitude and longitude values.
float lats[NLAT], lons[NLON];
// These arrays will hold the data we will read in. We will only
// need enough space to hold one timestep of data; one record.
float pres_in[NLVL][NLAT][NLON];
float temp_in[NLVL][NLAT][NLON];
// Change the error behavior of the netCDF C++ API by creating an
// NcError object. Until it is destroyed, this NcError object will
// ensure that the netCDF C++ API returns error codes on any
// failure, prints an error message, and leaves any other error
// handling to the calling program. In the case of this example, we
// just exit with an NC_ERR error code.
NcError err(NcError::verbose_nonfatal);
// Open the file.
NcFile dataFile("pres_temp_4D.nc", NcFile::ReadOnly);
// Check to see if the file was opened.
if(!dataFile.is_valid())
return NC_ERR;
// Get pointers to the latitude and longitude variables.
NcVar *latVar, *lonVar;
if (!(latVar = dataFile.get_var("latitude")))
return NC_ERR;
if (!(lonVar = dataFile.get_var("longitude")))
return NC_ERR;
// Get the lat/lon data from the file.
if (!latVar->get(lats, NLAT))
return NC_ERR;
if (!lonVar->get(lons, NLON))
return NC_ERR;
// Check the coordinate variable data.
for (int lat = 0; lat < NLAT; lat++)
if (lats[lat] != START_LAT + 5. * lat)
return NC_ERR;
for (int lon = 0; lon < NLON; lon++)
if (lons[lon] != START_LON + 5. * lon)
return NC_ERR;
// Get pointers to the pressure and temperature variables.
NcVar *presVar, *tempVar;
if (!(presVar = dataFile.get_var("pressure")))
return NC_ERR;
if (!(tempVar = dataFile.get_var("temperature")))
return NC_ERR;
// Read the data. Since we know the contents of the file we know
// that the data arrays in this program are the correct size to
// hold one timestep.
for (int rec = 0; rec < NREC; rec++)
{
// Read the data one record at a time.
if (!presVar->set_cur(rec, 0, 0, 0))
return NC_ERR;
if (!tempVar->set_cur(rec, 0, 0, 0))
return NC_ERR;
// Get 1 record of NLVL by NLAT by NLON values for each variable.
if (!presVar->get(&pres_in[0][0][0], 1, NLVL, NLAT, NLON))
return NC_ERR;
if (!tempVar->get(&temp_in[0][0][0], 1, NLVL, NLAT, NLON))
return NC_ERR;
// Check the data.
int i = 0;
for (int lvl = 0; lvl < NLVL; lvl++)
for (int lat = 0; lat < NLAT; lat++)
for (int lon = 0; lon < NLON; lon++)
if (pres_in[lvl][lat][lon] != SAMPLE_PRESSURE + i ||
temp_in[lvl][lat][lon] != SAMPLE_TEMP + i++)
return NC_ERR;
} // next record
// 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 reading example file pres_temp_4D.nc!" << endl;
return 0;
}

View File

@ -0,0 +1,149 @@
/* 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:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: pres_temp_4D_wr.cpp,v 1.11 2007/01/19 12:52:13 ed Exp $
*/
#include <iostream>
#include <netcdfcpp.h>
using namespace std;
// We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
// timesteps of data.
static const int NLVL = 2;
static const int NLAT = 6;
static const int NLON = 12;
static const int NREC = 2;
// These are used to construct some example data.
static const float SAMPLE_PRESSURE = 900.0;
static const float SAMPLE_TEMP = 9.0;
static const float START_LAT = 25.0;
static const float START_LON = -125.0;
// Return this code to the OS in case of failure.
static const int NC_ERR = 2;
int main()
{
// These arrays will store the latitude and longitude values.
float lats[NLAT],lons[NLON];
// These arrays will 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;
// 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] = SAMPLE_PRESSURE + i;
temp_out[lvl][lat][lon] = SAMPLE_TEMP + i++;
}
// Change the error behavior of the netCDF C++ API by creating an
// NcError object. Until it is destroyed, this NcError object will
// ensure that the netCDF C++ API returns error codes on any
// failure, prints an error message, and leaves any other error
// handling to the calling program. In the case of this example, we
// just exit with an NC_ERR error code.
NcError err(NcError::verbose_nonfatal);
// Create the file.
NcFile dataFile("pres_temp_4D.nc", NcFile::Replace);
// Check to see if the file was created.
if(!dataFile.is_valid())
return NC_ERR;
// Define the dimensions. NetCDF will hand back an ncDim object for
// each.
NcDim *lvlDim, *latDim, *lonDim, *recDim;
if (!(lvlDim = dataFile.add_dim("level", NLVL)))
return NC_ERR;
if (!(latDim = dataFile.add_dim("latitude", NLAT)))
return NC_ERR;
if (!(lonDim = dataFile.add_dim("longitude", NLON)))
return NC_ERR;
// Add an unlimited dimension...
if (!(recDim = dataFile.add_dim("time")))
return NC_ERR;
// Define the coordinate variables.
NcVar *latVar, *lonVar;
if (!(latVar = dataFile.add_var("latitude", ncFloat, latDim)))
return NC_ERR;
if (!(lonVar = dataFile.add_var("longitude", ncFloat, lonDim)))
return NC_ERR;
// Define units attributes for coordinate vars. This attaches a
// text attribute to each of the coordinate variables, containing
// the units.
if (!latVar->add_att("units", "degrees_north"))
return NC_ERR;
if (!lonVar->add_att("units", "degrees_east"))
return NC_ERR;
// Define the netCDF variables for the pressure and temperature
// data.
NcVar *presVar, *tempVar;
if (!(presVar = dataFile.add_var("pressure", ncFloat, recDim,
lvlDim, latDim, lonDim)))
return NC_ERR;
if (!(tempVar = dataFile.add_var("temperature", ncFloat, recDim,
lvlDim, latDim, lonDim)))
return NC_ERR;
// Define units attributes for data variables.
if (!presVar->add_att("units", "hPa"))
return NC_ERR;
if (!tempVar->add_att("units", "celsius"))
return NC_ERR;
// Write the coordinate variable data to the file.
if (!latVar->put(lats, NLAT))
return NC_ERR;
if (!lonVar->put(lons, NLON))
return NC_ERR;
// 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.
for (int rec = 0; rec < NREC; rec++)
{
if (!presVar->put_rec(&pres_out[0][0][0], rec))
return NC_ERR;
if (!tempVar->put_rec(&temp_out[0][0][0], rec))
return NC_ERR;
}
// 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 pres_temp_4D.nc!" << endl;
return 0;
}

View File

@ -0,0 +1,161 @@
/* 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 which reads some surface pressure and
temperatures. The data file read by this program is produced
companion program sfc_pres_temp_wr.cxx. It is intended to
illustrate the use of the netCDF C++ API.
This program is part of the netCDF tutorial:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: sfc_pres_temp_rd.cpp,v 1.17 2008/05/16 13:42:28 ed Exp $
*/
#include <iostream>
#include <cstring>
#include <netcdfcpp.h>
using namespace std;
// We are reading 2D data, a 6 x 12 lat-lon grid.
static const int NLAT = 6;
static const int NLON = 12;
// These are used to calculate the values we expect to find.
static const float SAMPLE_PRESSURE = 900;
static const float SAMPLE_TEMP = 9.0;
static const float START_LAT = 25.0;
static const float START_LON = -125.0;
// Return this code to the OS in case of failure.
static const int NC_ERR = 2;
int main(void)
{
// These will hold our pressure and temperature data.
float presIn[NLAT][NLON];
float tempIn[NLAT][NLON];
// These will hold our latitudes and longitudes.
float latsIn[NLAT];
float lonsIn[NLON];
// Change the error behavior of the netCDF C++ API by creating an
// NcError object. Until it is destroyed, this NcError object will
// ensure that the netCDF C++ API silently returns error codes on
// any failure, and leaves any other error handling to the calling
// program. In the case of this example, we just exit with an
// NC_ERR error code.
NcError err(NcError::silent_nonfatal);
// Open the file and check to make sure it's valid.
NcFile dataFile("sfc_pres_temp.nc", NcFile::ReadOnly);
if(!dataFile.is_valid())
return NC_ERR;
// There are a number of inquiry functions in netCDF which can be
// used to learn about an unknown netCDF file. In this case we know
// that there are 2 netCDF dimensions, 4 netCDF variables, no
// global attributes, and no unlimited dimension.
if (dataFile.num_dims() != 2 || dataFile.num_vars() != 4 ||
dataFile.num_atts() != 0 || dataFile.rec_dim() != 0)
return NC_ERR;
// We get back a pointer to each NcVar we request. Get the
// latitude and longitude coordinate variables.
NcVar *latVar, *lonVar;
if (!(latVar = dataFile.get_var("latitude")))
return NC_ERR;
if (!(lonVar = dataFile.get_var("longitude")))
return NC_ERR;
// Read the latitude and longitude coordinate variables into arrays
// latsIn and lonsIn.
if (!latVar->get(latsIn, NLAT))
return NC_ERR;
if (!lonVar->get(lonsIn, NLON))
return NC_ERR;
// Check the coordinate variable data.
for(int lat = 0; lat < NLAT; lat++)
if (latsIn[lat] != START_LAT + 5. * lat)
return NC_ERR;
// Check longitude values.
for (int lon = 0; lon < NLON; lon++)
if (lonsIn[lon] != START_LON + 5. * lon)
return NC_ERR;
// We get back a pointer to each NcVar we request.
NcVar *presVar, *tempVar;
if (!(presVar = dataFile.get_var("pressure")))
return NC_ERR;
if (!(tempVar = dataFile.get_var("temperature")))
return NC_ERR;
// Read the data. Since we know the contents of the file we know
// that the data arrays in this program are the correct size to
// hold all the data.
if (!presVar->get(&presIn[0][0], NLAT, NLON))
return NC_ERR;
if (!tempVar->get(&tempIn[0][0], NLAT, NLON))
return NC_ERR;
// Check the data.
for (int lat = 0; lat < NLAT; lat++)
for (int lon = 0; lon < NLON; lon++)
if (presIn[lat][lon] != SAMPLE_PRESSURE + (lon * NLAT + lat)
|| tempIn[lat][lon] != SAMPLE_TEMP + .25 * (lon * NLAT + lat))
return NC_ERR;
// Each of the netCDF variables has a "units" attribute. Let's read
// them and check them.
NcAtt *att;
char *units;
if (!(att = latVar->get_att("units")))
return NC_ERR;
units = att->as_string(0);
if (strncmp(units, "degrees_north", strlen("degrees_north")))
return NC_ERR;
// Attributes and attribute values should be deleted by the caller
// when no longer needed, to prevent memory leaks.
delete units;
delete att;
if (!(att = lonVar->get_att("units")))
return NC_ERR;
units = att->as_string(0);
if (strncmp(units, "degrees_east", strlen("degrees_east")))
return NC_ERR;
delete units;
delete att;
if (!(att = presVar->get_att("units")))
return NC_ERR;
units = att->as_string(0);
if (strncmp(units, "hPa", strlen("hPa")))
return NC_ERR;
delete units;
delete att;
if (!(att = tempVar->get_att("units")))
return NC_ERR;
units = att->as_string(0);
if (strncmp(units, "celsius", strlen("celsius")))
return NC_ERR;
delete units;
delete att;
// The file will be automatically closed by the destructor. This
// frees up any internal netCDF resources associated with the file,
// and flushes any buffers.
cout << "*** SUCCESS reading example file sfc_pres_temp.nc!" << endl;
return 0;
}

View File

@ -0,0 +1,142 @@
/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This example writes some surface pressure and temperatures. It is
intended to illustrate the use of the netCDF C++ API. The companion
program sfc_pres_temp_rd.cpp shows how to read the netCDF data file
created by this program.
This program is part of the netCDF tutorial:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: sfc_pres_temp_wr.cpp,v 1.12 2007/01/19 12:52:13 ed Exp $
*/
#include <iostream>
#include <netcdfcpp.h>
using namespace std;
// We are writing 2D data, a 6 x 12 lat-lon grid. We will need two
// netCDF dimensions.
static const int NLAT = 6;
static const int NLON = 12;
// These are used to construct some example data.
static const float SAMPLE_PRESSURE = 900;
static const float SAMPLE_TEMP = 9.0;
static const float START_LAT = 25.0;
static const float START_LON = -125.0;
// Return this to OS if there is a failure.
static const int NC_ERR = 2;
int main(void)
{
// These will hold our pressure and temperature data.
float presOut[NLAT][NLON];
float tempOut[NLAT][NLON];
// These will hold our latitudes and longitudes.
float lats[NLAT];
float lons[NLON];
// 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 lat = 0; lat < NLAT; lat++)
for(int lon = 0; lon < NLON; lon++)
{
presOut[lat][lon] = SAMPLE_PRESSURE + (lon * NLAT + lat);
tempOut[lat][lon] = SAMPLE_TEMP + .25 * (lon * NLAT + lat);
}
// Change the error behavior of the netCDF C++ API by creating an
// NcError object. Until it is destroyed, this NcError object will
// ensure that the netCDF C++ API silently returns error codes
// on any failure, and leaves any other error handling to the
// calling program. In the case of this example, we just exit with
// an NC_ERR error code.
NcError err(NcError::silent_nonfatal);
// Create the file. The Replace parameter tells netCDF to overwrite
// this file, if it already exists.
NcFile dataFile("sfc_pres_temp.nc", NcFile::Replace);
// Check to see if the file was created.
if(!dataFile.is_valid())
return NC_ERR;
// Define the dimensions. NetCDF will hand back an ncDim object for
// each.
NcDim *latDim, *lonDim;
if (!(latDim = dataFile.add_dim("latitude", NLAT)))
return NC_ERR;
if (!(lonDim = dataFile.add_dim("longitude", NLON)))
return NC_ERR;
// In addition to the latitude and longitude dimensions, we will
// also create latitude and longitude netCDF variables which will
// hold the actual latitudes and longitudes. Since they hold data
// about the coordinate system, the netCDF term for these is:
// "coordinate variables."
NcVar *latVar, *lonVar;
if (!(latVar = dataFile.add_var("latitude", ncFloat, latDim)))
return NC_ERR;
if (!(lonVar = dataFile.add_var("longitude", ncFloat, lonDim)))
return NC_ERR;
// Define units attributes for coordinate vars. This attaches a
// text attribute to each of the coordinate variables, containing
// the units.
if (!lonVar->add_att("units", "degrees_east"))
return NC_ERR;
if (!latVar->add_att("units", "degrees_north"))
return NC_ERR;
// Define the netCDF data variables.
NcVar *presVar, *tempVar;
if (!(presVar = dataFile.add_var("pressure", ncFloat, latDim, lonDim)))
return NC_ERR;
if (!(tempVar = dataFile.add_var("temperature", ncFloat, latDim, lonDim)))
return NC_ERR;
// Define units attributes for variables.
if (!presVar->add_att("units", "hPa"))
return NC_ERR;
if (!tempVar->add_att("units", "celsius"))
return NC_ERR;
// Write the coordinate variable data. This will put the latitudes
// and longitudes of our data grid into the netCDF file.
if (!latVar->put(lats, NLAT))
return NC_ERR;
if (!lonVar->put(lons, NLON))
return NC_ERR;
// Write the pretend data. This will write our surface pressure and
// surface temperature data. The arrays of data are the same size
// as the netCDF variables we have defined, and below we write them
// each in one step.
if (!presVar->put(&presOut[0][0], NLAT, NLON))
return NC_ERR;
if (!tempVar->put(&tempOut[0][0], NLAT, NLON))
return NC_ERR;
// 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 sfc_pres_temp.nc!" << endl;
return 0;
}

View File

@ -0,0 +1,67 @@
/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is a very simple example which reads a 2D array of
sample data produced by simple_xy_wr.cpp.
This example is part of the netCDF tutorial:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: simple_xy_rd.cpp,v 1.13 2007/01/19 12:52:13 ed Exp $
*/
#include <iostream>
#include <netcdfcpp.h>
using namespace std;
// We are reading 2D data, a 6 x 12 grid.
static const int NX = 6;
static const int NY = 12;
// Return this in event of a problem.
static const int NC_ERR = 2;
int main(void)
{
// This is the array we will read.
int dataIn[NX][NY];
// Open the file. The ReadOnly parameter tells netCDF we want
// read-only access to the file.
NcFile dataFile("simple_xy.nc", NcFile::ReadOnly);
// You should always check whether a netCDF file open or creation
// constructor succeeded.
if (!dataFile.is_valid())
{
cout << "Couldn't open file!\n";
return NC_ERR;
}
// For other method calls, the default behavior of the C++ API is
// to exit with a message if there is an error. If that behavior
// is OK, there is no need to check return values in simple cases
// like the following.
// Retrieve the variable named "data"
NcVar *data = dataFile.get_var("data");
// Read all the values from the "data" variable into memory.
data->get(&dataIn[0][0], NX, NY);
// Check the values.
for (int i = 0; i < NX; i++)
for (int j = 0; j < NY; j++)
if (dataIn[i][j] != i * NY + j)
return NC_ERR;
// The netCDF file is automatically closed by the NcFile destructor
cout << "*** SUCCESS reading example file simple_xy.nc!" << endl;
return 0;
}

View File

@ -0,0 +1,80 @@
/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is a very simple example which writes a 2D array of
sample data. To handle this in netCDF we create two shared
dimensions, "x" and "y", and a netCDF variable, called "data".
This example is part of the netCDF tutorial:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C++ API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx
$Id: simple_xy_wr.cpp,v 1.15 2007/01/19 12:52:13 ed Exp $
*/
#include <iostream>
#include <netcdfcpp.h>
using namespace std;
// We are writing 2D data, a 6 x 12 grid.
static const int NX = 6;
static const int NY = 12;
// Return this in event of a problem.
static const int NC_ERR = 2;
int
main(void)
{
// This is the data array we will write. It will just be filled
// with a progression of numbers for this example.
int dataOut[NX][NY];
// 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 i = 0; i < NX; i++)
for(int j = 0; j < NY; j++)
dataOut[i][j] = i * NY + j;
// Create the file. The Replace parameter tells netCDF to overwrite
// this file, if it already exists.
NcFile dataFile("simple_xy.nc", NcFile::Replace);
// You should always check whether a netCDF file creation or open
// constructor succeeded.
if (!dataFile.is_valid())
{
cout << "Couldn't open file!\n";
return NC_ERR;
}
// For other method calls, the default behavior of the C++ API is
// to exit with a message if there is an error. If that behavior
// is OK, there is no need to check return values in simple cases
// like the following.
// When we create netCDF dimensions, we get back a pointer to an
// NcDim for each one.
NcDim* xDim = dataFile.add_dim("x", NX);
NcDim* yDim = dataFile.add_dim("y", NY);
// Define a netCDF variable. The type of the variable in this case
// is ncInt (32-bit integer).
NcVar *data = dataFile.add_var("data", ncInt, xDim, yDim);
// Write the pretend data to the file. Although netCDF supports
// reading and writing subsets of data, in this case we write all
// the data in one operation.
data->put(&dataOut[0][0], NX, NY);
// The file will be automatically close when the NcFile object goes
// out of scope. This frees up any internal netCDF resources
// associated with the file, and flushes any buffers.
cout << "*** SUCCESS writing example file simple_xy.nc!" << endl;
return 0;
}

332
src/lib/ncvalues.cpp Normal file
View File

@ -0,0 +1,332 @@
/*********************************************************************
* Copyright 1992, University Corporation for Atmospheric Research
* See netcdf/README file for copying and redistribution conditions.
*
* Purpose: implementation of classes of typed arrays for netCDF
*
* $Header: /upc/share/CVS/netcdf-3/cxx/ncvalues.cpp,v 1.12 2008/03/05 16:45:32 russ Exp $
*********************************************************************/
#include <iostream>
#include <string>
#include <cstring>
#include "netcdf_config.h"
#include "ncvalues.h"
#pragma warning(disable : 4996)
NcValues::NcValues( void ) : the_type(ncNoType), the_number(0)
{}
NcValues::NcValues(NcType type, long num)
: the_type(type), the_number(num)
{}
NcValues::~NcValues( void )
{}
long NcValues::num( void )
{
return the_number;
}
std::ostream& operator<< (std::ostream& os, const NcValues& vals)
{
return vals.print(os);
}
implement(NcValues,ncbyte)
implement(NcValues,char)
implement(NcValues,short)
implement(NcValues,int)
implement(NcValues,nclong)
implement(NcValues,long)
implement(NcValues,float)
implement(NcValues,double)
Ncbytes_for_one_implement(ncbyte)
Ncbytes_for_one_implement(char)
Ncbytes_for_one_implement(short)
Ncbytes_for_one_implement(int)
Ncbytes_for_one_implement(nclong)
Ncbytes_for_one_implement(long)
Ncbytes_for_one_implement(float)
Ncbytes_for_one_implement(double)
as_ncbyte_implement(short)
as_ncbyte_implement(int)
as_ncbyte_implement(nclong)
as_ncbyte_implement(long)
as_ncbyte_implement(float)
as_ncbyte_implement(double)
inline ncbyte NcValues_char::as_ncbyte( long n ) const
{
return the_values[n];
}
inline ncbyte NcValues_ncbyte::as_ncbyte( long n ) const
{
return the_values[n];
}
as_char_implement(short)
as_char_implement(int)
as_char_implement(nclong)
as_char_implement(long)
as_char_implement(float)
as_char_implement(double)
inline char NcValues_ncbyte::as_char( long n ) const
{
return the_values[n] > CHAR_MAX ? ncBad_char : (char) the_values[n];
}
inline char NcValues_char::as_char( long n ) const
{
return the_values[n];
}
as_short_implement(int)
as_short_implement(nclong)
as_short_implement(long)
as_short_implement(float)
as_short_implement(double)
inline short NcValues_ncbyte::as_short( long n ) const
{
return the_values[n];
}
inline short NcValues_char::as_short( long n ) const
{
return the_values[n];
}
inline short NcValues_short::as_short( long n ) const
{
return the_values[n];
}
as_int_implement(float)
as_int_implement(double)
inline int NcValues_ncbyte::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_char::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_short::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_int::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_nclong::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_long::as_int( long n ) const
{
return the_values[n];
}
as_nclong_implement(float)
as_nclong_implement(double)
inline nclong NcValues_ncbyte::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_char::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_short::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_int::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_nclong::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_long::as_nclong( long n ) const
{
return the_values[n];
}
as_long_implement(float)
as_long_implement(double)
inline long NcValues_ncbyte::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_char::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_short::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_int::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_nclong::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_long::as_long( long n ) const
{
return the_values[n];
}
as_float_implement(ncbyte)
as_float_implement(char)
as_float_implement(short)
as_float_implement(int)
as_float_implement(nclong)
as_float_implement(long)
as_float_implement(float)
as_float_implement(double)
as_double_implement(ncbyte)
as_double_implement(char)
as_double_implement(short)
as_double_implement(int)
as_double_implement(nclong)
as_double_implement(long)
as_double_implement(float)
as_double_implement(double)
as_string_implement(short)
as_string_implement(int)
as_string_implement(nclong)
as_string_implement(long)
as_string_implement(float)
as_string_implement(double)
inline char* NcValues_ncbyte::as_string( long n ) const
{
char* s = new char[the_number + 1];
s[the_number] = '\0';
strncpy(s, (const char*)the_values + n, (int)the_number);
return s;
}
inline char* NcValues_char::as_string( long n ) const
{
char* s = new char[the_number + 1];
s[the_number] = '\0';
strncpy(s, (const char*)the_values + n, (int)the_number);
return s;
}
std::ostream& NcValues_short::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_int::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_nclong::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_long::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_ncbyte::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_char::print(std::ostream& os) const
{
os << '"';
long len = the_number;
while (the_values[--len] == '\0') // don't output trailing null bytes
;
for(int i = 0; i <= len; i++)
os << the_values[i] ;
os << '"';
return os;
}
std::ostream& NcValues_float::print(std::ostream& os) const
{
std::streamsize save=os.precision();
os.precision(7);
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
os.precision(save);
return os;
}
std::ostream& NcValues_double::print(std::ostream& os) const
{
std::streamsize save=os.precision();
os.precision(15);
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1];
os.precision(save);
return os;
}

279
src/lib/ncvalues.h Normal file
View File

@ -0,0 +1,279 @@
/*********************************************************************
* Copyright 1992, University Corporation for Atmospheric Research
* See netcdf/README file for copying and redistribution conditions.
*
* Purpose: interface for classes of typed arrays for netCDF
*
* $Header: /upc/share/CVS/netcdf-3/cxx/ncvalues.h,v 1.7 2006/07/26 21:12:06 russ Exp $
*********************************************************************/
#ifndef Ncvalues_def
#define Ncvalues_def
#include <iostream>
#include <sstream>
#include <limits.h>
#include "netcdf.h"
// Documentation warned this might change and now it has, for
// consistency with C interface
typedef signed char ncbyte;
#define NC_UNSPECIFIED ((nc_type)0)
// C++ interface dates from before netcdf-3, still uses some netcdf-2 names
#ifdef NO_NETCDF_2
#define NC_LONG NC_INT
#define FILL_LONG NC_FILL_INT
typedef int nclong;
#define NC_FATAL 1
#define NC_VERBOSE 2
#endif
enum NcType
{
ncNoType = NC_UNSPECIFIED,
ncByte = NC_BYTE,
ncChar = NC_CHAR,
ncShort = NC_SHORT,
ncInt = NC_INT,
ncLong = NC_LONG, // deprecated, someday want to use for 64-bit ints
ncFloat = NC_FLOAT,
ncDouble = NC_DOUBLE
};
#define ncBad_ncbyte ncBad_byte
static const ncbyte ncBad_byte = NC_FILL_BYTE;
static const char ncBad_char = NC_FILL_CHAR;
static const short ncBad_short = NC_FILL_SHORT;
static const nclong ncBad_nclong = FILL_LONG; // deprecated
static const int ncBad_int = NC_FILL_INT;
static const long ncBad_long = FILL_LONG; // deprecated
static const float ncBad_float = NC_FILL_FLOAT;
static const double ncBad_double = NC_FILL_DOUBLE;
// macros to glue tokens together to form new names (used to be in generic.h)
#define name2(a,b) a ## b
#define declare(clas,t) name2(clas,declare)(t)
#define implement(clas,t) name2(clas,implement)(t)
// This is the same as the name2 macro, but we need to define our own
// version since rescanning something generated with the name2 macro
// won't necessarily cause name2 to be expanded again.
#define makename2(z, y) makename2_x(z, y)
#define makename2_x(z, y) z##y
#define NcVal(TYPE) makename2(NcValues_,TYPE)
#define NcValuesdeclare(TYPE) \
class NcVal(TYPE) : public NcValues \
{ \
public: \
NcVal(TYPE)( void ); \
NcVal(TYPE)(long num); \
NcVal(TYPE)(long num, const TYPE* vals); \
NcVal(TYPE)(const NcVal(TYPE)&); \
virtual NcVal(TYPE)& operator=(const NcVal(TYPE)&); \
virtual ~NcVal(TYPE)( void ); \
virtual void* base( void ) const; \
virtual int bytes_for_one( void ) const; \
virtual ncbyte as_ncbyte( long n ) const; \
virtual char as_char( long n ) const; \
virtual short as_short( long n ) const; \
virtual int as_int( long n ) const; \
virtual int as_nclong( long n ) const; \
virtual long as_long( long n ) const; \
virtual float as_float( long n ) const; \
virtual double as_double( long n ) const; \
virtual char* as_string( long n ) const; \
virtual int invalid( void ) const; \
private: \
TYPE* the_values; \
std::ostream& print(std::ostream&) const; \
};
#define NcTypeEnum(TYPE) makename2(_nc__,TYPE)
#define _nc__ncbyte ncByte
#define _nc__char ncChar
#define _nc__short ncShort
#define _nc__int ncInt
#define _nc__nclong ncLong
#define _nc__long ncLong
#define _nc__float ncFloat
#define _nc__double ncDouble
#define NcValuesimplement(TYPE) \
NcVal(TYPE)::NcVal(TYPE)( void ) \
: NcValues(NcTypeEnum(TYPE), 0), the_values(0) \
{} \
\
NcVal(TYPE)::NcVal(TYPE)(long num, const TYPE* vals) \
: NcValues(NcTypeEnum(TYPE), num) \
{ \
the_values = new TYPE[num]; \
for(int i = 0; i < num; i++) \
the_values[i] = vals[i]; \
} \
\
NcVal(TYPE)::NcVal(TYPE)(long num) \
: NcValues(NcTypeEnum(TYPE), num), the_values(new TYPE[num]) \
{} \
\
NcVal(TYPE)::NcVal(TYPE)(const NcVal(TYPE)& v) : \
NcValues(v) \
{ \
delete[] the_values; \
the_values = new TYPE[v.the_number]; \
for(int i = 0; i < v.the_number; i++) \
the_values[i] = v.the_values[i]; \
} \
\
NcVal(TYPE)& NcVal(TYPE)::operator=(const NcVal(TYPE)& v) \
{ \
if ( &v != this) { \
NcValues::operator=(v); \
delete[] the_values; \
the_values = new TYPE[v.the_number]; \
for(int i = 0; i < v.the_number; i++) \
the_values[i] = v.the_values[i]; \
} \
return *this; \
} \
\
void* NcVal(TYPE)::base( void ) const \
{ \
return the_values; \
} \
\
NcVal(TYPE)::~NcVal(TYPE)( void ) \
{ \
delete[] the_values; \
} \
\
int NcVal(TYPE)::invalid( void ) const \
{ \
for(int i=0;i<the_number;i++) \
if (the_values[i] == makename2(ncBad_,TYPE)) return 1; \
return 0; \
} \
#define Ncbytes_for_one_implement(TYPE) \
int NcVal(TYPE)::bytes_for_one( void ) const \
{ \
return sizeof(TYPE); \
}
#define as_ncbyte_implement(TYPE) \
ncbyte NcVal(TYPE)::as_ncbyte( long n ) const \
{ \
if (the_values[n] < 0 || the_values[n] > UCHAR_MAX) \
return ncBad_byte; \
return (ncbyte) the_values[n]; \
}
#define as_char_implement(TYPE) \
char NcVal(TYPE)::as_char( long n ) const \
{ \
if (the_values[n] < CHAR_MIN || the_values[n] > CHAR_MAX) \
return ncBad_char; \
return (char) the_values[n]; \
}
#define as_short_implement(TYPE) \
short NcVal(TYPE)::as_short( long n ) const \
{ \
if (the_values[n] < SHRT_MIN || the_values[n] > SHRT_MAX) \
return ncBad_short; \
return (short) the_values[n]; \
}
#define NCINT_MIN INT_MIN
#define NCINT_MAX INT_MAX
#define as_int_implement(TYPE) \
int NcVal(TYPE)::as_int( long n ) const \
{ \
if (the_values[n] < NCINT_MIN || the_values[n] > NCINT_MAX) \
return ncBad_int; \
return (int) the_values[n]; \
}
#define NCLONG_MIN INT_MIN
#define NCLONG_MAX INT_MAX
#define as_nclong_implement(TYPE) \
nclong NcVal(TYPE)::as_nclong( long n ) const \
{ \
if (the_values[n] < NCLONG_MIN || the_values[n] > NCLONG_MAX) \
return ncBad_nclong; \
return (nclong) the_values[n]; \
}
#define as_long_implement(TYPE) \
long NcVal(TYPE)::as_long( long n ) const \
{ \
if (the_values[n] < LONG_MIN || the_values[n] > LONG_MAX) \
return ncBad_long; \
return (long) the_values[n]; \
}
#define as_float_implement(TYPE) \
inline float NcVal(TYPE)::as_float( long n ) const \
{ \
return (float) the_values[n]; \
}
#define as_double_implement(TYPE) \
inline double NcVal(TYPE)::as_double( long n ) const \
{ \
return (double) the_values[n]; \
}
#define as_string_implement(TYPE) \
char* NcVal(TYPE)::as_string( long n ) const \
{ \
char* s = new char[32]; \
std::ostringstream ostr; \
ostr << the_values[n]; \
ostr.str().copy(s, std::string::npos); \
s[ostr.str().length()] = 0; \
return s; \
}
class NcValues // ABC for value blocks
{
public:
NcValues( void );
NcValues(NcType, long);
virtual ~NcValues( void );
virtual long num( void );
virtual std::ostream& print(std::ostream&) const = 0;
virtual void* base( void ) const = 0;
virtual int bytes_for_one( void ) const = 0;
// The following member functions provide conversions from the value
// type to a desired basic type. If the value is out of range, the
// default "fill-value" for the appropriate type is returned.
virtual ncbyte as_ncbyte( long n ) const = 0; // nth value as a byte
virtual char as_char( long n ) const = 0; // nth value as char
virtual short as_short( long n ) const = 0; // nth value as short
virtual int as_int( long n ) const = 0; // nth value as int
virtual int as_nclong( long n ) const = 0; // nth value as nclong
virtual long as_long( long n ) const = 0; // nth value as long
virtual float as_float( long n ) const = 0; // nth value as floating-point
virtual double as_double( long n ) const = 0; // nth value as double
virtual char* as_string( long n ) const = 0; // value as string
protected:
NcType the_type;
long the_number;
friend std::ostream& operator<< (std::ostream&, const NcValues&);
};
declare(NcValues,ncbyte)
declare(NcValues,char)
declare(NcValues,short)
declare(NcValues,int)
declare(NcValues,nclong)
declare(NcValues,long)
declare(NcValues,float)
declare(NcValues,double)
#endif

1660
src/lib/netcdf.cpp Normal file

File diff suppressed because it is too large Load Diff

92
src/lib/netcdf_config.h Normal file
View File

@ -0,0 +1,92 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* if true, run extra tests which may not work yet */
#undef EXTRA_TESTS
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `nccreate' function. */
#undef HAVE_NCCREATE
/* Define to 1 if you have the `nc_def_opaque' function. */
#undef HAVE_NC_DEF_OPAQUE
/* Define to 1 if you have the `nc_set_log_level' function. */
#undef HAVE_NC_SET_LOG_LEVEL
/* Define to 1 if you have the `nc_use_parallel_enabled' function. */
#undef HAVE_NC_USE_PARALLEL_ENABLED
/* Define to 1 if you have the <netcdf.h> header file. */
#undef HAVE_NETCDF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* do large file tests */
#undef LARGE_FILE_TESTS
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Place to put very large netCDF test files. */
#undef TEMP_LARGE
/* Version number of package */
#undef VERSION
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES

469
src/lib/netcdfcpp.h Normal file
View File

@ -0,0 +1,469 @@
/*********************************************************************
* Copyright 1992, University Corporation for Atmospheric Research
* See netcdf/README file for copying and redistribution conditions.
*
* Purpose: C++ class interface for netCDF
*
* $Header: /upc/share/CVS/netcdf-3/cxx/netcdfcpp.h,v 1.15 2009/03/10 15:20:54 russ Exp $
*********************************************************************/
#ifndef NETCDF_HH
#define NETCDF_HH
#include "ncvalues.h" // arrays that know their element type
typedef const char* NcToken; // names for netCDF objects
typedef unsigned int NcBool; // many members return 0 on failure
class NcDim; // dimensions
class NcVar; // variables
class NcAtt; // attributes
/*
* ***********************************************************************
* A netCDF file.
* ***********************************************************************
*/
class NcFile
{
public:
virtual ~NcFile( void );
enum FileMode {
ReadOnly, // file exists, open read-only
Write, // file exists, open for writing
Replace, // create new file, even if already exists
New // create new file, fail if already exists
};
enum FileFormat {
Classic, // netCDF classic format (i.e. version 1 format)
Offset64Bits, // netCDF 64-bit offset format
Netcdf4, // netCDF-4 using HDF5 format
Netcdf4Classic, // netCDF-4 using HDF5 format using only netCDF-3 calls
BadFormat
};
NcFile( const char * path, FileMode = ReadOnly ,
size_t *bufrsizeptr = NULL, // optional tuning parameters
size_t initialsize = 0,
FileFormat = Classic );
NcBool is_valid( void ) const; // opened OK in ctr, still valid
int num_dims( void ) const; // number of dimensions
int num_vars( void ) const; // number of variables
int num_atts( void ) const; // number of (global) attributes
NcDim* get_dim( NcToken ) const; // dimension by name
NcVar* get_var( NcToken ) const; // variable by name
NcAtt* get_att( NcToken ) const; // global attribute by name
NcDim* get_dim( int ) const; // n-th dimension
NcVar* get_var( int ) const; // n-th variable
NcAtt* get_att( int ) const; // n-th global attribute
NcDim* rec_dim( void ) const; // unlimited dimension, if any
// Add new dimensions, variables, global attributes.
// These put the file in "define" mode, so could be expensive.
virtual NcDim* add_dim( NcToken dimname, long dimsize );
virtual NcDim* add_dim( NcToken dimname ); // unlimited
virtual NcVar* add_var( NcToken varname, NcType type, // scalar
const NcDim* dim0=0, // 1-dim
const NcDim* dim1=0, // 2-dim
const NcDim* dim2=0, // 3-dim
const NcDim* dim3=0, // 4-dim
const NcDim* dim4=0 ); // 5-dim
virtual NcVar* add_var( NcToken varname, NcType type, // n-dim
int ndims, const NcDim** dims );
NcBool add_att( NcToken attname, char ); // scalar attributes
NcBool add_att( NcToken attname, ncbyte );
NcBool add_att( NcToken attname, short );
NcBool add_att( NcToken attname, long );
NcBool add_att( NcToken attname, int );
NcBool add_att( NcToken attname, float );
NcBool add_att( NcToken attname, double );
NcBool add_att( NcToken attname, const char*); // string attribute
NcBool add_att( NcToken attname, int, const char* ); // vector attributes
NcBool add_att( NcToken attname, int, const ncbyte* );
NcBool add_att( NcToken attname, int, const short* );
NcBool add_att( NcToken attname, int, const long* );
NcBool add_att( NcToken attname, int, const int* );
NcBool add_att( NcToken attname, int, const float* );
NcBool add_att( NcToken attname, int, const double* );
enum FillMode {
Fill = NC_FILL, // prefill (default)
NoFill = NC_NOFILL, // don't prefill
Bad
};
NcBool set_fill( FillMode = Fill ); // set fill-mode
FillMode get_fill( void ) const; // get fill-mode
FileFormat get_format( void ) const; // get format version
NcBool sync( void ); // synchronize to disk
NcBool close( void ); // to close earlier than dtr
NcBool abort( void ); // back out of bad defines
// Needed by other Nc classes, but users will not need them
NcBool define_mode( void ); // leaves in define mode, if possible
NcBool data_mode( void ); // leaves in data mode, if possible
int id( void ) const; // id used by C interface
protected:
int the_id;
int in_define_mode;
FillMode the_fill_mode;
NcDim** dimensions;
NcVar** variables;
NcVar* globalv; // "variable" for global attributes
};
/*
* For backward compatibility. We used to derive NcOldFile and NcNewFile
* from NcFile, but that was over-zealous inheritance.
*/
#define NcOldFile NcFile
#define NcNewFile NcFile
#define Clobber Replace
#define NoClobber New
/*
* **********************************************************************
* A netCDF dimension, with a name and a size. These are only created
* by NcFile member functions, because they cannot exist independently
* of an open netCDF file.
* **********************************************************************
*/
class NcDim
{
public:
NcToken name( void ) const;
long size( void ) const;
NcBool is_valid( void ) const;
NcBool is_unlimited( void ) const;
NcBool rename( NcToken newname );
int id( void ) const;
NcBool sync( void );
private:
NcFile *the_file; // not const because of rename
int the_id;
char *the_name;
NcDim(NcFile*, int num); // existing dimension
NcDim(NcFile*, NcToken name, long sz); // defines a new dim
virtual ~NcDim( void );
// to construct dimensions, since constructor is private
friend class NcFile;
};
/*
* **********************************************************************
* Abstract base class for a netCDF variable or attribute, both of which
* have a name, a type, and associated values. These only exist as
* components of an open netCDF file.
* **********************************************************************
*/
class NcTypedComponent
{
public:
virtual ~NcTypedComponent( void ) {}
virtual NcToken name( void ) const = 0;
virtual NcType type( void ) const = 0;
virtual NcBool is_valid( void ) const = 0;
virtual long num_vals( void ) const = 0;
virtual NcBool rename( NcToken newname ) = 0;
virtual NcValues* values( void ) const = 0; // block of all values
// The following member functions provide conversions from the value
// type to a desired basic type. If the value is out of range,
// the default "fill-value" for the appropriate type is returned.
virtual ncbyte as_ncbyte( long n ) const; // nth value as an unsgnd char
virtual char as_char( long n ) const; // nth value as char
virtual short as_short( long n ) const; // nth value as short
virtual int as_int( long n ) const; // nth value as int
virtual int as_nclong( long n ) const; // nth value as nclong (deprecated)
virtual long as_long( long n ) const; // nth value as long
virtual float as_float( long n ) const; // nth value as floating-point
virtual double as_double( long n ) const; // nth value as double
virtual char* as_string( long n ) const; // nth value as string
protected:
NcFile *the_file;
NcTypedComponent( NcFile* );
virtual NcValues* get_space( long numVals = 0 ) const; // to hold values
};
/*
* **********************************************************************
* netCDF variables. In addition to a name and a type, these also have
* a shape, given by a list of dimensions
* **********************************************************************
*/
class NcVar : public NcTypedComponent
{
public:
virtual ~NcVar( void );
NcToken name( void ) const;
NcType type( void ) const;
NcBool is_valid( void ) const;
int num_dims( void ) const; // dimensionality of variable
NcDim* get_dim( int ) const; // n-th dimension
long* edges( void ) const; // dimension sizes
int num_atts( void ) const; // number of attributes
NcAtt* get_att( NcToken ) const; // attribute by name
NcAtt* get_att( int ) const; // n-th attribute
long num_vals( void ) const; // product of dimension sizes
NcValues* values( void ) const; // all values
// Put scalar or 1, ..., 5 dimensional arrays by providing enough
// arguments. Arguments are edge lengths, and their number must not
// exceed variable's dimensionality. Start corner is [0,0,..., 0] by
// default, but may be reset using the set_cur() member. FALSE is
// returned if type of values does not match type for variable.
NcBool put( const ncbyte* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const char* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const short* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const int* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const long* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const float* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
NcBool put( const double* vals,
long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
// Put n-dimensional arrays, starting at [0, 0, ..., 0] by default,
// may be reset with set_cur().
NcBool put( const ncbyte* vals, const long* counts );
NcBool put( const char* vals, const long* counts );
NcBool put( const short* vals, const long* counts );
NcBool put( const int* vals, const long* counts );
NcBool put( const long* vals, const long* counts );
NcBool put( const float* vals, const long* counts );
NcBool put( const double* vals, const long* counts );
// Get scalar or 1, ..., 5 dimensional arrays by providing enough
// arguments. Arguments are edge lengths, and their number must not
// exceed variable's dimensionality. Start corner is [0,0,..., 0] by
// default, but may be reset using the set_cur() member.
NcBool get( ncbyte* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( char* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( short* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( int* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( long* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( float* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
NcBool get( double* vals, long c0=0, long c1=0,
long c2=0, long c3=0, long c4=0 ) const;
// Get n-dimensional arrays, starting at [0, 0, ..., 0] by default,
// may be reset with set_cur().
NcBool get( ncbyte* vals, const long* counts ) const;
NcBool get( char* vals, const long* counts ) const;
NcBool get( short* vals, const long* counts ) const;
NcBool get( int* vals, const long* counts ) const;
NcBool get( long* vals, const long* counts ) const;
NcBool get( float* vals, const long* counts ) const;
NcBool get( double* vals, const long* counts ) const;
NcBool set_cur(long c0=-1, long c1=-1, long c2=-1,
long c3=-1, long c4=-1);
NcBool set_cur(long* cur);
// these put file in define mode, so could be expensive
NcBool add_att( NcToken, char ); // add scalar attributes
NcBool add_att( NcToken, ncbyte );
NcBool add_att( NcToken, short );
NcBool add_att( NcToken, int );
NcBool add_att( NcToken, long );
NcBool add_att( NcToken, float );
NcBool add_att( NcToken, double );
NcBool add_att( NcToken, const char* ); // string attribute
NcBool add_att( NcToken, int, const char* ); // vector attributes
NcBool add_att( NcToken, int, const ncbyte* );
NcBool add_att( NcToken, int, const short* );
NcBool add_att( NcToken, int, const int* );
NcBool add_att( NcToken, int, const long* );
NcBool add_att( NcToken, int, const float* );
NcBool add_att( NcToken, int, const double* );
NcBool rename( NcToken newname );
long rec_size ( void ); // number of values per record
long rec_size ( NcDim* ); // number of values per dimension slice
// Though following are intended for record variables, they also work
// for other variables, using first dimension as record dimension.
// Get a record's worth of data
NcValues *get_rec(void); // get current record
NcValues *get_rec(long rec); // get specified record
NcValues *get_rec(NcDim* d); // get current dimension slice
NcValues *get_rec(NcDim* d, long slice); // get specified dimension slice
// Put a record's worth of data in current record
NcBool put_rec( const ncbyte* vals );
NcBool put_rec( const char* vals );
NcBool put_rec( const short* vals );
NcBool put_rec( const int* vals );
NcBool put_rec( const long* vals );
NcBool put_rec( const float* vals );
NcBool put_rec( const double* vals );
// Put a dimension slice worth of data in current dimension slice
NcBool put_rec( NcDim* d, const ncbyte* vals );
NcBool put_rec( NcDim* d, const char* vals );
NcBool put_rec( NcDim* d, const short* vals );
NcBool put_rec( NcDim* d, const int* vals );
NcBool put_rec( NcDim* d, const long* vals );
NcBool put_rec( NcDim* d, const float* vals );
NcBool put_rec( NcDim* d, const double* vals );
// Put a record's worth of data in specified record
NcBool put_rec( const ncbyte* vals, long rec );
NcBool put_rec( const char* vals, long rec );
NcBool put_rec( const short* vals, long rec );
NcBool put_rec( const int* vals, long rec );
NcBool put_rec( const long* vals, long rec );
NcBool put_rec( const float* vals, long rec );
NcBool put_rec( const double* vals, long rec );
// Put a dimension slice worth of data in specified dimension slice
NcBool put_rec( NcDim* d, const ncbyte* vals, long slice );
NcBool put_rec( NcDim* d, const char* vals, long slice );
NcBool put_rec( NcDim* d, const short* vals, long slice );
NcBool put_rec( NcDim* d, const int* vals, long slice );
NcBool put_rec( NcDim* d, const long* vals, long slice );
NcBool put_rec( NcDim* d, const float* vals, long slice );
NcBool put_rec( NcDim* d, const double* vals, long slice );
// Get first record index corresponding to specified key value(s)
long get_index( const ncbyte* vals );
long get_index( const char* vals );
long get_index( const short* vals );
long get_index( const int* vals );
long get_index( const long* vals );
long get_index( const float* vals );
long get_index( const double* vals );
// Get first index of specified dimension corresponding to key values
long get_index( NcDim* d, const ncbyte* vals );
long get_index( NcDim* d, const char* vals );
long get_index( NcDim* d, const short* vals );
long get_index( NcDim* d, const int* vals );
long get_index( NcDim* d, const long* vals );
long get_index( NcDim* d, const float* vals );
long get_index( NcDim* d, const double* vals );
// Set current record
void set_rec ( long rec );
// Set current dimension slice
void set_rec ( NcDim* d, long slice );
int id( void ) const; // rarely needed, C interface id
NcBool sync( void );
private:
int dim_to_index(NcDim* rdim);
int the_id;
long* the_cur;
char* the_name;
long* cur_rec;
// private constructors because only an NcFile creates these
NcVar( void );
NcVar(NcFile*, int);
int attnum( NcToken attname ) const;
NcToken attname( int attnum ) const;
void init_cur( void );
// to make variables, since constructor is private
friend class NcFile;
};
/*
* **********************************************************************
* netCDF attributes. In addition to a name and a type, these are each
* associated with a specific variable, or are global to the file.
* **********************************************************************
*/
class NcAtt : public NcTypedComponent
{
public:
virtual ~NcAtt( void );
NcToken name( void ) const;
NcType type( void ) const;
NcBool is_valid( void ) const;
long num_vals( void ) const;
NcValues* values( void ) const;
NcBool rename( NcToken newname );
NcBool remove( void );
private:
const NcVar* the_variable;
char* the_name;
// protected constructors because only NcVars and NcFiles create
// attributes
NcAtt( NcFile*, const NcVar*, NcToken);
NcAtt( NcFile*, NcToken); // global attribute
// To make attributes, since constructor is private
friend class NcFile;
friend NcAtt* NcVar::get_att( NcToken ) const;
};
/*
* **********************************************************************
* To control error handling. Declaring an NcError object temporarily
* changes the error-handling behavior until the object is destroyed, at
* which time the previous error-handling behavior is restored.
* **********************************************************************
*/
class NcError {
public:
enum Behavior {
silent_nonfatal = 0,
silent_fatal = 1,
verbose_nonfatal = 2,
verbose_fatal = 3
};
// constructor saves previous error state, sets new state
NcError( Behavior b = verbose_fatal );
// destructor restores previous error state
virtual ~NcError( void );
int get_err( void ); // returns most recent error number
const char* get_errmsg( void ) {return nc_strerror(get_err());}
static int set_err( int err );
private:
int the_old_state;
int the_old_err;
static int ncopts;
static int ncerr;
};
#endif /* NETCDF_HH */