[MOAB-dev] commit/MOAB: danwu: Applied TIMESTEP write option to NC writer.
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Mon May 5 18:04:45 CDT 2014
1 new commit in MOAB:
https://bitbucket.org/fathomteam/moab/commits/6e49b0694060/
Changeset: 6e49b0694060
Branch: master
User: danwu
Date: 2014-05-06 01:04:31
Summary: Applied TIMESTEP write option to NC writer.
Affected #: 10 files
diff --git a/src/io/NCWriteHOMME.cpp b/src/io/NCWriteHOMME.cpp
index e2bb69e..1dd16d8 100644
--- a/src/io/NCWriteHOMME.cpp
+++ b/src/io/NCWriteHOMME.cpp
@@ -81,9 +81,9 @@ ErrorCode NCWriteHOMME::collect_mesh_info()
return MB_SUCCESS;
}
-ErrorCode NCWriteHOMME::collect_variable_data(std::vector<std::string>& var_names)
+ErrorCode NCWriteHOMME::collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
- NCWriteHelper::collect_variable_data(var_names);
+ NCWriteHelper::collect_variable_data(var_names, tstep_nums);
std::map<std::string, WriteNC::VarData>& varInfo = _writeNC->varInfo;
@@ -136,7 +136,7 @@ ErrorCode NCWriteHOMME::collect_variable_data(std::vector<std::string>& var_name
return MB_SUCCESS;
}
-ErrorCode NCWriteHOMME::write_values(std::vector<std::string>& var_names)
+ErrorCode NCWriteHOMME::write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
Interface*& mbImpl = _writeNC->mbImpl;
std::set<std::string>& usedCoordinates = _writeNC->usedCoordinates;
@@ -173,16 +173,14 @@ ErrorCode NCWriteHOMME::write_values(std::vector<std::string>& var_names)
// A typical variable has 3 dimensions as (time, lev, ncol)
// At each timestep, we need to transpose tag format (ncol, lev) back
// to NC format (lev, ncol) for writing
- // FIXME: Should use tstep_nums (from writing options) later
- int numTimeSteps = (int)variableData.varTags.size();
- for (int j = 0; j < numTimeSteps; j++) {
+ for (unsigned int t = 0; t < tstep_nums.size(); t++) {
// We will write one time step, and count will be one; start will be different
// Use tag_get_data instead of tag_iterate to get values, as localVertsOwned
// might not be contiguous. We should also transpose for level so that means
// deep copy for transpose
- variableData.writeStarts[0] = j; // This is time, again
+ variableData.writeStarts[0] = t; // This is time, again
std::vector<double> tag_data(num_local_verts_owned * variableData.numLev);
- ErrorCode rval = mbImpl->tag_get_data(variableData.varTags[j], localVertsOwned, &tag_data[0]);
+ ErrorCode rval = mbImpl->tag_get_data(variableData.varTags[t], localVertsOwned, &tag_data[0]);
ERRORR(rval, "Trouble getting tag data on owned vertices.");
#ifdef PNETCDF_FILE
diff --git a/src/io/NCWriteHOMME.hpp b/src/io/NCWriteHOMME.hpp
index 7bb99d9..ad689f5 100644
--- a/src/io/NCWriteHOMME.hpp
+++ b/src/io/NCWriteHOMME.hpp
@@ -26,10 +26,10 @@ private:
virtual ErrorCode collect_mesh_info();
//! Collect data for specified variables
- virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names);
+ virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
//! Implementation of NCWriteHelper::write_values()
- virtual ErrorCode write_values(std::vector<std::string>& var_names);
+ virtual ErrorCode write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
};
} // namespace moab
diff --git a/src/io/NCWriteHelper.cpp b/src/io/NCWriteHelper.cpp
index 1b4b70d..5ccf302 100644
--- a/src/io/NCWriteHelper.cpp
+++ b/src/io/NCWriteHelper.cpp
@@ -41,7 +41,7 @@ NCWriteHelper* NCWriteHelper::get_nc_helper(WriteNC* writeNC, int fileId, const
return NULL;
}
-ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_names)
+ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
Interface*& mbImpl = _writeNC->mbImpl;
std::vector<std::string>& dimNames = _writeNC->dimNames;
@@ -55,6 +55,12 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
usedCoordinates.clear();
+ if (tstep_nums.empty() && nTimeSteps > 0) {
+ // No timesteps input, get them all
+ for (int i = 0; i < nTimeSteps; i++)
+ tstep_nums.push_back(i);
+ }
+
for (size_t i = 0; i < var_names.size(); i++) {
std::string varname = var_names[i];
std::map<std::string, WriteNC::VarData>::iterator vit = varInfo.find(varname);
@@ -89,18 +95,14 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
// Process non-set variables with time steps
if (currentVarData.has_tsteps) {
- int index = 0;
- // FIXME: Should use tstep_nums (from writing options) later
- while (true) {
+ for (unsigned int t = 0; t < tstep_nums.size(); t++) {
Tag indexedTag = 0;
std::stringstream ssTagNameWithIndex;
- ssTagNameWithIndex << varname << index;
+ ssTagNameWithIndex << varname << tstep_nums[t];
rval = mbImpl->tag_get_handle(ssTagNameWithIndex.str().c_str(), indexedTag);
- if (MB_SUCCESS != rval)
- break;
- dbgOut.tprintf(2, " found indexed tag %d with name %s\n", index, ssTagNameWithIndex.str().c_str());
+ ERRORR(rval, "Can't find one tag.");
+ dbgOut.tprintf(2, " found indexed tag %d with name %s\n", tstep_nums[t], ssTagNameWithIndex.str().c_str());
currentVarData.varTags.push_back(indexedTag);
- index++; // We should get out of the loop at some point
// The type of the tag is fixed though
DataType type;
@@ -172,6 +174,14 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
dbgOut.tprintf(2, " found coordinate tag with name %s and length %d\n", coordName.c_str(),
sizeCoordinate);
+ // Find the type of tag, and use it
+ DataType type;
+ rval = mbImpl->tag_get_data_type(coordTag, type);
+ ERRORR(rval, "Can't get tag type.");
+ varCoordData.varDataType = NC_DOUBLE;
+ if (MB_TYPE_INTEGER == type)
+ varCoordData.varDataType = NC_INT;
+
// Get dimension length (the only dimension of this coordinate variable, with the same name)
assert(1 == varCoordData.varDims.size());
int coordDimLen = dimLens[varCoordData.varDims[0]];
@@ -181,12 +191,30 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
// The number of coordinates should be set to dimension length, instead of 1
assert(1 == sizeCoordinate);
sizeCoordinate = coordDimLen;
+
+ // No variable data to write
+ data = NULL;
}
else {
// The number of coordinates should be exactly the same as dimension length
assert(sizeCoordinate == coordDimLen);
}
+ // For time, the actual output size and values are determined by tstep_nums
+ if (varCoordData.varDims[0] == tDim) {
+ assert(tstep_nums.size() > 0 && tstep_nums.size() <= (size_t)sizeCoordinate);
+ sizeCoordinate = tstep_nums.size();
+
+ if (NULL != data) {
+ assert(NC_DOUBLE == varCoordData.varDataType);
+ timeStepVals.resize(sizeCoordinate);
+ for (unsigned int t = 0; t < tstep_nums.size(); t++)
+ timeStepVals[t] = ((double*)data)[tstep_nums[t]];
+
+ data = &timeStepVals[0];
+ }
+ }
+
// This is the length
varCoordData.sz = sizeCoordinate;
varCoordData.writeStarts.resize(1);
@@ -194,15 +222,6 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
varCoordData.writeCounts.resize(1);
varCoordData.writeCounts[0] = sizeCoordinate;
- // Find the type of tag, and use it
- DataType type;
- rval = mbImpl->tag_get_data_type(coordTag, type);
- ERRORR(rval, "Can't get tag type.");
-
- varCoordData.varDataType = NC_DOUBLE;
- if (MB_TYPE_INTEGER == type)
- varCoordData.varDataType = NC_INT;
-
assert(0 == varCoordData.memoryHogs.size()); // Nothing so far
varCoordData.memoryHogs.push_back((void*)data);
}
@@ -474,9 +493,9 @@ ErrorCode ScdNCWriteHelper::collect_mesh_info()
return MB_SUCCESS;
}
-ErrorCode ScdNCWriteHelper::collect_variable_data(std::vector<std::string>& var_names)
+ErrorCode ScdNCWriteHelper::collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
- NCWriteHelper::collect_variable_data(var_names);
+ NCWriteHelper::collect_variable_data(var_names, tstep_nums);
std::map<std::string, WriteNC::VarData>& varInfo = _writeNC->varInfo;
@@ -534,7 +553,7 @@ ErrorCode ScdNCWriteHelper::collect_variable_data(std::vector<std::string>& var_
// For CAM-EUL and CAM-FV variables on non-shared quads (e.g. T), this is not an issue
// We assume that there are no variables on vertices and we do not support variables
// on edges (e.g. US in CAM-FV) for the time being
-ErrorCode ScdNCWriteHelper::write_values(std::vector<std::string>& var_names)
+ErrorCode ScdNCWriteHelper::write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
Interface*& mbImpl = _writeNC->mbImpl;
std::set<std::string>& usedCoordinates = _writeNC->usedCoordinates;
@@ -553,7 +572,6 @@ ErrorCode ScdNCWriteHelper::write_values(std::vector<std::string>& var_names)
ERRORR(MB_FAILURE, "Can't find variable requested.");
WriteNC::VarData& variableData = vit->second;
- int numTimeSteps = (int)variableData.varTags.size();
if (variableData.has_tsteps) {
// Time should be the first dimension
assert(tDim == variableData.varDims[0]);
@@ -575,15 +593,15 @@ ErrorCode ScdNCWriteHelper::write_values(std::vector<std::string>& var_names)
size_t nk = variableData.writeCounts[1]; // lev
variableData.writeCounts[0] = 1; // We will write one time step
- // FIXME: Should use tstep_nums (from writing options) later
- for (int j = 0; j < numTimeSteps; j++) {
+
+ for (unsigned int t = 0; t < tstep_nums.size(); t++) {
// We will write one time step, and count will be one; start will be different
// We will write values directly from tag_iterate, but we should also transpose for level
// so that means deep copy for transpose
- variableData.writeStarts[0] = j; // This is time, again
+ variableData.writeStarts[0] = t; // This is time, again
int count;
void* dataptr;
- ErrorCode rval = mbImpl->tag_iterate(variableData.varTags[j], localCellsOwned.begin(), localCellsOwned.end(), count, dataptr);
+ ErrorCode rval = mbImpl->tag_iterate(variableData.varTags[t], localCellsOwned.begin(), localCellsOwned.end(), count, dataptr);
ERRORR(rval, "Failed to get tag iterator on owned faces.");
assert(count == (int)localCellsOwned.size());
diff --git a/src/io/NCWriteHelper.hpp b/src/io/NCWriteHelper.hpp
index 8c64eac..ff28da1 100644
--- a/src/io/NCWriteHelper.hpp
+++ b/src/io/NCWriteHelper.hpp
@@ -27,10 +27,10 @@ public:
virtual ErrorCode collect_mesh_info() = 0;
//! Collect data for specified variables
- virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names);
+ virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
//! Take the info from VarData and write first the coordinates, then the actual variables
- virtual ErrorCode write_values(std::vector<std::string>& var_names) = 0;
+ virtual ErrorCode write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums) = 0;
//! Initialize file: this is where all defines are done
//! The VarData dimension ids are filled up after define
@@ -63,6 +63,9 @@ protected:
//! Local owned cells, edges and vertices
Range localCellsOwned, localEdgesOwned, localVertsOwned;
+
+ //! Time values of output timesteps
+ std::vector<double> timeStepVals;
};
//! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
@@ -84,10 +87,10 @@ private:
virtual ErrorCode collect_mesh_info();
//! Collect data for specified variables
- virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names);
+ virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
//! Implementation of NCWriteHelper::write_values()
- virtual ErrorCode write_values(std::vector<std::string>& var_names);
+ virtual ErrorCode write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
protected:
//! Dimensions of my local part of grid
diff --git a/src/io/NCWriteMPAS.cpp b/src/io/NCWriteMPAS.cpp
index 8fca53d..36b2a65 100644
--- a/src/io/NCWriteMPAS.cpp
+++ b/src/io/NCWriteMPAS.cpp
@@ -117,9 +117,9 @@ ErrorCode NCWriteMPAS::collect_mesh_info()
return MB_SUCCESS;
}
-ErrorCode NCWriteMPAS::collect_variable_data(std::vector<std::string>& var_names)
+ErrorCode NCWriteMPAS::collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
- NCWriteHelper::collect_variable_data(var_names);
+ NCWriteHelper::collect_variable_data(var_names, tstep_nums);
std::vector<std::string>& dimNames = _writeNC->dimNames;
std::vector<int>& dimLens = _writeNC->dimLens;
@@ -231,7 +231,7 @@ ErrorCode NCWriteMPAS::collect_variable_data(std::vector<std::string>& var_names
return MB_SUCCESS;
}
-ErrorCode NCWriteMPAS::write_values(std::vector<std::string>& var_names)
+ErrorCode NCWriteMPAS::write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
{
Interface*& mbImpl = _writeNC->mbImpl;
std::set<std::string>& usedCoordinates = _writeNC->usedCoordinates;
@@ -282,15 +282,13 @@ ErrorCode NCWriteMPAS::write_values(std::vector<std::string>& var_names)
}
// A typical variable has 3 dimensions as (Time, nCells, nVertLevels)
- // FIXME: Should use tstep_nums (from writing options) later
- int numTimeSteps = (int)variableData.varTags.size();
- for (int j = 0; j < numTimeSteps; j++) {
+ for (unsigned int t = 0; t < tstep_nums.size(); t++) {
// We will write one time step, and count will be one; start will be different
// Use tag_get_data instead of tag_iterate to get values, as localEntsOwned
// might not be contiguous.
- variableData.writeStarts[0] = j; // This is time, again
+ variableData.writeStarts[0] = t; // This is time, again
std::vector<double> tag_data(pLocalEntsOwned->size() * variableData.numLev);
- ErrorCode rval = mbImpl->tag_get_data(variableData.varTags[j], *pLocalEntsOwned, &tag_data[0]);
+ ErrorCode rval = mbImpl->tag_get_data(variableData.varTags[t], *pLocalEntsOwned, &tag_data[0]);
ERRORR(rval, "Trouble getting tag data on owned vertices.");
#ifdef PNETCDF_FILE
diff --git a/src/io/NCWriteMPAS.hpp b/src/io/NCWriteMPAS.hpp
index 3c145cf..757a76b 100644
--- a/src/io/NCWriteMPAS.hpp
+++ b/src/io/NCWriteMPAS.hpp
@@ -26,10 +26,10 @@ private:
virtual ErrorCode collect_mesh_info();
//! Collect data for specified variables
- virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names);
+ virtual ErrorCode collect_variable_data(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
//! Implementation of NCWriteHelper::write_values()
- virtual ErrorCode write_values(std::vector<std::string>& var_names);
+ virtual ErrorCode write_values(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
};
} // namespace moab
diff --git a/src/io/WriteNC.cpp b/src/io/WriteNC.cpp
index ca63367..21a2c19 100644
--- a/src/io/WriteNC.cpp
+++ b/src/io/WriteNC.cpp
@@ -132,13 +132,13 @@ ErrorCode WriteNC::write_file(const char* file_name,
rval = myHelper->collect_mesh_info();
ERRORR(rval, "Trouble collecting mesh info.");
- rval = myHelper->collect_variable_data(var_names);
+ rval = myHelper->collect_variable_data(var_names, tstep_nums);
ERRORR(rval, "Trouble collecting variable data.");
rval = myHelper->init_file(var_names, desired_names, append);
ERRORR(rval, "Failed to initialize file.");
- rval = myHelper->write_values(var_names);
+ rval = myHelper->write_values(var_names, tstep_nums);
ERRORR(rval, "Failed to write values.");
success = NCFUNC(close)(fileId);
diff --git a/test/io/Makefile.am b/test/io/Makefile.am
index 256c8f2..b33eed8 100644
--- a/test/io/Makefile.am
+++ b/test/io/Makefile.am
@@ -93,5 +93,6 @@ MOSTLYCLEANFILES = dumped_acis.sat \
test_fv_T.nc \
test_homme_T.nc \
test_mpas_vars.nc \
+ test_eul_T2.nc \
test_eul_append.nc \
test_eul_ghosting.nc
diff --git a/test/io/write_nc.cpp b/test/io/write_nc.cpp
index 96ff728..c71b6c8 100644
--- a/test/io/write_nc.cpp
+++ b/test/io/write_nc.cpp
@@ -46,6 +46,10 @@ void test_homme_check_T();
void test_mpas_read_write_vars();
void test_mpas_check_vars();
+// Test timestep option
+void test_eul_read_write_timestep();
+void test_eul_check_timestep();
+
// Test append option
void test_eul_read_write_append();
void test_eul_check_append();
@@ -85,6 +89,9 @@ int main(int argc, char* argv[])
result += RUN_TEST(test_mpas_read_write_vars);
result += RUN_TEST(test_mpas_check_vars);
+ result += RUN_TEST(test_eul_read_write_timestep);
+ result += RUN_TEST(test_eul_check_timestep);
+
result += RUN_TEST(test_eul_read_write_append);
result += RUN_TEST(test_eul_check_append);
@@ -708,6 +715,118 @@ void test_mpas_check_vars()
}
}
+// Read non-set variable T on all 3 timesteps, and write only timestep 2
+void test_eul_read_write_timestep()
+{
+ int procs = 1;
+#ifdef USE_MPI
+ MPI_Comm_size(MPI_COMM_WORLD, &procs);
+#endif
+
+// We will not test NC writer in parallel without pnetcdf support
+#ifndef PNETCDF_FILE
+ if (procs > 1)
+ return;
+#endif
+
+ Core moab;
+ Interface& mb = moab;
+
+ std::string read_opts;
+ get_eul_read_options(read_opts);
+
+ EntityHandle set;
+ ErrorCode rval = mb.create_meshset(MESHSET_SET, set);
+ CHECK_ERR(rval);
+
+ // Read non-set variable T
+ read_opts += ";VARIABLE=T;DEBUG_IO=0";
+ rval = mb.load_file(example_eul, &set, read_opts.c_str());
+ CHECK_ERR(rval);
+
+ // Write variable T on timestep 2
+ std::string write_opts = ";;VARIABLE=T;TIMESTEP=2;DEBUG_IO=0";
+#ifdef USE_MPI
+ // Use parallel options
+ write_opts += ";PARALLEL=WRITE_PART";
+#endif
+ if (procs > 1)
+ rval = mb.write_file("test_par_eul_T2.nc", 0, write_opts.c_str(), &set, 1);
+ else
+ rval = mb.write_file("test_eul_T2.nc", 0, write_opts.c_str(), &set, 1);
+ CHECK_ERR(rval);
+}
+
+void test_eul_check_timestep()
+{
+ int rank = 0;
+ int procs = 1;
+#ifdef USE_MPI
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &procs);
+#endif
+
+// We will not test NC writer in parallel without pnetcdf support
+#ifndef PNETCDF_FILE
+ if (procs > 1)
+ return;
+#endif
+
+ if (0 == rank) {
+ int ncid;
+ int success;
+
+ std::string filename;
+ if (procs > 1)
+ filename = "test_par_eul_T2.nc";
+ else
+ filename = "test_eul_T2.nc";
+
+#ifdef PNETCDF_FILE
+ success = NCFUNC(open)(MPI_COMM_SELF, filename.c_str(), NC_NOWRITE, MPI_INFO_NULL, &ncid);
+#else
+ success = NCFUNC(open)(filename.c_str(), NC_NOWRITE, &ncid);
+#endif
+ CHECK_EQUAL(0, success);
+
+ int T_id;
+ success = NCFUNC(inq_varid)(ncid, "T", &T_id);
+ CHECK_EQUAL(0, success);
+
+#ifdef PNETCDF_FILE
+ // Enter independent I/O mode
+ success = NCFUNC(begin_indep_data)(ncid);
+ CHECK_EQUAL(0, success);
+#endif
+
+ NCDF_SIZE start[] = {0, 0, 0, 0};
+ NCDF_SIZE count[] = {1, 1, 48, 96}; // Read one timestep and one level
+
+ // Read variable T on 48 * 96 quads (first level)
+ double T_vals_lev1[48 * 96];
+ success = NCFUNC(get_vara_double)(ncid, T_id, start, count, T_vals_lev1);
+ CHECK_EQUAL(0, success);
+
+#ifdef PNETCDF_FILE
+ // End independent I/O mode
+ success = NCFUNC(end_indep_data)(ncid);
+ CHECK_EQUAL(0, success);
+#endif
+
+ double eps = 0.0001;
+
+ // Check T values at some strategically chosen places (first level)
+ // Timestep 2
+ CHECK_REAL_EQUAL(224.1966, T_vals_lev1[0], eps); // First quad
+ CHECK_REAL_EQUAL(236.1357, T_vals_lev1[2303], eps); // Median quad
+ CHECK_REAL_EQUAL(235.9430, T_vals_lev1[2304], eps); // Median quad
+ CHECK_REAL_EQUAL(218.7719, T_vals_lev1[4607], eps); // Last quad
+
+ success = NCFUNC(close)(ncid);
+ CHECK_EQUAL(0, success);
+ }
+}
+
// Read non-set variables T, U and V
// Write variable T, append U, and then append V (with a new name)
void test_eul_read_write_append()
diff --git a/test/parallel/Makefile.am b/test/parallel/Makefile.am
index db37e48..c0824c9 100644
--- a/test/parallel/Makefile.am
+++ b/test/parallel/Makefile.am
@@ -125,5 +125,6 @@ MOSTLYCLEANFILES = mhdf_ll.h5m tmp0.h5m tmp1.h5m tmp2.h5m tmp3.h5m \
test_par_fv_T.nc \
test_par_homme_T.nc \
test_par_mpas_vars.nc \
+ test_par_eul_T2.nc \
test_par_eul_append.nc \
test_par_eul_ghosting.nc
Repository URL: https://bitbucket.org/fathomteam/moab/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the moab-dev
mailing list