[MOAB-dev] commit/MOAB: danwu: Updated NC reader and writer to support reading variables whose timesteps spread across files and writing them to a file.

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Thu May 15 12:57:31 CDT 2014


1 new commit in MOAB:

https://bitbucket.org/fathomteam/moab/commits/a5907807ffc2/
Changeset:   a5907807ffc2
Branch:      master
User:        danwu
Date:        2014-05-15 19:57:18
Summary:     Updated NC reader and writer to support reading variables whose timesteps spread across files and writing them to a file.

Affected #:  5 files

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 59d6df4..ccca80c 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -61,7 +61,8 @@ NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions&
   return NULL;
 }
 
-ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums) {
+ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
+{
   Interface*& mbImpl = _readNC->mbImpl;
   std::vector<std::string>& dimNames = _readNC->dimNames;
   std::vector<int>& dimLens = _readNC->dimLens;
@@ -327,6 +328,58 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
   return MB_SUCCESS;
 }
 
+ErrorCode NCHelper::update_time_tag_vals()
+{
+  Interface*& mbImpl = _readNC->mbImpl;
+  std::vector<std::string>& dimNames = _readNC->dimNames;
+
+  ErrorCode rval;
+
+  // The time tag might be a dummy one (e.g. 'Time' for MPAS)
+  std::string time_tag_name = dimNames[tDim];
+  if (dummyVarNames.find(time_tag_name) != dummyVarNames.end())
+    return MB_SUCCESS;
+
+  Tag time_tag = 0;
+  const void* data = NULL;
+  int time_tag_size = 0;
+  rval = mbImpl->tag_get_handle(time_tag_name.c_str(), 0, MB_TYPE_DOUBLE, time_tag, MB_TAG_VARLEN);
+  ERRORR(rval, "Trouble getting time tag.");
+  rval = mbImpl->tag_get_by_ptr(time_tag, &_fileSet, 1, &data, &time_tag_size);
+  ERRORR(rval, "Trouble getting values for time tag.");
+  const double* time_tag_vals = static_cast<const double*>(data);
+
+  // Merge tVals (read from current file) to existing time tag
+  // Assume that time_tag_vals and tVals are both sorted
+  std::vector<double> merged_time_vals;
+  merged_time_vals.reserve(time_tag_size + nTimeSteps);
+  int i = 0;
+  int j = 0;
+
+  // Merge time values from time_tag_vals and tVals
+  while (i < time_tag_size && j < nTimeSteps) {
+    if (time_tag_vals[i] < tVals[j])
+      merged_time_vals.push_back(time_tag_vals[i++]);
+    else
+      merged_time_vals.push_back(tVals[j++]);
+  }
+
+  // Append remaining time values of time_tag_vals (if any)
+  while (i < time_tag_size)
+    merged_time_vals.push_back(time_tag_vals[i++]);
+
+  // Append remaining time values of tVals (if any)
+  while (j < nTimeSteps)
+    merged_time_vals.push_back(tVals[j++]);
+
+  data = &merged_time_vals[0];
+  time_tag_size = merged_time_vals.size();
+  rval = mbImpl->tag_set_by_ptr(time_tag, &_fileSet, 1, &data, &time_tag_size);
+  ERRORR(rval, "Failed to set data for time tag.");
+
+  return MB_SUCCESS;
+}
+
 ErrorCode NCHelper::read_variable_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
                                         std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
 {
@@ -636,6 +689,10 @@ ErrorCode NCHelper::get_tag_to_set(ReadNC::VarData& var_data, int tstep_num, Tag
 {
   Interface*& mbImpl = _readNC->mbImpl;
   DebugOutput& dbgOut = _readNC->dbgOut;
+  int& tStepBase = _readNC->tStepBase;
+
+  if (tStepBase > 0)
+    tstep_num += tStepBase;
 
   std::ostringstream tag_name;
   if (var_data.has_tsteps)
@@ -673,6 +730,10 @@ ErrorCode NCHelper::get_tag_to_nonset(ReadNC::VarData& var_data, int tstep_num,
 {
   Interface*& mbImpl = _readNC->mbImpl;
   DebugOutput& dbgOut = _readNC->dbgOut;
+  int& tStepBase = _readNC->tStepBase;
+
+  if (tStepBase > 0)
+    tstep_num += tStepBase;
 
   std::ostringstream tag_name;
   tag_name << var_data.varName << tstep_num;

diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 817257c..d134249 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -35,6 +35,9 @@ public:
   //! Create NC conventional tags
   ErrorCode create_conventional_tags(const std::vector<int>& tstep_nums);
 
+  //! Update time tag values if timesteps spread across files
+  ErrorCode update_time_tag_vals();
+
 protected:
   //! Separate set and non-set variables (common to scd mesh and ucd mesh)
   ErrorCode read_variable_setup(std::vector<std::string>& var_names,

diff --git a/src/io/NCWriteHelper.cpp b/src/io/NCWriteHelper.cpp
index 635b595..028bce4 100644
--- a/src/io/NCWriteHelper.cpp
+++ b/src/io/NCWriteHelper.cpp
@@ -224,12 +224,19 @@ ErrorCode NCWriteHelper::collect_variable_data(std::vector<std::string>& var_nam
     }
     else {
       // The number of coordinates should be exactly the same as dimension length
-      assert(sizeCoordinate == coordDimLen);
+      // However, if timesteps spread across files and time tag has been updated,
+      // sizeCoordinate will be larger
+      if (varCoordData.varDims[0] != tDim)
+        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);
+      // Does not apply to dummy time tag (e.g. 'Time' tag of MPAS), when timesteps
+      // spread across files
+      if (NULL != data)
+        assert(tstep_nums.size() > 0 && tstep_nums.size() <= (size_t)sizeCoordinate);
+
       sizeCoordinate = tstep_nums.size();
 
       if (NULL != data) {

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index 0a41cfa..98bf6b3 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -25,7 +25,7 @@ ReadNC::ReadNC(Interface* impl) :
   myPcomm(NULL),
 #endif
   noMesh(false), noVars(false), spectralMesh(false), noMixedElements(false), noEdges(false),
-  gatherSetRank(-1), myHelper(NULL)
+  gatherSetRank(-1), tStepBase(-1), myHelper(NULL)
 {
   assert(impl != NULL);
   impl->query_interface(readMeshIface);
@@ -119,7 +119,9 @@ ErrorCode ReadNC::load_file(const char* file_name, const EntityHandle* file_set,
   }
 
   // Create some conventional tags, e.g. __NUM_DIMS
-  // Keep a flag on the file set to prevent conventional tags from being created again on a second read
+  // For multiple reads to a specified file set, we assume a single file, or a series of
+  // files with separated timesteps. Keep a flag on the file set to prevent conventional
+  // tags from being created again on a second read
   Tag convTagsCreated = 0;
   int def_val = 0;
   rval = mbImpl->tag_get_handle("__CONV_TAGS_CREATED", 1, MB_TYPE_INTEGER, convTagsCreated,
@@ -127,6 +129,7 @@ ErrorCode ReadNC::load_file(const char* file_name, const EntityHandle* file_set,
   ERRORR(rval, "Trouble getting _CONV_TAGS_CREATED tag.");
   int create_conv_tags_flag = 0;
   rval = mbImpl->tag_get_data(convTagsCreated, &tmp_set, 1, &create_conv_tags_flag);
+  // The first read to the file set
   if (0 == create_conv_tags_flag) {
     // Read dimension variables to create tags like __<var_name>_DIMS
     rval = myHelper->read_variables(dimNames, tstep_nums);
@@ -139,6 +142,15 @@ ErrorCode ReadNC::load_file(const char* file_name, const EntityHandle* file_set,
     rval = mbImpl->tag_set_data(convTagsCreated, &tmp_set, 1, &create_conv_tags_flag);
     ERRORR(rval, "Trouble setting data for _CONV_TAGS_CREATED tag.");
   }
+  // Another read to the file set
+  else {
+    if (tStepBase > -1) {
+      // If timesteps spread across files, merge time values read
+      // from current file to existing time tag
+      rval = myHelper->update_time_tag_vals();
+      ERRORR(rval, "Trouble updating time tag values.");
+    }
+  }
 
   // Create mesh vertex/edge/face sequences
   Range faces;
@@ -205,8 +217,10 @@ ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string
     noVars = true;
   else
     noVars = false;
+
   opts.get_ints_option("TIMESTEP", tstep_nums);
   opts.get_reals_option("TIMEVAL", tstep_vals);
+
   rval = opts.get_null_option("NOMESH");
   if (MB_SUCCESS == rval)
     noMesh = true;
@@ -230,12 +244,14 @@ ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string
         std::cerr << var_names[i];
       std::cerr << std::endl;
     }
+
     if (!tstep_nums.empty()) {
       std::cerr << "Timesteps requested: ";
       for (unsigned int i = 0; i < tstep_nums.size(); i++)
         std::cerr << tstep_nums[i];
       std::cerr << std::endl;
     }
+
     if (!tstep_vals.empty()) {
       std::cerr << "Time vals requested: ";
       for (unsigned int i = 0; i < tstep_vals.size(); i++)
@@ -250,6 +266,12 @@ ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string
     return rval;
   }
 
+  rval = opts.get_int_option("TIMESTEPBASE", 0, tStepBase);
+  if (MB_TYPE_OUT_OF_RANGE == rval) {
+    readMeshIface->report_error("Invalid value for TIMESTEPBASE option");
+    return rval;
+  }
+
 #ifdef USE_MPI
   isParallel = (opts.match_option("PARALLEL","READ_PART") != MB_ENTITY_NOT_FOUND);
 

diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index 1a0ae91..1b81d15 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -208,6 +208,7 @@ private:
   bool noMixedElements;
   bool noEdges;
   int gatherSetRank;
+  int tStepBase;
 
   //! Helper class instance
   NCHelper* myHelper;

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