Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
NCHelper.hpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------
2 // Filename : NCHelper.hpp
3 //
4 // Purpose : Climate NC file helper
5 //
6 // Creator : Danqing Wu
7 //-------------------------------------------------------------------------
8 
9 #ifndef NCHELPER_HPP
10 #define NCHELPER_HPP
11 
12 #include "ReadNC.hpp"
13 
14 #ifdef WIN32
15 #ifdef size_t
16 #undef size_t
17 #endif
18 #endif
19 
20 namespace moab
21 {
22 
23 //! Helper class to isolate reading of several different nc file formats
24 class NCHelper
25 {
26  public:
27  NCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
28  : _readNC( readNC ), _fileId( fileId ), _opts( opts ), _fileSet( fileSet ), nTimeSteps( 0 ), nLevels( 1 ),
29  tDim( -1 ), levDim( -1 )
30  {
31  }
32  virtual ~NCHelper() {}
33 
34  //! Get appropriate format to read the file
35  static ReadNC::NCFormatType get_nc_format( ReadNC* readNC, int fileId );
36 
37  //! Get appropriate format to read the file
38  static std::string get_default_ncformat_options( ReadNC::NCFormatType format );
39 
40  //! Get appropriate helper instance for ReadNC class
41  static NCHelper* get_nc_helper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet );
42 
43  //! Interfaces to be implemented in child classes
44  virtual ErrorCode init_mesh_vals() = 0;
46  virtual ErrorCode create_mesh( Range& faces ) = 0;
47  virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums ) = 0;
48  virtual std::string get_mesh_type_name() = 0;
49 
50  //! Create NC conventional tags
51  ErrorCode create_conventional_tags( const std::vector< int >& tstep_nums );
52 
53  //! Update time tag values if timesteps spread across files
55 
56  // An object to hold vertex coordinates, and an operator
57  // for storing them in a STL tree-based container. use a tolerance saved somewhere as 1.e-12
58  class Node3D
59  {
60  public:
61  double coords[3];
62  bool operator<( const Node3D& ) const;
63  Node3D( double x, double y, double z )
64  {
65  coords[0] = x;
66  coords[1] = y;
67  coords[2] = z;
68  }
69  };
70 
71  protected:
72  //! Separate set and non-set variables (common to scd mesh and ucd mesh)
73  ErrorCode read_variables_setup( std::vector< std::string >& var_names,
74  std::vector< int >& tstep_nums,
75  std::vector< ReadNC::VarData >& vdatas,
76  std::vector< ReadNC::VarData >& vsetdatas );
77 
78  //! Read set variables (common to scd mesh and ucd mesh)
79  ErrorCode read_variables_to_set( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );
80 
81  ErrorCode read_coordinate( const char* var_name, int lmin, int lmax, std::vector< double >& cvals );
82 
83  ErrorCode get_tag_to_set( ReadNC::VarData& var_data, int tstep_num, Tag& tagh );
84 
85  ErrorCode get_tag_to_nonset( ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev );
86 
87  //! Create a character string attString of attMap. with '\0'
88  //! terminating each attribute name, ';' separating the data type
89  //! and value, and ';' separating one name/data type/value from
90  //! the next'. attLen stores the end position for each name/data
91  //! type/ value.
92  ErrorCode create_attrib_string( const std::map< std::string, ReadNC::AttData >& attMap,
93  std::string& attString,
94  std::vector< int >& attLen );
95 
96  //! For a dimension that does not have a corresponding coordinate variable (e.g. ncol for
97  //! HOMME), create a dummy variable with a sparse tag to store the dimension length
99 
100  private:
101  //! Used by read_variables_to_set()
102  ErrorCode read_variables_to_set_allocate( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );
103 
104  protected:
105  //! Allow NCHelper to directly access members of ReadNC
107 
108  //! Cache some information from ReadNC
109  int _fileId;
112 
113  //! Dimensions of time and level
115 
116  //! Values for time and level
117  std::vector< double > tVals, levVals;
118 
119  //! Dimension numbers for time and level
120  int tDim, levDim;
121 
122  //! Ignored variables
123  std::set< std::string > ignoredVarNames;
124 
125  //! Dummy variables
126  std::set< std::string > dummyVarNames;
127 };
128 
129 //! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
130 class ScdNCHelper : public NCHelper
131 {
132  public:
133  ScdNCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
134  : NCHelper( readNC, fileId, opts, fileSet ), iDim( -1 ), jDim( -1 ), iCDim( -1 ), jCDim( -1 )
135  {
136  for( unsigned int i = 0; i < 6; i++ )
137  {
138  gDims[i] = -1;
139  lDims[i] = -1;
140  gCDims[i] = -1;
141  lCDims[i] = -1;
142  }
143 
146  }
147  virtual ~ScdNCHelper() {}
148 
149  private:
150  //! Implementation of NCHelper::check_existing_mesh()
151  virtual ErrorCode check_existing_mesh();
152  //! Implementation of NCHelper::create_mesh()
153  virtual ErrorCode create_mesh( Range& faces );
154  //! Implementation of NCHelper::read_variables()
155  virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums );
156 
157  //! Read non-set variables for scd mesh
158  ErrorCode read_scd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
159  std::vector< int >& tstep_nums );
160  ErrorCode read_scd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );
161 
162  //! Create COORDS tag for quads coordinate
164 
165  template < typename T >
166  void kji_to_jik( size_t ni, size_t nj, size_t nk, void* dest, T* source )
167  {
168  size_t nik = ni * nk, nij = ni * nj;
169  T* tmp_data = reinterpret_cast< T* >( dest );
170  for( std::size_t j = 0; j != nj; j++ )
171  for( std::size_t i = 0; i != ni; i++ )
172  for( std::size_t k = 0; k != nk; k++ )
173  tmp_data[j * nik + i * nk + k] = source[k * nij + j * ni + i];
174  }
175 
176  protected:
177  //! Dimensions of global grid in file
178  int gDims[6];
179 
180  //! Dimensions of my local part of grid
181  int lDims[6];
182 
183  //! Center dimensions of global grid in file
184  int gCDims[6];
185 
186  //! Center dimensions of my local part of grid
187  int lCDims[6];
188 
189  //! Values for i/j
190  std::vector< double > ilVals, jlVals;
191 
192  //! Center values for i/j
193  std::vector< double > ilCVals, jlCVals;
194 
195  //! Dimension numbers for i/j
196  int iDim, jDim;
197 
198  //! Center dimension numbers for i/j
199  int iCDim, jCDim;
200 
201  //! Whether mesh is locally periodic in i or j or k
203 
204  //! Whether mesh is globally periodic in i or j or k
206 };
207 
208 //! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
209 class UcdNCHelper : public NCHelper
210 {
211  public:
212  UcdNCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
213  : NCHelper( readNC, fileId, opts, fileSet ), nCells( 0 ), nEdges( 0 ), nVertices( 0 ), nLocalCells( 0 ),
214  nLocalEdges( 0 ), nLocalVertices( 0 ), cDim( -1 ), eDim( -1 ), vDim( -1 )
215  {
216  }
217  virtual ~UcdNCHelper() {}
218 
219  private:
220  //! Implementation of NCHelper::read_variables()
221  virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums );
222 
223  //! Read non-set variables for ucd mesh (implemented differently in child classes)
224  virtual ErrorCode read_ucd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
225  std::vector< int >& tstep_nums ) = 0;
226 #ifdef MOAB_HAVE_PNETCDF
227  virtual ErrorCode read_ucd_variables_to_nonset_async( std::vector< ReadNC::VarData >& vdatas,
228  std::vector< int >& tstep_nums ) = 0;
229 #else
230  virtual ErrorCode read_ucd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas,
231  std::vector< int >& tstep_nums ) = 0;
232 #endif
233 
234  protected:
235  //! This version takes as input the moab range, from which we actually need just the
236  //! size of each sequence, for a proper transpose of the data
237  template < typename T >
238  void kji_to_jik_stride( size_t, size_t nj, size_t nk, void* dest, T* source, Range& localGid )
239  {
240  std::size_t idxInSource = 0; // Position of the start of the stride
241  // For each subrange, we will transpose a matrix of size
242  // subrange*nj*nk (subrange takes the role of ni)
243  T* tmp_data = reinterpret_cast< T* >( dest );
244  for( Range::pair_iterator pair_iter = localGid.pair_begin(); pair_iter != localGid.pair_end(); ++pair_iter )
245  {
246  std::size_t size_range = pair_iter->second - pair_iter->first + 1;
247  std::size_t nik = size_range * nk, nij = size_range * nj;
248  for( std::size_t j = 0; j != nj; j++ )
249  for( std::size_t i = 0; i != size_range; i++ )
250  for( std::size_t k = 0; k != nk; k++ )
251  tmp_data[idxInSource + j * nik + i * nk + k] =
252  source[idxInSource + k * nij + j * size_range + i];
253  idxInSource += ( size_range * nj * nk );
254  }
255  }
256 
257  //! Dimensions of global grid in file
258  int nCells;
259  int nEdges;
261 
262  //! Dimensions of my local part of grid
266 
267  //! Coordinate values for vertices
268  std::vector< double > xVertVals, yVertVals, zVertVals;
269 
270  //! Dimension numbers for nCells, nEdges and nVertices
271  int cDim, eDim, vDim;
272 
273  //! Local global ID for cells, edges and vertices
275 };
276 
277 } // namespace moab
278 
279 #endif