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