[MOAB-dev] commit/MOAB: 2 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Sat Mar 29 07:41:10 CDT 2014


2 new commits in MOAB:

https://bitbucket.org/fathomteam/moab/commits/c2765784f964/
Changeset:   c2765784f964
Branch:      None
User:        iulian07
Date:        2014-03-29 04:56:25
Summary:     first pass at nc writer

need to finish processing conventional tags, and form the
VarData and global attributes structure
a test is added for writing a temperature after reading

Affected #:  10 files

diff --git a/src/ReaderWriterSet.cpp b/src/ReaderWriterSet.cpp
index 5015a7f..1f254b0 100644
--- a/src/ReaderWriterSet.cpp
+++ b/src/ReaderWriterSet.cpp
@@ -48,6 +48,7 @@
 #ifdef NETCDF_FILE
 #  include "ReadNCDF.hpp"
 #  include "WriteNCDF.hpp"
+#  include "WriteNC.hpp"
 #  include "WriteSLAC.hpp"
 #  include "ReadNC.hpp"
 #  include "ReadGCRM.hpp"
@@ -105,7 +106,7 @@ ReaderWriterSet::ReaderWriterSet( Core* mdb, Error* handler )
   const char* exo_sufxs[] = { "exo", "exoII", "exo2", "g", "gen", NULL };
   register_factory( ReadNCDF::factory, WriteNCDF::factory, "Exodus II", exo_sufxs, "EXODUS" );
   register_factory( ReadGCRM::factory, NULL, "GCRM NC", "nc", "GCRM" );
-  register_factory( ReadNC::factory, NULL, "Climate NC", "nc", "NC" );
+  register_factory( ReadNC::factory, WriteNC::factory, "Climate NC", "nc", "NC" );
 #endif
 
 #ifdef CGNS_FILE

diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index 09fe3d3..232de85 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -15,6 +15,9 @@ AM_CPPFLAGS += -DIS_BUILDING_MB \
 if NETCDF_FILE
   MOAB_NETCDF_SRCS = ReadNCDF.cpp  ReadNCDF.hpp \
                      WriteNCDF.cpp WriteNCDF.hpp \
+                     WriteNC.cpp WriteNC.hpp \
+                     NCWriteHelper.cpp NCWriteHelper.hpp \
+                     NCWriteEuler.cpp NCWriteEuler.hpp \
                      WriteSLAC.cpp WriteSLAC.hpp \
                      ReadNC.cpp ReadNC.hpp \
                      NCHelper.cpp NCHelper.hpp \

diff --git a/src/io/NCWriteEuler.cpp b/src/io/NCWriteEuler.cpp
new file mode 100644
index 0000000..f17727b
--- /dev/null
+++ b/src/io/NCWriteEuler.cpp
@@ -0,0 +1,16 @@
+/*
+ * NCWriteEuler.cpp
+ *
+ *  Created on: Mar 28, 2014
+ */
+
+#include "NCWriteEuler.hpp"
+
+namespace moab {
+
+NCWriteEuler::~NCWriteEuler()
+{
+  // TODO Auto-generated destructor stub
+}
+
+} /* namespace moab */

diff --git a/src/io/NCWriteEuler.hpp b/src/io/NCWriteEuler.hpp
new file mode 100644
index 0000000..3e7f728
--- /dev/null
+++ b/src/io/NCWriteEuler.hpp
@@ -0,0 +1,25 @@
+/*
+ * NCWriteEuler.hpp
+ *
+ *  nc write helper for euler type data (CAM)
+ *  Created on: Mar 28, 2014
+ *
+ */
+
+#ifndef NCWRITEEULER_HPP_
+#define NCWRITEEULER_HPP_
+
+#include "NCWriteHelper.hpp"
+
+namespace moab {
+
+class NCWriteEuler: public NCWriteHelper
+{
+public:
+  NCWriteEuler(WriteNC* writeNC,  const FileOptions& opts, EntityHandle fileSet) :
+    NCWriteHelper(writeNC, opts, fileSet) {};
+  virtual ~NCWriteEuler();
+};
+
+} /* namespace moab */
+#endif /* NCWRITEEULER_HPP_ */

diff --git a/src/io/NCWriteHelper.cpp b/src/io/NCWriteHelper.cpp
new file mode 100644
index 0000000..37817d8
--- /dev/null
+++ b/src/io/NCWriteHelper.cpp
@@ -0,0 +1,22 @@
+/*
+ * NCWriteHelper.cpp
+ *
+ *  Created on: Mar 28, 2014
+ *      Author: iulian
+ */
+
+#include "NCWriteHelper.hpp"
+#include "NCWriteEuler.hpp"
+
+namespace moab {
+
+//! Get appropriate helper instance for WriteNC class; based on some info in the file set
+NCWriteHelper* NCWriteHelper::get_nc_helper(WriteNC* writeNC, const FileOptions& opts, EntityHandle fileSet)
+{
+
+  // right now, get a cam euler helper
+  return new (std::nothrow) NCWriteEuler(writeNC, opts, fileSet);
+}
+
+
+} /* namespace moab */

diff --git a/src/io/NCWriteHelper.hpp b/src/io/NCWriteHelper.hpp
new file mode 100644
index 0000000..54ce967
--- /dev/null
+++ b/src/io/NCWriteHelper.hpp
@@ -0,0 +1,206 @@
+/*
+ * NCWriteHelper.hpp
+ *
+ * Purpose       : Climate NC writer file helper; abstract, will be implemented for each type
+ *
+ *  Created on: Mar 28, 2014
+ */
+
+#ifndef NCWRITEHELPER_HPP_
+#define NCWRITEHELPER_HPP_
+#include "WriteNC.hpp"
+
+namespace moab {
+
+class NCWriteHelper
+{
+public:
+  NCWriteHelper(WriteNC* writeNC, const FileOptions& opts, EntityHandle fileSet)
+  :_writeNC(writeNC), _opts(opts), _fileSet(fileSet),
+    nTimeSteps(0), nLevels(1), tDim(-1), levDim(-1) {}
+  virtual ~NCWriteHelper() {};
+
+  //! Get appropriate helper instance for WriteNC class; based on some info in the
+  static NCWriteHelper* get_nc_helper(WriteNC* readNC, const FileOptions& opts, EntityHandle fileSet);
+
+  //! process NC conventional tags
+  ErrorCode process_conventional_tags(EntityHandle fileSet);
+protected:
+  //! Allow NCWriteHelper to directly access members of WriteNC
+  WriteNC* _writeNC;
+
+  const FileOptions& _opts;
+  EntityHandle _fileSet;
+
+  //! Dimensions of time and level
+  int nTimeSteps, nLevels;
+
+  //! Values for time and level
+  std::vector<double> tVals, levVals;
+
+  //! Dimension numbers for time and level
+  int tDim, levDim;
+
+  //! Ignored variables
+  std::set<std::string> ignoredVarNames;
+
+  //! Dummy variables
+  std::set<std::string> dummyVarNames;
+};
+
+#if 0
+
+//! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
+class ScdNCHelper : public NCHelper
+{
+public:
+  ScdNCHelper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
+: NCHelper(readNC, fileId, opts, fileSet),
+  iDim(-1), jDim(-1), iCDim(-1), jCDim(-1)
+  {
+    for (unsigned int i = 0; i < 6; i++) {
+      gDims[i] = -1;
+      lDims[i] = -1;
+      gCDims[i] = -1;
+      lCDims[i] = -1;
+    }
+
+    locallyPeriodic[0] = locallyPeriodic[1] = locallyPeriodic[2] = 0;
+    globallyPeriodic[0] = globallyPeriodic[1] = globallyPeriodic[2] = 0;
+  }
+  virtual ~ScdNCHelper() {}
+
+private:
+  //! Implementation of NCHelper::check_existing_mesh()
+  virtual ErrorCode check_existing_mesh();
+  //! Implementation of NCHelper::create_mesh()
+  virtual ErrorCode create_mesh(Range& faces);
+  //! Implementation of NCHelper::read_variables()
+  virtual ErrorCode read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
+
+  //! Read non-set variables for scd mesh
+  ErrorCode read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
+                                                 std::vector<int>& tstep_nums);
+  ErrorCode read_scd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas,
+                                        std::vector<int>& tstep_nums);
+
+  //! Create COORDS tag for quads coordinate
+  ErrorCode create_quad_coordinate_tag();
+
+  template <typename T> ErrorCode kji_to_jik(size_t ni, size_t nj, size_t nk, void* dest, T* source)
+  {
+    size_t nik = ni * nk, nij = ni * nj;
+    T* tmp_data = reinterpret_cast<T*>(dest);
+    for (std::size_t j = 0; j != nj; j++)
+      for (std::size_t i = 0; i != ni; i++)
+        for (std::size_t k = 0; k != nk; k++)
+          tmp_data[j*nik + i*nk + k] = source[k*nij + j*ni + i];
+    return MB_SUCCESS;
+  }
+
+protected:
+  //! Dimensions of global grid in file
+  int gDims[6];
+
+  //! Dimensions of my local part of grid
+  int lDims[6];
+
+  //! Center dimensions of global grid in file
+  int gCDims[6];
+
+  //! Center dimensions of my local part of grid
+  int lCDims[6];
+
+  //! Values for i/j
+  std::vector<double> ilVals, jlVals;
+
+  //! Center values for i/j
+  std::vector<double> ilCVals, jlCVals;
+
+  //! Dimension numbers for i/j
+  int iDim, jDim;
+
+  //! Center dimension numbers for i/j
+  int iCDim, jCDim;
+
+  //! Whether mesh is locally periodic in i or j or k
+  int locallyPeriodic[3];
+
+  //! Whether mesh is globally periodic in i or j or k
+  int globallyPeriodic[3];
+};
+
+//! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
+class UcdNCHelper : public NCHelper
+{
+public:
+  UcdNCHelper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
+: NCHelper(readNC, fileId, opts, fileSet),
+  nCells(0), nEdges(0), nVertices(0),
+  nLocalCells(0), nLocalEdges(0), nLocalVertices(0),
+  cDim(-1), eDim(-1), vDim(-1) {}
+  virtual ~UcdNCHelper() {}
+
+private:
+  //! Implementation of NCHelper::read_variables()
+  virtual ErrorCode read_variables(std::vector<std::string>& var_names,
+                                   std::vector<int> &tstep_nums);
+
+  //! Read non-set variables for ucd mesh (implemented differently in child classes)
+  virtual ErrorCode read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
+                                                         std::vector<int>& tstep_nums) = 0;
+#ifdef PNETCDF_FILE
+  virtual ErrorCode read_ucd_variable_to_nonset_async(std::vector<ReadNC::VarData>& vdatas,
+                                                      std::vector<int>& tstep_nums) = 0;
+#else
+  virtual ErrorCode read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas,
+                                                std::vector<int>& tstep_nums) = 0;
+#endif
+
+protected:
+  //! This version takes as input the moab range, from which we actually need just the
+  //! size of each sequence, for a proper transpose of the data
+  template <typename T> ErrorCode kji_to_jik_stride(size_t , size_t nj, size_t nk, void* dest, T* source, Range& localGid)
+  {
+    std::size_t idxInSource = 0; // Position of the start of the stride
+    // For each subrange, we will transpose a matrix of size
+    // subrange*nj*nk (subrange takes the role of ni)
+    T* tmp_data = reinterpret_cast<T*>(dest);
+    for (Range::pair_iterator pair_iter = localGid.pair_begin();
+        pair_iter != localGid.pair_end(); ++pair_iter) {
+      std::size_t size_range = pair_iter->second - pair_iter->first + 1;
+      std::size_t nik = size_range * nk, nij = size_range * nj;
+      for (std::size_t j = 0; j != nj; j++)
+        for (std::size_t i = 0; i != size_range; i++)
+          for (std::size_t k = 0; k != nk; k++)
+            tmp_data[idxInSource + j*nik + i*nk + k] = source[idxInSource + k*nij + j*size_range + i];
+      idxInSource += (size_range*nj*nk);
+    }
+    return MB_SUCCESS;
+  }
+
+  //! Dimensions of global grid in file
+  int nCells;
+  int nEdges;
+  int nVertices;
+
+  //! Dimensions of my local part of grid
+  int nLocalCells;
+  int nLocalEdges;
+  int nLocalVertices;
+
+  //! Coordinate values for vertices
+  std::vector<double> xVertVals, yVertVals, zVertVals;
+
+  //! Dimension numbers for nCells, nEdges and nVertices
+  int cDim, eDim, vDim;
+
+  //! Local global ID for cells, edges and vertices
+  Range localGidCells, localGidEdges, localGidVerts;
+};
+#endif
+
+} // namespace moab
+
+#endif
+

diff --git a/src/io/WriteNC.cpp b/src/io/WriteNC.cpp
new file mode 100644
index 0000000..4a3fd6e
--- /dev/null
+++ b/src/io/WriteNC.cpp
@@ -0,0 +1,490 @@
+#include "WriteNC.hpp"
+#include "moab/CN.hpp"
+#include "MBTagConventions.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Interface.hpp"
+#include "moab/Range.hpp"
+#include "moab/WriteUtilIface.hpp"
+#include "moab/FileOptions.hpp"
+#include "NCWriteHelper.hpp"
+
+#include <fstream>
+#include <map>
+#include <set>
+
+#include <iostream>
+
+#define ERRORR(rval, str) \
+  if (MB_SUCCESS != rval) { mWriteIface->report_error("%s", str); return rval; }
+
+#define ERRORS(err, str) \
+  if (err) { mWriteIface->report_error("%s", str); return MB_FAILURE; }
+
+namespace moab {
+
+WriterIface *WriteNC::factory( Interface* iface )
+  { return new WriteNC( iface ); }
+
+WriteNC::WriteNC(Interface *impl)
+    : mbImpl(impl), dbgOut(stderr), partMethod(ScdParData::ALLJORKORI), scdi(NULL),
+
+#ifdef USE_MPI
+  myPcomm(NULL),
+#endif
+
+  noMesh(false), noVars(false), /*spectralMesh(false), noMixedElements(false), noEdges(false),*/
+  gatherSetRank(-1), mGlobalIdTag(0), isParallel(false),
+   myHelper(NULL)
+{
+  assert(impl != NULL);
+  impl->query_interface(mWriteIface);
+}
+
+WriteNC::~WriteNC()
+{
+  mbImpl->release_interface(mWriteIface);
+  if (myHelper != NULL)
+    delete myHelper;
+}
+
+//! writes out a file
+ErrorCode WriteNC::write_file(const char *file_name,
+                                  const bool overwrite,
+                                  const FileOptions& options,
+                                  const EntityHandle *file_set,
+                                  const int num_set,
+                                  const std::vector<std::string>&,
+                                  const Tag*,
+                                  int,
+                                  int )
+{
+
+  ErrorCode rval;
+  // See if opts has variable(s) specified
+  std::vector<std::string> var_names;
+  std::vector<int> tstep_nums;
+  std::vector<double> tstep_vals;
+
+  // Get and cache predefined tag handles
+  int dum_val = 0;
+  rval = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, mGlobalIdTag, MB_TAG_DENSE , &dum_val);
+  if (MB_SUCCESS != rval)
+    return rval;
+
+  // num set has to be 1, we will write only one set, the original file set used to load
+  if (num_set!=1)
+    ERRORR(MB_FAILURE, "we should write only one set, the file set used to read data into");
+
+  rval = parse_options(options, var_names, tstep_nums, tstep_vals);
+  ERRORR(rval, "Trouble parsing option string.");
+
+  // important to create some data that will be used to write the file; dimensions, variables, etc
+  // new variables still need to have some way of defining their dimensions
+  // maybe it will be passed as write options
+  rval = process_conventional_tags(*file_set);
+  ERRORR(rval, "Trouble getting conventional tags.");
+
+  // Create the file ; assume we will overwrite always, for the time being
+  dbgOut.tprintf(1, "creating file %s\n", file_name);
+  fileName = file_name;
+  int success;
+
+#ifdef PNETCDF_FILE
+  int cmode= overwrite ? NC_CLOBBER : NC_NOCLOBBER;
+  if (isParallel)
+    success = NCFUNC(create)(myPcomm->proc_config().proc_comm(), file_name, cmode, MPI_INFO_NULL, &fileId);
+  else
+    success = NCFUNC(create)(MPI_COMM_SELF, file_name, cmode, MPI_INFO_NULL, &fileId);
+#else
+    // this is regular netcdf file
+  success = NCFUNC(create)(file_name,  overwrite ? NC_CLOBBER : NC_NOCLOBBER, &fileId);
+#endif
+  ERRORS(success, "failed to create file");
+
+  /* int nc_def_dim (int ncid, const char *name, size_t len, int *dimidp);
+   * example:  status = nc_def_dim(fileId, "lat", 18L, &latid);
+   * */
+
+  /*
+   * int nc_def_var (int ncid, const char *name, nc_type xtype,
+                     int ndims, const int dimids[], int *varidp);
+     example: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005fdef_005fvar.html#nc_005fdef_005fvar
+   */
+
+    /*
+     * Write an Entire Variable: nc_put_var_ type (double, int)
+     * int nc_put_var_double(int ncid, int varid, const double *dp);
+     */
+  /*
+   * Write an Array of Values: nc_put_vara_ type
+   * int nc_put_vara_double(int ncid, int varid, const size_t start[],
+                            const size_t count[], const double *dp);
+   */
+
+
+  return MB_SUCCESS;
+}
+
+ErrorCode WriteNC::parse_options(const FileOptions& opts, std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
+                                std::vector<double>& tstep_vals)
+{
+  int tmpval;
+  if (MB_SUCCESS == opts.get_int_option("DEBUG_IO", 1, tmpval)) {
+    dbgOut.set_verbosity(tmpval);
+    dbgOut.set_prefix("NCWrite");
+  }
+
+  ErrorCode rval = opts.get_strs_option("VARIABLE", var_names);
+  if (MB_TYPE_OUT_OF_RANGE == rval)
+    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;
+
+ /* these are not used yet, maybe later
+  rval = opts.get_null_option("SPECTRAL_MESH");
+  if (MB_SUCCESS == rval)
+    spectralMesh = true;
+
+  rval = opts.get_null_option("NO_MIXED_ELEMENTS");
+  if (MB_SUCCESS == rval)
+    noMixedElements = true;
+
+  rval = opts.get_null_option("NO_EDGES");
+  if (MB_SUCCESS == rval)
+    noEdges = true;*/
+
+  if (2 <= dbgOut.get_verbosity()) {
+    if (!var_names.empty()) {
+      std::cerr << "Variables requested: ";
+      for (unsigned int i = 0; i < var_names.size(); i++)
+        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++)
+        std::cerr << tstep_vals[i];
+      std::cerr << std::endl;
+    }
+  }
+
+  // the gather set will be important in parallel, this will be the rank that will accumulate the data
+  // to be written in serial
+  // improvement will be for writing in true parallel
+  rval = opts.get_int_option("GATHER_SET", 0, gatherSetRank);
+  if (MB_TYPE_OUT_OF_RANGE == rval) {
+    mWriteIface->report_error("Invalid value for GATHER_SET option");
+    return rval;
+  }
+// FIXME: copied from readnc, may need revise
+#ifdef USE_MPI
+  isParallel = (opts.match_option("PARALLEL","READ_PART") != MB_ENTITY_NOT_FOUND);
+
+  if (!isParallel)
+  // Return success here, since rval still has _NOT_FOUND from not finding option
+  // in this case, myPcomm will be NULL, so it can never be used; always check for isParallel
+  // before any use for myPcomm
+    return MB_SUCCESS;
+
+  int pcomm_no = 0;
+  rval = opts.get_int_option("PARALLEL_COMM", pcomm_no);
+  if (rval == MB_TYPE_OUT_OF_RANGE) {
+    mWriteIface->report_error("Invalid value for PARALLEL_COMM option");
+    return rval;
+  }
+  myPcomm = ParallelComm::get_pcomm(mbImpl, pcomm_no);
+  if (0 == myPcomm) {
+    myPcomm = new ParallelComm(mbImpl, MPI_COMM_WORLD);
+  }
+  const int rank = myPcomm->proc_config().proc_rank();
+  dbgOut.set_rank(rank);
+
+  int dum;
+  rval = opts.match_option("PARTITION_METHOD", ScdParData::PartitionMethodNames, dum);
+  if (rval == MB_FAILURE) {
+    mWriteIface->report_error("Unknown partition method specified.");
+    partMethod = ScdParData::ALLJORKORI;
+  }
+  else if (rval == MB_ENTITY_NOT_FOUND)
+    partMethod = ScdParData::ALLJORKORI;
+  else
+    partMethod = dum;
+#endif
+
+  return MB_SUCCESS;
+}
+
+// this is the inverse process to create conventional tags
+// will look at <pargal_source>/src/core/fileinfo.cpp, init dim, vars, atts
+ErrorCode WriteNC::process_conventional_tags(EntityHandle fileSet)
+{
+  ErrorCode rval;
+  // start copy
+  Tag tag = 0;
+  std::string tag_name = "__DIM_NAMES";
+  const void * data = NULL;
+  int num_dims = 0;
+  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, tag, MB_TAG_ANY);
+  ERRORR(rval, "Failed getting conventional tag __DIM_NAMES.");
+  rval = mbImpl->tag_get_by_ptr(tag, &fileSet, 1, &data, &num_dims);
+  ERRORR(rval, "Failed getting values for conventional tag __DIM_NAMES.");
+
+  dbgOut.tprintf(1, "dim names size: %d\n", num_dims);
+
+  std::size_t start = 0;
+  const char * p = static_cast<const char *>(data);
+  Tag dimValsTag = 0;
+  tag_name = "__DIM_LENS";
+  const void * valdata = NULL;
+  int num_vals = 0;
+  rval =  mbImpl->tag_get_handle(tag_name.c_str(), 0,  MB_TYPE_INTEGER,
+      dimValsTag,  MB_TAG_ANY);
+  ERRORR(rval, "Failed getting conventional tag __DIM_LENS.");
+
+  rval = mbImpl->tag_get_by_ptr(dimValsTag, &fileSet, 1, &valdata, &num_vals);
+  ERRORR(rval, "Failed getting values for conventional tag __DIM_LENS.");
+
+  dbgOut.tprintf(1, "num vals in dim lens tag %d\n", num_vals);
+  const int * intp = static_cast<const int*>(valdata);
+  int idx = -1;
+
+  for (std::size_t i = 0; i != static_cast<std::size_t>(num_dims); ++i)
+  {
+    if (p[i] == '\0')
+    {
+      std::string dim_name(&p[start], i - start);
+      ++idx;
+      int sz = intp[idx];
+      dimNames.push_back(dim_name);
+      dimLens.push_back(sz);
+      dbgOut.tprintf(2, "dimension %s has length %d\n", dim_name.c_str(), sz);
+      // fixme: need info from moab to set unlimited dimension
+      // currently assume each file has the same number of time dimensions
+      /*if ((dim_name == "time") || (dim_name == "Time"))
+        insert(dim_name,
+            *(new pcdim(dim_name, sz * m_file_names.size(), true)));
+      else
+        insert(dim_name, *(new pcdim(dim_name, sz)));*/
+      start = i + 1;
+    }
+  }
+
+  Tag tagMeshType = 0;
+  tag_name = "__MESH_TYPE";
+  data = NULL;
+  int sz = 0;
+  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, tagMeshType, MB_TAG_ANY);
+  ERRORR(rval, "Failed getting conventional tag __MESH_TYPE.");
+  rval = mbImpl->tag_get_by_ptr(tagMeshType, &fileSet, 1, &data, &sz);
+  ERRORR(rval, "Failed getting values for conventional tag __MESH_TYPE.");
+
+  p = static_cast<const char *>(data);
+  grid_type = std::string(&p[0], sz);
+  dbgOut.tprintf(2, "mesh type: %s \n", grid_type.c_str());
+  // read <__VAR_NAMES_LOCATIONS> tag
+  Tag varLocTag = 0;
+  tag_name = "__VAR_NAMES_LOCATIONS";
+  const void * loc_data = NULL;
+  int loc_sz = 0;
+  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0,
+      MB_TYPE_INTEGER, varLocTag, MB_TAG_ANY);
+  ERRORR(rval, "Failed getting conventional tag __VAR_NAMES_LOCATIONS.");
+  rval = mbImpl->tag_get_by_ptr(varLocTag, &fileSet, 1, &loc_data, &loc_sz);
+  ERRORR(rval, "Failed getting values for conventional tag __VAR_NAMES_LOCATIONS.");
+  const int * loc_p = static_cast<const int *>(loc_data);
+  std::vector<int> varLoc(loc_sz);
+  std::copy(loc_p, loc_p + loc_sz, varLoc.begin());
+
+ /*
+  std::map<int, std::string> locmap;
+  locmap[0] = "VERTEX";
+  locmap[1] = "NSEDGE";
+  locmap[2] = "EWEDGE";
+  if (grid_type == "MPAS")
+  {
+    locmap[3] = "POLYGON";
+  }
+  else
+  {
+    locmap[3] = "QUAD";
+  }
+  locmap[4] = "SET";
+  locmap[5] = "EDGE";
+  locmap[6] = "REGION";
+  */
+  int nthVar = 0;
+
+  Tag tagVarNames = 0;
+  tag_name = "__VAR_NAMES";
+  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, tagVarNames,
+      MB_TAG_ANY);
+  ERRORR(rval, "Failed getting conventional tag __VAR_NAMES.");
+  data = NULL;
+  int num_vars = 0;
+  rval = mbImpl->tag_get_by_ptr(tagVarNames, &fileSet, 1, &data, &num_vars);
+  ERRORR(rval, "Failed getting values for conventional tag __VAR_NAMES.");
+  p = static_cast<const char *>(data);
+  start = 0;
+  for (std::size_t i = 0; i != static_cast<std::size_t>(num_vars); ++i)
+  {
+    if (p[i] == '\0')
+    {
+      std::string var_name(&p[start], i - start);
+
+      sz = 0;
+      Tag dims_tag = 0;
+      std::string dim_names = "__" + var_name + "_DIMS";
+      rval = mbImpl->tag_get_handle(dim_names.c_str(), 0, MB_TYPE_OPAQUE,
+          dims_tag, MB_TAG_ANY);
+      ERRORR(rval, "FAILED to get tag for a variable dimensions");
+      //fixme: doesn't handle variables have 0 dimension
+      if (rval != moab::MB_SUCCESS)
+      {
+        start = i + 1;
+        ++nthVar;
+        continue;
+      }
+      rval = mbImpl->tag_get_length(dims_tag, sz);
+      ERRORR(rval, " size of dimensions for variable");
+      dbgOut.tprintf(2, "var name: %s has %d dimensions \n", var_name.c_str(), sz);
+      //std::vector<const pcdim*> dims(sz, NULL);
+      const void* ptr = NULL;
+      rval = mbImpl->tag_get_by_ptr(dims_tag, &fileSet, 1, &ptr);
+      //
+      const Tag * ptags = static_cast<const moab::Tag*>(ptr);
+      for (std::size_t j = 0; j != static_cast<std::size_t>(sz); ++j)
+      {
+        std::string dim_name;
+        rval = mbImpl->tag_get_name(ptags[j], dim_name);
+        ERRORR(rval, "name of tag for dimension");
+        dbgOut.tprintf(2, "var name: %s has %d dimensions \n", var_name.c_str(), sz);
+        //dims[j] = &(get_dim(dim_name));
+      }
+      /*insert(var_name,
+          *(new fvar(var_name, moab::MB_TYPE_DOUBLE, dims,
+              locmap[varLoc[nthVar++]])));*/
+      start = i + 1;
+    }
+  }
+
+  // attributes
+#if 0
+  std::vector<std::string> nameVec(num_vars+1);
+        nameVec[0] = "GLOBAL";
+        std::map<std::string, const fvar*>::iterator it = m_vars.begin();
+        for (std::size_t i=1; it != m_vars.end(); ++it, ++i)
+          nameVec[i] = it->first;
+
+        for (std::size_t vec_counter = 0; vec_counter != nameVec.size(); ++vec_counter)
+          {
+      // read __<var_name>_ATTRIBS tag
+      moab::Tag tag = 0;
+      std::string tag_name = "__"+nameVec[vec_counter]+"_ATTRIBS";
+      const void * data = NULL;
+      int sz = 0;
+      moab::ErrorCode rval = m_mb.tag_get_handle(tag_name.c_str(), 0, moab::MB_TYPE_OPAQUE, tag, moab::MB_TAG_ANY);
+      if (rval != moab::MB_SUCCESS)
+        throw pargal_except("Error: " + m_mb.get_error_string(rval),
+                __FILE__, __LINE__, __PRETTY_FUNCTION__);
+
+      rval = m_mb.tag_get_by_ptr(tag, &m_file_set, 1, &data, &sz);
+      const char * p = static_cast<const char *>(data);
+      std::string att_val(&p[0], sz);
+      if (vec_counter == 0) nameVec[0]="MOAB_GLOBAL";
+      const std::string& var_name = nameVec[vec_counter];
+
+      // read __<var_name>_ATTRIBS_LEN tag
+      moab::Tag attLenTag = 0;
+      tag_name = tag_name + "_LEN";
+      const void * len_data = NULL;
+      int len_sz = 0;
+      rval = m_mb.tag_get_handle(tag_name.c_str(), 0, moab::MB_TYPE_INTEGER, attLenTag, moab::MB_TAG_ANY);
+      rval = m_mb.tag_get_by_ptr(attLenTag, &m_file_set, 1, &len_data, &len_sz);
+      const int * len_p = static_cast<const int *>(len_data);
+      std::vector<int> attLen(len_sz);
+      std::copy(len_p, len_p+len_sz, attLen.begin());
+
+      // create attribute
+      insert(var_name, *(new pcatt(var_name, att_val, attLen)));
+#endif
+  return MB_SUCCESS;
+}
+#if 0
+
+
+    void
+    fileinfo::init_atts()
+    {
+      std::vector<std::string> nameVec(m_vars.size()+1);
+      nameVec[0] = "GLOBAL";
+      std::map<std::string, const fvar*>::iterator it = m_vars.begin();
+      for (std::size_t i=1; it != m_vars.end(); ++it, ++i)
+        nameVec[i] = it->first;
+
+      for (std::size_t vec_counter = 0; vec_counter != nameVec.size(); ++vec_counter)
+        {
+    // read __<var_name>_ATTRIBS tag
+    moab::Tag tag = 0;
+    std::string tag_name = "__"+nameVec[vec_counter]+"_ATTRIBS";
+    const void * data = NULL;
+    int sz = 0;
+    moab::ErrorCode rval = m_mb.tag_get_handle(tag_name.c_str(), 0, moab::MB_TYPE_OPAQUE, tag, moab::MB_TAG_ANY);
+    if (rval != moab::MB_SUCCESS)
+      throw pargal_except("Error: " + m_mb.get_error_string(rval),
+              __FILE__, __LINE__, __PRETTY_FUNCTION__);
+
+    rval = m_mb.tag_get_by_ptr(tag, &m_file_set, 1, &data, &sz);
+    const char * p = static_cast<const char *>(data);
+    std::string att_val(&p[0], sz);
+    if (vec_counter == 0) nameVec[0]="MOAB_GLOBAL";
+    const std::string& var_name = nameVec[vec_counter];
+
+    // read __<var_name>_ATTRIBS_LEN tag
+    moab::Tag attLenTag = 0;
+    tag_name = tag_name + "_LEN";
+    const void * len_data = NULL;
+    int len_sz = 0;
+    rval = m_mb.tag_get_handle(tag_name.c_str(), 0, moab::MB_TYPE_INTEGER, attLenTag, moab::MB_TAG_ANY);
+    rval = m_mb.tag_get_by_ptr(attLenTag, &m_file_set, 1, &len_data, &len_sz);
+    const int * len_p = static_cast<const int *>(len_data);
+    std::vector<int> attLen(len_sz);
+    std::copy(len_p, len_p+len_sz, attLen.begin());
+
+    // create attribute
+    insert(var_name, *(new pcatt(var_name, att_val, attLen)));
+        }
+    }
+
+    void
+    fileinfo::init_grid_type()
+    {
+      moab::Tag tag = 0;
+      std::string tag_name = "__MESH_TYPE";
+      const void * data = NULL;
+      int sz = 0;
+      moab::ErrorCode rval;
+      rval = m_mb.tag_get_handle(tag_name.c_str(), 0, moab::MB_TYPE_OPAQUE, tag, moab::MB_TAG_ANY);
+      rval = m_mb.tag_get_by_ptr(tag, &m_file_set, 1, &data, &sz);
+      if (rval != moab::MB_SUCCESS)
+        throw pargal_except("Error: " + m_mb.get_error_string(rval),
+          __FILE__, __LINE__, __PRETTY_FUNCTION__);
+      const char * p = static_cast<const char *>(data);
+      m_grid_type = std::string(&p[0], sz);
+    }
+
+  return MB_SUCCESS;
+}
+#endif
+
+} // end moab namespace

diff --git a/src/io/WriteNC.hpp b/src/io/WriteNC.hpp
new file mode 100644
index 0000000..c3b893a
--- /dev/null
+++ b/src/io/WriteNC.hpp
@@ -0,0 +1,208 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation.  Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef WRITENC_HPP_
+#define WRITENC_HPP_
+
+
+#ifndef IS_BUILDING_MB
+//#error "ReadNC.hpp isn't supposed to be included into an application"
+#endif
+
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+#include "moab/WriterIface.hpp"
+#include "moab/ScdInterface.hpp"
+#include "DebugOutput.hpp"
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#include "moab/ParallelComm.hpp"
+#endif
+
+#ifdef PNETCDF_FILE
+#include "pnetcdf.h"
+#define NCFUNC(func) ncmpi_ ## func
+
+//! Collective I/O mode get
+#define NCFUNCAG(func) ncmpi_get ## func ## _all
+
+//! Independent I/O mode get
+#define NCFUNCG(func) ncmpi_get ## func
+
+//! Nonblocking get (request aggregation), used so far only for ucd mesh
+#define NCFUNCREQG(func) ncmpi_iget ## func
+
+#define NCDF_SIZE MPI_Offset
+#define NCDF_DIFF MPI_Offset
+#else
+#include "netcdf.h"
+#define NCFUNC(func) nc_ ## func
+#define NCFUNCAG(func) nc_get ## func
+#define NCFUNCG(func) nc_get ## func
+#define NCDF_SIZE size_t
+#define NCDF_DIFF ptrdiff_t
+#endif
+
+namespace moab {
+
+class WriteUtilIface;
+class ScdInterface;
+class NCWriteHelper;
+
+/**
+ * \brief Export NC files.
+ */
+
+class WriteNC : public WriterIface
+{
+  friend class NCWriteHelper;
+  friend class NCWriteEuler;
+
+public:
+
+    //! factory method
+  static WriterIface* factory( Interface* );
+
+   //! Constructor
+  WriteNC(Interface *impl);
+
+   //! Destructor
+  virtual ~WriteNC();
+
+
+    //! writes out a file
+  ErrorCode write_file(const char *file_name,
+                         const bool overwrite,
+                         const FileOptions& opts,
+                         const EntityHandle *output_list,
+                         const int num_sets,
+                         const std::vector<std::string>& qa_list,
+                         const Tag* tag_list = NULL,
+                         int num_tags = 0,
+                         int export_dimension = 3);
+
+
+private:
+
+  enum EntityLocation {ENTLOCVERT = 0, ENTLOCNSEDGE, ENTLOCEWEDGE, ENTLOCFACE, ENTLOCSET, ENTLOCEDGE, ENTLOCREGION};
+
+  class AttData
+  {
+    public:
+    AttData() : attId(-1), attLen(0), attVarId(-2) {}
+    int attId;
+    NCDF_SIZE attLen;
+    int attVarId;
+    nc_type attDataType;
+    std::string attName;
+  };
+
+  class VarData
+  {
+    public:VarData() : varId(-1), numAtts(-1), entLoc(ENTLOCSET), numLev(1), sz(0), has_tsteps(false) {}
+    int varId;
+    int numAtts;
+    nc_type varDataType;
+    std::vector<int> varDims; // The dimension indices making up this multi-dimensional variable
+    std::map<std::string, AttData> varAtts;
+    std::string varName;
+    std::vector<Tag> varTags; // Tags created for this variable, e.g. one tag per timestep
+    std::vector<void*> memoryHogs; // these will point to the real data; fill before writing the data
+    std::vector<NCDF_SIZE> writeStarts; // Starting index for reading data values along each dimension
+    std::vector<NCDF_SIZE> writeCounts; // Number of data values to be read along each dimension
+    int entLoc;
+    int numLev;
+    int sz;
+    bool has_tsteps; // Indicate whether timestep numbers are appended to tag names
+  };
+
+  // this info will be reconstructed from metadata stored on conventional fileSet tags
+  //! Dimension names
+  std::vector<std::string> dimNames;
+
+  //! Dimension lengths
+  std::vector<int> dimLens;
+
+  //! Global attribs
+  std::map<std::string, AttData> globalAtts;
+
+  //! Variable info
+  std::map<std::string, VarData> varInfo;
+
+  ErrorCode parse_options(const FileOptions& opts, std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
+                                  std::vector<double>& tstep_vals);
+  /*
+   * map out the header, from tags on file set; it is the inverse process from
+   * ErrorCode NCHelper::create_conventional_tags
+   */
+  ErrorCode process_conventional_tags(EntityHandle fileSet);
+    // interface instance
+  Interface *mbImpl;
+  WriteUtilIface* mWriteIface;
+
+  // File var
+  const char *fileName;
+  int IndexFile;
+  //! File numbers assigned by (p)netcdf
+  int fileId;
+
+
+  //! Debug stuff
+  DebugOutput dbgOut;
+
+  //! Partitioning method
+  int partMethod;
+
+  //! Scd interface
+  ScdInterface* scdi;
+
+  //! Parallel data object, to be cached with ScdBox
+  ScdParData parData;
+
+#ifdef USE_MPI
+  ParallelComm* myPcomm;
+#endif
+  //! write options
+  //
+  bool noMesh;
+  bool noVars;
+  /*
+   *  not used yet, maybe later
+  bool spectralMesh;
+  bool noMixedElements;
+  bool noEdges;*/
+  int gatherSetRank;
+
+  //! Cached tags for writing. this will be important for ordering the data, in parallel
+  //
+  Tag mGlobalIdTag;
+
+  //! Are we writing in parallel? (probably in the future)
+  bool isParallel;
+
+  // CAM Euler, etc,
+  std::string grid_type;
+  //! Helper class instance
+  NCWriteHelper* myHelper;
+
+};
+
+} // namespace moab
+
+#endif

diff --git a/test/io/Makefile.am b/test/io/Makefile.am
index 61f932a..dd09c0e 100644
--- a/test/io/Makefile.am
+++ b/test/io/Makefile.am
@@ -12,7 +12,7 @@ AM_CPPFLAGS += -DSRCDIR=$(srcdir) \
 
 if NETCDF_FILE
   EXODUS_TEST = exodus_test
-  NC_TEST = read_nc read_ucd_nc read_mpas_nc
+  NC_TEST = read_nc read_ucd_nc read_mpas_nc write_nc
 else
   EXODUS_TEST = 
   NC_TEST = 

diff --git a/test/io/write_nc.cpp b/test/io/write_nc.cpp
new file mode 100644
index 0000000..713f886
--- /dev/null
+++ b/test/io/write_nc.cpp
@@ -0,0 +1,90 @@
+#include "TestUtil.hpp"
+#include "moab/Core.hpp"
+
+using namespace moab;
+
+#ifdef MESHDIR
+static const char example_eul[] = STRINGIFY(MESHDIR) "/io/camEul26x48x96.t3.nc";
+#else
+static const char example_eul[] = "/io/camEul26x48x96.t3.nc";
+#endif
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#include "moab/ParallelComm.hpp"
+#endif
+
+// CAM-EUL
+void test_read_write_one_var();
+
+ErrorCode get_options(std::string& opts);
+
+int main(int argc, char* argv[])
+{
+  int result = 0;
+
+#ifdef USE_MPI
+  int fail = MPI_Init(&argc, &argv);
+  if (fail)
+    return 1;
+#else
+  argv[0] = argv[argc - argc]; // To remove the warnings in serial mode about unused variables
+#endif
+
+  result += RUN_TEST(test_read_write_one_var);
+
+#ifdef USE_MPI
+  fail = MPI_Finalize();
+  if (fail)
+    return 1;
+#endif
+
+  return result;
+}
+
+void test_read_write_one_var()
+{
+  Core moab;
+  Interface& mb = moab;
+
+  std::string orig;
+  ErrorCode rval = get_options(orig);
+  CHECK_ERR(rval);
+
+  // we will have to read without mesh and without var first, to create some tags that we need
+  // later when we write
+  std::string opts;
+  opts = orig + std::string(";DEBUG_IO=3;NOMESH;VARIABLE=");
+
+  // Need a set for nomesh to work right
+  // this set will have as tags a lot of header information, that will be used for writing back the file
+  EntityHandle set;
+  rval = mb.create_meshset(MESHSET_SET, set);
+  CHECK_ERR(rval);
+
+  rval = mb.load_file(example_eul, &set, opts.c_str());
+  CHECK_ERR(rval);
+
+  // load one variable, and the mesh
+  opts= orig + std::string(";DEBUG_IO=3;VARIABLE=T");
+  rval = mb.load_file(example_eul, &set, opts.c_str());
+  CHECK_ERR(rval);
+
+  // first test will write information about one variable
+  std::string writeopts;
+  writeopts = std::string(";;VARIABLE=T;DEBUG_IO=2;");
+  rval = mb.write_file( "testT.nc", 0, writeopts.c_str(), &set, 1);
+  CHECK_ERR(rval);
+}
+
+ErrorCode get_options(std::string& opts)
+{
+#ifdef USE_MPI
+  // Use parallel options
+  opts = std::string(";;PARALLEL=READ_PART;PARTITION_METHOD=SQIJ");
+  return MB_SUCCESS;
+#else
+  opts = std::string(";;");
+  return MB_SUCCESS;
+#endif
+}


https://bitbucket.org/fathomteam/moab/commits/b92a2bb6602e/
Changeset:   b92a2bb6602e
Branch:      ncwriter
User:        iulian07
Date:        2014-03-29 13:39:46
Summary:     print some variables tags during debugging

Affected #:  1 file

diff --git a/src/io/WriteNC.cpp b/src/io/WriteNC.cpp
index 4a3fd6e..a65548a 100644
--- a/src/io/WriteNC.cpp
+++ b/src/io/WriteNC.cpp
@@ -333,15 +333,21 @@ ErrorCode WriteNC::process_conventional_tags(EntityHandle fileSet)
   data = NULL;
   int num_vars = 0;
   rval = mbImpl->tag_get_by_ptr(tagVarNames, &fileSet, 1, &data, &num_vars);
+  dbgOut.tprintf(2, "var names  has %d names \n", num_vars );
   ERRORR(rval, "Failed getting values for conventional tag __VAR_NAMES.");
   p = static_cast<const char *>(data);
   start = 0;
+  int idxVar=0;
   for (std::size_t i = 0; i != static_cast<std::size_t>(num_vars); ++i)
   {
     if (p[i] == '\0')
     {
       std::string var_name(&p[start], i - start);
 
+      dbgOut.tprintf(2, "var name: %s index %d \n", var_name.c_str(), idxVar);
+      // process var name:
+      // this will create/initiate map; we will populate variableDataStruct wit info about dims, tags, etc
+      VarData  variableDataStruct = varInfo[var_name];
       sz = 0;
       Tag dims_tag = 0;
       std::string dim_names = "__" + var_name + "_DIMS";
@@ -358,6 +364,7 @@ ErrorCode WriteNC::process_conventional_tags(EntityHandle fileSet)
       rval = mbImpl->tag_get_length(dims_tag, sz);
       ERRORR(rval, " size of dimensions for variable");
       dbgOut.tprintf(2, "var name: %s has %d dimensions \n", var_name.c_str(), sz);
+
       //std::vector<const pcdim*> dims(sz, NULL);
       const void* ptr = NULL;
       rval = mbImpl->tag_get_by_ptr(dims_tag, &fileSet, 1, &ptr);
@@ -368,13 +375,14 @@ ErrorCode WriteNC::process_conventional_tags(EntityHandle fileSet)
         std::string dim_name;
         rval = mbImpl->tag_get_name(ptags[j], dim_name);
         ERRORR(rval, "name of tag for dimension");
-        dbgOut.tprintf(2, "var name: %s has %d dimensions \n", var_name.c_str(), sz);
+        dbgOut.tprintf(2, "var name: %s has %s as dimension \n", var_name.c_str(), dim_name.c_str() );
         //dims[j] = &(get_dim(dim_name));
       }
       /*insert(var_name,
           *(new fvar(var_name, moab::MB_TYPE_DOUBLE, dims,
               locmap[varLoc[nthVar++]])));*/
       start = i + 1;
+      idxVar++;
     }
   }

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