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