MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
ionetcdf.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "ionetcdf.h"
8#include "COMM/mpioverride.h"
9#include "parallelio.h"
10
11#include <cstring>
12#include "globals.h"
13
14using namespace std;
15
16//--------------------------------------------------------------------------
18 DEBUG("IONetcdf::IONetcdf: entry", MAIA_DEBUG_ALLOCATION);
19 DEBUG("IONetcdf::IONetcdf: return", MAIA_DEBUG_ALLOCATION);
20}
21
22//--------------------------------------------------------------------------
24 DEBUG("IONetcdf::~IONetcdf: entry", MAIA_DEBUG_ALLOCATION);
25 DEBUG("IONetcdf::~IONetcdf: return", MAIA_DEBUG_ALLOCATION);
26}
27
28//--------------------------------------------------------------------------
30
31void IONetcdf::makeProperty(MProperty* p, const MString& name, ParallelIo* bdFile) {
32 // TRACE();
33 using namespace maia::parallel_io;
34 ParallelIo::size_type length, start;
35 maiabd_type type;
36 MInt noDims;
37 type = bdFile->getDatasetType(name);
38 noDims = bdFile->getDatasetNoDims(name);
39#ifndef MAIA_WINDOWS
40 switch(type) {
41 case PIO_INT: {
42 DEBUG("IONetcdf::makeProperty: found integer property :", MAIA_DEBUG_IO);
43 p->propertyType = MINT;
44 if(noDims == 0) {
45 p->elements = 1;
46 p->intField = new MInt[1];
47 bdFile->readScalar(p->intField, name);
48 if(p->intField[0] == NC_FILL_INT) {
49 stringstream errorMessage;
50 errorMessage << "IONetcdf::makeProperty: Error" << endl
51 << "Property int " << p->name << " is filled by value " << NC_FILL_INT
52 << ". This happens, because the property was declared in the property file but was never "
53 "initialized there. Go and fix it!";
54 mTerm(1, AT_, errorMessage.str());
55 }
56 DEBUG("IONetcdf::makeProperty: " << p->intField[0], MAIA_DEBUG_IO);
57 }
58 if(noDims == 1) {
59 /* look up the length of the array */
60 length = bdFile->getArraySize(name);
61 p->elements = length;
62 p->intField = new MInt[length];
63 bdFile->setOffset(length, 0);
64 bdFile->readArray(p->intField, name);
65 for(MInt i = 0; i < (MInt)length; i++) {
66 if(p->intField[i] == NC_FILL_INT) {
67 stringstream errorMessage;
68 errorMessage << "Property int " << p->name << " array is filled by the fill value " << NC_FILL_INT
69 << " at the position " << i
70 << ". This happens, because the property was declared in the property file but never "
71 "initialized there. Go and fix it!";
72 mTerm(1, AT_, errorMessage.str());
73 }
74 }
75 // for (MInt i=0; i < length; i++) // delete this line!
76 // DEBUG("IONetcdf::makeProperty: " << p->intField[i], MAIA_DEBUG_IO);
77 }
78 if(noDims == 2) {
79 /*NOT YET IMPLEMENTED !*/
80 }
81 break;
82 }
83 case PIO_FLOAT: {
84 DEBUG("IONetcdf::makeProperty: found float property :", MAIA_DEBUG_IO);
85 p->propertyType = MFLOAT;
86 if(noDims == 0) {
87 p->elements = 1;
88 p->floatField = new MFloat[1];
89 bdFile->readScalar(p->floatField, name);
90 DEBUG("IONetcdf::makeProperty: " << p->floatField[0], MAIA_DEBUG_IO);
91 if(approx(p->floatField[0], NC_FILL_DOUBLE, MFloatEps)) {
92 stringstream errorMessage;
93 errorMessage << "Property double " << p->name << " is filled by the fill value " << NC_FILL_DOUBLE
94 << ". This happens, because the property was declared in the property file but never "
95 "initialized there. Go and fix it!";
96 mTerm(1, AT_, errorMessage.str());
97 }
98 }
99 if(noDims == 1) {
100 /* look up the length of the array */
101 length = bdFile->getArraySize(name);
102 p->elements = length;
103 p->floatField = new MFloat[length];
104 bdFile->setOffset(length, 0);
105 bdFile->readArray(p->floatField, name);
106 for(MInt i = 0; i < (MInt)length; i++) {
107 if(approx(p->floatField[i], NC_FILL_DOUBLE, MFloatEps)) {
108 stringstream errorMessage;
109 errorMessage << "Property double " << p->name << " array is filled by the fill value " << NC_FILL_DOUBLE
110 << " at the position " << i
111 << ". This happens, because the property was declared in the property file but never "
112 "initialized there. Go and fix it!";
113 mTerm(1, AT_, errorMessage.str());
114 }
115 }
116 // for (MInt i=0; i < length; i++) //delete this line!
117 // DEBUG("IONetcdf::makeProperty: " << p->floatField[i], MAIA_DEBUG_IO);
118 }
119 if(noDims == 2) {
120 /*NOT YET IMPLEMENTED !*/
121 }
122 break;
123 }
124 case PIO_STRING: {
125 DEBUG("IONetcdf::makeProperty: found char property :", MAIA_DEBUG_IO);
126 p->propertyType = MSTRING;
127 if(noDims == 0) {
128 p->elements = 1;
129 p->stringField = new MString[1];
130 MString buf;
131 bdFile->readScalar(&buf, name);
132 if(buf[0] == NC_FILL_CHAR) {
133 stringstream errorMessage;
134 errorMessage << "Property char " << p->name << " is filled by the fill value \"" << NC_FILL_CHAR
135 << "\". This happens, because the property was declared in the property file but never "
136 "initialized there. Go and fix it!";
137 mTerm(1, AT_, errorMessage.str());
138 }
139 p->stringField->append(buf);
140 }
141 if(noDims == 1) {
142 p->elements = 1;
143 p->stringField = new MString[1];
144 /* look up the length of the string */
145 length = bdFile->getArraySize(name);
146 MString buf;
147 bdFile->setOffset(length, 0);
148 bdFile->readArray(&buf, name);
149 if(buf[0] == NC_FILL_CHAR) {
150 stringstream errorMessage;
151 errorMessage << "Property array of char " << p->name << " is filled by the fill value \"" << NC_FILL_CHAR
152 << "\". This happens, because the property was declared in the property file but never "
153 "initialized there. Go and fix it!";
154 mTerm(1, AT_, errorMessage.str());
155 }
156 p->stringField->append(buf);
157 DEBUG("IONetcdf::makeProperty: " << p->stringField[0], MAIA_DEBUG_IO);
158 }
159 if(noDims == 2) {
160 /* look up the number of strings */
161 length = bdFile->getArraySize(name, 0);
162 p->elements = length;
163 p->stringField = new MString[length];
164 /* loop over number of strings */
165 for(MInt i = 0; i < p->elements; i++) {
166 start = i;
167 bdFile->setOffset(1, start, 2);
168 MString buf;
169 bdFile->readArray(&buf, name);
170 if(buf[0] == NC_FILL_CHAR) {
171 stringstream errorMessage;
172 errorMessage << "Property array of array of char " << p->name << " element " << i << " of " << p->elements
173 << " is filled by the fill value \"" << NC_FILL_CHAR
174 << "\". This happens, because the property was declared in the property file but never "
175 "initialized there. Go and fix it!";
176 mTerm(1, AT_, errorMessage.str());
177 }
178 p->stringField[i] = buf;
179 DEBUG("IONetcdf::makeProperty: " << p->stringField[i], MAIA_DEBUG_IO);
180 }
181 }
182 break;
183 }
184 default: {
185 stringstream errorMessage;
186 errorMessage << "IONetcdf::makeProperty Error: Unsupported variable input type encountered!" << endl;
187 mTerm(1, AT_, errorMessage.str());
188 }
189 }
190 const pair<const MString, MProperty*> mp(p->name, p);
191
192 // produce the lowercase variant of the name to warn if property exists with different case
193 MString nameL = p->name;
194 std::transform(nameL.begin(), nameL.end(), nameL.begin(), [](unsigned char c) { return std::tolower(c); });
195
196 const pair<const MString, MProperty*> mpL(nameL, p);
197
198 // check if the lowercase variant of this property already exists but no regular-case variant
199 if(!(m_propertyMapLowercase->find(nameL) == m_propertyMapLowercase->end())
200 && (m_propertyMap->find(p->name) == m_propertyMap->end())) {
201 mTerm(1, AT_,
202 "There are multiple occurrences of the property " + p->name
203 + " with different cases. This should not happen!");
204 }
205 m_propertyMap->insert(mp);
206 m_propertyMapLowercase->insert(mpL);
207
208#else
209 // not supported
210 TERM(-1);
211#endif
212
213 DEBUG("IONetcdf::makeProperty: created default property ", MAIA_DEBUG_IO);
214 DEBUG("IONetcdf::makeProperty: elements = " << p->elements, MAIA_DEBUG_IO);
215 DEBUG("IONetcdf::makeProperty: m_noProperties = " << m_propertyMap->size(), MAIA_DEBUG_IO);
216}
217
218//--------------------------------------------------------------------------
224 TRACE();
225 MInt noVariables = 0;
226 const char MPropertySeperator = '.'; // Seperator that defines different Properties
227
228 /* read and store the zone information and the solver info*/
229 const char* du; // tmp variable
230
231 MString varName;
233
234 vector<MString> varNames = bdFile->getDatasetNames();
235 noVariables = varNames.size();
236 for(MInt n = 0; n < noVariables; n++) {
237 varName = varNames[n];
238 if(strstr(varName.c_str(), "zone_solvers.")) { // if a zone has been identified
239 du = strrchr(varName.c_str(), MPropertySeperator); // get pointer to where the "." is
240
241 /* create zone element */
242 MZone* zone;
243 zone = new MZone;
244 zone->name.append(++du);
245 if(zone->name == "default") {
246 mTerm(1, AT_, "IONetcdf::readZones Error: The zone name \"default\" is reserved and cannot be used!");
247 }
248 DEBUG("IONetcdf::readZones: zone found (name: " << zone->name << ")", MAIA_DEBUG_USER2);
249
250 /* get solvers for the zone */
251 length = bdFile->getArraySize(varName);
252 DEBUG("IONetcdf::readZones: the Zone has " << length << " solvers.", MAIA_DEBUG_USER2);
253 zone->noSolvers = length;
254 zone->solvers = new MInt[length];
255 /* There is an implicit conversion from int to unsigned int between netcdf
256 and the zone solvers */
257 for(ParallelIo::size_type i = 0; i < length; i++) {
258 MInt dsolvers;
259 bdFile->setOffset(1, i);
260 bdFile->readArray(&dsolvers, varName);
261 zone->solvers[i] = dsolvers;
262 }
263 /* insert the zone into the zoneMap*/
264 if(m_zoneMap->find(zone->name) == m_zoneMap->end()) {
265 m_zoneMap->insert(make_pair(zone->name, zone));
266 } else {
267 // if a zone with the same name exists throw error
268 stringstream errorMessage;
269 errorMessage << " Error : Double occurence of zone id! " << endl;
270 mTerm(1, AT_, errorMessage.str());
271 }
272 }
273 }
275}
276
277//--------------------------------------------------------------------------
283 TRACE();
284 /* create a zone named "default" */
285 MZone* zone;
286 zone = new MZone;
287 zone->name.append("default");
288
289 /* search for all solvers that are defined */
290 list<MInt> solverList;
291 for(zoneMap::const_iterator it = m_zoneMap->begin(); it != m_zoneMap->end(); it++) {
292 for(MInt i = 0; i < it->second->noSolvers; i++) {
293 solverList.push_back(it->second->solvers[i]);
294 }
295 }
296 solverList.sort();
297
298 /* The number of undefined solvers equals the number of total
299 solvers minus the number of defined solvers ... */
300 zone->noSolvers = (m_noSolvers - solverList.size());
301 zone->solvers = new MInt[zone->noSolvers];
302
303 /* this adds all solverId's that aren't defined to the default zone*/
304 MInt i = 0;
305 MInt simpleIterator = 0;
306 list<MInt>::const_iterator solverIt = solverList.begin();
307
308 while(i < m_noSolvers) {
309 if((!solverList.empty()) && (*solverIt == i)) {
310 i++;
311 solverIt++;
312 } else {
313 zone->solvers[simpleIterator] = i;
314 DEBUG("IONetcdf::buildDefaultZone: added solver " << i << " to the default zone. ", MAIA_DEBUG_IO);
315 i++;
316 simpleIterator++;
317 }
318 }
319
320 /* insert the default zone in the zone map */
321 m_zoneMap->insert(make_pair(zone->name, zone));
322 DEBUG("IONetcdf::buildDefaultZone: default zone has " << zone->noSolvers << " solvers.", MAIA_DEBUG_IO);
323}
324
325//--------------------------------------------------------------------------
331 TRACE();
332 MBool readNew = true;
333 MInt noVariables = 0;
334 m_noSolvers = 0;
337 m_zoneMap = new zoneMap;
338
339 if(readNew) {
340 // split into serial read and distribution is done here
341 if(globalDomainId() == 0) { // reading is only done in serial
342 //??? todo labels:IO change MPropertySeperator to MPropertySeparator
343 const char MPropertySeperator = '.'; // Separator that defines different Properties
344
345 /*open the property file*/
346 ParallelIo parallelIo(name, maia::parallel_io::PIO_READ, MPI_COMM_SELF);
347
348 /* get the number of solvers */
349 MInt dsolvers;
350 if(!parallelIo.hasDataset("noSolvers", 0)) {
351 dsolvers = 1;
352 // cerr << "IONetcdf::readPropertyFile, property \"noSolvers\" is not specified in properties file \"" <<
353 // name << "\" . Thats why it is set to 1." << endl;
354 } else {
355 parallelIo.readScalar(&dsolvers, "noSolvers");
356 }
357 m_noSolvers = dsolvers;
358 /* read and store the zone information and the solver info*/
359
360 readZones(&parallelIo);
361
362 MString varName;
363
364 MProperty* p;
365 /* check the consistency of the zone*/
367 vector<MString> varNames = parallelIo.getDatasetNames();
368 noVariables = varNames.size();
369
370 for(MInt id = 0; id < noVariables; id++) {
371 varName = varNames[id];
372 /* if default property */
373 if(!strstr(varName.c_str(), ".")) {
374 // if there's no dot in string (default prop)
375 // store default property in last solver,
376 // the others to their belonging id's
377
378 DEBUG("IONetcdf::readNCPropertyFile: default property : " << varName, MAIA_DEBUG_IO);
379 p = new MProperty;
380 p->solverId = m_noSolvers; // Insert default solver as last solver
381 p->name.append(varName);
382 // skip since netcdf 2 -> netcdf 4 conversion messes this up
383 if("standardTextLength" == varName) {
384 continue;
385 }
386 makeProperty(p, varName, &parallelIo); // create new Property
387 }
388 /* if a property defined for one or more zones */
389 else {
390 if(strstr(varName.c_str(), "_zones.")) {
391 DEBUG("IONetcdf::readPropertyFile: regular property: " << varName, MAIA_DEBUG_IO);
393 MInt noDims;
394 noDims = parallelIo.getDatasetNoDims(varName);
395 MString* zones = nullptr;
396 MInt noZones = 1;
397 DEBUG("IONetcdf::readPropertyFile: no. of dimensions = " << noDims, MAIA_DEBUG_IO);
398 switch(noDims) {
399 case 0: {
400 /* if only one char (and one zone) */
401 MString buf;
402 parallelIo.readScalar(&buf, varName);
403 zones = new MString(buf);
404 break;
405 }
406 case 1: {
407 /* look up the length of the string */
408 length = parallelIo.getArraySize(varName);
409 MString buf;
410 parallelIo.setOffset(length, 0);
411 parallelIo.readArray(&buf, varName);
412 zones = new MString(buf);
413 break;
414 }
415 case 2: {
416 /* look up the number of zones */
418 dzones = parallelIo.getArraySize(varName, 0);
419 noZones = (MInt)dzones;
420 zones = new MString[noZones];
421 /* look up the length of the string */
422 length = parallelIo.getArraySize(varName, 1);
424 /* loop over number of zones */
425 for(MInt i = 0; i < noZones; i++) {
426 start = i;
427 parallelIo.setOffset(1, start, 2);
428 MString buf;
429 parallelIo.readArray(&buf, varName);
430 (zones[i]).append(buf);
431 DEBUG("IONetcdf::readPropertyFile: " << zones[i], MAIA_DEBUG_IO);
432 }
433 break;
434 }
435 default: {
436 stringstream errorMessage;
437 errorMessage << "IONetcdf::readPropertyFile Error: only one dimensional zone lists allowed!" << endl;
438 mTerm(1, AT_, errorMessage.str());
439 }
440 }
441 /* find all solvers for the property */
442
443 list<MInt> solverList;
444 for(MInt i = 0; i != noZones; i++) {
445 DEBUG("IONetcdf::readPropertyFile: definition for zone " << zones[i], MAIA_DEBUG_IO);
446 zoneIterator zI;
447 /* look for the zone in the zoneMap */
448 zI = m_zoneMap->find(zones[i]);
449 /* append all solvers of the zone to the solverlist */
450 for(MInt j = 0; j < zI->second->noSolvers; j++) {
451 solverList.push_back(zI->second->solvers[j]);
452 }
453 }
454
455
456 const char* du;
457 du = strrchr(varName.c_str(), MPropertySeperator);
458 MString dummy(varName);
459 /* strip the varname of "_zones.1" */
460 dummy.replace(dummy.find("_zones."), dummy.size(), du);
461 DEBUG("IONetcdf::readPropertyFile: found property: " << dummy, MAIA_DEBUG_IO);
462 MString dName(dummy);
463
464 list<MInt>::const_iterator it = solverList.begin();
465 dummy.erase(dummy.find(".")); // erase the dot and the id
466 /* create the property for every solver */
467 for(; it != solverList.end(); it++) {
468 p = new MProperty;
469 p->solverId = *it;
470 p->name.append(dummy);
471 makeProperty(p, dName, &parallelIo); // create new Property
472 DEBUG("IONetcdf::readPropertyFile: created property for solver " << *it, MAIA_DEBUG_IO);
473 }
474 } // end of if ( strstr ( varName,"_zones." ) )
475 else {
476 // Determine the solverId
477 const char* du;
478 du = strrchr(varName.c_str(), MPropertySeperator) + 1;
479 MInt singleSolverId = atoi(du);
480
481 MString dummyName(varName);
482
483 if(singleSolverId || *du == '0') {
484 DEBUG("IONetcdf::readPropertyFile: Found single solver property definition for solver "
485 << singleSolverId,
486 MAIA_DEBUG_IO);
487 p = new MProperty;
488 p->solverId = singleSolverId;
489
490 MString dName(dummyName);
491
492 dummyName.erase(dummyName.find(".")); // erase the dot and the id
493 p->name.append(dummyName);
494 if("standardTextLength" != varName) {
495 makeProperty(p, dName, &parallelIo); // create new Property
496 }
497 }
498 }
499 }
500 }
501 /* Insert here the check for the property consistency */
503 DEBUG("IONetcdf::readPropertyFile: property consistency check succeeded", MAIA_DEBUG_IO);
504 } else {
505 stringstream errorMessage;
506 errorMessage << "IONetcdf::readPropertyFile Error: some properties are not defined for all solvers!" << endl;
507 mTerm(1, AT_, errorMessage.str());
508 }
509 } else {
510 stringstream errorMessage;
511 errorMessage << "IONetcdf::readPropertyFile Error: Inconsistent solver List!\n Make sure that solvers start "
512 "with index 0 and are consecutive!"
513 << endl;
514 mTerm(1, AT_, errorMessage.str());
515 }
516 //-------------NEW: SEND THE PROPERTIES AND ZONES
517 //-> PROPERTIES
518 //-->gather all the data
519 MInt noProperties = m_propertyMap->size();
520 //-->get the number of counts of each property and add it up
521 MInt totalCount = 0;
522 for(propertyIterator prop = m_propertyMap->begin(); prop != m_propertyMap->end(); prop++) {
523 totalCount += prop->second->count();
524 }
525 MInt sizeofallProp = noProperties * (256 + 4 * sizeof(MInt)) + totalCount * (256 + sizeof(MInt));
526 //-->allocate the size of the send array [name, type, count, values(asume to be 256chars)] (converted to chars)
527 MCharScratchSpace propMapArray(sizeofallProp, AT_, "propertyMapAsChar");
528 propMapArray.fill(0);
529 //-->put the variables into the scratchspace
530 MInt pCounter = 0;
531 for(propertyIterator prop = m_propertyMap->begin(); prop != m_propertyMap->end(); prop++) {
532 MInt asize = prop->first.size();
533 memcpy(&propMapArray(pCounter), &asize, sizeof(MInt));
534 pCounter += sizeof(MInt);
535 memcpy(&propMapArray(pCounter), prop->first.c_str(), asize * sizeof(MChar)); // copy the name
536 pCounter += asize * sizeof(MChar);
537 memcpy(&propMapArray(pCounter), (void*)&(prop->second->solverId), sizeof(MInt));
538 pCounter += sizeof(MInt);
539 memcpy(&propMapArray(pCounter), (void*)&(prop->second->propertyType), sizeof(MInt));
540 pCounter += sizeof(MInt);
541 MInt count = prop->second->count();
542 memcpy(&propMapArray(pCounter), &count, sizeof(MInt));
543 pCounter += sizeof(MInt);
544 switch(prop->second->propertyType) {
545 case MINT: {
546 memcpy((void*)&propMapArray(pCounter), (void*)&(prop->second->intField[0]), count * sizeof(MInt));
547 pCounter += count * sizeof(MInt);
548 break;
549 }
550 case MFLOAT: {
551 memcpy((void*)&propMapArray(pCounter), (void*)&(prop->second->floatField[0]), count * sizeof(MFloat));
552 pCounter += count * sizeof(MFloat);
553 break;
554 }
555 case MSTRING: {
556 for(MInt i = 0; i < count; i++) {
557 asize = prop->second->stringField[i].size();
558 memcpy(&propMapArray(pCounter), &asize, sizeof(MInt));
559 pCounter += sizeof(MInt);
560 memcpy(&propMapArray(pCounter), prop->second->stringField[i].c_str(),
561 prop->second->stringField[i].size() * sizeof(MChar));
562 pCounter += asize * sizeof(MChar);
563 }
564 break;
565 }
566 default: {
567 mTerm(1, AT_, "no such variable type!!!!");
568 break;
569 }
570 }
571 }
572 //-> ZONES
573 //-->gather all the data
574 MInt noZones = m_zoneMap->size();
575 //->get the number of counts of each zone and add it up
576 MInt zoneCount = 0;
577 for(zoneIterator zone = m_zoneMap->begin(); zone != m_zoneMap->end(); zone++) {
578 zoneCount += zone->second->noSolvers;
579 }
580 MInt sizeofZones = noProperties * (2 * (256 + sizeof(MInt)) + sizeof(MInt) * 2) + zoneCount * sizeof(MInt);
581 MCharScratchSpace zoneMapArray(sizeofZones, AT_, "zoneMapArrayAsChar");
582 zoneMapArray.fill(0);
583
584 pCounter = 0;
585 for(zoneIterator zone = m_zoneMap->begin(); zone != m_zoneMap->end(); zone++) {
586 MInt asize = zone->first.size();
587 memcpy(&zoneMapArray(pCounter), &asize, sizeof(MInt));
588 pCounter += sizeof(MInt);
589 memcpy(&zoneMapArray(pCounter), zone->first.c_str(), asize * sizeof(MChar)); // copy the name
590 pCounter += asize * sizeof(MChar);
591 memcpy(&zoneMapArray(pCounter), &(zone->second->id), sizeof(MInt));
592 pCounter += sizeof(MInt);
593 memcpy(&zoneMapArray(pCounter), &(zone->second->noSolvers), sizeof(MInt));
594 pCounter += sizeof(MInt);
595 memcpy(&zoneMapArray(pCounter), &(zone->second->solvers[0]), sizeof(MInt) * zone->second->noSolvers);
596 pCounter += sizeof(MInt) * zone->second->noSolvers;
597 }
598 // END OF DATA COLLECTION --> SENDING THE INFORMATION TO OTHER PROCESSES
599 MInt dummyInt[5] = {noProperties, totalCount, zoneCount, noZones, m_noSolvers};
600 MPI_Bcast(&dummyInt, 5, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dummyInt");
601 MPI_Bcast(propMapArray.getPointer(), sizeofallProp, MPI_CHAR, 0, MPI_COMM_WORLD, AT_,
602 "propMapArray.getPointer()");
603 MPI_Bcast(zoneMapArray.getPointer(), sizeofZones, MPI_CHAR, 0, MPI_COMM_WORLD, AT_, "zoneMapArray.getPointer()");
604 //->root has finished
605 } else { // ALL OTHER PROCESSES
606 //--> receive data
607 MInt dummyInt[5] = {0, 0, 0, 0, 0};
608 MPI_Bcast(&dummyInt, 5, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dummyInt");
609 MInt noProperties = dummyInt[0];
610 MInt totalCount = dummyInt[1];
611 MInt zoneCount = dummyInt[2];
612 MInt noZones = dummyInt[3];
613 m_noSolvers = dummyInt[4];
614 MInt sizeofallProp = noProperties * (256 + 4 * sizeof(MInt)) + totalCount * (256 + sizeof(MInt));
615 MInt sizeofZones = noProperties * (2 * (256 + sizeof(MInt)) + sizeof(MInt) * 2) + zoneCount * sizeof(MInt);
616 MCharScratchSpace propMapArray(sizeofallProp, AT_, "proptertydistribution");
617 propMapArray.fill(0);
618 MCharScratchSpace zoneMapArray(sizeofZones, AT_, "zoneMapArrayAsChar");
619 zoneMapArray.fill(0);
620 //-> receive data from root
621 MPI_Bcast(propMapArray.getPointer(), sizeofallProp, MPI_CHAR, 0, MPI_COMM_WORLD, AT_,
622 "propMapArray.getPointer()");
623 MPI_Bcast(zoneMapArray.getPointer(), sizeofZones, MPI_CHAR, 0, MPI_COMM_WORLD, AT_, "zoneMapArray.getPointer()");
624 //-> create properties again
625 MProperty* p;
626 MInt pCounter = 0;
627 for(MInt i = 0; i < noProperties; i++) {
628 // create the property again
629 p = new MProperty;
630 // analyze the field
631 MInt asize = 0;
632 //->get the size of the name
633 memcpy(&asize, &propMapArray[pCounter], sizeof(MInt));
634 pCounter += sizeof(MInt);
635 char* a = new char[asize + 1];
636 //->get the name
637 memcpy(a, &propMapArray[pCounter], asize);
638 a[asize] = '\0';
639 pCounter += asize * sizeof(MChar);
640 const char* b = a;
641 MString s(b);
642 delete[] a;
643 p->name = s;
644 memcpy(&(p->solverId), &propMapArray[pCounter], sizeof(MInt));
645 pCounter += sizeof(MInt);
646 MInt propertyType = -1;
647 memcpy(&propertyType, &propMapArray[pCounter], sizeof(MInt));
648 pCounter += sizeof(MInt);
649 switch(propertyType) {
650 case 0: {
651 p->propertyType = MINT;
652 break;
653 }
654 case 1: {
655 p->propertyType = MFLOAT;
656 break;
657 }
658 case 2: {
659 p->propertyType = MSTRING;
660 break;
661 }
662 default: {
663 mTerm(1, AT_, "no such variable type");
664 break;
665 }
666 }
667 memcpy(&(p->elements), &propMapArray[pCounter], sizeof(MInt));
668 pCounter += sizeof(MInt);
669 switch(p->propertyType) {
670 case MINT: {
671 p->intField = new MInt[p->elements];
672 memcpy(&(p->intField[0]), &propMapArray[pCounter], p->elements * sizeof(MInt));
673 pCounter += sizeof(MInt) * p->elements;
674 break;
675 }
676 case MFLOAT: {
677 p->floatField = new MFloat[p->elements];
678 memcpy(&(p->floatField[0]), &propMapArray[pCounter], p->elements * sizeof(MFloat));
679 pCounter += sizeof(MFloat) * p->elements;
680 break;
681 }
682 case MSTRING: {
683 p->stringField = new MString[p->elements];
684 for(MInt j = 0; j < p->elements; j++) {
685 asize = 0;
686 memcpy(&asize, &propMapArray(pCounter), sizeof(MINT));
687 pCounter += sizeof(MInt);
688 char* c = new char[asize + 1];
689 memcpy(c, &propMapArray[pCounter], asize * sizeof(MChar));
690 pCounter += asize * sizeof(MChar);
691 c[asize] = '\0';
692 const char* d = c;
693 MString st(d);
694 p->stringField[j] = st;
695 }
696 break;
697 }
698 default: {
699 mTerm(1, AT_, "no such variable type");
700 break;
701 }
702 }
703 // put property to property map
704 const pair<const MString, MProperty*> mp(p->name, p);
705
706 // produce the lowercase variant of the name to warn if property exists with different case
707 MString nameL = p->name;
708 std::transform(nameL.begin(), nameL.end(), nameL.begin(), [](unsigned char c) { return std::tolower(c); });
709
710 const pair<const MString, MProperty*> mpL(nameL, p);
711
712 // check if the lowercase variant of this property already exists but no regular-case variant
713 if(!(m_propertyMapLowercase->find(nameL) == m_propertyMapLowercase->end())
714 && (m_propertyMap->find(p->name) == m_propertyMap->end())) {
715 mTerm(1, AT_,
716 "There are multiple occurrences of the property " + p->name
717 + " with different cases. This should not happen!");
718 }
719 m_propertyMap->insert(mp);
720 m_propertyMapLowercase->insert(mpL);
721 }
722 //-> zone reconstruction
723 MZone* z;
724 MInt pCounterZ = 0;
725 // zones
726 for(MInt zo = 0; zo < noZones; zo++) {
727 // zones
728 MInt asize = 0;
729 z = new MZone;
730 memcpy(&asize, &zoneMapArray[pCounterZ], sizeof(MInt));
731 pCounterZ += sizeof(MInt);
732 char* c = new char[asize + 1];
733 memcpy(c, &zoneMapArray[pCounterZ], asize * sizeof(MChar));
734 pCounterZ += asize * sizeof(MChar);
735 c[asize] = '\0';
736 const char* d = c;
737 MString st(d);
738 z->name = st;
739 memcpy(&(z->id), &zoneMapArray[pCounterZ], sizeof(MInt));
740 pCounterZ += sizeof(MInt);
741 memcpy(&(z->noSolvers), &zoneMapArray[pCounterZ], sizeof(MInt));
742 pCounterZ += sizeof(MInt);
743 z->solvers = new MInt[z->noSolvers];
744 memcpy(&(z->solvers[0]), &zoneMapArray[pCounterZ], z->noSolvers * sizeof(MInt));
745 pCounterZ += z->noSolvers * sizeof(MInt);
746 m_zoneMap->insert(make_pair(z->name, z));
747 }
748 }
749 } else { // use old approach already better and corrected
750 //??? todo labels:IO change MPropertySeperator to MPropertySeparator
751 const char MPropertySeperator = '.'; // Separator that defines different Properties
752 /*open the property file*/
753 ParallelIo parallelIo(name, maia::parallel_io::PIO_READ, MPI_COMM_WORLD);
754 /* get the number of solvers */
755 MInt dsolvers;
756 if(!parallelIo.hasDataset("noSolvers", 0)) {
757 dsolvers = 1;
758 } else {
759 parallelIo.readScalar(&dsolvers, "noSolvers");
760 }
761 m_noSolvers = dsolvers;
762 /* read and store the zone information and the solver info*/
763 readZones(&parallelIo);
764 MString varName;
765 MProperty* p;
766 /* check the consistency of the zone*/
768 vector<MString> varNames = parallelIo.getDatasetNames();
769 noVariables = varNames.size();
770 for(MInt id = 0; id < noVariables; id++) {
771 varName = varNames[id];
772 /* if default property */
773 if(!strstr(varName.c_str(), ".")) {
774 // if there's no dot in string (default prop)
775 // store default property in last solver,
776 // the others to their belonging id's
777 DEBUG("IONetcdf::readNCPropertyFile: default property : " << varName, MAIA_DEBUG_IO);
778 p = new MProperty;
779 p->solverId = m_noSolvers; // Insert default solver as last solver
780 p->name.append(varName);
781 // skip since netcdf 2 -> netcdf 4 conversion messes this up
782 if("standardTextLength" == varName) {
783 continue;
784 }
785 makeProperty(p, varName, &parallelIo); // create new Property
786 }
787 /* if a property defined for one or more zones */
788 else {
789 if(strstr(varName.c_str(), "_zones.")) {
790 DEBUG("IONetcdf::readPropertyFile: regular property: " << varName, MAIA_DEBUG_IO);
792 MInt noDims;
793 noDims = parallelIo.getDatasetNoDims(varName);
794 MString* zones = nullptr;
795 MInt noZones = 1;
796 DEBUG("IONetcdf::readPropertyFile: no. of dimensions = " << noDims, MAIA_DEBUG_IO);
797 switch(noDims) {
798 case 0: {
799 /* if only one char (and one zone) */
800 MString buf;
801 parallelIo.readScalar(&buf, varName);
802 zones = new MString(buf);
803 break;
804 }
805 case 1: {
806 /* look up the length of the string */
807 length = parallelIo.getArraySize(varName);
808 MString buf;
809 parallelIo.setOffset(length, 0);
810 parallelIo.readArray(&buf, varName);
811 zones = new MString(buf);
812 break;
813 }
814 case 2: {
815 /* look up the number of zones */
817 dzones = parallelIo.getArraySize(varName, 0);
818 noZones = (MInt)dzones;
819 zones = new MString[noZones];
820 /* look up the length of the string */
821 length = parallelIo.getArraySize(varName, 1);
823 /* loop over number of zones */
824 for(MInt i = 0; i < noZones; i++) {
825 start = i;
826 parallelIo.setOffset(1, start, 2);
827 MString buf;
828 parallelIo.readArray(&buf, varName);
829 (zones[i]).append(buf);
830 DEBUG("IONetcdf::readPropertyFile: " << zones[i], MAIA_DEBUG_IO);
831 }
832 break;
833 }
834 default: {
835 stringstream errorMessage;
836 errorMessage << "IONetcdf::readPropertyFile Error: only one dimensional zone lists allowed!" << endl;
837 mTerm(1, AT_, errorMessage.str());
838 }
839 }
840 /* find all solvers for the property */
841
842 list<MInt> solverList;
843 for(MInt i = 0; i != noZones; i++) {
844 DEBUG("IONetcdf::readPropertyFile: definition for zone " << zones[i], MAIA_DEBUG_IO);
845 zoneIterator zI;
846 /* look for the zone in the zoneMap */
847 zI = m_zoneMap->find(zones[i]);
848 /* append all solvers of the zone to the solverlist */
849 for(MInt j = 0; j < zI->second->noSolvers; j++) {
850 solverList.push_back(zI->second->solvers[j]);
851 }
852 }
853 const char* du;
854 du = strrchr(varName.c_str(), MPropertySeperator);
855 MString dummy(varName);
856 /* strip the varname of "_zones.1" */
857 dummy.replace(dummy.find("_zones."), dummy.size(), du);
858 DEBUG("IONetcdf::readPropertyFile: found property: " << dummy, MAIA_DEBUG_IO);
859 MString dName(dummy);
860
861 list<MInt>::const_iterator it = solverList.begin();
862 dummy.erase(dummy.find(".")); // erase the dot and the id
863 /* create the property for every solver */
864 for(; it != solverList.end(); it++) {
865 p = new MProperty;
866 p->solverId = *it;
867 p->name.append(dummy);
868 makeProperty(p, dName, &parallelIo); // create new Property
869 DEBUG("IONetcdf::readPropertyFile: created property for solver " << *it, MAIA_DEBUG_IO);
870 }
871 } // end of if ( strstr ( varName,"_zones." ) )
872 else {
873 // Determine the solverId
874 const char* du;
875 du = strrchr(varName.c_str(), MPropertySeperator) + 1;
876 MInt singleSolverId = atoi(du);
877 MString dummyName(varName);
878 if(singleSolverId || *du == '0') {
879 DEBUG("IONetcdf::readPropertyFile: Found single solver property definition for solver " << singleSolverId,
880 MAIA_DEBUG_IO);
881 p = new MProperty;
882 p->solverId = singleSolverId;
883 MString dName(dummyName);
884 dummyName.erase(dummyName.find(".")); // erase the dot and the id
885 p->name.append(dummyName);
886 if("standardTextLength" != varName) {
887 makeProperty(p, dName, &parallelIo); // create new Property
888 }
889 }
890 }
891 }
892 }
893 /* Insert here the check for the property consistency */
895 DEBUG("IONetcdf::readPropertyFile: property consistency check succeeded", MAIA_DEBUG_IO);
896 } else {
897 stringstream errorMessage;
898 errorMessage << "IONetcdf::readPropertyFile Error: some properties are not defined for all solvers!" << endl;
899 mTerm(1, AT_, errorMessage.str());
900 }
901 } else {
902 stringstream errorMessage;
903 errorMessage << "IONetcdf::readPropertyFile Error: Inconsistent solver List!\n Make sure that solvers start "
904 "with index 0 and are consecutive!"
905 << endl;
906 mTerm(1, AT_, errorMessage.str());
907 }
908 } // end of else old approach for reading
909
910 m_assembly = new assembly;
914
915 return m_assembly;
916}
917
918//--------------------------------------------------------------------------------
924 TRACE();
925
926 for(propertyIterator i = m_propertyMap->begin(); i != m_propertyMap->end(); i++) {
927 /* if default property exists, then take next property */
928
929 if(m_propertyMap->lower_bound(i->second->name)->second->solverId == m_noSolvers) {
930 DEBUG("IONetcdf::checkPropertyConsistency: default property exists for :" << i->second->name, MAIA_DEBUG_IO);
931 } else {
932 return false;
933 }
934 }
935
936 return true;
937}
938
939//--------------------------------------------------------------------------
946 TRACE();
947 list<MInt> solverList;
948 list<MInt> compareList;
949 MInt index = 0;
950 for(zoneMap::const_iterator it = m_zoneMap->begin(); it != m_zoneMap->end(); it++) {
951 for(MInt i = 0; i < it->second->noSolvers; i++) {
952 solverList.push_back(it->second->solvers[i]);
953 compareList.push_back(index++);
954 }
955 }
956 solverList.sort();
957 if(solverList == compareList) {
958 return true;
959 } else {
960 return false;
961 }
962}
MInt m_noSolvers
Definition: ionetcdf.h:33
void readZones(ParallelIo *bdFile)
Definition: ionetcdf.cpp:223
MBool checkZoneConsistency()
Definition: ionetcdf.cpp:945
propertyMap * m_propertyMapLowercase
Definition: ionetcdf.h:36
void buildDefaultZone()
Definition: ionetcdf.cpp:282
assembly * readPropertyFile(const MString &fileName)
Definition: ionetcdf.cpp:330
IONetcdf()
Definition: ionetcdf.cpp:17
propertyMap * m_propertyMap
Definition: ionetcdf.h:35
MBool checkPropertyConsistency()
Definition: ionetcdf.cpp:923
~IONetcdf()
Definition: ionetcdf.cpp:23
zoneMap * m_zoneMap
Definition: ionetcdf.h:37
void makeProperty(MProperty *, const MString &, ParallelIo *bdFile)
Definition: ionetcdf.cpp:31
MInt solverCount()
Definition: ionetcdf.cpp:29
assembly * m_assembly
Definition: ionetcdf.h:32
MInt getDatasetType(const MString &name)
Returns the data type of an array.
Definition: parallelio.h:530
void readScalar(T *scalar, const MString &name)
Read scalar data from file. [MPI]
Definition: parallelio.h:1758
void setOffset(const size_type localCount, const size_type offset, const size_type noDims, const size_type noChunks)
Set the local and global counts, as well the local offset for array operations.
Definition: parallelio.h:1840
MBool hasDataset(const MString &name, MInt dimension)
Check if the file contains an dataset with the given name and dimension.
Definition: parallelio.h:467
std::vector< MString > getDatasetNames(const size_type dimensions=-1)
Returns a vector with the names of all existing datasets with given dimensionality in the file.
Definition: parallelio.h:554
MLong size_type
Type used for all size- and offset-related values.
Definition: parallelio.h:123
size_type getArraySize(const MString &name, const size_type dimensionId=0)
Get the length of an array in the file.
Definition: parallelio.h:667
size_type getDatasetNoDims(const MString &name)
Get the number of dimensions of a dataset with given name.
Definition: parallelio.h:594
void readArray(T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Read array data from file. [MPI]
Definition: parallelio.h:1523
This class is a ScratchSpace.
Definition: scratch.h:758
size_type size() const
Definition: scratch.h:302
T * getPointer() const
Deprecated: use begin() instead!
Definition: scratch.h:316
void fill(T val)
fill the scratch with a given value
Definition: scratch.h:311
std::map< MString, MZone * > zoneMap
Definition: contexttypes.h:17
zoneMap::const_iterator zoneIterator
Definition: contexttypes.h:18
std::multimap< MString, MProperty * > propertyMap
Definition: contexttypes.h:15
struct a assembly
propertyMap::const_iterator propertyIterator
Definition: contexttypes.h:16
@ MINT
Definition: enums.h:269
@ MFLOAT
Definition: enums.h:269
@ MSTRING
Definition: enums.h:269
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
MInt globalDomainId()
Return global domain id.
int32_t MInt
Definition: maiatypes.h:62
z { MString name MZone
define array structures
Definition: maiatypes.h:70
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
char MChar
Definition: maiatypes.h:56
MInt id
Definition: maiatypes.h:71
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
const MInt PIO_READ
Definition: parallelio.h:40
Definition: contexttypes.h:19
propertyMap * properties
Definition: contexttypes.h:20
zoneMap * zones
Definition: contexttypes.h:22
propertyMap * propertiesLowercase
Definition: contexttypes.h:21