Loading [MathJax]/extensions/tex2jax.js
MAIA bb96820c
Multiphysics at AIA
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
postdata.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 "postdata.h"
8#include <algorithm>
9#include <stack>
10#include "COMM/mpioverride.h"
11#include "IO/parallelio.h"
12#include "MEMORY/alloc.h"
13#include "UTIL/functions.h"
14#include "globals.h"
15
16using namespace std;
17
18// TODO labels:PP these variable names only work for FV. This means they probably should not be stored here.
19template <>
20const std::vector<std::vector<MString>> PostData<3>::m_averageVariableName = {
21 {"um", "vm", "wm", "rhom", "pm", "cm"}, // primitive
22 {"u'", "v'", "w'", "u'v'", "v'w'", "w'u'", "p'"}, // square
23 {"u''", "v''", "w''"}, // skewness
24 {"u'''", "v'''", "w'''"}, // kurtosis
25 {"hm", "c'", "h'"}, // statisticCombustionAnalysis
26 {"vort_x", "vort_y", "vort_z"}, // averageVorticities
27 {"c0", "dc0_dx", "dc0_dy", "dc0_dz"}, // averageSpeedOfSound
28 {"wxv_x", "wxv_y", "wxv_z"}, // lamb0
29 {"gradm_u_x", "gradm_v_y", "gradm_w_z"}, // du
30 {"gradm_rho_x", "gradm_rho_y", "gradm_rho_z"}, // drho
31 {"gradm_p_x", "gradm_p_y", "gradm_p_z"}, // dp
32 {"gradm_u_x", "gradm_u_y", "gradm_u_z", "gradm_v_x", "gradm_v_y", "gradm_v_z", "gradm_w_x", "gradm_w_y",
33 "gradm_w_z"}, // gradu
34 {"ugradu_x", "ugradu_y", "ugradu_z"}, // ugradu
35 {"ugradrho_x", "ugradrho_y", "ugradrho_z"}, // ugradrho
36 {"mgrad_p_rho_x", "mgrad_p_rho_y", "mgrad_p_rho_z"}, // gradrhop
37 {"rhodivu_x", "rhodivu_y", "rhodivu_z"}, // rhodivu
38 {"correlation_var"}};
39
40template <>
41const std::vector<std::vector<MString>> PostData<2>::m_averageVariableName = {
42 {"um", "vm", "rhom", "pm", "cm"}, // primitive
43 {"u'", "v'", "u'v'", "p'"}, // square
44 {"u''", "v''"}, // skewness
45 {"u'''", "v'''"}, // kurtosis
46 {"hm", "c'", "h'"}, // statisticCombustionAnalysis
47 {"vort_z"}, // averageVorticities
48 {"c0", "dc0_dx", "dc0_dy"}, // averageSpeedOfSound
49 {"wxv_x", "wxv_y"}, // lamb0
50 {"gradm_u_x", "gradm_v_y"}, // du
51 {"gradm_rho_x", "gradm_rho_y"}, // drho
52 {"gradm_p_x", "gradm_p_y"}, // dp
53 {"gradm_u_x", "gradm_u_y", "gradm_v_x", "gradm_v_y"}, // gradu
54 {"ugradu_x", "ugradu_y"}, // ugradu
55 {"ugradrho_x", "ugradrho_y"}, // ugradrho
56 {"mgrad_p_rho_x", "mgrad_p_rho_y"}, // gradrhop
57 {"rhodivu_x", "rhodivu_y"}, // rhodivu
58 {"correlation_var"}};
59
60template <MInt nDim>
61PostData<nDim>::PostData(MInt solverId_, GridProxy& gridProxy_, Geom& geometry_, const MPI_Comm comm)
62
63 : maia::CartesianSolver<nDim, PostData<nDim>>(solverId_, gridProxy_, comm, true),
64 m_geometry(&geometry_),
65 m_time(0.0) {
66 TRACE();
67
69
70 for(MInt i = 0; i < (MInt)m_propertyName.size(); i++) {
71 m_variableOffset.push_back(std::make_pair(std::numeric_limits<MInt>::max(), -std::numeric_limits<MInt>::max()));
72 }
73}
74
75template <MInt nDim>
77 TRACE();
78
90 m_outputFormat = "NETCDF";
91 m_outputFormat = Context::getSolverProperty<MString>("outputFormat", m_solverId, AT_, &m_outputFormat);
92
104 m_solutionOffset = 0;
105 m_solutionOffset = Context::getSolverProperty<MInt>("solutionOffset", m_solverId, AT_, &m_solutionOffset);
106
107 m_noVariables = 0;
108 m_noVariables = Context::getSolverProperty<MInt>("noVariables", m_solverId, AT_, &m_noVariables);
109}
110
111template <MInt nDim>
113 TRACE();
114
115 // d) Set Properties for valid-grid-cells
116 for(MInt i = 0; i < noNeighborDomains(); i++) {
117 for(MInt c = 0; c < noHaloCells(i); c++) {
118 a_isHalo(haloCellId(i, c)) = true;
119 }
120 for(MInt j = 0; j < noWindowCells(i); j++) {
121 a_isWindow(windowCellId(i, j)) = true;
122 }
123 }
124
125 // Inactive can only have halo cells, however noNeighborDomains=-1
126 if(!isActive()) {
127 for(MInt c = 0; c < a_noCells(); c++) {
128 a_isHalo(c) = true;
129 }
130 }
131}
132
133
134template <MInt nDim>
136 TRACE();
137
138 if(!isActive()) {
139 m_cells.clear();
140 m_cells.reset(grid().maxNoCells());
141 this->setHaloCellsOnInactiveRanks();
142 return;
143 }
144
145 setAndAllocateSolverData(true);
146}
147
148
149template <MInt nDim>
151 TRACE();
152
153 const MInt maxNoCells = maxNoGridCells();
154
155 mAlloc(m_recalcIds, maxNoCells, "m_recalcIds", -1, AT_);
156 for(MInt i = 0; i < maxNoCells; i++) {
157 m_recalcIds[i] = i;
158 }
159
160 m_cells.setNoVariables(noVariables());
161
162 m_cells.reset(grid().raw().treeb().capacity());
163 m_cells.append(c_noCells());
164
165 copyGridProperties();
166
167 // NOTE: setting default here
168 setVariableNames();
169
170 if(fullReset) {
171 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
172 for(MInt v = 0; v < noVariables(); v++) {
173 a_variable(cellId, v) = 0;
174 }
175 }
176 }
177}
178
179
180template <MInt nDim>
182 TRACE();
183
184 m_variablesName.clear();
185
186 for(MInt i = 0; i < noVariables(); i++) {
187 MString s = getVariableName(i);
188 auto it = std::find(m_variablesName.begin(), m_variablesName.end(), s);
189 if(it == m_variablesName.end()) {
190 m_variablesName.push_back(getVariableName(i));
191 }
192 }
193}
194
195
196template <MInt nDim>
198 MString s = "var" + std::to_string(offset);
199 if(offset >= getPropertyVariableOffset("primitive").first && offset < getPropertyVariableOffset("primitive").second) {
200 MInt index = offset - getPropertyVariableOffset("primitive").first;
201 s = m_averageVariableName[0][index];
202 }
203 if(offset >= getPropertyVariableOffset("square").first && offset < getPropertyVariableOffset("square").second) {
204 MInt index = offset - getPropertyVariableOffset("square").first;
205 s = m_averageVariableName[1][index];
206 }
207 if(offset >= getPropertyVariableOffset("skewness").first && offset < getPropertyVariableOffset("skewness").second) {
208 MInt index = offset - getPropertyVariableOffset("skewness").first;
209 s = m_averageVariableName[2][index];
210 }
211 if(offset >= getPropertyVariableOffset("kurtosis").first && offset < getPropertyVariableOffset("kurtosis").second) {
212 MInt index = offset - getPropertyVariableOffset("kurtosis").first;
213 s = m_averageVariableName[3][index];
214 }
215 if(offset >= getPropertyVariableOffset("statisticCombustionAnalysis").first
216 && offset < getPropertyVariableOffset("statisticCombustionAnalysis").second) {
217 MInt index = offset - getPropertyVariableOffset("statisticCombustionAnalysis").first;
218 s = m_averageVariableName[4][index];
219 }
220 if(offset >= getPropertyVariableOffset("averageVorticity").first
221 && offset < getPropertyVariableOffset("averageVorticity").second) {
222 MInt index = offset - getPropertyVariableOffset("averageVorticity").first;
223 s = m_averageVariableName[5][index];
224 }
225 if(offset >= getPropertyVariableOffset("averageSpeedOfSound").first
226 && offset < getPropertyVariableOffset("averageSpeedOfSound").second) {
227 MInt index = offset - getPropertyVariableOffset("averageSpeedOfSound").first;
228 s = m_averageVariableName[6][index];
229 }
230 if(offset >= getPropertyVariableOffset("lamb0").first && offset < getPropertyVariableOffset("lamb0").second) {
231 MInt index = offset - getPropertyVariableOffset("lamb0").first;
232 s = m_averageVariableName[7][index];
233 }
234 if(offset >= getPropertyVariableOffset("du").first && offset < getPropertyVariableOffset("du").second) {
235 MInt index = offset - getPropertyVariableOffset("du").first;
236 s = m_averageVariableName[8][index];
237 }
238 if(offset >= getPropertyVariableOffset("drho").first && offset < getPropertyVariableOffset("drho").second) {
239 MInt index = offset - getPropertyVariableOffset("drho").first;
240 s = m_averageVariableName[9][index];
241 }
242 if(offset >= getPropertyVariableOffset("dp").first && offset < getPropertyVariableOffset("dp").second) {
243 MInt index = offset - getPropertyVariableOffset("dp").first;
244 s = m_averageVariableName[10][index];
245 }
246 if(offset >= getPropertyVariableOffset("gradu").first && offset < getPropertyVariableOffset("gradu").second) {
247 MInt index = offset - getPropertyVariableOffset("gradu").first;
248 s = m_averageVariableName[11][index];
249 }
250 if(offset >= getPropertyVariableOffset("ugradu").first && offset < getPropertyVariableOffset("ugradu").second) {
251 MInt index = offset - getPropertyVariableOffset("ugradu").first;
252 s = m_averageVariableName[12][index];
253 }
254 if(offset >= getPropertyVariableOffset("ugradrho").first && offset < getPropertyVariableOffset("ugradrho").second) {
255 MInt index = offset - getPropertyVariableOffset("ugradrho").first;
256 s = m_averageVariableName[13][index];
257 }
258 if(offset >= getPropertyVariableOffset("gradprho").first && offset < getPropertyVariableOffset("gradprho").second) {
259 MInt index = offset - getPropertyVariableOffset("gradprho").first;
260 s = m_averageVariableName[14][index];
261 }
262 if(offset >= getPropertyVariableOffset("rhodivu").first && offset < getPropertyVariableOffset("rhodivu").second) {
263 MInt index = offset - getPropertyVariableOffset("rhodivu").first;
264 s = m_averageVariableName[15][index];
265 }
266 if(offset >= getPropertyVariableOffset("correlation").first
267 && offset < getPropertyVariableOffset("correlation").second) {
268 MInt index = offset - getPropertyVariableOffset("correlation").first;
269 s = m_averageVariableName[16][0 /*index*/] + to_string(index);
270 }
271 return s;
272}
273
274
275template <MInt nDim>
277 TRACE();
278
279 if(!isActive()) return;
280
281 if(m_restart) {
282 // TODO labels:PP allow to skip loading restart, e.g. if we want to start the averaging after adding the pp-solver
283 // at some point and just need everything set to zero instead?
284 loadRestartFile();
285 }
286}
287
288
289template <MInt nDim>
290void PostData<nDim>::writeRestartFile(const MBool writeRestart, const MBool writeBackup, const MString gridFileName,
291 MInt* recalcIdTree) {
292 TRACE();
293
294 // post-data has no cell-data
295 if(noVariables() == 0) return;
296
297 m_currentGridFileName = gridFileName;
298
299 if(m_recalcIds != nullptr) {
300 for(MInt cellId = 0; cellId < maxNoGridCells(); cellId++) {
301 m_recalcIds[cellId] = recalcIdTree[cellId];
302 }
303 }
304
305 if(writeRestart) {
306 saveRestartFile(writeBackup);
307 }
308}
309
310
311template <MInt nDim>
312MBool PostData<nDim>::prepareRestart(MBool writeRestart, MBool& writeGridRestart) {
313 TRACE();
314
315 writeGridRestart = false;
316
317 // write intermediate restart file
318 if(m_restartInterval == -1 && !writeRestart) {
319 writeRestart = false;
320 }
321
322 MInt relativeTimeStep = globalTimeStep - m_restartOffset;
323 MInt relativeRestartTimeStep = m_restartTimeStep - m_restartOffset;
324
325 if(((relativeTimeStep % m_restartInterval) == 0 && relativeTimeStep > relativeRestartTimeStep) || writeRestart) {
326 writeRestart = true;
327 }
328
329 if(m_forceWriteRestart) {
330 writeRestart = true;
331 if(m_adaptationSinceLastRestart) {
332 writeGridRestart = true;
333 }
334 }
335
336 return writeRestart;
337}
338
344template <MInt nDim>
346 TRACE();
347
348 if(doneRestart) {
349 m_adaptationSinceLastRestart = false;
350 }
351
352 m_forceWriteRestart = false;
353}
354
355template <MInt nDim>
356void PostData<nDim>::saveRestartFile(const MBool writeBackup) {
357 TRACE();
358
359 ASSERT(noVariables() > 0, "No variables set for PostData restart!");
360 ASSERT(!m_variablesName.empty(), "");
361 ASSERT((MInt)m_variablesName.size() == noVariables(), "");
362
363 // TODO labels:IO use same restart file name format for all solvers, e.g. restart_s[solverId]_[timeStep].[ext] with
364 // zero padded formatted timeStep
365 stringstream fileName;
366 fileName << outputDir() << "restartFile_" << solverId() << "_" << globalTimeStep << ParallelIo::fileExt();
367
368 saveDataFile(writeBackup, fileName.str(), noVariables(), m_variablesName, &a_variable(0, 0));
369}
370
371template <MInt nDim>
372void PostData<nDim>::saveDataFile(const MBool writeBackup, const MString fileName, const MInt noVars,
373 std::vector<MString>& variablesName, MFloat* variables) {
374 TRACE();
375
376 ASSERT(noVars > 0, "No variables set for PostData restart!");
377 ASSERT((MInt)variablesName.size() == noVars, "");
378
379 if(domainId() == 0) {
380 cerr << "Writing post data file '" << fileName << "' for solver " << solverId() << " at time step "
381 << globalTimeStep << " ...";
382 }
383
384 vector<MInt> reOrderedCells;
385 MInt countInternal = 0;
386 if(grid().newMinLevel() > 0) {
387 if(domainId() == 0) {
388 cerr << "Increasing minLevel for solver " << m_solverId;
389 }
390 this->reOrderCellIds(reOrderedCells);
391 for(MUint i = 0; i < reOrderedCells.size(); i++) {
392 if(a_isHalo(reOrderedCells[i])) continue;
393 countInternal++;
394 }
395 m_recalcIds = nullptr;
396 }
397 const MInt noCells = grid().newMinLevel() < 0 ? noInternalCells() : reOrderedCells.size();
398 const MInt noInternalCellIds = grid().newMinLevel() < 0 ? noInternalCells() : countInternal;
399
400 MFloatScratchSpace dbVariables(noCells * noVars, AT_, "dbVariables");
401 MIntScratchSpace idVariables(noCells * 2, AT_, "idVariables");
402 MFloatScratchSpace dbParameters(0, AT_, "dbParameters");
403 MIntScratchSpace idParameters(1, AT_, "idParameters");
404 vector<MString> dbVariablesName;
405 vector<MString> idVariablesName;
406 vector<MString> dbParametersName;
407 vector<MString> idParametersName;
408
409 this->collectVariables(variables, dbVariables, variablesName, dbVariablesName, noVars, noCells);
410
411 this->collectParameters(globalTimeStep, idParameters, "globalTimeStep", idParametersName);
412
413 MIntScratchSpace recalcIdsSolver(grid().tree().size(), AT_, "recalcIds");
414 if(m_recalcIds != nullptr) {
415 MInt cellId = 0;
416 for(MInt gridcell = 0; gridcell < grid().raw().m_noInternalCells; gridcell++) {
417 if(grid().raw().a_hasProperty(gridcell, Cell::IsHalo)) continue;
418 MInt l_solverId = grid().tree().grid2solver(m_recalcIds[gridcell]);
419 if(l_solverId > -1) {
420 recalcIdsSolver[cellId] = l_solverId;
421 cellId++;
422 ASSERT(grid().solverFlag(m_recalcIds[gridcell], m_solverId), "");
423 }
424 }
425 ASSERT(cellId == grid().noInternalCells(), "recalc ids size is wrong");
426 }
427
428 MString gridFile = (m_currentGridFileName == "") ? grid().gridInputFileName() : m_currentGridFileName;
429
430 saveGridFlowVars(fileName.c_str(), gridFile.c_str(), noCells, noInternalCellIds, dbVariables, dbVariablesName, 0,
431 idVariables, idVariablesName, 0, dbParameters, dbParametersName, idParameters, idParametersName,
432 recalcIdsSolver.begin(), -1);
433
434 // TODO labels:PP this is still specific to restart files
435 if(writeBackup) {
436 stringstream backupFileName;
437 backupFileName.clear();
438 backupFileName.str("");
439 backupFileName << outputDir() << "restartFileBackup_" << solverId() << "_" << globalTimeStep;
440 backupFileName << ParallelIo::fileExt();
441 if(domainId() == 0) cerr << "Writing post data (backup) for solver " << solverId() << "... ";
442
443 saveGridFlowVars((backupFileName.str()).c_str(), gridFile.c_str(), noCells, noInternalCellIds, dbVariables,
444 dbVariablesName, 0, idVariables, idVariablesName, 0, dbParameters, dbParametersName, idParameters,
445 idParametersName, recalcIdsSolver.begin(), -1);
446 }
447
448
449 if(domainId() == 0) cerr << "ok" << endl;
450}
451
452
453template <MInt nDim>
455 TRACE();
456
457 stringstream fileName;
458 fileName << restartDir() << "restartFile_" << solverId() << "_" << globalTimeStep << ParallelIo::fileExt();
459
460 if(domainId() == 0) {
461 cerr << "loading post data for solver " << solverId() << " at time step " << globalTimeStep << " ...";
462 }
463
464 vector<MString> name;
465 for(MInt v = 0; v < noVariables(); v++) {
466 name.push_back(m_variablesName[v]);
467 }
468
469 m_log << "loading postprocessing variables ... ";
470
471 loadGridFlowVars((fileName.str()).c_str(), noVariables(), name);
472
473 m_log << "ok" << endl;
474}
475
476
487template <MInt nDim>
489 TRACE();
490
491 if(!isActive()) return;
492
493 ParallelIo parallelIo(fileName, maia::parallel_io::PIO_READ, mpiComm());
494
495 if(parallelIo.hasAttribute(MString("isMeanFile"))) {
496 // This should be the same for all the variables
497 ParallelIo::size_type dimLen = noInternalCells();
498 ParallelIo::size_type start = domainOffset(domainId()) - grid().bitOffset();
499
500 // set offset for all read operations
501 parallelIo.setOffset(dimLen, start);
502
503 vector<MString> var_names = parallelIo.getDatasetNames(1);
504 m_fileNoVars = var_names.size();
505 const MInt noCells = noInternalCells();
506
507 // Note: allocate new storage for all variables from the file
508 mAlloc(m_averagedVars, noCells, m_fileNoVars, "m_averagedVars", AT_);
509 ScratchSpace<MFloat> tmpVars(noCells, AT_, "tmpVars");
510
511 m_fileVarNames.clear();
512 for(MInt varId = 0; varId < m_fileNoVars; varId++) {
513 // Check for variable 'name' attribute
514 if(parallelIo.hasAttribute("name", var_names[varId])) {
515 MString varName = "";
516 parallelIo.getAttribute(&varName, "name", var_names[varId]);
517 m_fileVarNames.push_back(varName);
518 } else {
519 TERMM(1, "Variable has no attribute 'name'.");
520 }
521
522 parallelIo.readArray(tmpVars.begin(), var_names[varId]);
523 for(MInt cellId = 0; cellId < noCells; cellId++) {
524 m_averagedVars[cellId][varId] = tmpVars[cellId];
525 }
526 }
527 TERMM_IF_COND(m_fileVarNames.size() > 0 && (MInt)m_fileVarNames.size() != m_fileNoVars,
528 "Error: not every variable in '" + MString(fileName) + "' has the 'name' attribute.");
529
530 m_isMeanFile = true;
531 } else {
532 TERMM(1, "FIXME try to load regular data file");
533 m_isMeanFile = false;
534 // loadGridFlowVars(...);
535 }
536}
537
538
544template <MInt nDim>
545void PostData<nDim>::loadGridFlowVars(const MChar* fileName, MInt noVariables, vector<MString> names) {
546 TRACE();
547
548 // File loading.
549 stringstream variables;
550
551 using namespace maia::parallel_io;
552 ParallelIo parallelIo(fileName, PIO_READ, mpiComm());
553
554 // This should be the same for all the variables
555 ParallelIo::size_type dimLen = noInternalCells();
556 ParallelIo::size_type start = domainOffset(domainId()) - grid().bitOffset();
557
558 // set offset for all read operations
559 parallelIo.setOffset(dimLen, start);
560
561 for(MInt vId = 0; vId < noVariables; vId++) {
562 MString varName = names[vId]; // varNames[vId];//
563
564 // Load our variables
565 MFloatScratchSpace tmpVar((MInt)dimLen, AT_, "tmpVar");
566
567 parallelIo.readArray(tmpVar.getPointer(), "variables" + to_string(vId));
568 for(MInt i = 0; i < (MInt)dimLen; ++i) {
569 a_variable(i, vId) = tmpVar.p[i];
570 }
571 }
572}
573
574template <MInt nDim>
576 TRACE();
577
578 if(!isActive()) return;
579
580 MInt offset = m_solutionOffset;
581
582 // solution output
583 // ---------------
584 if((((globalTimeStep - offset) % m_solutionInterval) == 0 && globalTimeStep >= offset)
585 || (m_solutionTimeSteps.count(globalTimeStep) > 0)) {
586 if(domainId() == 0)
587 cerr << "solverId: " << m_solverId << ", Writing " << m_outputFormat << " output at time step " << globalTimeStep
588 << ", time " << m_time << " ... ";
589
590 m_log << "Writing " << m_outputFormat << " output at time step " << globalTimeStep << ", time " << m_time
591 << " for postData ... ";
592
593 MFloatScratchSpace dbVariables(a_noCells() * noVariables(), AT_, "dbVariables");
594 MIntScratchSpace idVariables(a_noCells() * 2, AT_, "idVariables");
595 MFloatScratchSpace dbParameters(4, AT_, "dbParameters");
596 MIntScratchSpace idParameters(2, AT_, "idParameters");
597 vector<MString> dbVariablesName;
598 vector<MString> idVariablesName;
599 vector<MString> dbParametersName;
600 vector<MString> idParametersName;
601 vector<MString> name;
602
603 stringstream fileName;
604
605 fileName << m_solutionOutput << "ppQOUT_" << globalTimeStep;
606
607 for(MInt v = 0; v < noVariables(); v++) {
608 name.push_back(m_variablesName[v]);
609 }
610
611 this->collectVariables(&a_variable(0, 0), dbVariables, name, dbVariablesName, noVariables(), a_noCells());
612
613 this->collectParameters(globalTimeStep, idParameters, "globalTimeStep", idParametersName);
614
615 switch(string2enum(m_outputFormat)) {
616 case NETCDF: {
617 fileName << ParallelIo::fileExt();
618 // TODO: currently not working for adaptation, check save restartFile
619 // and get solver recalcIds!
620 //
621 saveGridFlowVars((fileName.str()).c_str(), grid().gridInputFileName().c_str(), a_noCells(), noInternalCells(),
622 dbVariables, dbVariablesName, 0, idVariables, idVariablesName, 0, dbParameters,
623 dbParametersName, idParameters, idParametersName, m_recalcIds, -1);
624 break;
625 }
626 case VTK:
627 case VTU:
628 case VTP: {
629 break;
630 }
631 default: {
632 stringstream errorMessage;
633 errorMessage << "PostData::saveSolverSolution(): switch variable 'm_outputFormat' with value " << m_outputFormat
634 << " not matching any case." << endl;
635 mTerm(1, AT_, errorMessage.str());
636 }
637 }
638
639 if(domainId() == 0) cerr << "ok" << endl;
640 }
641}
642
647template <MInt nDim>
648void PostData<nDim>::getSolverTimings(std::vector<std::pair<MString, MFloat>>& solverTimings, const MBool) {
649 TRACE();
650
651 const MString namePrefix = "s" + std::to_string(solverId()) + "_";
652
653 const MFloat load = returnLoadRecord();
654 const MFloat idle = returnIdleRecord();
655
656 solverTimings.emplace_back(namePrefix + "loadPostData", load);
657 solverTimings.emplace_back(namePrefix + "idlePostData", idle);
658}
659
669template <MInt nDim>
671 TRACE();
672
673 const MInt noLsLoadTypes = 1;
674
675 return noLsLoadTypes;
676}
677
682template <MInt nDim>
683void PostData<nDim>::getDefaultWeights(MFloat* weights, std::vector<MString>& names) const {
684 TRACE();
685
686 // TODO set sensible default values
687 weights[0] = 1.0;
688 names[0] = "pp_cell";
689 MInt count = 1;
690
691 // TODO: add other load types!
692
693 if(noLoadTypes() != count) {
694 TERMM(1, "Count does not match noLoadTypes.");
695 }
696}
697
702template <MInt nDim>
703void PostData<nDim>::getDomainDecompositionInformation(std::vector<std::pair<MString, MInt>>& domainInfo) {
704 TRACE();
705
706 const MString namePrefix = "s" + std::to_string(solverId()) + "_";
707
708 // Number of Post-Data-Cells
709 const MInt noCells = c_noCells();
710
711 domainInfo.emplace_back(namePrefix + "noPostCells", noCells);
712
713 // additionally add cells for probing
714}
715
720template <MInt nDim>
721void PostData<nDim>::setCellWeights(MFloat* solverCellWeight) {
722 TRACE();
723 const MInt noCellsGrid = grid().raw().treeb().size();
724 const MInt offset = noCellsGrid * solverId();
725
726 for(MInt cellId = 0; cellId < c_noCells(); cellId++) {
727 const MInt gridCellId = grid().tree().solver2grid(cellId);
728 const MInt id = gridCellId + offset;
729 // TODO: find good value for postData!
730 solverCellWeight[id] = 0.2;
731 }
732}
733
741template <MInt nDim>
742void PostData<nDim>::getLoadQuantities(MInt* const loadQuantities) const {
743 TRACE();
744
745 // Nothing to do if solver is not active
746 if(!isActive()) {
747 return;
748 }
749
750 // reset
751 for(MInt type = 0; type < noLoadTypes(); type++) {
752 loadQuantities[type] = 0;
753 }
754
755 loadQuantities[0] = c_noCells();
756
757 // TODO: add other load types!
758}
759
769template <MInt nDim>
770MFloat PostData<nDim>::getCellLoad(const MInt gridCellId, const MFloat* const weights) const {
771 TRACE();
772
773 ASSERT(isActive(), "solver is not active");
774
775 // Convert to solver cell id and check
776 const MInt cellId = grid().tree().grid2solver(gridCellId);
777 if(cellId < 0) {
778 return 0;
779 }
780
781 if(cellId < 0 || cellId >= grid().noInternalCells()) {
782 TERMM(1, "The given cell id is invalid.");
783 }
784
785 // Default cell load
786 MFloat cellLoad = 0.0;
787
788 cellLoad = weights[0];
789
790 // TODO: add other load types!
791
792 return cellLoad;
793}
794
799template <MInt nDim>
801 TRACE();
802
803 ASSERT(m_freeIndices.empty(), "");
804
805 m_adaptationLevel = maxUniformRefinementLevel();
806
807 if(!isActive()) return;
808}
809
814template <MInt nDim>
815void PostData<nDim>::setSensors(std::vector<std::vector<MFloat>>& sensors,
816 std::vector<MFloat>& sensorWeight,
817 std::vector<std::bitset<64>>& sensorCellFlag,
818 std::vector<MInt>& sensorSolverId) {
819 TRACE();
820
821 const MInt sensorOffset = (signed)sensors.size();
822 ASSERT(sensorOffset == 0 || grid().raw().treeb().noSolvers() > 1, "");
823 sensors.resize(sensorOffset + this->m_noSensors, vector<MFloat>(grid().raw().m_noInternalCells, F0));
824 sensorWeight.resize(sensorOffset + this->m_noSensors, -1);
825 sensorCellFlag.resize(grid().raw().m_noInternalCells, sensorOffset + this->m_noSensors);
826 sensorSolverId.resize(sensorOffset + this->m_noSensors, solverId());
827 ASSERT(sensorOffset + this->m_noSensors < CartesianGrid<nDim>::m_maxNoSensors, "Increase bitset size!");
828
829 for(MInt sen = 0; sen < this->m_noSensors; sen++) {
830 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
831 }
832
833 ASSERT(m_freeIndices.empty(), "");
834 m_freeIndices.clear();
835
836 if(!isActive()) return;
837 if(!this->m_adapts) return;
838
839 if(domainId() == 0) {
840 cerr << "Setting " << this->m_noSensors << " sensors for post-Data adaptation." << endl;
841 }
842
843 for(MInt sen = 0; sen < this->m_noSensors; sen++) {
844 (this->*(this->m_sensorFnPtr[sen]))(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen);
845 }
846}
847
848
853template <MInt nDim>
855 TRACE();
856
857 if(isActive()) {
858 this->compactCells();
859 m_freeIndices.clear();
860 } else {
861 grid().updateGridMap();
862 }
863
864 grid().updateOther();
865
866 updateDomainInfo(grid().domainId(), grid().noDomains(), grid().mpiComm(), AT_);
867 this->checkNoHaloLayers();
868
869 // Nothing further to be done if solver inactive
870 if(!isActive()) return;
871
872 copyGridProperties();
873
874 m_adaptationLevel++;
875}
876
881template <MInt nDim>
883 TRACE();
884
885 m_forceAdaptation = false;
886 m_adaptationSinceLastRestart = true;
887}
888
893template <MInt nDim>
894void PostData<nDim>::refineCell(const MInt gridCellId) {
895 TRACE();
896
897 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
898
899 for(MInt child = 0; child < grid().m_maxNoChilds; child++) {
900 const MInt childId = grid().raw().treeb().child(gridCellId, child);
901 if(childId == -1) continue;
902
903 if(!grid().raw().a_hasProperty(childId, Cell::WasNewlyCreated)
904 && grid().raw().a_hasProperty(gridCellId, Cell::IsPartLvlAncestor)) {
905 continue;
906 }
907
908 if(!g_multiSolverGrid) ASSERT(grid().raw().a_hasProperty(childId, Cell::WasNewlyCreated), "");
909
910 // If solver is inactive all cells musst be halo cells!
911 if(!isActive()) ASSERT(grid().raw().a_isHalo(childId), "");
912 // If child exists in grid but is not located inside solver geometry
913 if(!grid().solverFlag(childId, solverId())) continue;
914
915 const MInt solverChildId = this->createCellId(childId);
916
917 if(!g_multiSolverGrid) ASSERT(solverChildId == childId, "");
918
919 for(MInt v = 0; v < noVariables(); v++) {
920 a_variable(solverChildId, v) = a_variable(solverCellId, v);
921 }
922
923 // check-child-values
924#if !defined NDEBUG
925 for(MInt v = 0; v < noVariables(); v++) {
926 if(std::isnan(a_variable(solverChildId, v))) {
927 cerr << "Invalid-value in refined-Cell! "
928 << " " << solverChildId << " in rank " << domainId() << endl;
929 }
930 }
931#endif
932 }
933}
934
935
936template <MInt nDim>
937void PostData<nDim>::removeChilds(const MInt gridCellId) {
938 TRACE();
939 // If solver is inactive cell must never be an internal cell
940 if(!isActive()) {
941 ASSERT(grid().raw().a_isHalo(gridCellId), "");
942 }
943
944 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
945
946 ASSERT(solverCellId > -1 && solverCellId < m_cells.size(), "solverCellId is: " << solverCellId);
947
948 if(!g_multiSolverGrid) ASSERT(solverCellId == gridCellId, "");
949
950 for(MInt c = 0; c < grid().m_maxNoChilds; c++) {
951 MInt childId = c_childId(solverCellId, c);
952 if(childId < 0) continue;
953 this->removeCellId(childId);
954 }
955
956 if(!g_multiSolverGrid) {
957 ASSERT((grid().raw().treeb().size() - m_cells.size()) <= grid().m_maxNoChilds, "");
958 }
959}
960
961
965template <MInt nDim>
966void PostData<nDim>::removeCell(const MInt gridCellId) {
967 TRACE();
968 // If solver is inactive cell musst never be a internal cell
969 if(!isActive()) {
970 ASSERT(grid().raw().a_isHalo(gridCellId), "");
971 }
972
973 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
974
975 ASSERT(gridCellId > -1 && gridCellId < grid().raw().treeb().size() && solverCellId > -1
976 && solverCellId < m_cells.size() && grid().tree().solver2grid(solverCellId) == gridCellId,
977 "");
978
979 this->removeCellId(solverCellId);
980}
981
982
983template <MInt nDim>
985 grid().resizeGridMap(m_cells.size());
986}
987
988
993template <MInt nDim>
994void PostData<nDim>::swapCells(const MInt cellId0, const MInt cellId1) {
995 TRACE();
996
997 const MInt size = m_cells.size();
998 m_cells.append();
999 m_cells.erase(size);
1000 m_cells.copy(cellId0, size);
1001 m_cells.copy(cellId1, cellId0);
1002 m_cells.copy(size, cellId1);
1003 m_cells.erase(size);
1004 m_cells.size(size);
1005}
1006
1007
1012template <MInt nDim>
1013void PostData<nDim>::swapProxy(const MInt cellId0, const MInt cellId1) {
1014 grid().swapGridIds(cellId0, cellId1);
1015}
1016
1017
1024template <MInt nDim>
1025MInt PostData<nDim>::cellOutside(const MFloat* coords, const MInt level, const MInt gridCellId) {
1026 return -1;
1027
1028 std::ignore = coords;
1029 std::ignore = level;
1030 std::ignore = gridCellId;
1031}
1032
1033
1036template <MInt nDim>
1038 TRACE();
1039 mDeallocate(m_recalcIds);
1040}
1041
1045template <MInt nDim>
1047 TRACE();
1048
1049 // Note: every function that allocates persistent memory should first deallocate that memory, for
1050 // this to work initialize all pointers with nullptr in the class definition
1051
1052 // Set reinitialization stage
1053 m_loadBalancingReinitStage = 0;
1054
1055 // Store currently used memory
1056 /* const MLong previouslyAllocated = allocatedBytes(); */
1057
1058 // Update the grid proxy for this solver
1059 grid().update();
1060
1061 if(!grid().isActive()) {
1062 // Reset parallelization information if solver is not active
1063 updateDomainInfo(-1, -1, MPI_COMM_NULL, AT_);
1064 } else {
1065 // Set new domain info for solver
1066 updateDomainInfo(grid().domainId(), grid().noDomains(), grid().mpiComm(), AT_);
1067 }
1068
1069 // Return if solver is not active
1070 if(!grid().isActive()) {
1071 m_cells.reset(grid().maxNoCells());
1072 this->setHaloCellsOnInactiveRanks();
1073 return;
1074 }
1075
1076 // Resize cell collector to internal cells
1077 m_cells.reset(grid().raw().treeb().capacity());
1078
1079 setAndAllocateSolverData(false);
1080 this->checkNoHaloLayers();
1081}
1082
1086template <MInt nDim>
1088 TRACE();
1089
1090 m_loadBalancingReinitStage = 1;
1091 m_adaptationSinceLastRestart = true;
1092
1093 // Nothing to do if solver is not active
1094 if(!grid().isActive()) return;
1095
1096 m_loadBalancingReinitStage = 2;
1097}
1098
1101template <MInt nDim>
1103 TRACE();
1104
1105 // Nothing to do if solver is not active
1106 if(!grid().isActive()) return;
1107
1108 m_loadBalancingReinitStage = -1;
1109}
1110
1112template <MInt nDim>
1113MInt PostData<nDim>::cellDataSizeDlb(const MInt dataId, const MInt gridCellId) {
1114 // Inactive ranks do not have any data to communicate
1115 if(!isActive()) {
1116 return 0;
1117 }
1118
1119 // Convert to solver cell id and check
1120 const MInt cellId = grid().tree().grid2solver(gridCellId);
1121 if(cellId < 0 || cellId >= noInternalCells()) {
1122 return 0;
1123 }
1124
1125 MInt dataSize = 0;
1126
1127 switch(dataId) {
1128 case 0: // variables
1129 dataSize = noVariables();
1130 break;
1131 default:
1132 TERMM(1, "Unknown data id.");
1133 break;
1134 }
1135
1136 return dataSize;
1137}
1138
1139template class PostData<2>;
1140template class PostData<3>;
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
Definition: postdata.h:23
MFloat getCellLoad(const MInt cellId, const MFloat *const weights) const override
Return the load of a single cell (given computational weights).
Definition: postdata.cpp:770
MInt cellDataSizeDlb(const MInt dataId, const MInt gridCellId) override
Return data size to be communicated during DLB for a grid cell and given data id.
Definition: postdata.cpp:1113
void readProperties()
void setVariableNames()
Definition: postdata.cpp:181
void prepareAdaptation() override
prepare solver adaptation
Definition: postdata.cpp:800
void postAdaptation() override
reinit the solver after a single adaptation step
Definition: postdata.cpp:854
void finalizeInitSolver() override
Definition: postdata.cpp:276
void getDefaultWeights(MFloat *weights, std::vector< MString > &names) const
Return the default weights for all load quantities.
Definition: postdata.cpp:683
void refineCell(const MInt) override
Definition: postdata.cpp:894
MInt noLoadTypes() const override
Return the number of Ls load types.
Definition: postdata.cpp:670
void resizeGridMap() override
Swap the given cells.
Definition: postdata.cpp:984
void setCellWeights(MFloat *) override
sets the cell-weight for balancing and a restarting
Definition: postdata.cpp:721
typename CartesianSolver::GridProxy GridProxy
Definition: postdata.h:29
void getDomainDecompositionInformation(std::vector< std::pair< MString, MInt > > &domainInfo) override
Return decomposition information, i.e. number of local elements,...
Definition: postdata.cpp:703
void loadGridFlowVars(const MChar *fileName, MInt noVariables, std::vector< MString > name)
This function reads the parallel Netcdf cartesian grid cell based solution/restart file currently use...
Definition: postdata.cpp:545
void finalizeAdaptation() override
reinit the solver after the full adaptation loop!
Definition: postdata.cpp:882
void saveRestartFile(const MBool writeBackup)
Definition: postdata.cpp:356
std::vector< std::pair< MInt, MInt > > m_variableOffset
Definition: postdata.h:290
MBool prepareRestart(MBool, MBool &) override
Prepare the solvers for a grid-restart.
Definition: postdata.cpp:312
MInt cellOutside(const MFloat *, const MInt, const MInt) override
checks if a child lies outSide of the domain! necessary for refinement at the bndry!
Definition: postdata.cpp:1025
void saveDataFile(const MBool writeBackup, const MString fileName, const MInt noVars, std::vector< MString > &variablesName, MFloat *variables)
Definition: postdata.cpp:372
const std::vector< MString > m_propertyName
Definition: postdata.h:270
void removeChilds(const MInt) override
Coarsen the given cell.
Definition: postdata.cpp:937
void balancePre() override
Reinitialize solver for DLB prior to setting solution data.
Definition: postdata.cpp:1046
void finalizeBalance() override
Reinitialize solver after all data structures have been recreated.
Definition: postdata.cpp:1102
void initSolver() override
Definition: postdata.cpp:135
void setSensors(std::vector< std::vector< MFloat > > &sensors, std::vector< MFloat > &sensorWeight, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MInt > &sensorSolverId) override
set the sensors for a single adaptation step
Definition: postdata.cpp:815
void getSolverTimings(std::vector< std::pair< MString, MFloat > > &solverTimings, const MBool) override
Get solver timings.
Definition: postdata.cpp:648
PostData(MInt, GridProxy &gridProxy_, Geom &geometry_, const MPI_Comm comm)
Definition: postdata.cpp:61
void removeCell(const MInt) override
Remove the given cell.
Definition: postdata.cpp:966
void swapCells(const MInt, const MInt) override
Definition: postdata.cpp:994
MString getVariableName(MInt offset)
Definition: postdata.cpp:197
void setAndAllocateSolverData(const MBool)
Definition: postdata.cpp:150
void resetSolver() override
Reset the solver prior to load balancing.
Definition: postdata.cpp:1037
void saveSolverSolution(const MBool, const MBool)
Definition: postdata.cpp:575
typename maia::CartesianSolver< nDim, PostData > CartesianSolver
Definition: postdata.h:27
void reIntAfterRestart(MBool)
This function resets the grid-trigger after a restart that is handled by the grid-controller!
Definition: postdata.cpp:345
void copyGridProperties()
Definition: postdata.cpp:112
void loadMeanFile(const MString fileName)
load a file for averaging
Definition: postdata.cpp:488
void balancePost() override
Reinitialize solver for DLB after to setting solution data.
Definition: postdata.cpp:1087
void writeRestartFile(const MBool, const MBool, const MString, MInt *) override
Definition: postdata.cpp:290
void swapProxy(const MInt cellId0, const MInt cellId1) override
Definition: postdata.cpp:1013
void getLoadQuantities(MInt *const loadQuantities) const override
Return the cumulative load quantities on this domain.
Definition: postdata.cpp:742
void loadRestartFile()
Definition: postdata.cpp:454
This class is a ScratchSpace.
Definition: scratch.h:758
T * getPointer() const
Deprecated: use begin() instead!
Definition: scratch.h:316
pointer p
Deprecated: use [] instead!
Definition: scratch.h:315
iterator begin()
Definition: scratch.h:273
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ NETCDF
Definition: enums.h:18
@ VTK
Definition: enums.h:18
@ VTP
Definition: enums.h:18
@ VTU
Definition: enums.h:18
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
MInt globalTimeStep
MBool g_multiSolverGrid
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
uint32_t MUint
Definition: maiatypes.h:63
std::basic_string< char > MString
Definition: maiatypes.h:55
MInt noSolvers
Definition: maiatypes.h:73
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
char MChar
Definition: maiatypes.h:56
MInt id
Definition: maiatypes.h:71
const MInt PIO_READ
Definition: parallelio.h:40
Namespace for auxiliary functions/classes.
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292