1 #include "NCHelper.hpp"
2 #include "NCHelperEuler.hpp"
3 #include "NCHelperFV.hpp"
4 #include "NCHelperHOMME.hpp"
5 #include "NCHelperMPAS.hpp"
6 #include "NCHelperGCRM.hpp"
7
8 #include <sstream>
9
10 #include "MBTagConventions.hpp"
11
12 #ifdef WIN32
13 #ifdef size_t
14 #undef size_t
15 #endif
16 #endif
17
18 namespace moab {
19
get_nc_helper(ReadNC * readNC,int fileId,const FileOptions & opts,EntityHandle fileSet)20 NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
21 {
22 // Check if CF convention is being followed
23 bool is_CF = false;
24
25 std::map<std::string, ReadNC::AttData>& globalAtts = readNC->globalAtts;
26 std::map<std::string, ReadNC::AttData>::iterator attIt = globalAtts.find("conventions");
27 if (attIt == globalAtts.end())
28 attIt = globalAtts.find("Conventions");
29
30 if (attIt != globalAtts.end()) {
31 unsigned int sz = attIt->second.attLen;
32 std::string att_data;
33 att_data.resize(sz + 1);
34 att_data[sz] = '\000';
35 int success = NCFUNC(get_att_text)(fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0]);
36 if (0 == success && att_data.find("CF") != std::string::npos)
37 is_CF = true;
38 }
39
40 if (is_CF) {
41 if (NCHelperEuler::can_read_file(readNC, fileId))
42 return new (std::nothrow) NCHelperEuler(readNC, fileId, opts, fileSet);
43 else if (NCHelperFV::can_read_file(readNC, fileId))
44 return new (std::nothrow) NCHelperFV(readNC, fileId, opts, fileSet);
45 else if (NCHelperHOMME::can_read_file(readNC, fileId))
46 return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts, fileSet);
47 }
48 else {
49 if (NCHelperMPAS::can_read_file(readNC))
50 return new (std::nothrow) NCHelperMPAS(readNC, fileId, opts, fileSet);
51 // For a HOMME connectivity file, there might be no CF convention
52 else if (NCHelperHOMME::can_read_file(readNC, fileId))
53 return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts, fileSet);
54 // gcrm reader
55 else if (NCHelperGCRM::can_read_file(readNC))
56 return new (std::nothrow) NCHelperGCRM(readNC, fileId, opts, fileSet);
57 }
58
59 // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
60 return NULL;
61 }
62
create_conventional_tags(const std::vector<int> & tstep_nums)63 ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
64 {
65 Interface*& mbImpl = _readNC->mbImpl;
66 std::vector<std::string>& dimNames = _readNC->dimNames;
67 std::vector<int>& dimLens = _readNC->dimLens;
68 std::map<std::string, ReadNC::AttData>& globalAtts = _readNC->globalAtts;
69 std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
70 DebugOutput& dbgOut = _readNC->dbgOut;
71 int& partMethod = _readNC->partMethod;
72 ScdInterface* scdi = _readNC->scdi;
73
74 ErrorCode rval;
75 std::string tag_name;
76
77 // <__NUM_DIMS>
78 Tag numDimsTag = 0;
79 tag_name = "__NUM_DIMS";
80 int numDims = dimNames.size();
81 rval = mbImpl->tag_get_handle(tag_name.c_str(), 1, MB_TYPE_INTEGER, numDimsTag,
82 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
83 rval = mbImpl->tag_set_data(numDimsTag, &_fileSet, 1, &numDims);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
84 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
85
86 // <__NUM_VARS>
87 Tag numVarsTag = 0;
88 tag_name = "__NUM_VARS";
89 int numVars = varInfo.size();
90 rval = mbImpl->tag_get_handle(tag_name.c_str(), 1, MB_TYPE_INTEGER, numVarsTag,
91 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
92 rval = mbImpl->tag_set_data(numVarsTag, &_fileSet, 1, &numVars);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
93 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
94
95 // <__DIM_NAMES>
96 Tag dimNamesTag = 0;
97 tag_name = "__DIM_NAMES";
98 std::string dimnames;
99 unsigned int dimNamesSz = dimNames.size();
100 for (unsigned int i = 0; i != dimNamesSz; i++) {
101 dimnames.append(dimNames[i]);
102 dimnames.push_back('\0');
103 }
104 int dimnamesSz = dimnames.size();
105 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag,
106 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
107 const void* ptr = dimnames.c_str();
108 rval = mbImpl->tag_set_by_ptr(dimNamesTag, &_fileSet, 1, &ptr, &dimnamesSz);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
109 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
110
111 // <__DIM_LENS>
112 Tag dimLensTag = 0;
113 tag_name = "__DIM_LENS";
114 int dimLensSz = dimLens.size();
115 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag,
116 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
117 ptr = &(dimLens[0]);
118 rval = mbImpl->tag_set_by_ptr(dimLensTag, &_fileSet, 1, &ptr, &dimLensSz);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
119 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
120
121 // <__VAR_NAMES>
122 Tag varNamesTag = 0;
123 tag_name = "__VAR_NAMES";
124 std::string varnames;
125 std::map<std::string, ReadNC::VarData>::iterator mapIter;
126 for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
127 varnames.append(mapIter->first);
128 varnames.push_back('\0');
129 }
130 int varnamesSz = varnames.size();
131 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag,
132 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
133 ptr = varnames.c_str();
134 rval = mbImpl->tag_set_by_ptr(varNamesTag, &_fileSet, 1, &ptr, &varnamesSz);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
135 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
136
137 // __<dim_name>_LOC_MINMAX (for time)
138 for (unsigned int i = 0; i != dimNamesSz; i++) {
139 if (dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t") {
140 // some files might have Time dimension as 0, it will not appear in any
141 // variables, so skip it
142 if (nTimeSteps==0)
143 continue;
144 std::stringstream ss_tag_name;
145 ss_tag_name << "__" << dimNames[i] << "_LOC_MINMAX";
146 tag_name = ss_tag_name.str();
147 Tag tagh = 0;
148 std::vector<int> val(2, 0);
149 val[0] = 0;
150 val[1] = nTimeSteps - 1;
151 rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh,
152 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
153 rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
154 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
155 }
156 }
157
158 // __<dim_name>_LOC_VALS (for time)
159 for (unsigned int i = 0; i != dimNamesSz; i++) {
160 if (dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t") {
161 std::vector<int> val;
162 if (!tstep_nums.empty())
163 val = tstep_nums;
164 else {
165 // some files might have Time dimension as 0, it will not appear in any
166 // variables, so skip it
167 if (tVals.empty())
168 continue;
169 val.resize(tVals.size());
170 for (unsigned int j = 0; j != tVals.size(); j++)
171 val[j] = j;
172 }
173 Tag tagh = 0;
174 std::stringstream ss_tag_name;
175 ss_tag_name << "__" << dimNames[i] << "_LOC_VALS";
176 tag_name = ss_tag_name.str();
177 rval = mbImpl->tag_get_handle(tag_name.c_str(), val.size(), MB_TYPE_INTEGER, tagh,
178 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
179 rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
180 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
181 }
182 }
183
184 // __<var_name>_DIMS
185 for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
186 Tag varNamesDimsTag = 0;
187 std::stringstream ss_tag_name;
188 ss_tag_name << "__" << mapIter->first << "_DIMS";
189 tag_name = ss_tag_name.str();
190 unsigned int varDimSz = varInfo[mapIter->first].varDims.size();
191 if (varDimSz == 0)
192 continue;
193 std::vector<Tag> varDimTags(varDimSz);
194 for (unsigned int i = 0; i != varDimSz; i++) {
195 Tag tmptag = 0;
196 std::string tmptagname = dimNames[varInfo[mapIter->first].varDims[i]];
197 rval = mbImpl->tag_get_handle(tmptagname.c_str(), 0, MB_TYPE_OPAQUE, tmptag, MB_TAG_ANY);MB_CHK_SET_ERR(rval, "Trouble getting tag " << tmptagname);
198 varDimTags[i] = tmptag;
199 }
200 // rval = mbImpl->tag_get_handle(tag_name.c_str(), varDimSz, MB_TYPE_HANDLE, varNamesDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
201 // We should not use MB_TYPE_HANDLE for Tag here. Tag is a pointer, which is 4 bytes on 32 bit machines and 8 bytes on 64 bit machines.
202 // Normally, entity handle is 8 bytes on 64 bit machines, but it can also be configured to 4 bytes.
203 rval = mbImpl->tag_get_handle(tag_name.c_str(), varDimSz*sizeof(Tag), MB_TYPE_OPAQUE, varNamesDimsTag,
204 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
205 rval = mbImpl->tag_set_data(varNamesDimsTag, &_fileSet, 1, &(varDimTags[0]));MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
206 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
207 }
208
209 // <PARTITION_METHOD>
210 Tag part_tag = scdi->part_method_tag();
211 if (!part_tag)
212 MB_SET_ERR(MB_FAILURE, "Trouble getting PARTITION_METHOD tag");
213 rval = mbImpl->tag_set_data(part_tag, &_fileSet, 1, &partMethod);MB_CHK_SET_ERR(rval, "Trouble setting data to PARTITION_METHOD tag");
214 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
215
216 // <__GLOBAL_ATTRIBS>
217 tag_name = "__GLOBAL_ATTRIBS";
218 Tag globalAttTag = 0;
219 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag,
220 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
221 std::string gattVal;
222 std::vector<int> gattLen;
223 rval = create_attrib_string(globalAtts, gattVal, gattLen);MB_CHK_SET_ERR(rval, "Trouble creating global attribute string");
224 const void* gattptr = gattVal.c_str();
225 int globalAttSz = gattVal.size();
226 rval = mbImpl->tag_set_by_ptr(globalAttTag, &_fileSet, 1, &gattptr, &globalAttSz);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
227 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
228
229 // <__GLOBAL_ATTRIBS_LEN>
230 tag_name = "__GLOBAL_ATTRIBS_LEN";
231 Tag globalAttLenTag = 0;
232 if (gattLen.size() == 0)
233 gattLen.push_back(0);
234 rval = mbImpl->tag_get_handle(tag_name.c_str(), gattLen.size(), MB_TYPE_INTEGER, globalAttLenTag,
235 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
236 rval = mbImpl->tag_set_data(globalAttLenTag, &_fileSet, 1, &gattLen[0]);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
237 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
238
239 // __<var_name>_ATTRIBS and __<var_name>_ATTRIBS_LEN
240 for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
241 std::stringstream ssTagName;
242 ssTagName << "__" << mapIter->first << "_ATTRIBS";
243 tag_name = ssTagName.str();
244 Tag varAttTag = 0;
245 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag,
246 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
247
248 std::string varAttVal;
249 std::vector<int> varAttLen;
250 if (mapIter->second.numAtts < 1) {
251 if (dummyVarNames.find(mapIter->first) != dummyVarNames.end()) {
252 // This variable is a dummy coordinate variable
253 varAttVal = "DUMMY_VAR";
254 }
255 else {
256 // This variable has no attributes
257 varAttVal = "NO_ATTRIBS";
258 }
259 }
260 else {
261 rval = create_attrib_string(mapIter->second.varAtts, varAttVal, varAttLen);MB_CHK_SET_ERR(rval, "Trouble creating attribute string for variable " << mapIter->first);
262 }
263 const void* varAttPtr = varAttVal.c_str();
264 int varAttSz = varAttVal.size();
265 if (0 == varAttSz)
266 varAttSz = 1;
267 rval = mbImpl->tag_set_by_ptr(varAttTag, &_fileSet, 1, &varAttPtr, &varAttSz);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
268 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
269
270 ssTagName << "_LEN";
271 tag_name = ssTagName.str();
272 Tag varAttLenTag = 0;
273 if (0 == varAttLen.size())
274 varAttLen.push_back(0);
275 rval = mbImpl->tag_get_handle(tag_name.c_str(), varAttLen.size(), MB_TYPE_INTEGER, varAttLenTag,
276 MB_TAG_SPARSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
277 rval = mbImpl->tag_set_data(varAttLenTag, &_fileSet, 1, &varAttLen[0]);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
278 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
279 }
280
281 // <__VAR_NAMES_LOCATIONS>
282 tag_name = "__VAR_NAMES_LOCATIONS";
283 Tag varNamesLocsTag = 0;
284 std::vector<int> varNamesLocs(varInfo.size());
285 rval = mbImpl->tag_get_handle(tag_name.c_str(), varNamesLocs.size(), MB_TYPE_INTEGER, varNamesLocsTag,
286 MB_TAG_CREAT | MB_TAG_SPARSE);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
287 for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
288 varNamesLocs[std::distance(varInfo.begin(), mapIter)] = mapIter->second.entLoc;
289 }
290 rval = mbImpl->tag_set_data(varNamesLocsTag, &_fileSet, 1, &varNamesLocs[0]);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
291 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
292
293 // <__MESH_TYPE>
294 Tag meshTypeTag = 0;
295 tag_name = "__MESH_TYPE";
296 std::string meshTypeName = get_mesh_type_name();
297
298 rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag,
299 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating conventional tag " << tag_name);
300 ptr = meshTypeName.c_str();
301 int leng = meshTypeName.size();
302 rval = mbImpl->tag_set_by_ptr(meshTypeTag, &_fileSet, 1, &ptr, &leng);MB_CHK_SET_ERR(rval, "Trouble setting data to conventional tag " << tag_name);
303 dbgOut.tprintf(2, "Conventional tag %s created\n", tag_name.c_str());
304
305 return MB_SUCCESS;
306 }
307
update_time_tag_vals()308 ErrorCode NCHelper::update_time_tag_vals()
309 {
310 Interface*& mbImpl = _readNC->mbImpl;
311 std::vector<std::string>& dimNames = _readNC->dimNames;
312
313 ErrorCode rval;
314
315 // The time tag might be a dummy one (e.g. 'Time' for MPAS)
316 std::string time_tag_name = dimNames[tDim];
317 if (dummyVarNames.find(time_tag_name) != dummyVarNames.end())
318 return MB_SUCCESS;
319
320 Tag time_tag = 0;
321 const void* data = NULL;
322 int time_tag_size = 0;
323 rval = mbImpl->tag_get_handle(time_tag_name.c_str(), 0, MB_TYPE_DOUBLE, time_tag, MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble getting tag " << time_tag_name);
324 rval = mbImpl->tag_get_by_ptr(time_tag, &_fileSet, 1, &data, &time_tag_size);MB_CHK_SET_ERR(rval, "Trouble getting data of tag " << time_tag_name);
325 const double* time_tag_vals = static_cast<const double*>(data);
326
327 // Merge tVals (read from current file) to existing time tag
328 // Assume that time_tag_vals and tVals are both sorted
329 std::vector<double> merged_time_vals;
330 merged_time_vals.reserve(time_tag_size + nTimeSteps);
331 int i = 0;
332 int j = 0;
333
334 // Merge time values from time_tag_vals and tVals
335 while (i < time_tag_size && j < nTimeSteps) {
336 if (time_tag_vals[i] < tVals[j])
337 merged_time_vals.push_back(time_tag_vals[i++]);
338 else
339 merged_time_vals.push_back(tVals[j++]);
340 }
341
342 // Append remaining time values of time_tag_vals (if any)
343 while (i < time_tag_size)
344 merged_time_vals.push_back(time_tag_vals[i++]);
345
346 // Append remaining time values of tVals (if any)
347 while (j < nTimeSteps)
348 merged_time_vals.push_back(tVals[j++]);
349
350 data = &merged_time_vals[0];
351 time_tag_size = merged_time_vals.size();
352 rval = mbImpl->tag_set_by_ptr(time_tag, &_fileSet, 1, &data, &time_tag_size);MB_CHK_SET_ERR(rval, "Trouble setting data to tag " << time_tag_name);
353
354 return MB_SUCCESS;
355 }
356
read_variables_setup(std::vector<std::string> & var_names,std::vector<int> & tstep_nums,std::vector<ReadNC::VarData> & vdatas,std::vector<ReadNC::VarData> & vsetdatas)357 ErrorCode NCHelper::read_variables_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
358 std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
359 {
360 std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
361 std::vector<std::string>& dimNames = _readNC->dimNames;
362
363 std::map<std::string, ReadNC::VarData>::iterator mit;
364
365 // If empty read them all (except ignored variables)
366 if (var_names.empty()) {
367 for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
368 ReadNC::VarData vd = (*mit).second;
369
370 // If read all variables at once, skip ignored ones
371 if (ignoredVarNames.find(vd.varName) != ignoredVarNames.end())
372 continue;
373
374 // Coordinate variables (include dummy ones) were read to the file set by default
375 if (std::find(dimNames.begin(), dimNames.end(), vd.varName) != dimNames.end())
376 continue;
377
378 if (vd.entLoc == ReadNC::ENTLOCSET)
379 vsetdatas.push_back(vd);
380 else
381 vdatas.push_back(vd);
382 }
383 }
384 else {
385 // Read specified variables (might include ignored ones)
386 for (unsigned int i = 0; i < var_names.size(); i++) {
387 mit = varInfo.find(var_names[i]);
388 if (mit != varInfo.end()) {
389 ReadNC::VarData vd = (*mit).second;
390
391 // Upon creation of dummy coordinate variables, tag values have already been set
392 if (dummyVarNames.find(vd.varName) != dummyVarNames.end())
393 continue;
394
395 if (vd.entLoc == ReadNC::ENTLOCSET)
396 vsetdatas.push_back(vd);
397 else
398 vdatas.push_back(vd);
399 }
400 else {
401 MB_SET_ERR(MB_FAILURE, "Couldn't find specified variable " << var_names[i]);
402 }
403 }
404 }
405
406 if (tstep_nums.empty() && nTimeSteps > 0) {
407 // No timesteps input, get them all
408 for (int i = 0; i < nTimeSteps; i++)
409 tstep_nums.push_back(i);
410 }
411
412 if (!tstep_nums.empty()) {
413 for (unsigned int i = 0; i < vdatas.size(); i++) {
414 vdatas[i].varTags.resize(tstep_nums.size(), 0);
415 vdatas[i].varDatas.resize(tstep_nums.size());
416 // NC reader assumes that non-set variables always have timesteps
417 assert(std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim) != vdatas[i].varDims.end());
418 vdatas[i].has_tsteps = true;
419 }
420
421 for (unsigned int i = 0; i < vsetdatas.size(); i++) {
422 if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
423 && (vsetdatas[i].varName != dimNames[tDim])) {
424 // Set variables with timesteps: e.g. xtime(Time) or xtime(Time, StrLen)
425 vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
426 vsetdatas[i].varDatas.resize(tstep_nums.size());
427 vsetdatas[i].has_tsteps = true;
428 }
429 else {
430 // Set variables without timesteps: no time dimension, or time itself
431 vsetdatas[i].varTags.resize(1, 0);
432 vsetdatas[i].varDatas.resize(1);
433 vsetdatas[i].has_tsteps = false;
434 }
435 }
436 }
437
438 return MB_SUCCESS;
439 }
440
read_variables_to_set(std::vector<ReadNC::VarData> & vdatas,std::vector<int> & tstep_nums)441 ErrorCode NCHelper::read_variables_to_set(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
442 {
443 Interface*& mbImpl = _readNC->mbImpl;
444 DebugOutput& dbgOut = _readNC->dbgOut;
445
446 ErrorCode rval = read_variables_to_set_allocate(vdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble allocating space to read set variables");
447
448 // Finally, read into that space
449 int success;
450 for (unsigned int i = 0; i < vdatas.size(); i++) {
451 // Note, for set variables without timesteps, loop one time and then break
452 for (unsigned int t = 0; t < tstep_nums.size(); t++) {
453 void* data = vdatas[i].varDatas[t];
454
455 // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
456 if (vdatas[i].has_tsteps) {
457 // Set readStart for each timestep along time dimension
458 vdatas[i].readStarts[0] = tstep_nums[t];
459 }
460
461 switch (vdatas[i].varDataType) {
462 case NC_BYTE:
463 case NC_CHAR:
464 success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
465 &vdatas[i].readCounts[0], (char*) data);
466 if (success)
467 MB_SET_ERR(MB_FAILURE, "Failed to read byte/char data for variable " << vdatas[i].varName);
468 break;
469 case NC_SHORT:
470 case NC_INT:
471 success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
472 &vdatas[i].readCounts[0], (int*) data);
473 if (success)
474 MB_SET_ERR(MB_FAILURE, "Failed to read short/int data for variable " << vdatas[i].varName);
475 break;
476 case NC_FLOAT:
477 case NC_DOUBLE:
478 success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
479 &vdatas[i].readCounts[0], (double*) data);
480 if (success)
481 MB_SET_ERR(MB_FAILURE, "Failed to read float/double data for variable " << vdatas[i].varName);
482 break;
483 default:
484 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName);
485 }
486
487 dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
488 rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &data, &vdatas[i].sz);MB_CHK_SET_ERR(rval, "Trouble setting tag data for variable " << vdatas[i].varName);
489
490 // Memory pointed by pointer data can be deleted, as tag_set_by_ptr() has already copied the tag values
491 switch (vdatas[i].varDataType) {
492 case NC_BYTE:
493 case NC_CHAR:
494 delete[] (char*) data;
495 break;
496 case NC_SHORT:
497 case NC_INT:
498 delete[] (int*) data;
499 break;
500 case NC_FLOAT:
501 case NC_DOUBLE:
502 delete[] (double*) data;
503 break;
504 default:
505 break;
506 }
507 vdatas[i].varDatas[t] = NULL;
508
509 // Loop continues only for set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
510 if (!vdatas[i].has_tsteps)
511 break;
512 }
513 }
514
515 // Debug output, if requested
516 if (1 == dbgOut.get_verbosity()) {
517 dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
518 for (unsigned int i = 1; i < vdatas.size(); i++)
519 dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
520 dbgOut.tprintf(1, "\n");
521 }
522
523 return rval;
524 }
525
read_coordinate(const char * var_name,int lmin,int lmax,std::vector<double> & cvals)526 ErrorCode NCHelper::read_coordinate(const char* var_name, int lmin, int lmax, std::vector<double>& cvals)
527 {
528 std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
529 std::map<std::string, ReadNC::VarData>::iterator vmit = varInfo.find(var_name);
530 if (varInfo.end() == vmit)
531 MB_SET_ERR(MB_FAILURE, "Couldn't find variable " << var_name);
532
533 assert(lmin >= 0 && lmax >= lmin);
534 NCDF_SIZE tstart = lmin;
535 NCDF_SIZE tcount = lmax - lmin + 1;
536 NCDF_DIFF dum_stride = 1;
537 int success;
538
539 // Check size
540 if ((std::size_t)tcount != cvals.size())
541 cvals.resize(tcount);
542
543 // Check to make sure it's a float or double
544 switch ((*vmit).second.varDataType) {
545 case NC_FLOAT:
546 case NC_DOUBLE:
547 // Read float as double
548 success = NCFUNCAG(_vars_double)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &cvals[0]);
549 if (success)
550 MB_SET_ERR(MB_FAILURE, "Failed to read float/double data for variable " << var_name);
551 break;
552 default:
553 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << var_name);
554 }
555
556 return MB_SUCCESS;
557 }
558
get_tag_to_set(ReadNC::VarData & var_data,int tstep_num,Tag & tagh)559 ErrorCode NCHelper::get_tag_to_set(ReadNC::VarData& var_data, int tstep_num, Tag& tagh)
560 {
561 Interface*& mbImpl = _readNC->mbImpl;
562 DebugOutput& dbgOut = _readNC->dbgOut;
563 int& tStepBase = _readNC->tStepBase;
564
565 if (tStepBase > 0)
566 tstep_num += tStepBase;
567
568 std::ostringstream tag_name;
569 if (var_data.has_tsteps)
570 tag_name << var_data.varName << tstep_num;
571 else
572 tag_name << var_data.varName;
573
574 ErrorCode rval = MB_SUCCESS;
575 tagh = 0;
576 switch (var_data.varDataType) {
577 case NC_BYTE:
578 case NC_CHAR:
579 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_OPAQUE, tagh,
580 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
581 break;
582 case NC_SHORT:
583 case NC_INT:
584 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_INTEGER, tagh,
585 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
586 break;
587 case NC_FLOAT:
588 case NC_DOUBLE:
589 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_DOUBLE, tagh,
590 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
591 break;
592 default:
593 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << var_data.varName);
594 }
595
596 dbgOut.tprintf(2, "Tag %s created\n", tag_name.str().c_str());
597
598 return rval;
599 }
600
get_tag_to_nonset(ReadNC::VarData & var_data,int tstep_num,Tag & tagh,int num_lev)601 ErrorCode NCHelper::get_tag_to_nonset(ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev)
602 {
603 Interface*& mbImpl = _readNC->mbImpl;
604 DebugOutput& dbgOut = _readNC->dbgOut;
605 int& tStepBase = _readNC->tStepBase;
606
607 if (tStepBase > 0)
608 tstep_num += tStepBase;
609
610 std::ostringstream tag_name;
611 tag_name << var_data.varName << tstep_num;
612
613 ErrorCode rval = MB_SUCCESS;
614 tagh = 0;
615 switch (var_data.varDataType) {
616 case NC_BYTE:
617 case NC_CHAR:
618 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_OPAQUE, tagh,
619 MB_TAG_DENSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
620 break;
621 case NC_SHORT:
622 case NC_INT:
623 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_INTEGER, tagh,
624 MB_TAG_DENSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
625 break;
626 case NC_FLOAT:
627 case NC_DOUBLE:
628 rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_DOUBLE, tagh,
629 MB_TAG_DENSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating tag " << tag_name.str());
630 break;
631 default:
632 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << var_data.varName);
633 }
634
635 dbgOut.tprintf(2, "Tag %s created\n", tag_name.str().c_str());
636
637 return rval;
638 }
639
create_attrib_string(const std::map<std::string,ReadNC::AttData> & attMap,std::string & attVal,std::vector<int> & attLen)640 ErrorCode NCHelper::create_attrib_string(const std::map<std::string, ReadNC::AttData>& attMap, std::string& attVal, std::vector<int>& attLen)
641 {
642 int success;
643 std::stringstream ssAtt;
644 unsigned int sz = 0;
645 std::map<std::string, ReadNC::AttData>::const_iterator attIt = attMap.begin();
646 for (; attIt != attMap.end(); ++attIt) {
647 ssAtt << attIt->second.attName;
648 ssAtt << '\0';
649 void* attData = NULL;
650 switch (attIt->second.attDataType) {
651 case NC_BYTE:
652 case NC_CHAR:
653 sz = attIt->second.attLen;
654 attData = (char *) malloc(sz);
655 success = NCFUNC(get_att_text)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (char*) attData);
656 if (success)
657 MB_SET_ERR(MB_FAILURE, "Failed to read byte/char data for attribute " << attIt->second.attName);
658 ssAtt << "char;";
659 break;
660 case NC_SHORT:
661 sz = attIt->second.attLen * sizeof(short);
662 attData = (short *) malloc(sz);
663 success = NCFUNC(get_att_short)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (short*) attData);
664 if (success)
665 MB_SET_ERR(MB_FAILURE, "Failed to read short data for attribute " << attIt->second.attName);
666 ssAtt << "short;";
667 break;
668 case NC_INT:
669 sz = attIt->second.attLen * sizeof(int);
670 attData = (int *) malloc(sz);
671 success = NCFUNC(get_att_int)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (int*) attData);
672 if (success)
673 MB_SET_ERR(MB_FAILURE, "Failed to read int data for attribute " << attIt->second.attName);
674 ssAtt << "int;";
675 break;
676 case NC_FLOAT:
677 sz = attIt->second.attLen * sizeof(float);
678 attData = (float *) malloc(sz);
679 success = NCFUNC(get_att_float)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (float*) attData);
680 if (success)
681 MB_SET_ERR(MB_FAILURE, "Failed to read float data for attribute " << attIt->second.attName);
682 ssAtt << "float;";
683 break;
684 case NC_DOUBLE:
685 sz = attIt->second.attLen * sizeof(double);
686 attData = (double *) malloc(sz);
687 success = NCFUNC(get_att_double)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (double*) attData);
688 if (success)
689 MB_SET_ERR(MB_FAILURE, "Failed to read double data for attribute " << attIt->second.attName);
690 ssAtt << "double;";
691 break;
692 default:
693 MB_SET_ERR(MB_FAILURE, "Unexpected data type for attribute " << attIt->second.attName);
694 }
695 char* tmpc = (char *) attData;
696 for (unsigned int counter = 0; counter != sz; ++counter)
697 ssAtt << tmpc[counter];
698 free(attData);
699 ssAtt << ';';
700 attLen.push_back(ssAtt.str().size() - 1);
701 }
702 attVal = ssAtt.str();
703
704 return MB_SUCCESS;
705 }
706
create_dummy_variables()707 ErrorCode NCHelper::create_dummy_variables()
708 {
709 Interface*& mbImpl = _readNC->mbImpl;
710 std::vector<std::string>& dimNames = _readNC->dimNames;
711 std::vector<int>& dimLens = _readNC->dimLens;
712 std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
713 DebugOutput& dbgOut = _readNC->dbgOut;
714
715 // Hack: look at all dimensions, and see if we have one that does not appear in the list of varInfo names
716 // Right now, candidates are from unstructured meshes, such as ncol (HOMME) and nCells (MPAS)
717 // For each of them, create a dummy coordinate variable with a sparse tag to store the dimension length
718 for (unsigned int i = 0; i < dimNames.size(); i++) {
719 // If there is a variable with this dimension name, skip
720 if (varInfo.find(dimNames[i]) != varInfo.end())
721 continue;
722
723 // Create a dummy coordinate variable
724 int sizeTotalVar = varInfo.size();
725 std::string var_name(dimNames[i]);
726 ReadNC::VarData& data = varInfo[var_name];
727 data.varName = var_name;
728 data.varId = sizeTotalVar;
729 data.varTags.resize(1, 0);
730 data.varDataType = NC_INT;
731 data.varDims.resize(1);
732 data.varDims[0] = (int)i;
733 data.numAtts = 0;
734 data.entLoc = ReadNC::ENTLOCSET;
735 dummyVarNames.insert(var_name);
736 dbgOut.tprintf(2, "Dummy coordinate variable created for dimension %s\n", var_name.c_str());
737
738 // Create a corresponding sparse tag
739 Tag tagh;
740 ErrorCode rval = mbImpl->tag_get_handle(var_name.c_str(), 0, MB_TYPE_INTEGER, tagh,
741 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);MB_CHK_SET_ERR(rval, "Trouble creating tag for dummy coordinate variable " << var_name);
742
743 // Tag value is the dimension length
744 const void* ptr = &dimLens[i];
745 // Tag size is 1
746 int size = 1;
747 rval = mbImpl->tag_set_by_ptr(tagh, &_fileSet, 1, &ptr, &size);MB_CHK_SET_ERR(rval, "Trouble setting tag data for dummy coordinate variable " << var_name);
748
749 dbgOut.tprintf(2, "Sparse tag created for dimension %s\n", var_name.c_str());
750 }
751
752 return MB_SUCCESS;
753 }
754
read_variables_to_set_allocate(std::vector<ReadNC::VarData> & vdatas,std::vector<int> & tstep_nums)755 ErrorCode NCHelper::read_variables_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
756 {
757 std::vector<int>& dimLens = _readNC->dimLens;
758 DebugOutput& dbgOut = _readNC->dbgOut;
759
760 ErrorCode rval = MB_SUCCESS;
761
762 for (unsigned int i = 0; i < vdatas.size(); i++) {
763 // Set up readStarts and readCounts
764 if (vdatas[i].has_tsteps) {
765 // First: time
766 vdatas[i].readStarts.push_back(0); // This value is timestep dependent, will be set later
767 vdatas[i].readCounts.push_back(1);
768
769 // Next: other dimensions
770 for (unsigned int idx = 1; idx != vdatas[i].varDims.size(); idx++) {
771 vdatas[i].readStarts.push_back(0);
772 vdatas[i].readCounts.push_back(dimLens[vdatas[i].varDims[idx]]);
773 }
774 }
775 else {
776 if (vdatas[i].varDims.empty()) {
777 // Scalar variable
778 vdatas[i].readStarts.push_back(0);
779 vdatas[i].readCounts.push_back(1);
780 }
781 else {
782 for (unsigned int idx = 0; idx != vdatas[i].varDims.size(); idx++) {
783 vdatas[i].readStarts.push_back(0);
784 vdatas[i].readCounts.push_back(dimLens[vdatas[i].varDims[idx]]);
785 }
786 }
787 }
788
789 // Get variable size
790 vdatas[i].sz = 1;
791 for (std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++)
792 vdatas[i].sz *= vdatas[i].readCounts[idx];
793
794 // Note, for set variables without timesteps, loop one time and then break
795 for (unsigned int t = 0; t < tstep_nums.size(); t++) {
796 dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
797
798 if (tstep_nums[t] >= dimLens[tDim]) {
799 MB_SET_ERR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t]);
800 }
801
802 // Get the tag to read into
803 if (!vdatas[i].varTags[t]) {
804 rval = get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[i].varTags[t]);MB_CHK_SET_ERR(rval, "Trouble getting tag to set variable " << vdatas[i].varName);
805 }
806
807 switch (vdatas[i].varDataType) {
808 case NC_BYTE:
809 case NC_CHAR:
810 vdatas[i].varDatas[t] = new char[vdatas[i].sz];
811 break;
812 case NC_SHORT:
813 case NC_INT:
814 vdatas[i].varDatas[t] = new int[vdatas[i].sz];
815 break;
816 case NC_FLOAT:
817 case NC_DOUBLE:
818 vdatas[i].varDatas[t] = new double[vdatas[i].sz];
819 break;
820 default:
821 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName);
822 }
823
824 // Loop continues only for set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
825 if (!vdatas[i].has_tsteps)
826 break;
827 }
828 }
829
830 return rval;
831 }
832
check_existing_mesh()833 ErrorCode ScdNCHelper::check_existing_mesh() {
834 Interface*& mbImpl = _readNC->mbImpl;
835
836 // Get the number of vertices
837 int num_verts;
838 ErrorCode rval = mbImpl->get_number_entities_by_dimension(_fileSet, 0, num_verts);MB_CHK_SET_ERR(rval, "Trouble getting number of vertices");
839
840 /*
841 // Check against parameters
842 // When ghosting is used, this check might fail (to be updated later)
843 if (num_verts > 0) {
844 int expected_verts = (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) * (-1 == lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
845 if (num_verts != expected_verts) {
846 MB_SET_ERR(MB_FAILURE, "Number of vertices doesn't match");
847 }
848 }
849 */
850
851 // Check the number of elements too
852 int num_elems;
853 rval = mbImpl->get_number_entities_by_dimension(_fileSet, (-1 == lCDims[2] ? 2 : 3), num_elems);MB_CHK_SET_ERR(rval, "Trouble getting number of elements");
854
855 /*
856 // Check against parameters
857 // When ghosting is used, this check might fail (to be updated later)
858 if (num_elems > 0) {
859 int expected_elems = (lCDims[3] - lCDims[0] + 1) * (lCDims[4] - lCDims[1] + 1) * (-1 == lCDims[2] ? 1 : (lCDims[5] - lCDims[2] + 1));
860 if (num_elems != expected_elems) {
861 MB_SET_ERR(MB_FAILURE, "Number of elements doesn't match");
862 }
863 }
864 */
865
866 return MB_SUCCESS;
867 }
868
create_mesh(Range & faces)869 ErrorCode ScdNCHelper::create_mesh(Range& faces)
870 {
871 Interface*& mbImpl = _readNC->mbImpl;
872 Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
873 const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
874 DebugOutput& dbgOut = _readNC->dbgOut;
875 ScdInterface* scdi = _readNC->scdi;
876 ScdParData& parData = _readNC->parData;
877
878 Range tmp_range;
879 ScdBox* scd_box;
880
881 ErrorCode rval = scdi->construct_box(HomCoord(lDims[0], lDims[1], lDims[2], 1), HomCoord(lDims[3], lDims[4], lDims[5], 1),
882 NULL, 0, scd_box, locallyPeriodic, &parData, true);MB_CHK_SET_ERR(rval, "Trouble creating scd vertex sequence");
883
884 // Add verts to tmp_range first, so we can duplicate global ids in vertex ids
885 tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1);
886
887 if (mpFileIdTag) {
888 int count;
889 void* data;
890 rval = mbImpl->tag_iterate(*mpFileIdTag, tmp_range.begin(), tmp_range.end(), count, data);MB_CHK_SET_ERR(rval, "Failed to iterate file ID tag on local vertices");
891 assert(count == scd_box->num_vertices());
892 int* fid_data = (int*) data;
893 rval = mbImpl->tag_iterate(mGlobalIdTag, tmp_range.begin(), tmp_range.end(), count, data);MB_CHK_SET_ERR(rval, "Failed to iterate global ID tag on local vertices");
894 assert(count == scd_box->num_vertices());
895 int* gid_data = (int*) data;
896 for (int i = 0; i < count; i++)
897 fid_data[i] = gid_data[i];
898 }
899
900 // Then add box set and elements to the range, then to the file set
901 tmp_range.insert(scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1);
902 tmp_range.insert(scd_box->box_set());
903 rval = mbImpl->add_entities(_fileSet, tmp_range);MB_CHK_SET_ERR(rval, "Couldn't add new vertices to current file set");
904
905 dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_elements(), scd_box->num_vertices());
906
907 // Set the vertex coordinates
908 double *xc, *yc, *zc;
909 rval = scd_box->get_coordinate_arrays(xc, yc, zc);MB_CHK_SET_ERR(rval, "Couldn't get vertex coordinate arrays");
910
911 int i, j, k, il, jl, kl;
912 int dil = lDims[3] - lDims[0] + 1;
913 int djl = lDims[4] - lDims[1] + 1;
914 assert(dil == (int)ilVals.size() && djl == (int)jlVals.size() &&
915 (-1 == lDims[2] || lDims[5] - lDims[2] + 1 == (int)levVals.size()));
916
917 for (kl = lDims[2]; kl <= lDims[5]; kl++) {
918 k = kl - lDims[2];
919 for (jl = lDims[1]; jl <= lDims[4]; jl++) {
920 j = jl - lDims[1];
921 for (il = lDims[0]; il <= lDims[3]; il++) {
922 i = il - lDims[0];
923 unsigned int pos = i + j * dil + k * dil * djl;
924 xc[pos] = ilVals[i];
925 yc[pos] = jlVals[j];
926 zc[pos] = (-1 == lDims[2] ? 0.0 : levVals[k]);
927 }
928 }
929 }
930
931 #ifndef NDEBUG
932 int num_verts = (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) * (-1 == lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
933 std::vector<int> gids(num_verts);
934 Range verts(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1);
935 rval = mbImpl->tag_get_data(mGlobalIdTag, verts, &gids[0]);MB_CHK_SET_ERR(rval, "Trouble getting local gid values of vertices");
936 int vmin = *(std::min_element(gids.begin(), gids.end())), vmax = *(std::max_element(gids.begin(), gids.end()));
937 dbgOut.tprintf(1, "Vertex gids %d-%d\n", vmin, vmax);
938 #endif
939
940 // Add elements to the range passed in
941 faces.insert(scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1);
942
943 if (2 <= dbgOut.get_verbosity()) {
944 assert(scd_box->boundary_complete());
945 EntityHandle dum_ent = scd_box->start_element();
946 rval = mbImpl->list_entities(&dum_ent, 1);MB_CHK_SET_ERR(rval, "Trouble listing first hex");
947
948 std::vector<EntityHandle> connect;
949 rval = mbImpl->get_connectivity(&dum_ent, 1, connect);MB_CHK_SET_ERR(rval, "Trouble getting connectivity");
950
951 rval = mbImpl->list_entities(&connect[0], connect.size());MB_CHK_SET_ERR(rval, "Trouble listing element connectivity");
952 }
953
954 Range edges;
955 mbImpl->get_adjacencies(faces, 1, true, edges, Interface::UNION);
956
957 // Create COORDS tag for quads
958 rval = create_quad_coordinate_tag();MB_CHK_SET_ERR(rval, "Trouble creating COORDS tag for quads");
959
960 return MB_SUCCESS;
961 }
962
read_variables(std::vector<std::string> & var_names,std::vector<int> & tstep_nums)963 ErrorCode ScdNCHelper::read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
964 {
965 std::vector<ReadNC::VarData> vdatas;
966 std::vector<ReadNC::VarData> vsetdatas;
967
968 ErrorCode rval = read_variables_setup(var_names, tstep_nums, vdatas, vsetdatas);MB_CHK_SET_ERR(rval, "Trouble setting up to read variables");
969
970 if (!vsetdatas.empty()) {
971 rval = read_variables_to_set(vsetdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading variables to set");
972 }
973
974 if (!vdatas.empty()) {
975 rval = read_scd_variables_to_nonset(vdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading variables to verts/edges/faces");
976 }
977
978 return MB_SUCCESS;
979 }
980
read_scd_variables_to_nonset_allocate(std::vector<ReadNC::VarData> & vdatas,std::vector<int> & tstep_nums)981 ErrorCode ScdNCHelper::read_scd_variables_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
982 {
983 Interface*& mbImpl = _readNC->mbImpl;
984 std::vector<int>& dimLens = _readNC->dimLens;
985 DebugOutput& dbgOut = _readNC->dbgOut;
986
987 Range* range = NULL;
988
989 // Get vertices
990 Range verts;
991 ErrorCode rval = mbImpl->get_entities_by_dimension(_fileSet, 0, verts);MB_CHK_SET_ERR(rval, "Trouble getting vertices in current file set");
992 assert("Should only have a single vertex subrange, since they were read in one shot" &&
993 verts.psize() == 1);
994
995 Range edges;
996 rval = mbImpl->get_entities_by_dimension(_fileSet, 1, edges);MB_CHK_SET_ERR(rval, "Trouble getting edges in current file set");
997
998 // Get faces
999 Range faces;
1000 rval = mbImpl->get_entities_by_dimension(_fileSet, 2, faces);MB_CHK_SET_ERR(rval, "Trouble getting faces in current file set");
1001 assert("Should only have a single face subrange, since they were read in one shot" &&
1002 faces.psize() == 1);
1003
1004 #ifdef MOAB_HAVE_MPI
1005 moab::Range faces_owned;
1006 bool& isParallel = _readNC->isParallel;
1007 if (isParallel) {
1008 ParallelComm*& myPcomm = _readNC->myPcomm;
1009 rval = myPcomm->filter_pstatus(faces, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &faces_owned);MB_CHK_SET_ERR(rval, "Trouble getting owned faces in current file set");
1010 }
1011 else
1012 faces_owned = faces; // Not running in parallel, but still with MPI
1013 #endif
1014
1015 for (unsigned int i = 0; i < vdatas.size(); i++) {
1016 // Support non-set variables with 4 dimensions like (time, lev, lat, lon)
1017 assert(4 == vdatas[i].varDims.size());
1018
1019 // For a non-set variable, time should be the first dimension
1020 assert(tDim == vdatas[i].varDims[0]);
1021
1022 // Set up readStarts and readCounts
1023 vdatas[i].readStarts.resize(4);
1024 vdatas[i].readCounts.resize(4);
1025
1026 // First: time
1027 vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
1028 vdatas[i].readCounts[0] = 1;
1029
1030 // Next: lev
1031 vdatas[i].readStarts[1] = 0;
1032 vdatas[i].readCounts[1] = vdatas[i].numLev;
1033
1034 // Finally: lat (or slat) and lon (or slon)
1035 switch (vdatas[i].entLoc) {
1036 case ReadNC::ENTLOCVERT:
1037 // Vertices
1038 vdatas[i].readStarts[2] = lDims[1];
1039 vdatas[i].readCounts[2] = lDims[4] - lDims[1] + 1;
1040 vdatas[i].readStarts[3] = lDims[0];
1041 vdatas[i].readCounts[3] = lDims[3] - lDims[0] + 1;
1042 range = &verts;
1043 break;
1044 case ReadNC::ENTLOCNSEDGE:
1045 case ReadNC::ENTLOCEWEDGE:
1046 case ReadNC::ENTLOCEDGE:
1047 // Not implemented yet, set a global error
1048 MB_SET_GLB_ERR(MB_NOT_IMPLEMENTED, "Reading edge data is not implemented yet");
1049 case ReadNC::ENTLOCFACE:
1050 // Faces
1051 vdatas[i].readStarts[2] = lCDims[1];
1052 vdatas[i].readCounts[2] = lCDims[4] - lCDims[1] + 1;
1053 vdatas[i].readStarts[3] = lCDims[0];
1054 vdatas[i].readCounts[3] = lCDims[3] - lCDims[0] + 1;
1055 #ifdef MOAB_HAVE_MPI
1056 range = &faces_owned;
1057 #else
1058 range = &faces;
1059 #endif
1060 break;
1061 default:
1062 MB_SET_ERR(MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName);
1063 }
1064
1065 for (unsigned int t = 0; t < tstep_nums.size(); t++) {
1066 dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
1067
1068 if (tstep_nums[t] >= dimLens[tDim]) {
1069 MB_SET_ERR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t]);
1070 }
1071
1072 // Get the tag to read into
1073 if (!vdatas[i].varTags[t]) {
1074 rval = get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);MB_CHK_SET_ERR(rval, "Trouble getting tag to non-set variable " << vdatas[i].varName);
1075 }
1076
1077 // Get ptr to tag space
1078 void* data;
1079 int count;
1080 rval = mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), range->end(), count, data);MB_CHK_SET_ERR(rval, "Failed to iterate tag for non-set variable " << vdatas[i].varName);
1081 assert((unsigned)count == range->size());
1082 vdatas[i].varDatas[t] = data;
1083 }
1084
1085 // Get variable size
1086 vdatas[i].sz = 1;
1087 for (std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++)
1088 vdatas[i].sz *= vdatas[i].readCounts[idx];
1089 }
1090
1091 return rval;
1092 }
1093
read_scd_variables_to_nonset(std::vector<ReadNC::VarData> & vdatas,std::vector<int> & tstep_nums)1094 ErrorCode ScdNCHelper::read_scd_variables_to_nonset(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
1095 {
1096 DebugOutput& dbgOut = _readNC->dbgOut;
1097
1098 ErrorCode rval = read_scd_variables_to_nonset_allocate(vdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble allocating space to read non-set variables");
1099
1100 // Finally, read into that space
1101 int success;
1102 for (unsigned int i = 0; i < vdatas.size(); i++) {
1103 std::size_t sz = vdatas[i].sz;
1104
1105 // A typical supported variable: float T(time, lev, lat, lon)
1106 // For tag values, need transpose (lev, lat, lon) to (lat, lon, lev)
1107 size_t ni = vdatas[i].readCounts[3]; // lon or slon
1108 size_t nj = vdatas[i].readCounts[2]; // lat or slat
1109 size_t nk = vdatas[i].readCounts[1]; // lev
1110
1111 for (unsigned int t = 0; t < tstep_nums.size(); t++) {
1112 // Tag data for this timestep
1113 void* data = vdatas[i].varDatas[t];
1114
1115 // Set readStart for each timestep along time dimension
1116 vdatas[i].readStarts[0] = tstep_nums[t];
1117
1118 switch (vdatas[i].varDataType) {
1119 case NC_BYTE:
1120 case NC_CHAR: {
1121 std::vector<char> tmpchardata(sz);
1122 success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
1123 &tmpchardata[0]);
1124 if (success)
1125 MB_SET_ERR(MB_FAILURE, "Failed to read byte/char data for variable " << vdatas[i].varName);
1126 if (vdatas[i].numLev > 1)
1127 // Transpose (lev, lat, lon) to (lat, lon, lev)
1128 kji_to_jik(ni, nj, nk, data, &tmpchardata[0]);
1129 else {
1130 for (std::size_t idx = 0; idx != tmpchardata.size(); idx++)
1131 ((char*) data)[idx] = tmpchardata[idx];
1132 }
1133 break;
1134 }
1135 case NC_SHORT:
1136 case NC_INT: {
1137 std::vector<int> tmpintdata(sz);
1138 success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
1139 &tmpintdata[0]);
1140 if (success)
1141 MB_SET_ERR(MB_FAILURE, "Failed to read short/int data for variable " << vdatas[i].varName);
1142 if (vdatas[i].numLev > 1)
1143 // Transpose (lev, lat, lon) to (lat, lon, lev)
1144 kji_to_jik(ni, nj, nk, data, &tmpintdata[0]);
1145 else {
1146 for (std::size_t idx = 0; idx != tmpintdata.size(); idx++)
1147 ((int*) data)[idx] = tmpintdata[idx];
1148 }
1149 break;
1150 }
1151 case NC_FLOAT:
1152 case NC_DOUBLE: {
1153 std::vector<double> tmpdoubledata(sz);
1154 success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
1155 &tmpdoubledata[0]);
1156 if (success)
1157 MB_SET_ERR(MB_FAILURE, "Failed to read float/double data for variable " << vdatas[i].varName);
1158 if (vdatas[i].numLev > 1)
1159 // Transpose (lev, lat, lon) to (lat, lon, lev)
1160 kji_to_jik(ni, nj, nk, data, &tmpdoubledata[0]);
1161 else {
1162 for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
1163 ((double*) data)[idx] = tmpdoubledata[idx];
1164 }
1165 break;
1166 }
1167 default:
1168 MB_SET_ERR(MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName);
1169 }
1170 }
1171 }
1172
1173 // Debug output, if requested
1174 if (1 == dbgOut.get_verbosity()) {
1175 dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
1176 for (unsigned int i = 1; i < vdatas.size(); i++)
1177 dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
1178 dbgOut.tprintf(1, "\n");
1179 }
1180
1181 return rval;
1182 }
1183
create_quad_coordinate_tag()1184 ErrorCode ScdNCHelper::create_quad_coordinate_tag() {
1185 Interface*& mbImpl = _readNC->mbImpl;
1186
1187 Range ents;
1188 ErrorCode rval = mbImpl->get_entities_by_type(_fileSet, moab::MBQUAD, ents);MB_CHK_SET_ERR(rval, "Trouble getting quads");
1189
1190 std::size_t numOwnedEnts = 0;
1191 #ifdef MOAB_HAVE_MPI
1192 Range ents_owned;
1193 bool& isParallel = _readNC->isParallel;
1194 if (isParallel) {
1195 ParallelComm*& myPcomm = _readNC->myPcomm;
1196 rval = myPcomm->filter_pstatus(ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &ents_owned);MB_CHK_SET_ERR(rval, "Trouble getting owned quads");
1197 numOwnedEnts = ents_owned.size();
1198 }
1199 else {
1200 numOwnedEnts = ents.size();
1201 ents_owned = ents;
1202 }
1203 #else
1204 numOwnedEnts = ents.size();
1205 #endif
1206
1207 if (numOwnedEnts == 0)
1208 return MB_SUCCESS;
1209
1210 assert(numOwnedEnts == ilCVals.size() * jlCVals.size());
1211 std::vector<double> coords(numOwnedEnts * 3);
1212 std::size_t pos = 0;
1213 for (std::size_t j = 0; j != jlCVals.size(); ++j) {
1214 for (std::size_t i = 0; i != ilCVals.size(); ++i) {
1215 pos = j * ilCVals.size() * 3 + i * 3;
1216 coords[pos] = ilCVals[i];
1217 coords[pos + 1] = jlCVals[j];
1218 coords[pos + 2] = 0.0;
1219 }
1220 }
1221 std::string tag_name = "COORDS";
1222 Tag tagh = 0;
1223 rval = mbImpl->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh,
1224 MB_TAG_DENSE | MB_TAG_CREAT);MB_CHK_SET_ERR(rval, "Trouble creating COORDS tag");
1225
1226 void *data;
1227 int count;
1228 #ifdef MOAB_HAVE_MPI
1229 rval = mbImpl->tag_iterate(tagh, ents_owned.begin(), ents_owned.end(), count, data);MB_CHK_SET_ERR(rval, "Failed to iterate COORDS tag on quads");
1230 #else
1231 rval = mbImpl->tag_iterate(tagh, ents.begin(), ents.end(), count, data);MB_CHK_SET_ERR(rval, "Failed to iterate COORDS tag on quads");
1232 #endif
1233 assert(count == (int)numOwnedEnts);
1234 double* quad_data = (double*) data;
1235 std::copy(coords.begin(), coords.end(), quad_data);
1236
1237 return MB_SUCCESS;
1238 }
1239
read_variables(std::vector<std::string> & var_names,std::vector<int> & tstep_nums)1240 ErrorCode UcdNCHelper::read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
1241 {
1242 std::vector<ReadNC::VarData> vdatas;
1243 std::vector<ReadNC::VarData> vsetdatas;
1244
1245 ErrorCode rval = read_variables_setup(var_names, tstep_nums, vdatas, vsetdatas);MB_CHK_SET_ERR(rval, "Trouble setting up to read variables");
1246
1247 if (!vsetdatas.empty()) {
1248 rval = read_variables_to_set(vsetdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading variables to set");
1249 }
1250
1251 if (!vdatas.empty()) {
1252 #ifdef MOAB_HAVE_PNETCDF
1253 // With pnetcdf support, we will use async read
1254 rval = read_ucd_variables_to_nonset_async(vdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading variables to verts/edges/faces");
1255 #else
1256 // Without pnetcdf support, we will use old read
1257 rval = read_ucd_variables_to_nonset(vdatas, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading variables to verts/edges/faces");
1258 #endif
1259 }
1260
1261 return MB_SUCCESS;
1262 }
1263
1264 } // namespace moab
1265