15#include <unordered_map>
33 : m_maxNoCells(maxCells), m_mpiComm(comm), m_paraViewPlugin((
MBool)!fileName.empty()), m_maxNoNghbrs(m_noDirs) {
36 if(paraViewPlugin()) {
37 cerr <<
"Initialising MAIA for the ParaView-Plugin" << endl;
43 copy_n(bBox, 2 * nDim, &m_boundingBox[0]);
46 copy_n(bBox, 2 * nDim, &m_boundingBoxBackup[0]);
50 MPI_Comm_rank(mpiComm(), &m_domainId);
51 MPI_Comm_size(mpiComm(), &m_noDomains);
54 NEW_TIMER_GROUP(gridTimer,
"Cartesian Grid");
55 NEW_TIMER(timertotal,
"Total", gridTimer);
56 NEW_SUB_TIMER(timerAllocProp,
"allocProperties", timertotal);
57 NEW_SUB_TIMER(timerLoadGridPar,
"loadGrid", timertotal);
58 NEW_SUB_TIMER(timerCreateMB,
"window/halo generation", timertotal);
60 RECORD_TIMER_START(timertotal);
61 RECORD_TIMER_START(timerAllocProp);
63 if(!m_paraViewPlugin) {
64 m_partitionCellOffspringThreshold = 50000;
77 mTerm(1, AT_,
"Error: Property minCellMaxSize is deprecated. Please rename to partitionCellOffspringThreshold.");
80 cerr <<
"Warning: Property partitionCellMaxNoOffspring is deprecated. Please rename to "
81 "partitionCellOffspringThreshold."
83 m_partitionCellOffspringThreshold =
84 Context::getBasicProperty<MInt>(
"partitionCellMaxNoOffspring", AT_, &m_partitionCellOffspringThreshold);
86 m_partitionCellOffspringThreshold =
87 Context::getBasicProperty<MInt>(
"partitionCellOffspringThreshold", AT_, &m_partitionCellOffspringThreshold);
90 m_partitionCellWorkloadThreshold = 50000.;
102 m_partitionCellWorkloadThreshold =
103 Context::getBasicProperty<MFloat>(
"partitionCellWorkloadThreshold", AT_, &m_partitionCellWorkloadThreshold);
105 m_maxUniformRefinementLevel = -1;
107 m_maxUniformRefinementLevel = Context::getBasicProperty<MInt>(
"maxGeometricalRfnLvl", AT_);
109 cerr <<
"Warning: Property maxGeometricalRfnLvl is deprecated and should be provided as "
110 "maxUniformRefinementLevel by the grid file."
114 m_maxRfnmntLvl = Context::getBasicProperty<MInt>(
"maxRfnmntLvl", AT_);
115 if(m_maxRfnmntLvl > 63) {
117 "Error: m_maxRfnmntLvl > 31 not supported. Long bitshift from FPOW2() only provides 63 correct entries.");
120 m_allowInterfaceRefinement =
false;
121 m_allowInterfaceRefinement =
122 Context::getBasicProperty<MBool>(
"allowInterfaceRefinement", AT_, &m_allowInterfaceRefinement);
125 m_cutOff = (
MBool)Context::getBasicProperty<MInt>(
"cutOff", AT_, &m_cutOff);
141 m_newMinLevel = Context::getBasicProperty<MInt>(
"newMinLevel", AT_, &m_newMinLevel);
143 m_noPeriodicCartesianDirs = 0;
144 m_periodicCartesianDir.fill(0.0);
158 for(
MInt dir = 0; dir < nDim; dir++) {
159 m_periodicCartesianDir[dir] =
160 Context::getBasicProperty<MInt>(
"periodicCartesianDir", AT_, &m_periodicCartesianDir[dir], dir);
163 for(
MInt dir = 0; dir < nDim; dir++) {
164 m_periodicCartesianDir[dir] =
165 Context::getBasicProperty<MInt>(
"periodicDir", AT_, &m_periodicCartesianDir[dir], dir);
169 m_azimuthalPer =
false;
170 m_azimuthalPer = Context::getBasicProperty<MBool>(
"azimuthalPer", AT_, &m_azimuthalPer);
173 for(
MInt dir = 0; dir < nDim; dir++) {
174 m_azimuthalAngle = PI / 180.0 * Context::getBasicProperty<MFloat>(
"azimuthalAngle", AT_, &m_azimuthalAngle);
175 m_azimuthalPerCenter[dir] =
176 Context::getBasicProperty<MFloat>(
"azimuthalPerCenter", AT_, &m_azimuthalPerCenter[dir], dir);
177 if(m_periodicCartesianDir[dir] == 0) {
178 ASSERT(nDim == 3,
"2D grid but periodicCartesianDir is 0!");
179 m_azimuthalAxialDir = dir;
181 ASSERT(cnt < 2,
"Azimuthal periodicity is used, but more than 2 peridodic directions!");
182 m_azimuthalPeriodicDir[cnt] = dir;
186 ASSERT(cnt == 2,
"Azimuthal periodicity is used, but less than 2 peridodic directions!");
188 for(
MInt dir = 0; dir < nDim; dir++) {
189 if(m_periodicCartesianDir[dir]) m_noPeriodicCartesianDirs++;
191 m_log <<
"Number of periodic Cartesian directions is " << m_noPeriodicCartesianDirs <<
" ("
192 << m_periodicCartesianDir[0] <<
"," << m_periodicCartesianDir[1] <<
"," << m_periodicCartesianDir[2] <<
")"
197 testcaseDir = Context::getBasicProperty<MString>(
"testcaseDir", AT_, &testcaseDir);
210 m_outputDir = Context::getBasicProperty<MString>(
"outputDir", AT_);
213 m_restart = Context::getBasicProperty<MBool>(
"restartFile", AT_, &m_restart);
216 pp = Context::getBasicProperty<MBool>(
"postProcessing", AT_, &pp);
230 m_restartDir = Context::getBasicProperty<MString>(
"restartDir", AT_, &m_outputDir);
231 if(!m_restart && !pp) {
232 m_restartDir = testcaseDir + m_outputDir;
234 m_restartDir = testcaseDir + m_restartDir;
236 m_outputDir = testcaseDir + m_outputDir;
250 m_noHaloLayers = Context::getBasicProperty<MInt>(
"noHaloLayers", AT_, &m_noHaloLayers);
253 m_loadGridPartition =
false;
266 m_loadGridPartition = Context::getBasicProperty<MBool>(
"loadGridPartition", AT_, &m_loadGridPartition);
275 m_loadPartition =
false;
276 m_loadPartition = Context::getBasicProperty<MBool>(
"loadPartition", AT_, &m_loadPartition);
289 m_partitionParallelSplit =
false;
290 m_partitionParallelSplit =
291 Context::getBasicProperty<MBool>(
"partitionParallelSplit", AT_, &m_partitionParallelSplit);
309 MBool offset =
false;
310 offset = Context::getBasicProperty<MBool>(
"bitOffset", AT_, &offset);
311 if(offset) m_32BitOffset = std::numeric_limits<MInt>::max();
323 m_lbGridChecks =
false;
325 m_lbGridChecks = Context::getBasicProperty<MBool>(
"lbGridChecks", AT_);
338 m_coarseRatio = Context::getBasicProperty<MFloat>(
"coarseRatio", AT_, &m_coarseRatio);
347 m_allowCoarsening =
true;
348 m_allowCoarsening = Context::getBasicProperty<MBool>(
"allowCoarsening", AT_, &m_allowCoarsening);
362 m_updatePartitionCellsOnRestart =
true;
363 m_updatePartitionCellsOnRestart =
364 Context::getBasicProperty<MBool>(
"updatePartitionCellsOnRestart", AT_, &m_updatePartitionCellsOnRestart);
367 m_lowMemAdaptation =
true;
368 m_lowMemAdaptation = Context::getBasicProperty<MBool>(
"lowMemAdaptation", AT_, &m_lowMemAdaptation);
369 if(m_lowMemAdaptation) {
370 m_log <<
"Adaptation mode: low memory" << endl;
372 m_log <<
"Adaptation mode: default" << endl;
377 m_loadGridPartition = 0;
378 m_partitionCellOffspringThreshold = 50000;
379 m_partitionCellWorkloadThreshold = 50000.;
380 m_noPeriodicCartesianDirs = 0;
381 m_periodicCartesianDir.fill(0.0);
383 m_lbGridChecks =
false;
389 RECORD_TIMER_STOP(timerAllocProp);
391 m_log <<
"Initializing collector | "
392 <<
"#maxCells: " << maxCells <<
" | #dimensions: " << nDim << endl;
395 m_tree.reset(maxCells);
399 noSolvers = Context::getBasicProperty<MInt>(
"noSolvers", AT_);
401 }
else if(m_paraViewPlugin) {
404 m_gridInputFileName = fileName;
406 if(grid.hasAttribute(
"noSolvers")) {
407 grid.getAttribute(&
noSolvers,
"noSolvers");
413 m_addSolverToGrid =
false;
414 if(!m_paraViewPlugin) {
415 m_addSolverToGrid = Context::getBasicProperty<MBool>(
"addSolverToGrid", AT_, &m_addSolverToGrid);
416 m_referenceSolver = Context::getBasicProperty<MInt>(
"referenceSolver", AT_, &m_referenceSolver);
418 if(domainId() == 0 && m_addSolverToGrid) {
419 cerr <<
"Adding additional solver to the grid file based on solver " << m_referenceSolver << endl;
427 if(domainId() == 0) {
428 cerr <<
"Grid consisting of " <<
noSolvers <<
" solvers." << endl;
435 if(!m_paraViewPlugin) {
436 m_gridInputFileName =
"";
437 setGridInputFilename();
440 m_log <<
"Collector initialized" << endl;
458 if(!m_paraViewPlugin) {
459 m_haloMode = Context::getBasicProperty<MInt>(
"haloMode", AT_, &m_haloMode);
460 TERMM_IF_NOT_COND(m_haloMode >= 0 && m_haloMode <= 2,
"Check your input, dude!");
461 if(m_haloMode == 0 && domainId() == 0)
462 cerr <<
"\033[0;31m#### WARNING:\033[0m haloMode==0 is deprecated!!!" << endl;
468 mAlloc(m_noSolverHaloLayers, treeb().
noSolvers(),
"m_noSolverHaloLayers", AT_);
469 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
471 m_noSolverHaloLayers[solver] = m_noHaloLayers;
473 m_noSolverHaloLayers[solver] = Context::getSolverProperty<MInt>(
"noHaloLayers", solver, AT_);
474 ASSERT(m_noSolverHaloLayers[solver] < WINDOWLAYER_MAX,
"");
475 m_noHaloLayers = std::max(m_noHaloLayers, m_noSolverHaloLayers[solver]);
476 ASSERT(m_noSolverHaloLayers[solver] <= m_noHaloLayers,
"");
477 m_log <<
" -- solverId " << solver <<
" -- no Solver Halo-Layers : " << m_noSolverHaloLayers[solver] << endl;
482 mAlloc(m_checkRefinementHoles, treeb().
noSolvers(),
"m_checkRefinementHoles", AT_);
491 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
492 m_checkRefinementHoles[solver] = Context::getSolverProperty<MBool>(
"checkRefinementHoles", solver, AT_);
504 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
505 m_diagSmoothing[solver] =
false;
506 m_diagSmoothing[solver] =
507 Context::getSolverProperty<MBool>(
"diagSmoothing", solver, AT_, &m_diagSmoothing[solver]);
513 ASSERT(m_noIdenticalSolvers <= treeb().
noSolvers(),
"");
514 mAlloc(m_identicalSolvers, m_noIdenticalSolvers * 2,
"m_identicalSolvers", AT_);
515 mAlloc(m_identicalSolverMaxLvl, m_noIdenticalSolvers,
"m_identicalSolverMaxLvl", AT_);
516 mAlloc(m_identicalSolverLvlJumps, m_noIdenticalSolvers,
"m_identicalSolverLvlJumps", AT_);
517 for(
MInt s = 0; s < m_noIdenticalSolvers * 2; s++) {
518 m_identicalSolvers[s] = Context::getBasicProperty<MInt>(
"identicalSolvers", AT_, s);
520 for(
MInt pair = 0; pair < m_noIdenticalSolvers; pair++) {
521 const MInt slaveId = m_identicalSolvers[pair * 2];
522 const MInt masterId = m_identicalSolvers[pair * 2 + 1];
523 MInt slaveMaxLvl = Context::getSolverProperty<MInt>(
"maxRfnmntLvl", slaveId, AT_);
525 slaveMaxLvl = Context::getSolverProperty<MInt>(
"identicalSolverMaxLevel", slaveId, AT_);
527 const MInt masterMaxLvl = Context::getSolverProperty<MInt>(
"maxRfnmntLvl", masterId, AT_);
528 m_identicalSolverMaxLvl[pair] = slaveMaxLvl;
529 m_identicalSolverLvlJumps[pair] = masterMaxLvl - slaveMaxLvl;
530 cerr0 <<
"Slave solverId " << slaveId <<
" has maxRefinementLevel " << slaveMaxLvl <<
" and "
531 << m_identicalSolverLvlJumps[pair] <<
" refinement-Jumps towards the master!" << endl;
535 m_log <<
"/***** STARTING FLOW SOLVER ******/" << endl;
536 loadGridFile(timerLoadGridPar, timerCreateMB);
538 if(!m_paraViewPlugin) {
544 if(m_addSolverToGrid) {
546 if(domainId() == 0) {
547 cerr <<
"Applying solver bounding box to solver " << treeb().noSolvers() - 1 << endl;
549 std::array<MFloat, nDim * 2> boxCoordinates;
550 for(
MInt i = 0; i < nDim * 2; i++) {
551 boxCoordinates[i] = Context::getBasicProperty<MFloat>(
"solverBoundingBox", AT_, i);
553 MInt solverMaxLvl = maxRefinementLevel();
554 solverMaxLvl = Context::getBasicProperty<MInt>(
"solverMaxLevel", AT_, &solverMaxLvl);
558 const MInt solverId = treeb().noSolvers() - 1;
559 for(
MInt lvl = maxRefinementLevel(); lvl >= minLevel(); lvl--) {
561 if(a_level(cellId) != lvl)
continue;
562 if(!treeb().solver(cellId, treeb().
noSolvers() - 1))
continue;
563 if(a_hasChildren(cellId, treeb().
noSolvers() - 1))
continue;
564 for(
MInt i = 0; i < nDim; i++) {
565 if(a_coordinate(cellId, i) < boxCoordinates[i] || a_coordinate(cellId, i) > boxCoordinates[nDim + i]) {
566 treeb().solver(cellId, treeb().
noSolvers() - 1) =
false;
569 if(a_level(cellId) > solverMaxLvl) {
570 treeb().solver(cellId, solverId) =
false;
575 MInt addedSolverMaxLevel = Context::getBasicProperty<MInt>(
"addedSolverMaxLevel", AT_);
577 if(!treeb().solver(cellId, treeb().
noSolvers() - 1))
continue;
578 if(a_level(cellId) > addedSolverMaxLevel) {
579 treeb().solver(cellId, treeb().
noSolvers() - 1) =
false;
582 MInt* recalcIds =
nullptr;
585 ASSERT(m_tree.noSolvers() > 1,
"");
588 saveGrid((m_outputDir + m_gridInputFileName).c_str(), recalcIds);
594 exchangeSolverBitset(&m_tree.solverBits(0));
600 MInt* recalcIds =
nullptr;
602 saveGrid((m_outputDir + m_gridInputFileName +
"+addSolver").c_str(), recalcIds);
606 computeLocalBoundingBox(&m_localBoundingBox[0]);
609 if(noDomains() > 1) {
610 m_log <<
" -- minLevel for current domain: " << m_minLevel << endl;
611 m_log <<
" -- maxLevel for current domain: " << m_maxLevel << endl;
613 m_log <<
" -- minLevel = " << m_minLevel << endl;
614 m_log <<
" -- maxLevel = " << m_maxLevel << endl;
617 m_log <<
" [ Grid file has " << m_tree.size() <<
" cells ] " << endl;
619 RECORD_TIMER_STOP(timertotal);
620 DISPLAY_TIMER(timertotal);
625 MInt maxCellVolumeLevel = (m_maxLevel < 32) ? 32 : m_maxLevel;
626 mAlloc(m_gridCellVolume, maxCellVolumeLevel,
"m_gridCellVolume", AT_);
627 for(
MInt level = 0; level < maxCellVolumeLevel; level++) {
628 m_gridCellVolume[level] = F1;
629 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
630 m_gridCellVolume[level] *= cellLengthAtLevel(level);
636 if(!m_paraViewPlugin && m_newMinLevel > 0) {
638 MInt noUnrefinedMinCells = 0;
640 if(a_isHalo(cellId))
continue;
641 if(a_level(cellId) < m_newMinLevel) {
642 if(a_noChildren(cellId) < 1) noUnrefinedMinCells++;
645 MPI_Allreduce(MPI_IN_PLACE, &noUnrefinedMinCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
646 "noUnrefinedMinCells");
648 if(noUnrefinedMinCells > 0) {
649 if(domainId() == 0) {
650 cerr <<
"Mincells not yet sufficiently refined for minLevel increase from " << m_minLevel <<
" to "
651 << m_newMinLevel <<
"!" << endl;
653 }
else if(noDomains() == 1) {
655 std::rename((m_restartDir + m_gridInputFileName).c_str(),
656 (m_restartDir + m_gridInputFileName +
"backup").c_str());
658 m_targetGridMinLevel = m_newMinLevel;
659 m_updatedPartitionCells =
false;
660 MInt* recalcIds =
nullptr;
662 if(m_maxUniformRefinementLevel < m_newMinLevel) {
663 m_maxUniformRefinementLevel = m_newMinLevel;
666 saveGrid((m_outputDir + m_gridInputFileName).c_str(), recalcIds);
668 cerr0 <<
"Successfully written new grid file! Exiting MAIA." << endl;
669 mTerm(0, AT_,
"Finished writing new grid restartFile!");
673 if(!m_paraViewPlugin) {
674 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
675 MInt inactiveMinCells = 0;
677 if(a_level(cellId) != minLevel())
continue;
678 if(a_isHalo(cellId))
continue;
679 if(!a_solver(cellId, solver)) {
683 MPI_Allreduce(MPI_IN_PLACE, &inactiveMinCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
686 if(inactiveMinCells > 0) {
687 cerr0 <<
"Solver " << solver <<
" has " << inactiveMinCells <<
" inactive mincells!" << endl;
721 MBool tmpFalse =
false;
723 const MBool restart = forceRestart || m_restart;
725 const MBool useNonSpecifiedRestartFile =
726 restart ? Context::getBasicProperty<MBool>(
"useNonSpecifiedRestartFile", AT_, &tmpFalse) :
true;
728 const MInt restartTimeStep = useNonSpecifiedRestartFile ? 0 : Context::getBasicProperty<MInt>(
"restartTimeStep", AT_);
729 MBool multilevel =
false;
731 multilevel = Context::getBasicProperty<MBool>(
"multilevel", AT_, &multilevel);
732 m_zonal = Context::getBasicProperty<MBool>(
"zonal", AT_, &m_zonal);
736 const MInt gridSolverId = 0;
738 MString solverType = Context::getSolverProperty<MString>(
"solvertype", gridSolverId, AT_);
741 if(solverType ==
"MAIA_LS_SOLVER" || solverType ==
"MAIA_MULTI_LS") {
745 if(domainId() == 0) {
746 cerr <<
"cartesian grid file name has to be 'grid.Netcdf'" << endl;
748 m_gridInputFileName =
"grid.Netcdf";
749 MBool m_adaptation = Context::getBasicProperty<MBool>(
"adaptation", AT_, &m_adaptation);
750 if(m_adaptation && m_restart) {
751 MInt restartTime = Context::getBasicProperty<MInt>(
"restartTimeStep", AT_);
753 stringstream reinitFile;
754 reinitFile <<
"restartGrid_00" << restartTime <<
".Netcdf";
756 m_gridInputFileName = reinitFile.str();
757 cerr <<
"grid file name changed to : " << m_gridInputFileName << endl;
762 stringstream varFileName;
763 if(solverType ==
"MAIA_LATTICE_BOLTZMANN") {
765 varFileName << m_restartDir;
766 varFileName <<
"restart_" << restartTimeStep << ParallelIo::fileExt();
767 }
else if(solverType ==
"MAIA_DISCONTINUOUS_GALERKIN") {
769 if(useNonSpecifiedRestartFile) {
770 varFileName << m_restartDir <<
"restart" << ParallelIo::fileExt();
772 varFileName << m_restartDir <<
"restart_b" << gridSolverId <<
"_" << setw(8) << setfill(
'0')
773 << restartTimeStep << ParallelIo::fileExt();
775 varFileName << m_restartDir <<
"restart_" << setw(8) << setfill(
'0') << restartTimeStep
776 << ParallelIo::fileExt();
778 }
else if(solverType ==
"MAIA_DG_MULTISOLVER") {
780 if(useNonSpecifiedRestartFile) {
781 varFileName << m_restartDir <<
"restart_b0" << ParallelIo::fileExt();
783 varFileName << m_restartDir <<
"restart_b0_" << setw(8) << setfill(
'0') << restartTimeStep
784 << ParallelIo::fileExt();
786 }
else if(solverType ==
"MAIA_LEVELSET_SOLVER") {
787 varFileName << m_restartDir <<
"restartLSCG";
788 if(treeb().
noSolvers() > 1) varFileName <<
"_" << gridSolverId;
789 if(!useNonSpecifiedRestartFile) varFileName <<
"_" << restartTimeStep;
790 varFileName << ParallelIo::fileExt();
795 varFileName << m_restartDir <<
"restartVariables" << gridSolverId;
797 varFileName << m_restartDir <<
"restartVariables";
799 if(!useNonSpecifiedRestartFile) varFileName <<
"_" << restartTimeStep;
800 varFileName << ParallelIo::fileExt();
803 const MInt maxLength = 256;
804 array<MChar, maxLength> buffer{};
805 snprintf(buffer.data(), maxLength,
"restart_b00_t%08d", restartTimeStep);
806 varFileName << m_restartDir <<
MString(buffer.data()) << ParallelIo::fileExt();
809 const MString fileName = varFileName.str();
810 m_log <<
"Trying to read grid input file name from restart file " << fileName << endl;
813 parallelIo.getAttribute(&name,
"gridFile");
816 MString tmp = Context::getBasicProperty<MString>(
"gridInputFileName", AT_);
820 MString tmp = Context::getBasicProperty<MString>(
"gridInputFileName", AT_);
823 m_gridInputFileName = s.str();
824 struct stat buffer {};
825 if(restart && stat((m_restartDir + m_gridInputFileName).c_str(), &buffer) != 0) {
826 mTerm(1, AT_,
"Grid input file " + m_restartDir + m_gridInputFileName +
" does not exist.");
828 m_log <<
"Cartesian Grid input file name is " << m_gridInputFileName
829 <<
" (full path: " << m_restartDir + m_gridInputFileName <<
")." << endl;
844 RECORD_TIMER_START(timerLoadGridPar);
845 loadGrid(m_restartDir + m_gridInputFileName);
846 RECORD_TIMER_STOP(timerLoadGridPar);
852 if(noDomains() > 1 || m_noPeriodicCartesianDirs > 0) {
853 RECORD_TIMER_START(timerCreateMB);
855 setupWindowHaloCellConnectivity();
856 RECORD_TIMER_STOP(timerCreateMB);
858 storeMinLevelCells();
862#ifdef MAIA_GRID_SANITY_CHECKS
864 checkWindowHaloConsistency(
true);
885 if(globalId < domainOffsets[0] || globalId > domainOffsets[noDomains]) {
886 TERMM(1,
"Invalid global id: " + std::to_string(globalId)
887 +
"; domainOffset[0]=" + std::to_string(domainOffsets[noDomains])
888 +
"; domainOffset[noDomains]=" + std::to_string(domainOffsets[noDomains]));
893 auto lowerBound = std::lower_bound(&domainOffsets[0], &domainOffsets[0] + noDomains, globalId);
894 const MInt dist = std::distance(&domainOffsets[0], lowerBound);
896 const MBool isDomainOffset = (*lowerBound == globalId);
911template <
class ITERATOR,
typename U>
913 if(distance(first, last) <= 0)
return -1;
914 auto idx = (
MInt)distance(first, find(first, last, val));
915 if(idx == (
MInt)distance(first, last)) idx = -1;
928template <
typename TA,
typename TB,
typename TC>
931 ASSERT(ndom > -1,
"");
932 if(m_nghbrDomainIndex[ndom] < 0) {
936 m_nghbrDomainIndex[ndom] = (signed)m_nghbrDomains.size();
937 m_nghbrDomains.push_back(ndom);
939 return m_nghbrDomainIndex[ndom];
947template <
typename TA,
typename TB>
949 ASSERT(ndom > -1,
"");
950 if(m_nghbrDomainIndex[ndom] < 0) {
953 m_nghbrDomainIndex[ndom] = (signed)m_nghbrDomains.size();
954 m_nghbrDomains.push_back(ndom);
956 return m_nghbrDomainIndex[ndom];
965 vector<vector<MInt>>& vecB) {
966 ASSERT(ndom > -1,
"");
967 if(m_azimuthalNghbrDomainIndex[ndom] < 0) {
970 m_azimuthalHigherLevelConnectivity.emplace_back();
971 m_azimuthalNghbrDomainIndex[ndom] = (signed)m_azimuthalNghbrDomains.size();
972 m_azimuthalNghbrDomains.push_back(ndom);
974 return m_azimuthalNghbrDomainIndex[ndom];
983 vector<vector<MLong>>& vecB) {
984 ASSERT(ndom > -1,
"");
985 if(m_azimuthalNghbrDomainIndex[ndom] < 0) {
988 m_azimuthalHigherLevelConnectivity.emplace_back();
989 m_azimuthalNghbrDomainIndex[ndom] = (signed)m_azimuthalNghbrDomains.size();
990 m_azimuthalNghbrDomains.push_back(ndom);
992 return m_azimuthalNghbrDomainIndex[ndom];
1006 auto logDuration = [
this](
const MFloat timeStart,
const MString comment) {
1007 logDuration_(timeStart,
"WINDOW/HALO", comment, mpiComm(), domainId(), noDomains());
1011 std::vector<MInt>().swap(m_nghbrDomains);
1012 std::vector<MInt>().swap(m_nghbrDomainIndex);
1013 std::vector<std::vector<MInt>>().swap(m_haloCells);
1014 std::vector<std::vector<MInt>>().swap(m_windowCells);
1015 std::vector<std::unordered_map<MInt, M32X4bit<true>>>().swap(m_windowLayer_);
1017 cerr0 <<
"Establish window/halo connectivity..." << endl;
1024 std::vector<MInt>().swap(m_nghbrDomains);
1025 m_nghbrDomainIndex.resize(noDomains());
1026 std::fill_n(m_nghbrDomainIndex.begin(), noDomains(), -1);
1028 if(m_azimuthalPer) {
1029 m_azimuthalNghbrDomains.clear();
1030 m_azimuthalNghbrDomainIndex.resize(noDomains());
1031 std::fill_n(m_azimuthalNghbrDomainIndex.begin(), noDomains(), -1);
1033 m_azimuthalHaloCells.clear();
1034 m_azimuthalUnmappedHaloCells.clear();
1035 m_azimuthalWindowCells.clear();
1040 createMinLevelExchangeCells();
1041 logDuration(minExchangeTimeStart,
"Create min level exchange cells");
1045 if(m_maxLevel > m_minLevel) {
1048 createHigherLevelExchangeCells();
1050 createHigherLevelExchangeCells_old();
1052 logDuration(higherExchangeTimeStart,
"Create higher level exchange cells");
1054#ifdef MAIA_GRID_SANITY_CHECKS
1055 checkWindowHaloConsistency();
1059 exchangeProperties();
1062 updateHaloCellCollectors();
1067 exchangeSolverBitset(&m_tree.solverBits(0));
1072 if(m_azimuthalPer) {
1073 if(noAzimuthalNeighborDomains() > 0) {
1075 &m_tree.solverBits(0), m_tree.size());
1079 for(
MInt i = 0; i < noAzimuthalUnmappedHaloCells(); i++) {
1080 MInt cellId = azimuthalUnmappedHaloCell(i);
1081 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
1082 m_tree.solver(cellId, solver) =
true;
1087 correctAzimuthalSolverBits();
1090 storeMinLevelCells();
1094 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1095 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
1096 a_hasProperty(m_haloCells[i][j], Cell::IsHalo) =
true;
1097 a_hasProperty(m_haloCells[i][j], Cell::IsWindow) =
false;
1099 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1100 a_hasProperty(m_windowCells[i][j], Cell::IsHalo) =
false;
1101 a_hasProperty(m_windowCells[i][j], Cell::IsWindow) =
true;
1104 if(m_azimuthalPer) {
1105 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1106 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
1107 a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsHalo) =
true;
1108 a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsWindow) =
false;
1110 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
1111 a_hasProperty(m_azimuthalWindowCells[i][j], Cell::IsHalo) =
false;
1112 a_hasProperty(m_azimuthalWindowCells[i][j], Cell::IsWindow) =
true;
1115 for(
MInt j = 0; j < noAzimuthalUnmappedHaloCells(); j++) {
1116 a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsHalo) =
true;
1120 createGlobalToLocalIdMapping();
1122 MFloat cellCnt[4] = {F0, F0, F0, F0};
1123 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1124 cellCnt[0] += (
MFloat)m_haloCells[i].size();
1125 cellCnt[1] += (
MFloat)m_windowCells[i].size();
1127 cellCnt[2] = (
MFloat)m_tree.size();
1128 cellCnt[3] = (
MFloat)noNeighborDomains();
1129 m_log <<
"Grid local halo/window cell ratio: " << cellCnt[0] <<
" " << cellCnt[1] << endl;
1130 m_log <<
"Grid local halo/window cell ratio: " << cellCnt[0] <<
"; relative " << cellCnt[0] / cellCnt[2] <<
"; "
1131 << cellCnt[1] <<
"; relative " << cellCnt[1] / cellCnt[2] << endl;
1133 MFloat maxHaloCellRatio = cellCnt[0] / cellCnt[2];
1134 MPI_Allreduce(MPI_IN_PLACE, &maxHaloCellRatio, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1135 "maxHaloCellRatio");
1136 m_log <<
"Grid maximum halo cell ratio: " << maxHaloCellRatio << endl;
1138 MFloat maxWindowCellRatio = cellCnt[1] / cellCnt[2];
1139 MPI_Allreduce(MPI_IN_PLACE, &maxWindowCellRatio, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1140 "maxWindowCellRatio");
1141 m_log <<
"Grid maximum window cell ratio: " << maxWindowCellRatio << endl;
1143 MPI_Allreduce(MPI_IN_PLACE, cellCnt, 4, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"cellCnt");
1144 cellCnt[0] /= cellCnt[2];
1145 cellCnt[1] /= cellCnt[2];
1146 cellCnt[3] /= (
MFloat)noDomains();
1147 m_log <<
"Grid global halo/window cell ratio: " << cellCnt[0] <<
" " << cellCnt[1] << endl;
1148 MInt maxNoNeighborDomains = noNeighborDomains();
1149 MPI_Allreduce(MPI_IN_PLACE, &maxNoNeighborDomains, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1150 "maxNoNeighborDomains");
1151 m_log <<
"Grid maximum number of neighbor domains: " << maxNoNeighborDomains <<
", average: " << cellCnt[3] << endl;
1154 cerr0 <<
"done." << endl;
1155 logDuration(winHaloTimeStart,
"Window/halo total");
1170 if(domainId() == 0) cerr <<
" * create minLevel exchange cells...";
1172 const MInt oldNoCells = m_tree.size();
1176 vector<vector<MInt>> halos;
1177 vector<vector<MLong>> hilbertIds;
1178 vector<vector<MLong>> recvHilbertIds;
1179 MInt noMinLevelCells = 0;
1181 for(
MInt i = 0; i < nDim; i++) {
1182 bbox[i] = numeric_limits<MFloat>::max();
1183 bbox[nDim + i] = numeric_limits<MFloat>::lowest();
1185 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
1186 for(
MInt i = 0; i < nDim; i++) {
1187 bbox[i] =
mMin(bbox[i], a_coordinate(cellId, i) - F1B2 * cellLengthAtLevel(a_level(cellId)));
1188 bbox[nDim + i] =
mMax(bbox[nDim + i], a_coordinate(cellId, i) + F1B2 * cellLengthAtLevel(a_level(cellId)));
1193 const MFloat halfLength0 = 0.5 * ((F1 + F1 /
FPOW2(30)) * m_lengthLevel0);
1194 for(
MInt i = 0; i < nDim; i++) {
1195 ASSERT(bbox[i] > m_centerOfGravity[i] - halfLength0 && bbox[nDim + i] < m_centerOfGravity[i] + halfLength0,
1196 "bbox " + std::to_string(bbox[i]) +
"," + std::to_string(bbox[nDim + i]) +
", center = "
1197 + std::to_string(m_centerOfGravity[i]) +
", halfLenght0 = " + std::to_string(halfLength0));
1199 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[0]");
1200 MPI_Allreduce(MPI_IN_PLACE, &bbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[nDim]");
1202 if(((
MLong)pow(2.0, m_targetGridMinLevel * nDim)) > std::numeric_limits<MLong>::max()) {
1203 mTerm(1, AT_,
"Error: minLevel cell size is bigger than std::numeric_limits<MInt>::max()");
1207 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
1208 a_isToDelete(cellId) =
false;
1209 if(a_level(cellId) == m_minLevel) {
1213 ASSERT(noMinLevelCells > 0,
"Error: no min-level cell (including partition level ancestors) found.");
1215 unordered_multimap<MLong, MInt> hilbertToLocal;
1216 hilbertToLocal.reserve(noMinLevelCells + noMinLevelCells / 5);
1220 MLong minHilbertIndex = std::numeric_limits<MLong>::max();
1221 MLong prevHilbertIndex = std::numeric_limits<MLong>::min();
1222 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
1223 if(a_level(cellId) != m_minLevel)
continue;
1224 const MLong hilbertId = hilbertIndexGeneric(&a_coordinate(cellId, 0));
1225 hilbertToLocal.insert(make_pair(hilbertId, cellId));
1226 if(a_hasProperty(cellId, Cell::IsHalo)) {
1227 MInt ndom = findNeighborDomainId(a_globalId(cellId));
1228 ASSERT(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
"");
1229 ASSERT(ndom > -1,
"");
1230 MInt idx = setNeighborDomainIndex(ndom, halos, hilbertIds);
1231 ASSERT(idx > -1,
"");
1232 halos[idx].push_back(cellId);
1233 hilbertIds[idx].push_back(hilbertId);
1236 ASSERT((cellId < m_noInternalCells) != a_hasProperty(cellId, Cell::IsHalo),
"");
1237 ASSERT(a_hasProperty(cellId, Cell::IsHalo)
1238 == (a_hasProperty(cellId, Cell::IsPartLvlAncestor) && (cellId >= m_noInternalCells)),
1240 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
1241 minHilbertIndex =
mMin(minHilbertIndex, hilbertId);
1242 ASSERT(hilbertId > prevHilbertIndex,
1243 "Min level cells not sorted by Hilbert id: " + to_string(hilbertId) +
" > " + to_string(prevHilbertIndex));
1244 prevHilbertIndex = hilbertId;
1246 MPI_Allgather(&minHilbertIndex, 1, MPI_LONG, &hilbertOffsets[0], 1, MPI_LONG, mpiComm(), AT_,
"minHilbertIndex",
1247 "hilbertOffsets[0]");
1248 hilbertOffsets[0] = 0;
1249 hilbertOffsets[noDomains()] = std::numeric_limits<MLong>::max();
1252 for(
MInt cpu = noDomains() - 1; cpu >= 0; cpu--) {
1253 if(hilbertOffsets[cpu] == std::numeric_limits<MLong>::max()) {
1254 hilbertOffsets[cpu] = hilbertOffsets[cpu + 1];
1256 ASSERT(hilbertOffsets[cpu] <= hilbertOffsets[cpu + 1],
"");
1260 const MInt maxNoAdjacentCells =
ipow(2 * m_noHaloLayers + 1, 3);
1262 MInt ifcDirs[m_noDirs];
1264 vector<pair<MInt, MInt>> interfaceCells;
1265 for(
MInt cellId = 0; cellId < oldNoCells; cellId++) {
1266 if(a_level(cellId) > m_minLevel)
continue;
1267 for(
MInt dir = 0; dir < m_noDirs; dir++) {
1268 if(a_hasNeighbor(cellId, dir) > 0)
continue;
1269 interfaceCells.emplace_back(cellId, dir);
1275 while(cnt < interfaceCells.size()) {
1276 fill(&ifcDirs[0], &ifcDirs[0] + m_noDirs, 0);
1277 const MInt cellId = interfaceCells[cnt].first;
1278 while(cnt < interfaceCells.size() && cellId == interfaceCells[cnt].first) {
1279 ifcDirs[interfaceCells[cnt].second] = 1;
1283 cellList[cellCnt++] = cellId;
1284 for(
MInt dim = 0; dim < nDim; dim++) {
1285 const MInt cellCnt0 = cellCnt;
1286 for(
MInt ori = 0; ori < 2; ori++) {
1287 const MInt dir = 2 * dim + ori;
1288 if(!ifcDirs[dir])
continue;
1289 for(
MInt c = 0; c < cellCnt0; c++) {
1290 MInt nextId = cellList[c];
1291 for(
MInt layer = 0; layer < m_noHaloLayers; layer++) {
1292 if(a_hasNeighbor(nextId, dir) > 0)
1293 nextId = a_neighborId(nextId, dir);
1295 nextId = createAdjacentHaloCell(nextId, dir, &hilbertOffsets[0], hilbertToLocal, bbox, &noHalos[0], halos,
1297 if(nextId < 0)
break;
1298 cellList[cellCnt++] = nextId;
1305 MPI_Alltoall(&noHalos[0], 1, MPI_INT, &noWindows[0], 1, MPI_INT, mpiComm(), AT_,
"noHalos[0]",
"noWindows[0]");
1307 for(
MInt i = 0; i < noDomains(); i++) {
1308 if(noHalos[i] == 0 && noWindows[i] > 0) {
1309 ASSERT(m_nghbrDomainIndex[i] < 0,
"");
1310 setNeighborDomainIndex(i, halos, hilbertIds);
1315 sendReq.
fill(MPI_REQUEST_NULL);
1316 recvHilbertIds.resize(noNeighborDomains());
1317 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1318 ASSERT(m_nghbrDomains[i] > -1 && m_nghbrDomains[i] < noDomains(),
"");
1319 recvHilbertIds[i].resize(noWindows[m_nghbrDomains[i]]);
1321 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1322 for(
MInt k = 0; k < noHalos[m_nghbrDomains[i]]; k++) {
1323 ASSERT(hilbertIds[i][k] >= hilbertOffsets[m_nghbrDomains[i]]
1324 && hilbertIds[i][k] < hilbertOffsets[m_nghbrDomains[i] + 1],
1325 to_string(hilbertIds[i][k]) +
" " + to_string(hilbertOffsets[m_nghbrDomains[i]]) +
" "
1326 + to_string(hilbertOffsets[m_nghbrDomains[i] + 1]));
1329 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1330 MPI_Issend(&hilbertIds[i][0], noHalos[m_nghbrDomains[i]], MPI_LONG, m_nghbrDomains[i], 34, mpiComm(), &sendReq[i],
1331 AT_,
"hilbertIds[i][0]");
1333 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1334 MPI_Recv(&recvHilbertIds[i][0], noWindows[m_nghbrDomains[i]], MPI_LONG, m_nghbrDomains[i], 34, mpiComm(),
1335 MPI_STATUS_IGNORE, AT_,
"recvHilbertIds[i][0]");
1337 if(noNeighborDomains() > 0)
MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
1338 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1339 for(
MInt k = 0; k < noWindows[m_nghbrDomains[i]]; k++) {
1340 ASSERT(recvHilbertIds[i][k] >= hilbertOffsets[domainId()]
1341 && recvHilbertIds[i][k] < hilbertOffsets[domainId() + 1],
1346 vector<vector<MLong>> sendGlobalIds;
1347 vector<vector<MLong>> recvGlobalIds;
1348 sendGlobalIds.resize(noNeighborDomains());
1349 recvGlobalIds.resize(noNeighborDomains());
1350 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1351 ASSERT(m_nghbrDomains[i] > -1 && m_nghbrDomains[i] < noDomains(),
"");
1352 sendGlobalIds[i].resize(noWindows[m_nghbrDomains[i]]);
1353 recvGlobalIds[i].resize(noHalos[m_nghbrDomains[i]]);
1356 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1357 m_windowCells.push_back(vector<MInt>());
1358 for(
MInt k = 0; k < noWindows[m_nghbrDomains[i]]; k++) {
1360 auto range = hilbertToLocal.equal_range(recvHilbertIds[i][k]);
1361 for(
auto it = range.first; it != range.second; ++it) {
1362 if(!a_hasProperty(it->second, Cell::IsPeriodic) && !a_hasProperty(it->second, Cell::IsHalo)) {
1363 windowId = it->second;
1366 ASSERT(windowId > -2 && windowId < m_noInternalCells, to_string(windowId) +
" " + to_string(m_noInternalCells));
1368 ASSERT(a_level(windowId) == m_minLevel,
"");
1369 m_windowCells[i].push_back(windowId);
1370 sendGlobalIds[i][k] = a_globalId(windowId);
1372 sendGlobalIds[i][k] = -1;
1378 sendReq.
fill(MPI_REQUEST_NULL);
1379 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1380 MPI_Issend(&sendGlobalIds[i][0], noWindows[m_nghbrDomains[i]], MPI_LONG, m_nghbrDomains[i], 35, mpiComm(),
1381 &sendReq[i], AT_,
"sendGlobalIds[i][0]");
1383 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1384 MPI_Recv(&recvGlobalIds[i][0], noHalos[m_nghbrDomains[i]], MPI_LONG, m_nghbrDomains[i], 35, mpiComm(),
1385 MPI_STATUS_IGNORE, AT_,
"recvGlobalIds[i][0]");
1387 if(noNeighborDomains() > 0)
MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
1391 posMapping.
fill(-1);
1392 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
1393 posMapping[cellId] = cellId;
1398 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1399 for(
MInt k = 0; k < noHalos[m_nghbrDomains[i]]; k++) {
1400 MInt cellId = halos[i][k];
1401 MLong globalId = recvGlobalIds[i][k];
1402 a_globalId(cellId) = globalId;
1404 ASSERT(cellId >= oldNoCells,
"Attempting to delete parent gap halo cell.");
1405 delFlag[cellId] = 1;
1406 posMapping[cellId] = -1;
1411 for(
MInt cellId = oldNoCells; cellId < m_tree.size(); cellId++) {
1412 if(delFlag[cellId]) {
1413 MInt otherCellId = deleteCell(cellId);
1414 if(otherCellId > -1) {
1415 ASSERT(delFlag[otherCellId] || posMapping[otherCellId] == otherCellId,
"");
1416 if(!delFlag[otherCellId]) posMapping[otherCellId] = cellId;
1417 delFlag[cellId] = delFlag[otherCellId];
1418 delFlag[otherCellId] = 0;
1424 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1425 m_haloCells.push_back(vector<MInt>());
1426 for(
MInt k = 0; k < noHalos[m_nghbrDomains[i]]; k++) {
1427 MLong globalId = recvGlobalIds[i][k];
1429 ASSERT(posMapping[halos[i][k]] > -1,
"");
1430 MInt cellId = posMapping[halos[i][k]];
1431 ASSERT(cellId > -1 && cellId < m_tree.size(),
"");
1432 ASSERT(a_globalId(cellId) == globalId,
"");
1433 m_haloCells[i].push_back(cellId);
1439 for(
MInt i = 0; i < nDim; i++) {
1440 if(m_periodicCartesianDir[i] > 0) {
1441 m_periodicCartesianLength[i] = bbox[nDim + i] - bbox[i];
1443#ifdef MAIA_PGI_COMPILER
1444 m_periodicCartesianLength[i] = numeric_limits<MFloat>::quiet_NaN();
1446 m_periodicCartesianLength[i] = numeric_limits<MFloat>::signaling_NaN();
1451 IF_CONSTEXPR(nDim == 3) {
1452 if(m_azimuthalPer) {
1455 for(
MInt i = 0; i < nDim; i++) {
1456 MFloat dirLength = bbox[i + nDim] - bbox[i];
1457 MInt nBins = (
MInt)(dirLength / cellLengthAtLevel(m_minLevel));
1458 m_azimuthalBbox.minCoord[i] = bbox[i];
1459 m_azimuthalBbox.boxLength[i] = dirLength;
1460 m_azimuthalBbox.nBins[i] = nBins;
1463 m_azimuthalBbox.init(m_azimuthalAngle, m_azimuthalPeriodicDir[0], m_azimuthalPeriodicDir[1], m_noHaloLayers);
1464 MInt perSize1 = m_azimuthalBbox.nBins[m_azimuthalBbox.perDir1];
1465 MInt perSize2 = m_azimuthalBbox.nBins[m_azimuthalBbox.perDir2];
1467 minPer1.
fill(std::numeric_limits<MFloat>::max());
1469 maxPer1.
fill(-std::numeric_limits<MFloat>::max());
1471 minPer2.
fill(std::numeric_limits<MFloat>::max());
1473 maxPer2.
fill(-std::numeric_limits<MFloat>::max());
1476 minPer3.
fill(std::numeric_limits<MFloat>::max());
1478 maxPer3.
fill(-std::numeric_limits<MFloat>::max());
1481 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
1482 if(a_level(cellId) != m_minLevel)
continue;
1484 MInt ind1 = m_azimuthalBbox.index(&a_coordinate(cellId, 0), m_azimuthalBbox.perDir1);
1485 MInt ind2 = m_azimuthalBbox.index(&a_coordinate(cellId, 0), m_azimuthalBbox.perDir2);
1486 cartesianToCylindric(&a_coordinate(cellId, 0), coordsCyl);
1487 minPer1[ind1] =
mMin(coordsCyl[1], minPer1[ind1]);
1488 maxPer1[ind1] =
mMax(coordsCyl[1], maxPer1[ind1]);
1489 minPer2[ind2] =
mMin(coordsCyl[1], minPer2[ind2]);
1490 maxPer2[ind2] =
mMax(coordsCyl[1], maxPer2[ind2]);
1492 minPer3[ind1 * perSize2 + ind2] =
mMin(coordsCyl[1], minPer3[ind1 * perSize2 + ind2]);
1493 maxPer3[ind1 * perSize2 + ind2] =
mMax(coordsCyl[1], maxPer3[ind1 * perSize2 + ind2]);
1495 MPI_Allreduce(MPI_IN_PLACE, &minPer1[0], perSize1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
1497 MPI_Allreduce(MPI_IN_PLACE, &maxPer1[1], perSize1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1499 MPI_Allreduce(MPI_IN_PLACE, &minPer2[0], perSize2, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
1501 MPI_Allreduce(MPI_IN_PLACE, &maxPer2[1], perSize2, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1504 MPI_Allreduce(MPI_IN_PLACE, &minPer3[0], perSize1 * perSize2, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
1506 MPI_Allreduce(MPI_IN_PLACE, &maxPer3[1], perSize1 * perSize2, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
1509 MFloat minPhi = minPer1[0];
1510 MFloat maxPhi = maxPer1[0];
1511 for(
MInt p = 0; p < perSize1; p++) {
1512 minPhi =
mMin(minPhi, minPer1[p]);
1513 maxPhi =
mMax(maxPhi, maxPer1[p]);
1515 for(
MInt p = 0; p < perSize2; p++) {
1516 minPhi =
mMin(minPhi, minPer2[p]);
1517 maxPhi =
mMax(maxPhi, maxPer2[p]);
1519 MFloat center = F1B2 * (minPhi + maxPhi);
1521 std::copy_n(&minPer3[0], perSize1 * perSize2, &m_azimuthalBbox.minPer3[0]);
1522 std::copy_n(&maxPer3[0], perSize1 * perSize2, &m_azimuthalBbox.maxPer3[0]);
1523 m_azimuthalBbox.center = center;
1528 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1530 hilbertIds[i].clear();
1532 hilbertToLocal.clear();
1533 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
1534 if(a_level(cellId) != m_minLevel)
continue;
1535 const MLong hilbertId = hilbertIndexGeneric(&a_coordinate(cellId, 0));
1536 hilbertToLocal.insert(make_pair(hilbertId, cellId));
1542 while(cnt < interfaceCells.size()) {
1543 fill(&ifcDirs[0], &ifcDirs[0] + m_noDirs, 0);
1544 const MInt cellId = interfaceCells[cnt].first;
1545 while(cnt < interfaceCells.size() && cellId == interfaceCells[cnt].first) {
1546 ifcDirs[interfaceCells[cnt].second] = 1;
1550 cellList[cellCnt] = cellId;
1551 cellLayer[cellCnt++] = 0;
1552 for(
MInt dim = 0; dim < nDim; dim++) {
1553 const MInt cellCnt0 = cellCnt;
1554 for(
MInt ori = 0; ori < 2; ori++) {
1555 const MInt dir = 2 * dim + ori;
1556 if(!ifcDirs[dir])
continue;
1557 for(
MInt c = 0; c < cellCnt0; c++) {
1558 MInt nextId = cellList[c];
1559 MInt startLayer = cellLayer[c];
1560 for(
MInt layer = startLayer; layer < m_noHaloLayers; layer++) {
1561 if(a_hasNeighbor(nextId, dir) > 0)
1562 nextId = a_neighborId(nextId, dir);
1564 nextId = createAzimuthalHaloCell(nextId, dir, &hilbertOffsets[0], hilbertToLocal, bbox, &noHalos[0],
1566 if(nextId < 0)
break;
1567 cellList[cellCnt] = nextId;
1568 cellLayer[cellCnt++] = layer;
1575 MPI_Alltoall(&noHalos[0], 1, MPI_INT, &noWindows[0], 1, MPI_INT, mpiComm(), AT_,
"noHalos[0]",
"noWindows[0]");
1577 for(
MInt i = 0; i < noDomains(); i++) {
1578 if(noHalos[i] == 0 && noWindows[i] > 0) {
1579 setAzimuthalNeighborDomainIndex(i, halos, hilbertIds);
1584 sendReqAzi.
fill(MPI_REQUEST_NULL);
1585 recvHilbertIds.resize(noAzimuthalNeighborDomains());
1586 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1587 ASSERT(m_azimuthalNghbrDomains[i] > -1 && m_azimuthalNghbrDomains[i] < noDomains(),
"");
1588 recvHilbertIds[i].resize(noWindows[m_azimuthalNghbrDomains[i]]);
1590 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1591 for(
MInt k = 0; k < noHalos[m_azimuthalNghbrDomains[i]]; k++) {
1592 ASSERT(hilbertIds[i][k] >= hilbertOffsets[m_azimuthalNghbrDomains[i]]
1593 && hilbertIds[i][k] < hilbertOffsets[m_azimuthalNghbrDomains[i] + 1],
1594 to_string(hilbertIds[i][k]) +
" " + to_string(hilbertOffsets[m_azimuthalNghbrDomains[i]]) +
" "
1595 + to_string(hilbertOffsets[m_azimuthalNghbrDomains[i] + 1]));
1598 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1599 MPI_Issend(&hilbertIds[i][0], noHalos[m_azimuthalNghbrDomains[i]], MPI_LONG, m_azimuthalNghbrDomains[i], 34,
1600 mpiComm(), &sendReqAzi[i], AT_,
"hilbertIds[i][0]");
1602 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1603 MPI_Recv(&recvHilbertIds[i][0], noWindows[m_azimuthalNghbrDomains[i]], MPI_LONG, m_azimuthalNghbrDomains[i], 34,
1604 mpiComm(), MPI_STATUS_IGNORE, AT_,
"recvHilbertIds[i][0]");
1606 if(noAzimuthalNeighborDomains() > 0)
1607 MPI_Waitall(noAzimuthalNeighborDomains(), &sendReqAzi[0], MPI_STATUSES_IGNORE, AT_);
1608 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1609 for(
MInt k = 0; k < noWindows[m_azimuthalNghbrDomains[i]]; k++) {
1610 ASSERT(recvHilbertIds[i][k] >= hilbertOffsets[domainId()]
1611 && recvHilbertIds[i][k] < hilbertOffsets[domainId() + 1],
1616 sendGlobalIds.resize(noAzimuthalNeighborDomains());
1617 recvGlobalIds.resize(noAzimuthalNeighborDomains());
1618 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1619 ASSERT(m_azimuthalNghbrDomains[i] > -1 && m_azimuthalNghbrDomains[i] < noDomains(),
"");
1620 sendGlobalIds[i].resize(noWindows[m_azimuthalNghbrDomains[i]]);
1621 recvGlobalIds[i].resize(noHalos[m_azimuthalNghbrDomains[i]]);
1624 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1625 m_azimuthalWindowCells.push_back(vector<MInt>());
1626 for(
MInt k = 0; k < noWindows[m_azimuthalNghbrDomains[i]]; k++) {
1628 auto range = hilbertToLocal.equal_range(recvHilbertIds[i][k]);
1629 for(
auto it = range.first; it != range.second; ++it) {
1630 if(!a_hasProperty(it->second, Cell::IsPeriodic) && !a_hasProperty(it->second, Cell::IsHalo)) {
1631 windowId = it->second;
1634 ASSERT(windowId > -2 && windowId < m_noInternalCells,
1635 to_string(windowId) +
" " + to_string(m_noInternalCells));
1637 ASSERT(a_level(windowId) == m_minLevel,
"");
1638 m_azimuthalWindowCells[i].push_back(windowId);
1639 sendGlobalIds[i][k] = a_globalId(windowId);
1641 sendGlobalIds[i][k] = -1;
1647 sendReqAzi.
fill(MPI_REQUEST_NULL);
1648 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1649 MPI_Issend(&sendGlobalIds[i][0], noWindows[m_azimuthalNghbrDomains[i]], MPI_LONG, m_azimuthalNghbrDomains[i],
1650 35, mpiComm(), &sendReqAzi[i], AT_,
"sendGlobalIds[i][0]");
1652 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1653 MPI_Recv(&recvGlobalIds[i][0], noHalos[m_azimuthalNghbrDomains[i]], MPI_LONG, m_azimuthalNghbrDomains[i], 35,
1654 mpiComm(), MPI_STATUS_IGNORE, AT_,
"recvGlobalIds[i][0]");
1656 if(noAzimuthalNeighborDomains() > 0)
1657 MPI_Waitall(noAzimuthalNeighborDomains(), &sendReqAzi[0], MPI_STATUSES_IGNORE, AT_);
1660 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1661 m_azimuthalHaloCells.push_back(vector<MInt>());
1662 for(
MInt k = 0; k < noHalos[m_azimuthalNghbrDomains[i]]; k++) {
1663 MInt cellId = halos[i][k];
1664 MLong globalId = recvGlobalIds[i][k];
1666 ASSERT(cellId > -1 && cellId < m_tree.size(),
"");
1667 a_globalId(cellId) = globalId;
1668 m_azimuthalHaloCells[i].push_back(cellId);
1670 ASSERT(cellId > -1 && cellId < m_tree.size(),
"");
1671 a_globalId(cellId) = -1;
1672 m_azimuthalUnmappedHaloCells.push_back(cellId);
1673 m_azimuthalUnmappedHaloDomains.push_back(m_azimuthalNghbrDomains[i]);
1681 std::vector<MInt>().swap(m_gridBndryCells);
1682 MBool adaptation =
false;
1683 adaptation = Context::getBasicProperty<MBool>(
"adaptation", AT_, &adaptation);
1686 cerr << endl <<
"Azimuthal periodic cells are not refined at grid bndry if adaption is on!" << endl;
1688 if(domainId() == 0) cerr <<
"Set gridBndryCells on minLevel." << endl;
1690 gridBndryCells.
fill(-1);
1691 MBool isBndry =
false;
1692 for(
MInt cellId = 0; cellId < oldNoCells; cellId++) {
1693 if(a_level(cellId) != m_minLevel)
continue;
1695 for(
MInt dir = 0; dir < m_noDirs; dir++) {
1696 if(a_hasNeighbor(cellId, dir) > 0)
continue;
1697 if(!m_periodicCartesianDir[dir / 2]) {
1699 for(
MInt d = 0; d < nDim; d++) {
1700 coords[d] = a_coordinate(cellId, d);
1702 coords[dir / 2] += ((dir % 2) == 0 ? -F1 : F1) * cellLengthAtLevel(m_minLevel);
1703 if(coords[dir / 2] < bbox[dir / 2] || coords[dir / 2] > bbox[nDim + dir / 2])
continue;
1708 if(!a_isHalo(cellId)) m_gridBndryCells.push_back(cellId);
1709 gridBndryCells[cellId] = 1;
1710 for(
MInt dir = 0; dir < m_noDirs; dir++) {
1711 if(a_hasNeighbor(cellId, dir) > 0) {
1712 MInt nghbrId = a_neighborId(cellId, dir);
1713 if(!a_isHalo(nghbrId)) m_gridBndryCells.push_back(nghbrId);
1714 gridBndryCells[nghbrId] = 1;
1720 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1721 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1722 if(gridBndryCells[m_windowCells[i][j]] == 1) {
1723 m_gridBndryCells.push_back(m_windowCells[i][j]);
1738 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1739 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
1740 ASSERT(!a_hasProperty(m_haloCells[i][j], Cell::IsWindow),
"halo cell is marked as window");
1741 a_hasProperty(m_haloCells[i][j], Cell::IsHalo) =
true;
1743 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1744 ASSERT(!a_isHalo(m_windowCells[i][j]),
"window cell is marked as halo");
1745 a_hasProperty(m_windowCells[i][j], Cell::IsWindow) =
true;
1748 if(m_azimuthalPer) {
1749 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1750 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
1751 ASSERT(!a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsWindow),
"azimuthal halo cell is marked as window");
1752 a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsHalo) =
true;
1754 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
1755 ASSERT(!a_isHalo(m_azimuthalWindowCells[i][j]),
"azimuthal window cell is marked as halo");
1756 a_hasProperty(m_azimuthalWindowCells[i][j], Cell::IsWindow) =
true;
1759 for(
MInt j = 0; j < noAzimuthalUnmappedHaloCells(); j++) {
1760 ASSERT(!a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsWindow),
1761 "azimuthal halo cell is marked as window");
1762 a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsHalo) =
true;
1766 if(m_haloMode > 0) {
1767 tagActiveWindowsAtMinLevel(m_minLevel);
1769 checkWindowLayer(
"tagActiveWindowsAtMinLevel completed: ");
1774 exchangeSolverBitset(&m_tree.solverBits(0));
1777 if(m_haloMode == 2) {
1778 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1779 std::vector<MInt> haloCells;
1780 haloCells.reserve(m_haloCells[i].size());
1781 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
1782 const MInt haloCellId = m_haloCells[i][j];
1783 if(m_tree.solverBits(haloCellId).any())
1784 haloCells.push_back(haloCellId);
1786 removeCell<false>(haloCellId);
1789 m_haloCells[i] = haloCells;
1792 std::vector<MInt> windowCells;
1793 windowCells.reserve(m_windowCells[i].size());
1794 std::set<MInt> erased;
1795 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1796 const MInt windowCellId = m_windowCells[i][j];
1797 ASSERT(m_windowLayer_[i].find(windowCellId) != m_windowLayer_[i].end()
1798 || erased.find(windowCellId) != erased.end(),
1800 MBool validWindow =
false;
1801 for(
MInt solverId = 0; solverId < treeb().noSolvers(); ++solverId) {
1802 if(isSolverWindowCell(i, windowCellId, solverId)) {
1803 windowCells.push_back(windowCellId);
1809 const MBool ok = m_windowLayer_[i].erase(windowCellId);
1810 ASSERT(ok || erased.find(windowCellId) != erased.end(),
"");
1811 erased.insert(windowCellId);
1812 MBool isWindow =
false;
1813 for(
const auto& w : m_windowLayer_) {
1814 if(w.find(windowCellId) != w.end()) {
1819 if(!isWindow) a_hasProperty(windowCellId, Cell::IsWindow) =
false;
1822 m_windowCells[i] = windowCells;
1830 checkWindowHaloConsistency(
false,
"createMinLevelExchangeCells completed: ");
1835 cerr0 <<
" done." << endl;
1849 const MInt onlyLevel,
const MBool duringMeshAdaptation,
1850 const std::vector<std::function<
void(
const MInt)>>& refineCellSolver,
const std::vector<std::function<
void(
const MInt)>>& removeCellSolver,
const MBool forceLeafLvlCorrection) {
1853 auto logDuration = [
this] (
const MFloat timeStart,
const MString comment) {
1854 logDuration_(timeStart,
"WINDOW/HALO HIGHER LEVEL", comment, mpiComm(), domainId(), noDomains());
1858 vector<MLong> refineChildIds;
1859 vector<MLong> recvChildIds;
1860 vector<vector<MInt>> haloMap;
1861 vector<vector<MInt>> windMap;
1862 vector<MInt> refineIds;
1864 if(domainId() == 0 && onlyLevel < 0) cerr <<
" * create higher level exchange cells...";
1867 if(m_maxPartitionLevelShift > 0) {
1868 for(
MUint i = 0; i < m_partitionLevelAncestorIds.size(); i++) {
1869 plaMap[m_partitionLevelAncestorIds[i]] = i;
1873 if(m_azimuthalPer && onlyLevel <= m_minLevel) {
1874 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
1875 m_azimuthalHigherLevelConnectivity[i].clear();
1881 for(
MInt level = m_minLevel; level < m_maxLevel; level++) {
1882 if(onlyLevel > -1 && onlyLevel != level)
continue;
1887 checkWindowHaloConsistency(
false,
"createHigherLevelExchangeCells level=" + to_string(level) +
": ");
1893 haloMap.resize(noNeighborDomains());
1894 windMap.resize(noNeighborDomains());
1898 vector<std::set<MInt>> haloCellSet(noNeighborDomains());
1899 vector<std::set<MInt>> windCellSet(noNeighborDomains());
1901 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1902 haloMap[i].resize(m_haloCells[i].size());
1903 windMap[i].resize(m_windowCells[i].size());
1904 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
1905 haloMap[i][j] = haloCnt++;
1907 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1908 windMap[i][j] = windowCnt++;
1911 haloCellSet[i].insert(m_haloCells[i].begin(), m_haloCells[i].end());
1912 windCellSet[i].insert(m_windowCells[i].begin(), m_windowCells[i].end());
1915 recvChildIds.resize(haloCnt * m_maxNoChilds);
1916 fill(recvChildIds.begin(), recvChildIds.end(), -1);
1917 refineChildIds.clear();
1918 refineChildIds.resize(windowCnt * m_maxNoChilds);
1919 fill(refineChildIds.begin(), refineChildIds.end(), -1);
1922 for (
MInt cellId = 0; cellId < m_tree.size(); ++cellId) {
1923 if (!a_isToDelete(cellId)) {
1924 if (a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPeriodic)) {
1925 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
1926 const MInt maxNghbrDomId =
1927 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
1928 if (domainId()>=minNghbrDomId && domainId()<=maxNghbrDomId) {
1929 TERMM_IF_NOT_COND(a_hasChildren(cellId),
"d=" + to_string(domainId()) +
" nghbrs="
1930 + to_string(minNghbrDomId) +
"|" + to_string(maxNghbrDomId) +
" isHalo=" + to_string(a_isHalo(cellId)));
1936 TERMM_IF_COND(bitOffset() && m_maxPartitionLevelShift>0,
"Not a good idea to use bitOffset==true & partLvlShift!");
1938 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1939 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
1940 const MInt cellId = m_windowCells[i][j];
1942 if (!a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
1943 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
1945 const MInt maxNghbrDomId =
1946 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)std::max(1,a_noOffsprings(cellId))-1));
1947 TERMM_IF_NOT_COND(minNghbrDomId==maxNghbrDomId && minNghbrDomId==domainId(),
1948 "Window cell is not partLvlAncestor, but seems to have children on different domains!");
1962 if (m_maxPartitionLevelShift>0) {
1964 std::set<MInt> partLvlAncSet;
1965 for(
MUint i = 0; i < m_partitionLevelAncestorIds.size(); i++) {
1966 const MInt cellId = m_partitionLevelAncestorIds[i];
1967 if (a_level(cellId)!=level)
continue;
1969 ASSERT(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
1970 "not a partition level ancestor: cellId" + std::to_string(cellId) +
" halo"
1971 + std::to_string(a_hasProperty(cellId, Cell::IsHalo)) +
" domain" + std::to_string(domainId()));
1972 ASSERT(a_hasProperty(cellId, Cell::IsHalo) || findNeighborDomainId(a_globalId(cellId)) == domainId(),
"");
1973 ASSERT(a_noChildren(cellId)>0,
"PartLvlAncestor cell must have children!");
1974 ASSERT((
signed)i==plaMap[cellId],
"");
1978 std::set<MInt> nghbrDomIds;
1979 for(
MInt child = 0; child < m_maxNoChilds; child++) {
1980 if(m_partitionLevelAncestorChildIds[i * m_maxNoChilds + child] > -1) {
1981 nghbrDomIds.insert(findNeighborDomainId(m_partitionLevelAncestorChildIds[i * m_maxNoChilds + child]));
1984 const MBool multikultiCell = nghbrDomIds.size()>1;
1986 const MInt noChildren = a_noChildren(cellId);
1987 if(multikultiCell) {
1988 partLvlAncSet.insert(cellId);
1990 MLong* childIds = &m_partitionLevelAncestorChildIds[i * m_maxNoChilds];
1991 if(accumulate(childIds, childIds + m_maxNoChilds,
static_cast<MLong>(-1),
1994 refineCell(cellId, childIds, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
1997 if (a_noChildren(cellId)>noChildren)
1998 refineIds.push_back(cellId);
2000 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2001 const MInt childId = a_childId(cellId, child);
2002 if(childId < 0)
continue;
2004 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2005 ASSERT(a_globalId(childId) > -1,
"");
2006 const MInt ndom = findNeighborDomainId(a_globalId(childId));
2007 ASSERT(ndom > -1,
"");
2009 if (a_isHalo(childId)) {
2011 ASSERT(ndom!=domainId(),
"");
2013 ASSERT(ndom==domainId(),
"");
2016 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
2044 vector<MInt> sendDomIdx;
2045 vector<M32X4bit<>::type> sendData;
2047 fill(cellFlag.
begin(), cellFlag.
end(),
false);
2048 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2049 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
2050 const MInt cellId = m_windowCells[i][j];
2051 ASSERT(m_windowLayer_[i].find(cellId)!=m_windowLayer_[i].end(),
"");
2053 if (partLvlAncSet.find(cellId)!=partLvlAncSet.end()) {
2054 ASSERT(a_level(cellId) == level && a_noChildren(cellId) > 0,
"");
2056 std::set<MInt> nghbrs;
2058 MBool windowChild =
false;
2059 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2060 const MInt cnt = windMap[i][j];
2063 const MInt pId = plaMap[cellId];
2065 if(m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child] > -1) {
2066 refineChildIds[m_maxNoChilds * cnt + child] = m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child];
2067 const MInt domainChild = findNeighborDomainId(m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child]);
2068 if (domainChild != domainId()) {
2069 nghbrs.insert(domainChild);
2072 const MInt childId = a_childId(cellId, child);
2073 ASSERT(childId>-1,
" ");
2075 TERMM_IF_COND(windowsTemp.find(std::make_pair(m_nghbrDomains[i],childId))!=windowsTemp.end()
2076 && m_noPeriodicCartesianDirs==0,
" ");
2077 M32X4bit<true> windowLayer = m_windowLayer_[i].find(childId)!=m_windowLayer_[i].end()
2078 ? m_windowLayer_[i].at(childId) : m_windowLayer_[i].at(cellId);
2079 windowsTemp.insert({std::make_pair(m_nghbrDomains[i],childId), windowLayer});
2083 ASSERT(windowChild,
"At least one child must reside on current domain!");
2084 ASSERT(nghbrs.size()>0,
"At least one child must reside on a different domain!");
2086 for (
const auto ndom : nghbrs) {
2087 const MInt idx = findIndex(m_nghbrDomains.begin(), m_nghbrDomains.end(), ndom);
2088 ASSERT(idx > -1,
"");
2089 ASSERT(m_nghbrDomains[idx] == ndom,
"");
2094 if (ndom != m_nghbrDomains[i] || m_noPeriodicCartesianDirs>0) {
2095 sendDomIdx.push_back(idx);
2096 sendData.push_back(m_nghbrDomains[i]);
2097 sendData.push_back(a_globalId(cellId));
2099 sendData.push_back(windowLayer.
data());
2101 if (!cellFlag[cellId]) {
2102 sendDomIdx.push_back(idx);
2103 sendData.push_back(domainId());
2104 sendData.push_back(a_globalId(cellId));
2106 sendData.push_back(windowLayer.
data());
2109 cellFlag[cellId] =
true;
2115 vector<MInt> recvOffs;
2116 vector<M32X4bit<>::type> recvData;
2120 const MInt noNgbrDomainsBak = noNeighborDomains();
2121 for(
MInt i = 0; i < noNgbrDomainsBak; i++) {
2122 set<MInt> check4PeriodicHalos;
2123 for(
MInt j = recvOffs[i]; j < recvOffs[i + 1]; j++) {
2124 auto ndom =
static_cast<MInt>(recvData[3 * j]);
2125 const MLong globalCellId = recvData[3 * j + 1];
2126 if (ndom==domainId()) {
2128 ASSERT(m_noPeriodicCartesianDirs>0,
"");
2129 if (check4PeriodicHalos.find(globalCellId)==check4PeriodicHalos.end()) {
2130 check4PeriodicHalos.insert(globalCellId);
2134 auto windowLayer = recvData[3 * j + 2];
2135 ASSERT(ndom>-1,
"");
2136 ASSERT(m_globalToLocalId.find(globalCellId)!=m_globalToLocalId.end(),
"");
2137 const MInt cellId = m_globalToLocalId[globalCellId];
2138 ASSERT(cellId > -1,
"");
2139 ASSERT(a_globalId(cellId) == globalCellId,
"");
2140 ASSERT(findNeighborDomainId(globalCellId) != domainId(),
"");
2153 MBool foundWindow =
false;
2154 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2155 const MInt childId = a_childId(cellId, child);
2156 if(childId < 0 || a_isHalo(childId))
continue;
2160 ASSERT(windowsTemp.find(std::make_pair(ndom,childId))==windowsTemp.end()
2161 || m_noPeriodicCartesianDirs>0,
" ");
2165 windowsTemp.insert({std::make_pair(ndom,childId),
M32X4bit<true>(windowLayer)});
2167 ASSERT(foundWindow,
"");
2175 std::vector<MInt> nghbrDomains(m_nghbrDomains);
2177 tagActiveWindows2_(refineChildIds, level);
2180 haloCellSet.resize(noNeighborDomains());
2181 windCellSet.resize(noNeighborDomains());
2185#pragma omp parallel for
2187 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2188 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
2189 const MInt cellId = m_windowCells[i][j];
2191 if(a_level(cellId) == level && a_noChildren(cellId) > 0) {
2192 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2193 const MInt cnt = windMap[i][j];
2195 if(refineChildIds[m_maxNoChilds * cnt + child] > 0) {
2196 const MInt childId = a_childId(cellId, child);
2197 ASSERT(childId > -1,
"");
2198 ASSERT((a_globalId(
static_cast<MInt>(childId)) >= m_domainOffsets[domainId()]
2199 && a_globalId(
static_cast<MInt>(childId)) < m_domainOffsets[domainId() + 1])
2200 || a_hasProperty(cellId, Cell::IsPartLvlAncestor),
2201 to_string(a_globalId(
static_cast<MInt>(childId))) +
" "
2202 + to_string(m_domainOffsets[domainId()]) +
" " + to_string(m_domainOffsets[domainId() + 1]));
2203 refineChildIds[m_maxNoChilds * cnt + child] = a_globalId(
static_cast<MInt>(childId));
2215 refineChildIds.data(),
2216 recvChildIds.data(),
2220 if(m_maxPartitionLevelShift > 0) {
2221 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2222 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
2223 MInt cellId = m_haloCells[i][j];
2224 if(a_level(cellId) == level) {
2225 MInt pId = plaMap[cellId];
2226 if(m_maxPartitionLevelShift > 0 && pId > -1) {
2227 MInt cnt = haloMap[i][j];
2228 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2229 const MLong childId = m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child];
2230 ASSERT(childId == recvChildIds[m_maxNoChilds * cnt + child],
2231 std::to_string(childId) +
" != " + std::to_string(recvChildIds[m_maxNoChilds * cnt + child])
2232 +
"; c" + std::to_string(cellId) +
"; g" + std::to_string(a_globalId(cellId)) +
"; p"
2233 + std::to_string(pId));
2244 if (m_maxPartitionLevelShift>0) {
2245 for (
const auto& item : windowsTemp) {
2247 const MInt ndom = item.first.first;
2249 const MInt childId = item.first.second;
2250 ASSERT(a_hasProperty(a_parentId(childId), Cell::IsPartLvlAncestor),
"");
2252 const MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells, m_windowLayer_);
2253 ASSERT(idx > -1,
"");
2255 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
"");
2258 if(idx ==
static_cast<MInt>(windCellSet.size())) {
2259 windCellSet.emplace_back();
2260 haloCellSet.emplace_back();
2263 if (m_noPeriodicCartesianDirs==0) {
2264 if(windCellSet[idx].find(childId) != windCellSet[idx].end())
2269 if ((
signed)windowsTemp.count(std::make_pair(ndom,childId))<=std::count(m_windowCells[idx].begin(), m_windowCells[idx].end(), childId))
2273 m_windowCells[idx].push_back(childId);
2274 windCellSet[idx].insert(childId);
2276 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2277 if (m_tree.solver(childId, solver) && !isSolverWindowCell(idx,childId,solver) && windowLayer.
get(solver)<=m_noSolverHaloLayers[solver]) {
2278 const MInt w = std::max(windowLayer.
get(solver), m_noSolverHaloLayers[solver]);
2279 m_windowLayer_[idx][childId].set(solver, w);
2284 if (m_windowLayer_[idx].find(childId)==m_windowLayer_[idx].end()) {
2285 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2291 const MInt w = m_tree.solver(childId, solver) ?
2292 std::max(windowLayer.
get(solver), m_noSolverHaloLayers[solver]):
2293 m_noSolverHaloLayers[solver]+1;
2294 m_windowLayer_[idx][childId].set(solver, w);
2303 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2304 if (m_windowCells[i].size()==0)
continue;
2305 vector<MInt> oldWindowVec(m_windowCells[i]);
2306 std::set<MInt> oldWindCellSet(windCellSet[i]);
2308 std::vector<MInt>().swap(m_windowCells[i]);
2309 windCellSet[i].clear();
2311 for(
MInt j = 0; j < (signed)oldWindowVec.size(); j++) {
2312 MInt cellId = oldWindowVec[j];
2314 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet[i].find(cellId) == windCellSet[i].end(),
2315 "duplicate window cell: " + std::to_string(cellId) +
" " + std::to_string(a_globalId(cellId)) +
" "
2316 + std::to_string(j));
2318 m_windowCells[i].push_back(cellId);
2319 windCellSet[i].insert(cellId);
2321 ASSERT(cellId < m_tree.size(), to_string(level));
2323 if(a_level(cellId) == level && a_noChildren(cellId) > 0) {
2324 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2325 MInt cnt = windMap[i][j];
2327 const MInt childId = a_childId(cellId, child);
2328 if(childId < 0)
continue;
2332 if(oldWindCellSet.find(childId) != oldWindCellSet.end()) {
2333 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
2334 "not a partition level ancestor or partition cell");
2338 const MLong globalChildId = refineChildIds[m_maxNoChilds * cnt + child];
2339 if(globalChildId > -1) {
2340 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2343 MInt ndom = findNeighborDomainId(globalChildId);
2344 if(ndom == domainId()) {
2345 ASSERT(globalChildId == a_globalId(childId),
"");
2347 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet[i].find(childId) == windCellSet[i].end(),
2348 "duplicate window cell: " + std::to_string(childId));
2350 m_windowCells[i].push_back(childId);
2363 MBool validWindow =
false;
2364 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2365 if (isSolverWindowCell(i,childId,solver)) {
2370 TERMM_IF_NOT_COND(validWindow,
"");
2373 windCellSet[i].insert(childId);
2383 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2384 if (m_haloCells[i].size()==0)
continue;
2385 vector<MInt> oldHaloVec(m_haloCells[i]);
2386 std::set<MInt> oldHaloCellSet(haloCellSet[i]);
2388 std::vector<MInt>().swap(m_haloCells[i]);
2389 haloCellSet[i].clear();
2391 for(
MInt j = 0; j < (signed)oldHaloVec.size(); j++) {
2392 MInt cellId = oldHaloVec[j];
2394 ASSERT(haloCellSet[i].find(cellId) == haloCellSet[i].end(),
2395 "duplicate halo cell: " + std::to_string(cellId) +
" " + std::to_string(a_globalId(cellId)) +
" "
2396 + std::to_string(j));
2398 m_haloCells[i].push_back(cellId);
2399 haloCellSet[i].insert(cellId);
2401 if(a_level(cellId) == level) {
2402 MInt cnt = haloMap[i][j];
2404 if(accumulate(&recvChildIds[m_maxNoChilds * cnt], &recvChildIds[m_maxNoChilds * cnt] + m_maxNoChilds,
2407 refineCell(cellId, &recvChildIds[m_maxNoChilds * cnt], a_hasProperty(cellId, Cell::IsPartLvlAncestor));
2408 refineIds.push_back(cellId);
2410 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2411 const MInt childId = a_childId(cellId, child);
2412 if(childId < 0)
continue;
2415 if(oldHaloCellSet.find(childId) != oldHaloCellSet.end()) {
2416 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
2417 "not a partition level ancestor or partition cell");
2421 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2422 ASSERT(a_globalId(childId) > -1,
"");
2423 MInt ndom = findNeighborDomainId(a_globalId(childId));
2424 ASSERT(ndom > -1,
"");
2425 if(recvChildIds[m_maxNoChilds * cnt + child] > -1)
2426 ASSERT(a_globalId(childId) == recvChildIds[m_maxNoChilds * cnt + child],
"");
2427 if(recvChildIds[m_maxNoChilds * cnt + child] < 0) ASSERT(ndom == domainId(),
"");
2428 if(ndom == m_nghbrDomains[i]) {
2429 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
2431 if(haloCellSet[i].find(childId) != haloCellSet[i].end()) {
2436 m_haloCells[i].push_back(childId);
2437 haloCellSet[i].insert(childId);
2438 }
else if(m_maxPartitionLevelShift > 0) {
2442 if (ndom==domainId() && a_hasProperty(cellId, Cell::IsPeriodic))
2443 TERMM_IF_NOT_COND(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
"");
2447 if(ndom != domainId() || a_hasProperty(cellId, Cell::IsPeriodic)) {
2448 const MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells, m_windowLayer_);
2449 ASSERT(idx > -1,
"");
2452 if(idx ==
static_cast<MInt>(windCellSet.size())) {
2453 windCellSet.emplace_back();
2454 haloCellSet.emplace_back();
2457 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
2459 if(haloCellSet[idx].find(childId) != haloCellSet[idx].end()) {
2464 m_haloCells[idx].push_back(childId);
2465 haloCellSet[idx].insert(childId);
2468 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
2470 if(a_noChildren(cellId) == 0)
mTerm(1, AT_,
"all children gone");
2477 if(m_maxPartitionLevelShift > 0) {
2478 for(
MUint i = 0; i < m_partitionLevelAncestorIds.size(); i++) {
2479 const MInt cellId = m_partitionLevelAncestorIds[i];
2481 ASSERT(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
2482 "not a partition level ancestor: cellId" + std::to_string(cellId) +
" halo"
2483 + std::to_string(a_hasProperty(cellId, Cell::IsHalo)) +
" domain" + std::to_string(domainId()));
2485 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
2486 ASSERT(findNeighborDomainId(a_globalId(cellId)) == domainId(),
"");
2487 if(a_level(cellId) == level) {
2488 MLong* childIds = &m_partitionLevelAncestorChildIds[i * m_maxNoChilds];
2489 if(accumulate(childIds, childIds + m_maxNoChilds,
static_cast<MLong>(-1),
2492 refineCell(cellId, childIds, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
2493 refineIds.push_back(cellId);
2495 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2496 const MInt childId = a_childId(cellId, child);
2497 if(childId < 0)
continue;
2498 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2499 a_globalId(childId) = childIds[child];
2500 MInt ndom = findNeighborDomainId(a_globalId(childId));
2501 ASSERT(ndom > -1,
"");
2502 if(ndom != domainId()) {
2503 MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells, m_windowLayer_);
2504 ASSERT(idx > -1,
"");
2507 if(idx ==
static_cast<MInt>(windCellSet.size())) {
2508 windCellSet.emplace_back();
2509 haloCellSet.emplace_back();
2512 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
2514 if(haloCellSet[idx].find(childId) != haloCellSet[idx].end()) {
2519 m_haloCells[idx].push_back(childId);
2520 haloCellSet[idx].insert(childId);
2522 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
2525 if(a_noChildren(cellId) == 0)
mTerm(1, AT_,
"all children gone");
2531 if(m_azimuthalPer) {
2532 refineChildIds.clear();
2533 recvChildIds.clear();
2536 tagAzimuthalHigherLevelExchangeCells(refineChildIds, recvChildIds, level);
2538 vector<vector<MLong>> shiftWindows;
2539 shiftWindows.resize(noDomains());
2540 MIntScratchSpace noShiftWindows(noNeighborDomains(), AT_,
"noShiftWindows");
2541 noShiftWindows.
fill(0);
2544 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
2545 vector<MInt> oldWindowVec(m_azimuthalWindowCells[i]);
2546 vector<MInt> oldHigherLevelCon(m_azimuthalHigherLevelConnectivity[i]);
2548 m_azimuthalWindowCells[i].clear();
2549 m_azimuthalHigherLevelConnectivity[i].clear();
2551 for(
MInt j = 0; j < (signed)oldWindowVec.size(); j++) {
2552 MInt cellId = oldWindowVec[j];
2554 if(find(oldHigherLevelCon.begin(), oldHigherLevelCon.end(), j) != oldHigherLevelCon.end()) {
2555 m_azimuthalHigherLevelConnectivity[i].push_back(m_azimuthalWindowCells[i].size());
2557 m_azimuthalWindowCells[i].push_back(cellId);
2559 ASSERT(cellId < m_tree.size(), to_string(level));
2561 if(a_level(cellId) == level) {
2562 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2563 const MLong globalChildId = refineChildIds[m_maxNoChilds * cnt + child];
2565 if(globalChildId > -1) {
2566 MInt ndom = findNeighborDomainId(globalChildId);
2572 if(ndom == domainId()) {
2573 const MInt childId = globalIdToLocalId(globalChildId,
true);
2574 if(level == m_minLevel && a_level(childId) <= m_minLevel) {
2575 m_azimuthalHigherLevelConnectivity[i].push_back(m_azimuthalWindowCells[i].size());
2577 m_azimuthalWindowCells[i].push_back(childId);
2579 ASSERT(m_nghbrDomainIndex[ndom] > -1,
"");
2580 shiftWindows[m_nghbrDomainIndex[ndom]].push_back(globalChildId);
2581 shiftWindows[m_nghbrDomainIndex[ndom]].push_back(azimuthalNeighborDomain(i));
2582 noShiftWindows[m_nghbrDomainIndex[ndom]]++;
2591 vector<vector<MInt>> shiftHalos;
2592 shiftHalos.resize(noDomains());
2593 vector<vector<MInt>> shiftHaloDoms;
2594 shiftHaloDoms.resize(noDomains());
2596 noShiftHalos.
fill(0);
2598 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
2599 vector<MInt> oldHaloVec(m_azimuthalHaloCells[i]);
2601 m_azimuthalHaloCells[i].clear();
2603 for(
MInt j = 0; j < (signed)oldHaloVec.size(); j++) {
2604 MInt cellId = oldHaloVec[j];
2606 m_azimuthalHaloCells[i].push_back(cellId);
2608 if(a_level(cellId) == level) {
2609 if(accumulate(&recvChildIds[m_maxNoChilds * cnt], &recvChildIds[m_maxNoChilds * cnt] + m_maxNoChilds,
2614 refineCell(cellId,
nullptr, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
2615 refineIds.push_back(cellId);
2617 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2618 const MInt childId = a_childId(cellId, child);
2619 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2620 a_hasProperty(childId, Cell::IsHalo) = a_hasProperty(cellId, Cell::IsHalo);
2621 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
2622 a_globalId(childId) = recvChildIds[m_maxNoChilds * cnt + child];
2623 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2624 treeb().solver(childId, solver) = treeb().solver(cellId, solver);
2629 if(a_globalId(childId) == -1) {
2630 m_azimuthalUnmappedHaloCells.push_back(childId);
2631 m_azimuthalUnmappedHaloDomains.push_back(azimuthalNeighborDomain(i));
2635 ASSERT(a_globalId(childId) > -1,
"");
2636 MInt ndom = findNeighborDomainId(a_globalId(childId));
2643 if(ndom == azimuthalNeighborDomain(i)) {
2644 m_azimuthalHaloCells[i].push_back(childId);
2646 shiftHalos[ndom].push_back(childId);
2647 shiftHaloDoms[ndom].push_back(azimuthalNeighborDomain(i));
2648 noShiftHalos[ndom]++;
2658 vector<vector<MLong>> newWindows;
2659 newWindows.resize(noNeighborDomains());
2661 noNewWindows.
fill(0);
2662 vector<MInt> noValsToReceive;
2663 noValsToReceive.assign(noNeighborDomains(), 1);
2667 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2668 newWindows[i].resize(2*noNewWindows[i]);
2672 sendReq.
fill(MPI_REQUEST_NULL);
2674 const MInt magic_mpi_tag = 12;
2675 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2676 if(noShiftWindows[i] == 0) {
continue;
2681 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2682 if(noNewWindows[i] == 0) {
continue;
2687 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2688 if(noShiftWindows[i] == 0) {
continue;
2690 MPI_Wait(&sendReq[i], MPI_STATUSES_IGNORE, AT_);
2694 for(
MInt i = 0; i < noDomains(); i++) {
2695 shiftWindows[i].clear();
2696 for(
MInt d = 0; d < noDomains(); d++) {
2697 MInt nghbrDomId = m_nghbrDomainIndex[d];
2698 if(nghbrDomId == -1) {
continue;
2700 for(
MInt j = 0; j < noNewWindows[nghbrDomId]; j++ ) {
2701 MInt haloDomain = newWindows[nghbrDomId][j*2 + 1];
2702 if(haloDomain == i) { shiftWindows[i].push_back(newWindows[nghbrDomId][j*2]);
2709 for(
MInt i = 0; i < noDomains(); i++) {
2710 for(
MUint j = 0; j < shiftWindows[i].size(); j++ ) {
2711 const MLong globalChildId = shiftWindows[i][j];
2712 ASSERT(findNeighborDomainId(globalChildId) == domainId(),
"Wrong domain!");
2714 const MInt childId = globalIdToLocalId(globalChildId,
true);
2715 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
2717 if(level == m_minLevel && a_level(childId) <= m_minLevel) {
2718 m_azimuthalHigherLevelConnectivity[idx].push_back(m_azimuthalWindowCells[idx].size());
2720 m_azimuthalWindowCells[idx].push_back(childId);
2725 for(
MInt i = 0; i < noDomains(); i++) {
2726 vector<MInt> shiftHalosBck(shiftHalos[i]);
2727 shiftHalos[i].clear();
2728 for(
MInt d = 0; d < noDomains(); d++) {
2729 for(
MInt j = 0; j < noShiftHalos[i]; j++ ) {
2730 MInt nghbrDomain = shiftHaloDoms[i][j];
2732 if(nghbrDomain == d) { shiftHalos[i].push_back(shiftHalosBck[j]);
2739 for(
MInt i = 0; i < noDomains(); i++) {
2740 for(
MInt j = 0; j < noShiftHalos[i]; j++ ) {
2741 const MInt childId = shiftHalos[i][j];
2742 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
2744 m_azimuthalHaloCells[idx].push_back(childId);
2749 if(!refineCellSolver.empty()) {
2750 if(domainId() == 0) { cerr <<
"Attention: Unmapped halo are not refined during adaptation!" << endl;
2753 shiftWindows.clear();
2754 recvChildIds.clear();
2755 vector<MInt> recvChildDomainIds;
2756 tagAzimuthalUnmappedHaloCells(shiftWindows, recvChildIds, recvChildDomainIds, level);
2762 for(
MInt i = 0; i < noDomains(); i++) {
2763 for(
MUint j = 0; j < shiftWindows[i].size(); j++ ) {
2764 const MLong globalChildId = shiftWindows[i][j];
2765 if(globalChildId < 0) {
continue;
2768 ASSERT(findNeighborDomainId(globalChildId) == domainId(),
"Wrong domain! " + to_string(globalChildId) +
" " + to_string(findNeighborDomainId(globalChildId)) +
" " + to_string(domainId()));
2770 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
2772 const MInt childId = globalIdToLocalId(globalChildId,
true);
2773 m_azimuthalWindowCells[idx].push_back(childId);
2781 MInt noUnmappedCells = noAzimuthalUnmappedHaloCells();
2782 for(
MInt i = 0; i < noUnmappedCells; i++ ) {
2783 MInt cellId = azimuthalUnmappedHaloCell(i);
2784 if(a_level(cellId) == level) {
2785 if(accumulate(&recvChildIds[m_maxNoChilds * i], &recvChildIds[m_maxNoChilds * i] + m_maxNoChilds,
2789 refineCell(cellId,
nullptr, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
2790 refineIds.push_back(cellId);
2792 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2793 const MInt childId = a_childId(cellId, child);
2795 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
2796 a_hasProperty(childId, Cell::IsHalo) = a_hasProperty(cellId, Cell::IsHalo);
2797 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
2798 a_globalId(childId) = recvChildIds[m_maxNoChilds * i + child];
2799 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2800 treeb().solver(childId, solver) = treeb().solver(cellId, solver);
2803 MInt dom = recvChildDomainIds[m_maxNoChilds * i + child];
2805 if(a_globalId(childId) == -1) {
2806 m_azimuthalUnmappedHaloCells.push_back(childId);
2807 m_azimuthalUnmappedHaloDomains.push_back(dom);
2811 ASSERT(findNeighborDomainId(a_globalId(childId)) == dom,
"Wrong domain! " + to_string(a_globalId(childId)) +
" " + to_string(findNeighborDomainId(a_globalId(childId))) +
" " + to_string(dom) +
" " + to_string(domainId()) +
" " + to_string(cellId));
2813 MInt idx = setAzimuthalNeighborDomainIndex(dom, m_azimuthalHaloCells, m_azimuthalWindowCells);
2815 m_azimuthalHaloCells[idx].push_back(childId);
2823 MBool adaptation =
false;
2824 adaptation = Context::getBasicProperty<MBool>(
"adaptation", AT_, &adaptation);
2826 std::array<MFloat, 2*nDim> bbox;
2827 for(
MInt i = 0; i < nDim; i++) {
2828 bbox[i] = numeric_limits<MFloat>::max();
2829 bbox[nDim + i] = numeric_limits<MFloat>::lowest();
2831 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
2832 for(
MInt i = 0; i < nDim; i++) {
2833 bbox[i] =
mMin(bbox[i], a_coordinate(cellId, i) - F1B2 * cellLengthAtLevel(a_level(cellId)));
2834 bbox[nDim + i] =
mMax(bbox[nDim + i], a_coordinate(cellId, i) + F1B2 * cellLengthAtLevel(a_level(cellId)));
2837 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[0]");
2838 MPI_Allreduce(MPI_IN_PLACE, &bbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[nDim]");
2839 MBool isBndry =
false;
2840 for(
MInt i = 0; i < m_noInternalCells; i++) {
2842 if(a_level(cellId) != level+1) {
continue;
2845 for(
MInt dir = 0; dir < m_noDirs; dir++) {
2846 if(a_hasNeighbor(cellId, dir) > 0) {
continue;
2848 if(a_hasParent(cellId) && a_hasNeighbor(a_parentId(cellId), dir) > 0) {
2849 MInt nghbrParentId = a_neighborId(a_parentId(cellId),dir);
2850 if(a_noChildren(nghbrParentId) == 0) {
2854 if(!m_periodicCartesianDir[dir/2]) {
2855 std::array<MFloat, nDim> coords;
2856 for(
MInt d = 0; d < nDim; d++) {
2857 coords[d] = a_coordinate(cellId,d);
2859 coords[dir / 2] += ((dir % 2) == 0 ? -F1 : F1) * cellLengthAtLevel(m_minLevel);
2860 if(coords[dir / 2] < bbox[dir / 2] || coords[dir / 2] > bbox[nDim + dir / 2]) {
2867 if(!a_isHalo(cellId)) { m_gridBndryCells.push_back(cellId);
2869 for(
MInt dir = 0; dir < m_noDirs; dir++) {
2870 if(a_hasNeighbor(cellId, dir) > 0) {
2871 MInt nghbrId = a_neighborId(cellId, dir);
2872 if(!a_isHalo(nghbrId)) {
2873 m_gridBndryCells.push_back(nghbrId);
2885 if(m_maxPartitionLevelShift > 0) {
2886 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2887 sort(m_haloCells[i].begin(), m_haloCells[i].end(),
2888 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
2889 sort(m_windowCells[i].begin(), m_windowCells[i].end(),
2890 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
2899 exchangeSolverBitset(&m_tree.solverBits(0));
2901 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
2902 maia::mpi::exchangeBitset(m_azimuthalNghbrDomains, m_azimuthalHaloCells, m_azimuthalWindowCells, mpiComm(), &m_tree.solverBits(0),
2907 correctAzimuthalSolverBits();
2911 if(!refineCellSolver.empty()) {
2913 for(
auto& cellId : refineIds) {
2914 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
2915 if(!m_tree.solver(cellId, solver))
continue;
2916 if(a_hasChildren(cellId, solver)) {
2917 refineCellSolver[solver](cellId);
2925 if (m_haloMode==2 && (forceLeafLvlCorrection || (onlyLevel==-1 && level==m_maxLevel-1))) {
2926 tagActiveWindowsOnLeafLvl3(level+1, duringMeshAdaptation, removeCellSolver);
2934 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
2935 if(a_isHalo(cellId) || a_isToDelete(cellId)) {
2938 bprops(cellId, 0) = (
MInt)a_hasProperty(cellId, Cell::IsPartLvlAncestor);
2939 bprops(cellId, 1) = a_noOffsprings(cellId);
2941 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
2942 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
2943 + std::to_string(bprops(cellId, 1)));
2951 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2952 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
2953 const MInt cellId = m_haloCells[i][j];
2954 ASSERT(!a_isToDelete(cellId),
"");
2955 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
2956 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
2957 + std::to_string(bprops(cellId, 1)));
2958 a_hasProperty(cellId, Cell::IsPartLvlAncestor) = (
MBool)bprops(cellId, 0);
2959 a_noOffsprings(cellId) = bprops(cellId, 1);
2965 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2968 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
2969 ASSERT(!a_hasProperty(m_haloCells[i][j], Cell::IsWindow),
"halo cell is marked as window");
2970 ASSERT(a_hasProperty(m_haloCells[i][j], Cell::IsHalo),
"halo cell flag not set!");
2975 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
2976 ASSERT(!a_isHalo(m_windowCells[i][j]),
"window cell is marked as halo");
2978 a_hasProperty(m_windowCells[i][j], Cell::IsWindow) =
true;
2981 if(m_azimuthalPer) {
2982 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
2983 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
2984 ASSERT(!a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsWindow),
"azimuthal halo cell is marked as window");
2985 a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsHalo) =
true;
2987 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
2988 ASSERT(!a_isHalo(m_azimuthalWindowCells[i][j]),
"azimuthal window cell is marked as halo");
2989 a_hasProperty(m_azimuthalWindowCells[i][j], Cell::IsWindow) =
true;
2992 for(
MInt j = 0; j < noAzimuthalUnmappedHaloCells(); j++ ) {
2993 ASSERT(!a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsWindow),
"azimuthal halo cell is marked as window");
2994 a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsHalo) =
true;
3000 for (
MInt i = 0; i < noNeighborDomains(); i++) {
3002 haloCellSet[i].clear();
3003 std::copy(m_haloCells[i].begin(), m_haloCells[i].end(), std::inserter(haloCellSet[i], haloCellSet[i].begin()));
3004 for (
MInt j = 0; j < (signed)m_haloCells[i].size(); ++j) {
3005 MInt parentId = m_haloCells[i][j];
3006 TERMM_IF_NOT_COND(a_isHalo(parentId),
"");
3007 char isSolverHalo = 0;
3008 for (
MInt solver = 0; solver < treeb().noSolvers(); ++solver) {
3009 if (m_tree.solver(parentId,solver)) {
3010 isSolverHalo = isSolverHalo | (1 << solver);
3013 while(a_parentId(parentId)>-1) {
3014 parentId = a_parentId(parentId);
3015 TERMM_IF_NOT_COND(a_isHalo(parentId) || a_hasProperty(parentId, Cell::IsPartLvlAncestor),
"");
3016 TERMM_IF_NOT_COND(haloCellSet[i].find(parentId)!=haloCellSet[i].end()
3017 || a_hasProperty(parentId, Cell::IsPartLvlAncestor),
"");
3018 for (
MInt solver = 0; solver < treeb().noSolvers(); ++solver) {
3019 if (isSolverHalo & (1<<solver)) {
3020 TERMM_IF_NOT_COND(m_tree.solver(parentId,solver),
"");
3022 if (m_tree.solver(parentId,solver)) {
3023 isSolverHalo = isSolverHalo | (1 << solver);
3030 checkWindowHaloConsistency(
false,
"createHigherLevelExchangeCells completed on level="+to_string(level)+
": ");
3033 logDuration(levelTimeStart,
"level #"+std::to_string(level)+
" total");
3037 if (onlyLevel==-1 || forceLeafLvlCorrection)
3038 checkWindowLayer(
"createHigherLevelExchangeCells completed: ");
3041 if(domainId() == 0 && onlyLevel < 0) cerr << endl;
3054 const MInt onlyLevel,
const std::vector<std::function<
void(
const MInt)>>& refineCellSolver) {
3058 vector<MLong> refineChildIds;
3059 vector<MLong> recvChildIds;
3060 vector<vector<MInt>> haloMap;
3061 vector<vector<MInt>> windMap;
3062 vector<MInt> refineIds;
3064 if(domainId() == 0 && onlyLevel < 0) cerr <<
" * create higher level exchange cells...";
3067 if(m_maxPartitionLevelShift > 0) {
3068 for(
MUint i = 0; i < m_partitionLevelAncestorIds.size(); i++) {
3069 plaMap[m_partitionLevelAncestorIds[i]] = i;
3073 if(m_azimuthalPer && onlyLevel <= m_minLevel) {
3074 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
3075 m_azimuthalHigherLevelConnectivity[i].clear();
3081 for(
MInt level = m_minLevel; level < m_maxLevel; level++) {
3082 if(onlyLevel > -1 && onlyLevel != level)
continue;
3090 haloMap.resize(noNeighborDomains());
3091 windMap.resize(noNeighborDomains());
3095 vector<std::set<MInt>> haloCellSet(noNeighborDomains());
3096 vector<std::set<MInt>> windCellSet(noNeighborDomains());
3098 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3099 haloMap[i].resize(m_haloCells[i].size());
3100 windMap[i].resize(m_windowCells[i].size());
3101 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
3102 haloMap[i][j] = haloCnt++;
3104 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
3105 windMap[i][j] = windowCnt++;
3108 haloCellSet[i].insert(m_haloCells[i].begin(), m_haloCells[i].end());
3109 windCellSet[i].insert(m_windowCells[i].begin(), m_windowCells[i].end());
3112 recvChildIds.resize(haloCnt * m_maxNoChilds);
3113 fill(recvChildIds.begin(), recvChildIds.end(), -1);
3114 refineChildIds.clear();
3115 tagActiveWindows(refineChildIds, level);
3120#pragma omp parallel for
3122 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3123 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
3124 MInt cellId = m_windowCells[i][j];
3126 if(a_level(cellId) == level && a_noChildren(cellId) > 0) {
3127 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3128 MInt cnt = windMap[i][j];
3130 if(refineChildIds[m_maxNoChilds * cnt + child] > 0) {
3131 ASSERT(a_childId(cellId, child) > -1,
"");
3132 ASSERT((a_globalId(
static_cast<MInt>(a_childId(cellId, child))) >= m_domainOffsets[domainId()]
3133 && a_globalId(
static_cast<MInt>(a_childId(cellId, child))) < m_domainOffsets[domainId() + 1])
3134 || a_hasProperty(cellId, Cell::IsPartLvlAncestor),
3135 to_string(a_globalId(
static_cast<MInt>(a_childId(cellId, child)))) +
" "
3136 + to_string(m_domainOffsets[domainId()]) +
" " + to_string(m_domainOffsets[domainId() + 1]));
3137 refineChildIds[m_maxNoChilds * cnt + child] = a_globalId(
static_cast<MInt>(a_childId(cellId, child)));
3140 MInt pId = plaMap[cellId];
3141 if(m_maxPartitionLevelShift > 0 && pId > -1) {
3142 if(m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child] > -1) {
3143 ASSERT(refineChildIds[m_maxNoChilds * cnt + child] < 0
3144 || refineChildIds[m_maxNoChilds * cnt + child]
3145 == m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child],
3146 std::to_string(refineChildIds[m_maxNoChilds * cnt + child]) +
" plac"
3147 + std::to_string(m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child]) +
"; c"
3148 + std::to_string(cellId) +
"; pId" + std::to_string(pId) +
"; cnt" + std::to_string(cnt));
3150 refineChildIds[m_maxNoChilds * cnt + child] =
3151 m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child];
3164 refineChildIds.data(),
3165 recvChildIds.data(),
3169 if(m_maxPartitionLevelShift > 0) {
3170 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3171 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
3172 MInt cellId = m_haloCells[i][j];
3173 if(a_level(cellId) == level) {
3174 MInt pId = plaMap[cellId];
3175 if(m_maxPartitionLevelShift > 0 && pId > -1) {
3176 MInt cnt = haloMap[i][j];
3177 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3178 const MLong childId = m_partitionLevelAncestorChildIds[pId * m_maxNoChilds + child];
3179 ASSERT(childId == recvChildIds[m_maxNoChilds * cnt + child],
3180 std::to_string(childId) +
" != " + std::to_string(recvChildIds[m_maxNoChilds * cnt + child])
3181 +
"; c" + std::to_string(cellId) +
"; g" + std::to_string(a_globalId(cellId)) +
"; p"
3182 + std::to_string(pId));
3194 if(m_maxPartitionLevelShift > 0) {
3196 vector<MInt> sendDomIdx;
3197 vector<MLong> sendData;
3201 fill(cellFlag.
begin(), cellFlag.
end(),
false);
3203 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3204 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
3205 const MInt cellId = m_windowCells[i][j];
3206 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"window cell marked as halo");
3208 if(a_level(cellId) == level && a_noChildren(cellId) > 0) {
3209 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3210 const MLong childId = refineChildIds[m_maxNoChilds * windMap[i][j] + child];
3211 if(childId < 0)
continue;
3212 MInt ndom = findNeighborDomainId(childId);
3213 ASSERT(ndom > -1 && ndom < noDomains(),
"");
3214 if(ndom != domainId()) {
3215 ASSERT(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
"");
3216 MInt idx = findIndex(m_nghbrDomains.begin(), m_nghbrDomains.end(), ndom);
3217 ASSERT(idx > -1,
"");
3218 ASSERT(m_nghbrDomains[idx] == ndom,
"");
3219 if(ndom != m_nghbrDomains[i]) {
3220 sendDomIdx.push_back(idx);
3221 sendData.push_back(m_nghbrDomains[i]);
3222 sendData.push_back(childId);
3224 if(!cellFlag[cellId]) {
3225 sendDomIdx.push_back(idx);
3226 sendData.push_back(domainId());
3227 sendData.push_back(childId);
3232 cellFlag[cellId] =
true;
3237 vector<MInt> recvOffs;
3238 vector<MLong> recvData;
3242 const MInt noNgbrDomainsBak = noNeighborDomains();
3243 for(
MInt i = 0; i < noNgbrDomainsBak; i++) {
3244 for(
MInt j = recvOffs[i]; j < recvOffs[i + 1]; j++) {
3245 auto ndom =
static_cast<MInt>(recvData[2 * j]);
3246 MLong globalChildId = recvData[2 * j + 1];
3248 MInt childId = m_globalToLocalId[globalChildId];
3249 ASSERT(childId > -1,
"");
3250 ASSERT(a_globalId(childId) == globalChildId,
"");
3251 ASSERT(findNeighborDomainId(globalChildId) == domainId(),
"");
3252 MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells);
3253 ASSERT(idx > -1,
"");
3256 if(idx ==
static_cast<MInt>(windCellSet.size())) {
3257 windCellSet.emplace_back();
3258 haloCellSet.emplace_back();
3261 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
3263 if(windCellSet[idx].find(childId) != windCellSet[idx].end()) {
3268 ASSERT(windCellSet[idx].find(childId) == windCellSet[idx].end(),
3269 "duplicate window cell: " + std::to_string(childId));
3271 m_windowCells[idx].push_back(childId);
3272 windCellSet[idx].insert(childId);
3281 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3282 vector<MInt> oldWindowVec(m_windowCells[i]);
3283 std::set<MInt> oldWindCellSet(windCellSet[i]);
3285 std::vector<MInt>().swap(m_windowCells[i]);
3286 windCellSet[i].clear();
3288 for(
MInt j = 0; j < (signed)oldWindowVec.size(); j++) {
3289 MInt cellId = oldWindowVec[j];
3292 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet[i].find(cellId) == windCellSet[i].end(),
3293 "duplicate window cell: " + std::to_string(cellId) +
" " + std::to_string(a_globalId(cellId)) +
" "
3294 + std::to_string(j));
3296 m_windowCells[i].push_back(cellId);
3297 windCellSet[i].insert(cellId);
3299 ASSERT(cellId < m_tree.size(), to_string(level));
3301 if(a_level(cellId) == level && a_noChildren(cellId) > 0) {
3302 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3303 MInt cnt = windMap[i][j];
3305 const MInt childId = a_childId(cellId, child);
3306 if(childId < 0)
continue;
3310 if(oldWindCellSet.find(childId) != oldWindCellSet.end()) {
3311 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
3312 "not a partition level ancestor or partition cell");
3316 const MLong globalChildId = refineChildIds[m_maxNoChilds * cnt + child];
3317 if(globalChildId > -1) {
3318 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
3321 MInt ndom = findNeighborDomainId(globalChildId);
3322 if(ndom == domainId()) {
3323 ASSERT(globalChildId == a_globalId(childId),
"");
3326 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet[i].find(childId) == windCellSet[i].end(),
3327 "duplicate window cell: " + std::to_string(childId));
3329 m_windowCells[i].push_back(childId);
3330 windCellSet[i].insert(childId);
3340 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3341 vector<MInt> oldHaloVec(m_haloCells[i]);
3342 std::set<MInt> oldHaloCellSet(haloCellSet[i]);
3344 std::vector<MInt>().swap(m_haloCells[i]);
3345 haloCellSet[i].clear();
3347 for(
MInt j = 0; j < (signed)oldHaloVec.size(); j++) {
3348 MInt cellId = oldHaloVec[j];
3350 ASSERT(haloCellSet[i].find(cellId) == haloCellSet[i].end(),
3351 "duplicate halo cell: " + std::to_string(cellId) +
" " + std::to_string(a_globalId(cellId)) +
" "
3352 + std::to_string(j));
3354 m_haloCells[i].push_back(cellId);
3355 haloCellSet[i].insert(cellId);
3357 if(a_level(cellId) == level) {
3358 MInt cnt = haloMap[i][j];
3360 if(accumulate(&recvChildIds[m_maxNoChilds * cnt], &recvChildIds[m_maxNoChilds * cnt] + m_maxNoChilds,
3371 refineCell(cellId, &recvChildIds[m_maxNoChilds * cnt], a_hasProperty(cellId, Cell::IsPartLvlAncestor));
3372 refineIds.push_back(cellId);
3374 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3375 const MInt childId = a_childId(cellId, child);
3376 if(childId < 0)
continue;
3379 if(oldHaloCellSet.find(childId) != oldHaloCellSet.end()) {
3380 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
3381 "not a partition level ancestor or partition cell");
3385 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
3386 ASSERT(a_globalId(childId) > -1,
"");
3387 MInt ndom = findNeighborDomainId(a_globalId(childId));
3388 ASSERT(ndom > -1,
"");
3389 if(recvChildIds[m_maxNoChilds * cnt + child] > -1)
3390 ASSERT(a_globalId(childId) == recvChildIds[m_maxNoChilds * cnt + child],
"");
3391 if(recvChildIds[m_maxNoChilds * cnt + child] < 0) ASSERT(ndom == domainId(),
"");
3392 if(ndom == m_nghbrDomains[i]) {
3393 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
3395 if(haloCellSet[i].find(childId) != haloCellSet[i].end()) {
3400 m_haloCells[i].push_back(childId);
3401 haloCellSet[i].insert(childId);
3402 }
else if(m_maxPartitionLevelShift > 0) {
3403 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && a_hasProperty(cellId, Cell::IsPeriodic))
3404 mTerm(1, AT_,
"check code here!!!");
3405 if(ndom != domainId()) {
3406 MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells);
3407 ASSERT(idx > -1,
"");
3410 if(idx ==
static_cast<MInt>(windCellSet.size())) {
3411 windCellSet.emplace_back();
3412 haloCellSet.emplace_back();
3415 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
3417 if(haloCellSet[idx].find(childId) != haloCellSet[idx].end()) {
3422 m_haloCells[idx].push_back(childId);
3423 haloCellSet[idx].insert(childId);
3426 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
3428 if(a_noChildren(cellId) == 0)
mTerm(1, AT_,
"all children gone");
3435 if(m_maxPartitionLevelShift > 0) {
3436 for(
MUint i = 0; i < m_partitionLevelAncestorIds.size(); i++) {
3437 const MInt cellId = m_partitionLevelAncestorIds[i];
3439 ASSERT(a_hasProperty(cellId, Cell::IsPartLvlAncestor),
3440 "not a partition level ancestor: cellId" + std::to_string(cellId) +
" halo"
3441 + std::to_string(a_hasProperty(cellId, Cell::IsHalo)) +
" domain" + std::to_string(domainId()));
3443 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
3444 ASSERT(findNeighborDomainId(a_globalId(cellId)) == domainId(),
"");
3445 if(a_level(cellId) == level) {
3446 MLong* childIds = &m_partitionLevelAncestorChildIds[i * m_maxNoChilds];
3447 if(accumulate(childIds, childIds + m_maxNoChilds,
static_cast<MLong>(-1),
3450 refineCell(cellId, childIds, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
3451 refineIds.push_back(cellId);
3453 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3454 const MInt childId = a_childId(cellId, child);
3455 if(childId < 0)
continue;
3456 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
3457 a_globalId(childId) = childIds[child];
3458 MInt ndom = findNeighborDomainId(a_globalId(childId));
3459 ASSERT(ndom > -1,
"");
3460 if(ndom != domainId()) {
3461 MInt idx = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells);
3462 ASSERT(idx > -1,
"");
3465 if(idx ==
static_cast<MInt>(windCellSet.size())) {
3466 windCellSet.emplace_back();
3467 haloCellSet.emplace_back();
3470 if(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell)) {
3472 if(haloCellSet[idx].find(childId) != haloCellSet[idx].end()) {
3477 m_haloCells[idx].push_back(childId);
3478 haloCellSet[idx].insert(childId);
3480 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
3483 if(a_noChildren(cellId) == 0)
mTerm(1, AT_,
"all children gone");
3489 if(m_azimuthalPer) {
3490 refineChildIds.clear();
3491 recvChildIds.clear();
3494 tagAzimuthalHigherLevelExchangeCells(refineChildIds, recvChildIds, level);
3496 vector<vector<MLong>> shiftWindows;
3497 shiftWindows.resize(noDomains());
3498 MIntScratchSpace noShiftWindows(noNeighborDomains(), AT_,
"noShiftWindows");
3499 noShiftWindows.
fill(0);
3502 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
3503 vector<MInt> oldWindowVec(m_azimuthalWindowCells[i]);
3504 vector<MInt> oldHigherLevelCon(m_azimuthalHigherLevelConnectivity[i]);
3506 m_azimuthalWindowCells[i].clear();
3507 m_azimuthalHigherLevelConnectivity[i].clear();
3509 for(
MInt j = 0; j < (signed)oldWindowVec.size(); j++) {
3510 MInt cellId = oldWindowVec[j];
3512 if(find(oldHigherLevelCon.begin(), oldHigherLevelCon.end(), j) != oldHigherLevelCon.end()) {
3513 m_azimuthalHigherLevelConnectivity[i].push_back(m_azimuthalWindowCells[i].size());
3515 m_azimuthalWindowCells[i].push_back(cellId);
3517 ASSERT(cellId < m_tree.size(), to_string(level));
3519 if(a_level(cellId) == level) {
3520 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3521 const MLong globalChildId = refineChildIds[m_maxNoChilds * cnt + child];
3523 if(globalChildId > -1) {
3524 MInt ndom = findNeighborDomainId(globalChildId);
3530 if(ndom == domainId()) {
3531 const MInt childId = globalIdToLocalId(globalChildId,
true);
3532 if(level == m_minLevel && a_level(childId) <= m_minLevel) {
3533 m_azimuthalHigherLevelConnectivity[i].push_back(m_azimuthalWindowCells[i].size());
3535 m_azimuthalWindowCells[i].push_back(childId);
3537 ASSERT(m_nghbrDomainIndex[ndom] > -1,
"");
3538 shiftWindows[m_nghbrDomainIndex[ndom]].push_back(globalChildId);
3539 shiftWindows[m_nghbrDomainIndex[ndom]].push_back(azimuthalNeighborDomain(i));
3540 noShiftWindows[m_nghbrDomainIndex[ndom]]++;
3549 vector<vector<MInt>> shiftHalos;
3550 shiftHalos.resize(noDomains());
3551 vector<vector<MInt>> shiftHaloDoms;
3552 shiftHaloDoms.resize(noDomains());
3554 noShiftHalos.
fill(0);
3556 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
3557 vector<MInt> oldHaloVec(m_azimuthalHaloCells[i]);
3559 m_azimuthalHaloCells[i].clear();
3561 for(
MInt j = 0; j < (signed)oldHaloVec.size(); j++) {
3562 MInt cellId = oldHaloVec[j];
3564 m_azimuthalHaloCells[i].push_back(cellId);
3566 if(a_level(cellId) == level) {
3567 if(accumulate(&recvChildIds[m_maxNoChilds * cnt], &recvChildIds[m_maxNoChilds * cnt] + m_maxNoChilds,
3572 refineCell(cellId,
nullptr, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
3573 refineIds.push_back(cellId);
3575 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3576 const MInt childId = a_childId(cellId, child);
3577 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
3578 a_hasProperty(childId, Cell::IsHalo) = a_hasProperty(cellId, Cell::IsHalo);
3579 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
3580 a_globalId(childId) = recvChildIds[m_maxNoChilds * cnt + child];
3581 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
3582 treeb().solver(childId, solver) = treeb().solver(cellId, solver);
3587 if(a_globalId(childId) == -1) {
3588 m_azimuthalUnmappedHaloCells.push_back(childId);
3589 m_azimuthalUnmappedHaloDomains.push_back(azimuthalNeighborDomain(i));
3593 ASSERT(a_globalId(childId) > -1,
"");
3594 MInt ndom = findNeighborDomainId(a_globalId(childId));
3601 if(ndom == azimuthalNeighborDomain(i)) {
3602 m_azimuthalHaloCells[i].push_back(childId);
3604 shiftHalos[ndom].push_back(childId);
3605 shiftHaloDoms[ndom].push_back(azimuthalNeighborDomain(i));
3606 noShiftHalos[ndom]++;
3616 vector<vector<MLong>> newWindows;
3617 newWindows.resize(noNeighborDomains());
3619 noNewWindows.
fill(0);
3620 vector<MInt> noValsToReceive;
3621 noValsToReceive.assign(noNeighborDomains(), 1);
3625 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3626 newWindows[i].resize(2*noNewWindows[i]);
3630 sendReq.
fill(MPI_REQUEST_NULL);
3632 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3633 if(noShiftWindows[i] == 0)
continue;
3637 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3638 if(noNewWindows[i] == 0)
continue;
3642 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3643 if(noShiftWindows[i] == 0)
continue;
3644 MPI_Wait(&sendReq[i], MPI_STATUSES_IGNORE, AT_);
3648 for(
MInt i = 0; i < noDomains(); i++) {
3649 shiftWindows[i].clear();
3650 for(
MInt d = 0; d < noDomains(); d++) {
3651 MInt nghbrDomId = m_nghbrDomainIndex[d];
3652 if(nghbrDomId == -1)
continue;
3653 for(
MInt j = 0; j < noNewWindows[nghbrDomId]; j++ ) {
3654 MInt haloDomain = newWindows[nghbrDomId][j*2 + 1];
3655 if(haloDomain == i) shiftWindows[i].push_back(newWindows[nghbrDomId][j*2]);
3661 for(
MInt i = 0; i < noDomains(); i++) {
3662 for(
MUint j = 0; j < shiftWindows[i].size(); j++ ) {
3663 const MLong globalChildId = shiftWindows[i][j];
3664 ASSERT(findNeighborDomainId(globalChildId) == domainId(),
"Wrong domain!");
3666 const MInt childId = globalIdToLocalId(globalChildId,
true);
3667 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
3669 if(level == m_minLevel && a_level(childId) <= m_minLevel) {
3670 m_azimuthalHigherLevelConnectivity[idx].push_back(m_azimuthalWindowCells[idx].size());
3672 m_azimuthalWindowCells[idx].push_back(childId);
3677 for(
MInt i = 0; i < noDomains(); i++) {
3678 vector<MInt> shiftHalosBck(shiftHalos[i]);
3679 shiftHalos[i].clear();
3680 for(
MInt d = 0; d < noDomains(); d++) {
3681 for(
MInt j = 0; j < noShiftHalos[i]; j++ ) {
3682 MInt nghbrDomain = shiftHaloDoms[i][j];
3684 if(nghbrDomain == d) shiftHalos[i].push_back(shiftHalosBck[j]);
3690 for(
MInt i = 0; i < noDomains(); i++) {
3691 for(
MInt j = 0; j < noShiftHalos[i]; j++ ) {
3692 const MInt childId = shiftHalos[i][j];
3693 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
3695 m_azimuthalHaloCells[idx].push_back(childId);
3700 if(!refineCellSolver.empty()) {
3701 if(domainId() == 0) cerr <<
"Attention: Unmapped halo are not refined during adaptation!" << endl;
3703 shiftWindows.clear();
3704 recvChildIds.clear();
3705 vector<MInt> recvChildDomainIds;
3706 tagAzimuthalUnmappedHaloCells(shiftWindows, recvChildIds, recvChildDomainIds, level);
3712 for(
MInt i = 0; i < noDomains(); i++) {
3713 for(
MUint j = 0; j < shiftWindows[i].size(); j++ ) {
3714 const MLong globalChildId = shiftWindows[i][j];
3715 if(globalChildId < 0)
continue;
3717 ASSERT(findNeighborDomainId(globalChildId) == domainId(),
"Wrong domain! " + to_string(globalChildId) +
" " + to_string(findNeighborDomainId(globalChildId)) +
" " + to_string(domainId()));
3719 MInt idx = setAzimuthalNeighborDomainIndex(i, m_azimuthalHaloCells, m_azimuthalWindowCells);
3721 const MInt childId = globalIdToLocalId(globalChildId,
true);
3722 m_azimuthalWindowCells[idx].push_back(childId);
3730 MInt noUnmappedCells = noAzimuthalUnmappedHaloCells();
3731 for(
MInt i = 0; i < noUnmappedCells; i++ ) {
3732 MInt cellId = azimuthalUnmappedHaloCell(i);
3733 if(a_level(cellId) == level) {
3734 if(accumulate(&recvChildIds[m_maxNoChilds * i], &recvChildIds[m_maxNoChilds * i] + m_maxNoChilds,
3738 refineCell(cellId,
nullptr, a_hasProperty(cellId, Cell::IsPartLvlAncestor));
3739 refineIds.push_back(cellId);
3741 for(
MInt child = 0; child < m_maxNoChilds; child++) {
3742 const MInt childId = a_childId(cellId, child);
3744 ASSERT(childId > -1 && childId < m_tree.size(), to_string(childId) +
" " + to_string(m_tree.size()));
3745 a_hasProperty(childId, Cell::IsHalo) = a_hasProperty(cellId, Cell::IsHalo);
3746 a_hasProperty(childId, Cell::IsPeriodic) = a_hasProperty(cellId, Cell::IsPeriodic);
3747 a_globalId(childId) = recvChildIds[m_maxNoChilds * i + child];
3748 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
3749 treeb().solver(childId, solver) = treeb().solver(cellId, solver);
3752 MInt dom = recvChildDomainIds[m_maxNoChilds * i + child];
3754 if(a_globalId(childId) == -1) {
3755 m_azimuthalUnmappedHaloCells.push_back(childId);
3756 m_azimuthalUnmappedHaloDomains.push_back(dom);
3760 ASSERT(findNeighborDomainId(a_globalId(childId)) == dom,
"Wrong domain! " + to_string(a_globalId(childId)) +
" " + to_string(findNeighborDomainId(a_globalId(childId))) +
" " + to_string(dom) +
" " + to_string(domainId()) +
" " + to_string(cellId));
3762 MInt idx = setAzimuthalNeighborDomainIndex(dom, m_azimuthalHaloCells, m_azimuthalWindowCells);
3764 m_azimuthalHaloCells[idx].push_back(childId);
3772 MBool adaptation =
false;
3773 adaptation = Context::getBasicProperty<MBool>(
"adaptation", AT_, &adaptation);
3775 std::array<MFloat, 2 * nDim> bbox;
3776 for(
MInt i = 0; i < nDim; i++) {
3777 bbox[i] = numeric_limits<MFloat>::max();
3778 bbox[nDim + i] = numeric_limits<MFloat>::lowest();
3780 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
3781 for(
MInt i = 0; i < nDim; i++) {
3782 bbox[i] =
mMin(bbox[i], a_coordinate(cellId, i) - F1B2 * cellLengthAtLevel(a_level(cellId)));
3783 bbox[nDim + i] =
mMax(bbox[nDim + i], a_coordinate(cellId, i) + F1B2 * cellLengthAtLevel(a_level(cellId)));
3786 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[0]");
3787 MPI_Allreduce(MPI_IN_PLACE, &bbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[nDim]");
3788 MBool isBndry =
false;
3789 for(
MInt i = 0; i < m_noInternalCells; i++) {
3791 if(a_level(cellId) != level+1) {
continue;
3794 for(
MInt dir = 0; dir < m_noDirs; dir++) {
3795 if(a_hasNeighbor(cellId, dir) > 0) {
continue;
3797 if(a_hasParent(cellId) && a_hasNeighbor(a_parentId(cellId), dir) > 0) {
3798 MInt nghbrParentId = a_neighborId(a_parentId(cellId),dir);
3799 if(a_noChildren(nghbrParentId) == 0) {
3803 if(!m_periodicCartesianDir[dir/2]) {
3804 std::array<MFloat, nDim> coords;
3805 for(
MInt d = 0; d < nDim; d++) {
3806 coords[d] = a_coordinate(cellId,d);
3808 coords[dir / 2] += ((dir % 2) == 0 ? -F1 : F1) * cellLengthAtLevel(m_minLevel);
3809 if(coords[dir / 2] < bbox[dir / 2] || coords[dir / 2] > bbox[nDim + dir / 2]) {
3816 if(!a_isHalo(cellId)) { m_gridBndryCells.push_back(cellId);
3818 for(
MInt dir = 0; dir < m_noDirs; dir++) {
3819 if(a_hasNeighbor(cellId, dir) > 0) {
3820 MInt nghbrId = a_neighborId(cellId, dir);
3821 if(!a_isHalo(nghbrId)) {
3822 m_gridBndryCells.push_back(nghbrId);
3834 if(m_maxPartitionLevelShift > 0) {
3835 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3836 sort(m_haloCells[i].begin(), m_haloCells[i].end(),
3837 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
3838 sort(m_windowCells[i].begin(), m_windowCells[i].end(),
3839 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
3844 if(treeb().noSolvers() > 1) {
3847 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
3848 maia::mpi::exchangeBitset(m_azimuthalNghbrDomains, m_azimuthalHaloCells, m_azimuthalWindowCells, mpiComm(), &m_tree.solverBits(0),
3853 correctAzimuthalSolverBits();
3858 if(!refineCellSolver.empty()) {
3860 for(
auto& cellId : refineIds) {
3861 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
3862 if(!m_tree.solver(cellId, solver))
continue;
3863 if(a_hasChildren(cellId, solver)) {
3864 refineCellSolver[solver](cellId);
3872 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3873 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
3874 ASSERT(!a_hasProperty(m_haloCells[i][j], Cell::IsWindow),
"halo cell is marked as window");
3875 a_hasProperty(m_haloCells[i][j], Cell::IsHalo) =
true;
3878 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
3879 ASSERT(!a_isHalo(m_windowCells[i][j]),
"window cell is marked as halo");
3881 a_hasProperty(m_windowCells[i][j], Cell::IsWindow) =
true;
3884 if(m_azimuthalPer) {
3885 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
3886 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
3887 ASSERT(!a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsWindow),
"azimuthal halo cell is marked as window");
3888 a_hasProperty(m_azimuthalHaloCells[i][j], Cell::IsHalo) =
true;
3890 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
3891 ASSERT(!a_isHalo(m_azimuthalWindowCells[i][j]),
"azimuthal window cell is marked as halo");
3892 a_hasProperty(m_azimuthalWindowCells[i][j], Cell::IsWindow) =
true;
3895 for(
MInt j = 0; j < noAzimuthalUnmappedHaloCells(); j++ ) {
3896 ASSERT(!a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsWindow),
"azimuthal halo cell is marked as window");
3897 a_hasProperty(m_azimuthalUnmappedHaloCells[j], Cell::IsHalo) =
true;
3902 if(domainId() == 0 && onlyLevel < 0) cerr << endl;
3916template <std::
size_t N>
3926 static_assert(N <= 64,
"conversion to ulong not appropriate, change to ullong!");
3928 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
3929 MInt receiveCount = 0;
3930 for (
const auto& vecHalo : m_haloCells) receiveCount+=vecHalo.size();
3932 for (
MInt i = 0, offset = 0; i < noNeighborDomains(); i++) {
3933 const MInt noHaloCells = m_haloCells[i].size();
3934 if (noHaloCells<1)
continue;
3937 m_nghbrDomains[i], mpiComm(), &recvRequests[i], AT_,
"haloBuffer[offset]");
3939 offset += noHaloCells;
3944 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
3946 for (
const auto& vecWindow : m_windowCells) sendCount+=vecWindow.size();
3948 for (
MInt i = 0, idx = 0; i < noNeighborDomains(); i++) {
3949 const MInt offset = idx;
3950 const MInt noWindowCells = m_windowCells[i].size();
3951 if (noWindowCells<1)
continue;
3952 for (
const auto cellId : m_windowCells[i]) {
3953 const auto backup = data[cellId].to_ulong();
3954 ASSERT(m_windowLayer_[i].find(cellId)!=m_windowLayer_[i].end(),
"You don't know what you are doing!");
3955 for (
MInt solverId = 0; solverId < treeb().noSolvers(); ++solverId) {
3956 if (!isSolverWindowCell(i, cellId, solverId)) {
3957 data[cellId][solverId] = defaultVal;
3960 tmp_data[idx++] = data[cellId].to_ulong();
3961 data[cellId] = std::bitset<N>(backup);
3963 ASSERT(idx-offset==noWindowCells,
"");
3966 mpiComm(), &sendRequests[i], AT_,
"tmp_data");
3970 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
3971 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
3973 for (
MInt i = 0, idx = 0; i < noNeighborDomains(); i++) {
3974 for (
const auto cellId : m_haloCells[i])
3975 data[cellId] = std::bitset<N>(haloBuffer[idx++]);
3985 unordered_multimap<MLong, MInt>& hilbertToLocal,
3987 vector<vector<MInt>>& halos, vector<vector<MLong>>& hilbertIds) {
3988 static constexpr MInt revDir[6] = {1, 0, 3, 2, 5, 4};
3989 const MFloat cellLength = cellLengthAtCell(cellId);
3994 for(
MInt i = 0; i < nDim; i++) {
3995 coords[i] = a_coordinate(cellId, i);
3997 coords[dir / 2] += ((dir % 2) == 0 ? -F1 : F1) * cellLength;
3999 for(
MInt i = 0; i < nDim; i++) {
4000 if(!m_periodicCartesianDir[dir / 2] && (coords[dir / 2] < bbox[dir / 2] || coords[dir / 2] > bbox[nDim + dir / 2]))
4005 for(
MInt i = 0; i < nDim; i++) {
4006 if(coords[i] < bbox[i] || coords[i] > bbox[nDim + i]) insd =
false;
4008 MBool isPeriodic = !insd;
4010 if(m_azimuthalPer && isPeriodic)
return -1;
4013 for(
MInt i = 0; i < nDim; i++) {
4014 dx[i] = bbox[nDim + i] - bbox[i];
4016 for(
MInt i = 0; i < nDim; i++) {
4017 dummyCoords[i] = coords[i];
4020 for(
MInt i = 0; i < nDim; i++) {
4021 if(coords[i] < bbox[i])
4022 dummyCoords[i] += dx[i];
4023 else if(coords[i] > bbox[nDim + i])
4024 dummyCoords[i] -= dx[i];
4028 for(
MInt i = 0; i < nDim; i++) {
4029 if(dummyCoords[i] < bbox[i] || dummyCoords[i] > bbox[nDim + i]) {
4030 mTerm(1, AT_,
"Halo cell coords outside domain");
4034 const MLong hilbertIndex = hilbertIndexGeneric(&dummyCoords[0]);
4036 while(hilbertIndex >= hilbertOffsets[ndom + 1]) {
4038 if(ndom == noDomains() - 1)
break;
4040 ASSERT(ndom > -1,
"");
4041 ASSERT(hilbertIndex >= hilbertOffsets[ndom] && hilbertIndex < hilbertOffsets[ndom + 1],
4042 to_string(hilbertIndex) +
" " + to_string(hilbertOffsets[ndom]) +
" " + to_string(hilbertOffsets[ndom + 1]));
4044 const MInt haloCellId = m_tree.size();
4047 for(
MInt i = 0; i < nDim; i++) {
4048 a_level(haloCellId) = a_level(cellId);
4051 for(
MInt i = 0; i < nDim; i++) {
4052 a_coordinate(haloCellId, i) = coords[i];
4055 hilbertToLocal.insert(make_pair(hilbertIndex, haloCellId));
4057 for(
MInt i = 0; i < m_noDirs; i++) {
4058 a_neighborId(haloCellId, i) = -1;
4060 for(
MInt i = 0; i < m_maxNoChilds; i++) {
4061 a_childId(haloCellId, i) = -1;
4063 a_parentId(haloCellId) = -1;
4065 a_neighborId(cellId, dir) = haloCellId;
4066 a_neighborId(haloCellId, revDir[dir]) = cellId;
4067 for(
MInt otherDir = 0; otherDir < m_noDirs; otherDir++) {
4068 if(otherDir / 2 == dir / 2)
continue;
4069 if(a_hasNeighbor(cellId, otherDir) == 0)
continue;
4070 MInt nghbrId = a_neighborId(cellId, otherDir);
4071 if(a_hasNeighbor(nghbrId, dir) > 0) {
4072 nghbrId = a_neighborId(nghbrId, dir);
4073 a_neighborId(nghbrId, revDir[otherDir]) = haloCellId;
4074 a_neighborId(haloCellId, otherDir) = nghbrId;
4077 for(
MInt ndir = 0; ndir < m_noDirs; ndir++) {
4078 if(a_hasNeighbor(haloCellId, ndir) > 0)
continue;
4079 for(
MInt i = 0; i < nDim; i++) {
4080 dummyCoords[i] = a_coordinate(haloCellId, i);
4082 dummyCoords[ndir / 2] += ((ndir % 2) == 0 ? -F1 : F1) * cellLength;
4083 for(
MInt i = 0; i < nDim; i++) {
4084 dcoords[i] = dummyCoords[i];
4086 for(
MInt i = 0; i < nDim; i++) {
4087 if(dummyCoords[i] < bbox[i])
4088 dummyCoords[i] += dx[i];
4089 else if(dummyCoords[i] > bbox[nDim + i])
4090 dummyCoords[i] -= dx[i];
4092 const MLong nghbrHilbertId = hilbertIndexGeneric(&dummyCoords[0]);
4094 auto range = hilbertToLocal.equal_range(nghbrHilbertId);
4095 for(
auto it = range.first; it != range.second; ++it) {
4097 for(
MInt i = 0; i < nDim; i++) {
4098 dist +=
POW2(a_coordinate(it->second, i) - dcoords[i]);
4101 if(
dist < 0.001 * cellLength) {
4102 if(nghbrId > -1) cerr <<
"duplicate " << hilbertToLocal.count(nghbrHilbertId) << endl;
4103 nghbrId = it->second;
4106 if(nghbrId < 0)
continue;
4109 for(
MInt i = 0; i < nDim; i++) {
4110 ASSERT(fabs(a_coordinate(nghbrId, i) - a_coordinate(haloCellId, i)) < cellLength * 1.0001,
"");
4113 a_neighborId(nghbrId, revDir[ndir]) = haloCellId;
4114 a_neighborId(haloCellId, ndir) = nghbrId;
4117 a_resetProperties(haloCellId);
4118 a_hasProperty(haloCellId, Cell::IsHalo) =
true;
4119 a_hasProperty(haloCellId, Cell::IsPeriodic) = isPeriodic;
4121 MInt idx = setNeighborDomainIndex(ndom, halos, hilbertIds);
4122 ASSERT(idx > -1,
"");
4123 halos[idx].push_back(haloCellId);
4124 hilbertIds[idx].push_back(hilbertIndex);
4141 const auto noNghbrDomains0 = (signed)m_nghbrDomains.size();
4142 const auto noAzimuthalNghbrDomains0 = (signed)m_azimuthalNghbrDomains.size();
4143 if(noNghbrDomains0 == 0 && noAzimuthalNghbrDomains0 == 0) {
4153 vector<pair<MInt, MInt>> tmpDoms;
4154 tmpDoms.reserve(noNghbrDomains0);
4157 for(
MInt i = 0; i < noNghbrDomains0; i++) {
4158 if(m_haloCells[i].size() > 0 || m_windowCells[i].size() > 0) {
4159 tmpDoms.push_back(make_pair(m_nghbrDomains[i], i));
4162 sort(tmpDoms.begin(), tmpDoms.end());
4164 std::vector<MInt>().swap(m_nghbrDomains);
4165 ASSERT(m_nghbrDomainIndex.size() >=
static_cast<size_t>(noDomains()),
4166 "m_nghbrDomainIndex size is " + std::to_string(m_nghbrDomainIndex.size())
4167 +
" which is smaller than noDomains() = " + std::to_string(noDomains()));
4168 std::fill_n(m_nghbrDomainIndex.begin(), noDomains(), -1);
4169 for(
MInt i = 0; i < (signed)tmpDoms.size(); i++) {
4170 domMap[i] = tmpDoms[i].second;
4171 m_nghbrDomainIndex[tmpDoms[i].first] = m_nghbrDomains.
size();
4172 m_nghbrDomains.push_back(tmpDoms[i].first);
4173 if(m_nghbrDomains[i] == domainId() && m_noPeriodicCartesianDirs == 0) {
4174 TERMM(1,
"Not supposed to happen: connection to self without periodicity.");
4176 if(m_nghbrDomains[i] == domainId())
m_log << domainId() <<
": periodic connection to self." << endl;
4181 const MBool sortHaloWindowCells =
false;
4182 if(sortHaloWindowCells) {
4183 for(
MInt i = 0; i < noNghbrDomains0; i++) {
4184 sort(m_haloCells[i].begin(), m_haloCells[i].end(),
4185 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
4186 sort(m_windowCells[i].begin(), m_windowCells[i].end(),
4187 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
4193 vector<std::vector<MInt>> haloCellBak(m_haloCells);
4194 vector<std::vector<MInt>> windowCellBak(m_windowCells);
4195 m_haloCells.resize(noNeighborDomains());
4196 m_windowCells.resize(noNeighborDomains());
4197 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4198 m_haloCells[i].resize(haloCellBak[domMap[i]].size());
4199 m_windowCells[i].resize(windowCellBak[domMap[i]].size());
4200 ASSERT(m_haloCells[i].size() >= haloCellBak[domMap[i]].size(),
"");
4201 ASSERT(m_windowCells[i].size() >= windowCellBak[domMap[i]].size(),
"");
4202 copy(haloCellBak[domMap[i]].begin(), haloCellBak[domMap[i]].end(), m_haloCells[i].begin());
4203 copy(windowCellBak[domMap[i]].begin(), windowCellBak[domMap[i]].end(), m_windowCells[i].begin());
4207 if (m_windowLayer_.size()>0 && m_haloMode>0) {
4208 ASSERT(noNeighborDomains()<=(
signed)m_windowLayer_.size(),
"");
4209 std::vector<std::unordered_map<MInt, M32X4bit<true>>> windowLayerBak(m_windowLayer_);
4210 m_windowLayer_.resize(noNeighborDomains());
4211 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4212 m_windowLayer_[i] = windowLayerBak[domMap[i]];
4217 if(m_azimuthalPer) {
4221 tmpDoms.reserve(noAzimuthalNghbrDomains0);
4222 for(
MInt i = 0; i < noAzimuthalNghbrDomains0; i++) {
4223 if(m_azimuthalHaloCells[i].size() > 0 || m_azimuthalWindowCells[i].size() > 0) {
4224 tmpDoms.push_back(make_pair(m_azimuthalNghbrDomains[i], i));
4227 sort(tmpDoms.begin(), tmpDoms.end());
4229 m_azimuthalNghbrDomains.clear();
4230 ASSERT(m_azimuthalNghbrDomainIndex.size() >=
static_cast<size_t>(noDomains()),
4231 "m_azimuthalNghbrDomainIndex size is " + std::to_string(m_azimuthalNghbrDomainIndex.size())
4232 +
" which is smaller than noDomains() = " + std::to_string(noDomains()));
4233 std::fill_n(m_azimuthalNghbrDomainIndex.begin(), noDomains(), -1);
4234 for(
MInt i = 0; i < (signed)tmpDoms.size(); i++) {
4235 domMapAzi[i] = tmpDoms[i].second;
4236 m_azimuthalNghbrDomainIndex[tmpDoms[i].first] = m_azimuthalNghbrDomains.
size();
4237 m_azimuthalNghbrDomains.push_back(tmpDoms[i].first);
4238 if(m_azimuthalNghbrDomains[i] == domainId())
m_log << domainId() <<
": periodic connection to self." << endl;
4242 if(sortHaloWindowCells) {
4243 vector<MInt> posMapAzi;
4244 for(
MInt i = 0; i < noAzimuthalNghbrDomains0; i++) {
4245 sort(m_azimuthalHaloCells[i].begin(), m_azimuthalHaloCells[i].end(),
4246 [
this](
const MInt&
a,
const MInt&
b) {
return a_globalId(
a) < a_globalId(
b); });
4248 vector<pair<MInt, MInt>> azimuthalWindowCells;
4249 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
4250 azimuthalWindowCells.push_back(make_pair(m_azimuthalWindowCells[i][j], j));
4252 m_azimuthalWindowCells[i].clear();
4253 sort(azimuthalWindowCells.begin(), azimuthalWindowCells.end(),
4254 [&](
const auto&
a,
const auto&
b) { return a_globalId(a.first) < a_globalId(b.first); });
4255 m_azimuthalWindowCells[i].resize(azimuthalWindowCells.size());
4256 posMapAzi.resize(azimuthalWindowCells.size());
4257 for(
MInt j = 0; j < (signed)azimuthalWindowCells.size(); j++) {
4258 m_azimuthalWindowCells[i][j] = azimuthalWindowCells[j].first;
4259 posMapAzi[azimuthalWindowCells[j].second] = j;
4261 vector<MInt> higherLevelConnectivityBak(m_azimuthalHigherLevelConnectivity[i]);
4262 m_azimuthalHigherLevelConnectivity[i].resize(higherLevelConnectivityBak.size());
4263 for(
MInt c = 0; c < (signed)higherLevelConnectivityBak.size(); c++) {
4264 m_azimuthalHigherLevelConnectivity[i].push_back(posMapAzi[higherLevelConnectivityBak[c]]);
4266 azimuthalWindowCells.clear();
4267 higherLevelConnectivityBak.clear();
4272 haloCellBak.clear();
4273 windowCellBak.clear();
4274 haloCellBak = m_azimuthalHaloCells;
4275 windowCellBak = m_azimuthalWindowCells;
4276 vector<vector<MInt>> higherLevelConnectivityBak2(m_azimuthalHigherLevelConnectivity);
4277 m_azimuthalHaloCells.resize(noAzimuthalNeighborDomains());
4278 m_azimuthalWindowCells.resize(noAzimuthalNeighborDomains());
4279 m_azimuthalHigherLevelConnectivity.resize(noAzimuthalNeighborDomains());
4280 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
4281 m_azimuthalHaloCells[i].resize(haloCellBak[domMapAzi[i]].size());
4282 m_azimuthalWindowCells[i].resize(windowCellBak[domMapAzi[i]].size());
4283 m_azimuthalHigherLevelConnectivity[i].resize(higherLevelConnectivityBak2[domMapAzi[i]].size());
4284 ASSERT(m_azimuthalHaloCells[i].size() >= haloCellBak[domMapAzi[i]].size(),
"");
4285 ASSERT(m_azimuthalWindowCells[i].size() >= windowCellBak[domMapAzi[i]].size(),
"");
4286 copy(haloCellBak[domMapAzi[i]].begin(), haloCellBak[domMapAzi[i]].end(), m_azimuthalHaloCells[i].begin());
4287 copy(windowCellBak[domMapAzi[i]].begin(), windowCellBak[domMapAzi[i]].end(), m_azimuthalWindowCells[i].begin());
4288 copy(higherLevelConnectivityBak2[domMapAzi[i]].begin(), higherLevelConnectivityBak2[domMapAzi[i]].end(), m_azimuthalHigherLevelConnectivity[i].begin());
4303 constexpr MInt maxNghbrDoms = 1024;
4305 vector<std::bitset<maxNghbrDoms>> nghrDomFlag(m_tree.size());
4306 vector<std::bitset<maxNghbrDoms>> nghrDomFlagBak;
4307 vector<std::bitset<maxNghbrDoms>> nghrDomFlagBak2;
4308 set<MInt> exchangeCellList;
4309 if(noNeighborDomains() > maxNghbrDoms) {
4310 mTerm(1, AT_,
"Too many neighbor domains(" + std::to_string(noNeighborDomains()) +
"). Increase bitset size.");
4315 constexpr MBool testingFix_partitionLevelShift =
true;
4318 constexpr MBool multiSolverHaloLayer =
true;
4321 for(
MInt i = 0; i < noNeighborDomains(); i++)
4322 windowCnt += m_windowCells[i].size();
4323 refineChildIds.resize(windowCnt * m_maxNoChilds);
4324 fill(refineChildIds.begin(), refineChildIds.end(), -1);
4328 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4329 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
4330 const MInt cellId = m_windowCells[i][j];
4333 if(a_noChildren(cellId) > 0) {
4334 if(a_level(cellId) == level) {
4335 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4336 MInt childId = a_childId(cellId, child);
4337 if(childId < 0)
continue;
4342 exchangeCellList.insert(childId);
4347 exchangeCellList.insert(cellId);
4356 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
4357 if(a_isHalo(cellId)) {
4358 exchangeCellList.insert(cellId);
4365 if(m_maxPartitionLevelShift > 0) {
4370 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
4371 if(a_isHalo(cellId) || a_isToDelete(cellId)) {
4374 bprops(cellId, 0) = (
MInt)a_hasProperty(cellId, Cell::IsPartLvlAncestor);
4375 bprops(cellId, 1) = a_noOffsprings(cellId);
4377 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
4378 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
4379 + std::to_string(bprops(cellId, 1)));
4386 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4387 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
4388 const MInt cellId = m_haloCells[i][j];
4389 ASSERT(!a_isToDelete(cellId),
"");
4390 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
4391 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
4392 + std::to_string(bprops(cellId, 1)));
4393 a_hasProperty(cellId, Cell::IsPartLvlAncestor) = (
MBool)bprops(cellId, 0);
4394 a_noOffsprings(cellId) = bprops(cellId, 1);
4399 for(
MInt i = m_tree.size(); i--;) {
4400 for(
MInt j = 0; j < maxNghbrDoms; j++) {
4401 ASSERT(!nghrDomFlag[i][j],
"");
4406 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4407 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
4408 const MInt cellId = m_haloCells[i][j];
4410 nghrDomFlag[cellId][i] =
true;
4412 if(m_maxPartitionLevelShift > 0) {
4413 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
4414 MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
4415 MInt maxNghbrDomId =
4416 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)));
4417 for(
MInt k = 0; k < noNeighborDomains(); k++) {
4418 if(m_nghbrDomains[k] >= minNghbrDomId && m_nghbrDomains[k] <= maxNghbrDomId) {
4419 nghrDomFlag[cellId][k] =
true;
4420 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4421 MInt childId = a_childId(cellId, child);
4423 nghrDomFlag[childId][k] =
true;
4433 map<MInt, MInt> solverCellsAdded;
4434 solverCellsAdded.clear();
4439 for(
MInt layer = 0; layer < m_noHaloLayers; layer++) {
4440 nghrDomFlagBak.assign(nghrDomFlag.begin(), nghrDomFlag.end());
4442 for(
MInt cellId : exchangeCellList) {
4443 if(a_level(cellId) > (level + 1))
continue;
4444 if(a_level(cellId) < (level + 1) && a_noChildren(cellId) > 0)
continue;
4445 const MInt counter = getAdjacentGridCells(cellId, nghbrList, level);
4447 for(
MInt n = 0; n < counter; n++) {
4448 MInt nghbrId = nghbrList[n];
4449 if(nghbrId < 0)
continue;
4456 for(
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4457 if(!treeb().solver(nghbrId, solverId) && layer < m_noSolverHaloLayers[solverId] ) {
4458 solverCellsAdded.insert(make_pair(nghbrId, solverId));
4463 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4464 if(nghrDomFlagBak[nghbrId][i]) {
4465 nghrDomFlag[cellId][i] =
true;
4486 if(m_maxPartitionLevelShift > 0) {
4487 MInt rootId = a_parentId(cellId) > -1 ? a_parentId(cellId) : cellId;
4488 if(a_hasProperty(rootId, Cell::IsPartLvlAncestor)) {
4489 MInt minNghbrDomId = findNeighborDomainId(a_globalId(rootId));
4490 MInt maxNghbrDomId =
4491 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(rootId) + (
MLong)a_noOffsprings(rootId)));
4492 for(
MInt k = 0; k < noNeighborDomains(); k++) {
4493 if(m_nghbrDomains[k] >= minNghbrDomId && m_nghbrDomains[k] <= maxNghbrDomId) {
4494 nghrDomFlag[cellId][k] =
true;
4503 if(!solverCellsAdded.empty()) {
4504 nghrDomFlagBak2.assign(nghrDomFlag.begin(), nghrDomFlag.end());
4506 for(map<MInt, MInt>::iterator it = solverCellsAdded.begin(); it != solverCellsAdded.end(); it++) {
4507 const MInt cellId = it->first;
4508 const MInt solverId = it->second;
4513 const MInt counter = getAdjacentGridCells(cellId, nghbrList, level,
true);
4515 MBool anyNeighbor =
false;
4516 const MInt size = noNeighborDomains();
4518 fill(addedCell.
begin(), addedCell.
end(),
false);
4519 for(
MInt n = 0; n < counter; n++) {
4520 const MInt nghbrId = nghbrList[n];
4521 if(nghbrId < 0)
continue;
4522 MInt parentId = a_parentId(cellId);
4524 if(!treeb().solver(parentId, solverId))
continue;
4528 MBool checkParentChilds =
false;
4529 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4530 MInt childId = a_childId(cellId, child);
4532 if(!treeb().solver(childId, solverId)) {
4533 checkParentChilds =
true;
4538 if(checkParentChilds)
continue;
4540 if(treeb().solver(nghbrId, solverId)) anyNeighbor =
true;
4543 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4544 if(nghrDomFlagBak2[nghbrId][i]) {
4545 if(!nghrDomFlag[cellId][i]) {
4546 addedCell[i] =
true;
4548 nghrDomFlag[cellId][i] =
true;
4558 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4560 nghrDomFlag[cellId][i] =
false;
4566 solverCellsAdded.clear();
4567 nghrDomFlagBak2.clear();
4573 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4574 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
4575 MInt cellId = m_windowCells[i][j];
4576 if(a_level(cellId) == level) {
4577 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4578 MInt childId = a_childId(cellId, child);
4580 if(nghrDomFlag[childId][i]) {
4581 refineChildIds[m_maxNoChilds * cnt + child] = 1;
4582 }
else if(testingFix_partitionLevelShift && a_level(cellId) < m_minLevel + m_maxPartitionLevelShift) {
4583 refineChildIds[m_maxNoChilds * cnt + child] = 1;
4608 auto newNghbrDomainsIndex = m_nghbrDomainIndex;
4609 auto newNghbrDomains = m_nghbrDomains;
4612 std::set<MInt> allWindows;
4619 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4620 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
4621 const MInt cellId = m_haloCells[i][j];
4624 ASSERT(a_level(cellId)<=level || m_maxPartitionLevelShift>0,
"");
4625 if (a_level(cellId)>level)
continue;
4631 if (a_level(cellId)==level || (a_noChildren(cellId)==0 && a_level(cellId)<level)) {
4632 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4636 if (treeb().solver(cellId, solverId)) {
4637 exchangeCellList.insert({std::make_tuple(0, cellId, i, solverId)});
4643 if (a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
4644 if (a_level(cellId)==level || (a_noChildren(cellId)==0 && a_level(cellId)<level)) {
4647 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
4648 const MInt maxNghbrDomId =
4649 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
4651 for (
MInt nghbrDom = minNghbrDomId; nghbrDom <= maxNghbrDomId; ++nghbrDom) {
4652 MInt k = newNghbrDomainsIndex[nghbrDom];
4653 if (nghbrDom==domainId())
continue;
4657 k = newNghbrDomains.size();
4658 newNghbrDomainsIndex[nghbrDom] = k;
4659 newNghbrDomains.push_back(nghbrDom);
4663 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4667 if (treeb().solver(cellId, solverId)) {
4668 exchangeCellList.insert({std::make_tuple(0, cellId, k, solverId)});
4670 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4671 const MInt childId = a_childId(cellId, child);
4676 const MInt minNghbrDomId2 = findNeighborDomainId(a_globalId(childId));
4677 const MInt maxNghbrDomId2 =
4678 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(childId) + (
MLong)a_noOffsprings(childId)-1));
4679 MInt lay = (newNghbrDomains[k] >= minNghbrDomId2 && newNghbrDomains[k] <= maxNghbrDomId2) ? 0 : 1;
4681 if (a_isHalo(childId)) lay = 0;
4683 exchangeCellList.insert({std::make_tuple(lay, childId, k, solverId)});
4684 if (!a_isHalo(childId)) {
4685 if (treeb().solver(childId, solverId)) {
4689 m_windowLayer_[setNeighborDomainIndex(nghbrDom, m_haloCells, m_windowCells, m_windowLayer_)][childId].set(solverId, lay);
4708 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4709 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
4710 const MInt cellId = m_windowCells[i][j];
4712 allWindows.insert(cellId);
4713 TERMM_IF_COND(m_windowLayer_[i].find(cellId)==m_windowLayer_[i].end(), std::to_string(m_maxPartitionLevelShift));
4714 TERMM_IF_COND(m_windowLayer_[i].at(cellId).all(),
"");
4717 if (a_level(cellId)==level) {
4718 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4719 const MInt windowLayer = m_windowLayer_[i].at(cellId).get(solverId);
4721 if (!a_hasChildren(cellId, solverId) && windowLayer<m_noSolverHaloLayers[solverId]) {
4725 exchangeCellList.insert({std::make_tuple(windowLayer, cellId, i, solverId)});
4732 if (a_hasProperty(cellId, Cell::IsPartLvlAncestor) && a_level(cellId)==level) {
4733 ASSERT(a_noChildren(cellId)>0,
"");
4734 ASSERT(!a_isHalo(cellId),
"");
4736 MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
4737 MInt maxNghbrDomId =
4738 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
4742 for (
MInt nD = minNghbrDomId; nD<=maxNghbrDomId; ++nD) {
4743 if (nD==domainId())
continue;
4744 MBool found =
false;
4745 for (
MInt ii = 0; ii < noNeighborDomains(); ii++) {
4746 if (m_nghbrDomains[ii]== nD) {
4751 TERMM_IF_NOT_COND(found, to_string(a_isHalo(cellId)) +
" " + to_string(a_noOffsprings(cellId)));
4754 if(m_nghbrDomains[i] >= minNghbrDomId && m_nghbrDomains[i] <= maxNghbrDomId) {
4757 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4758 if (treeb().solver(cellId, solverId)) {
4759 exchangeCellList.insert({std::make_tuple(0, cellId, i, solverId)});
4764 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4765 const MInt childId = a_childId(cellId, child);
4767 if (childId<0)
continue;
4771 minNghbrDomId = findNeighborDomainId(a_globalId(childId));
4773 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(childId) + (
MLong)a_noOffsprings(childId)-1));
4777 MInt lay = (m_nghbrDomains[i] >= minNghbrDomId && m_nghbrDomains[i] <= maxNghbrDomId) ? 0 : 1;
4779 if (a_isHalo(childId)) lay = 0;
4781 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4784 if (treeb().solver(cellId, solverId)) {
4785 exchangeCellList.insert({std::make_tuple(lay, childId, i, solverId)});
4786 if (!a_isHalo(childId)) {
4787 if (treeb().solver(childId, solverId)) {
4789 m_windowLayer_[i][childId].set(solverId, lay);
4802 std::vector<std::unordered_map<MInt, M32X4bit<true>>> haloLayer_(newNghbrDomains.size());
4803 for(
MInt layer = 0; layer < m_noHaloLayers; layer++) {
4805 const auto it_begin = exchangeCellList.lower_bound(std::make_tuple(layer,std::numeric_limits<MInt>::min(),
4806 std::numeric_limits<MInt>::min(),std::numeric_limits<MInt>::min()));
4807 const auto it_end = exchangeCellList.upper_bound(std::make_tuple(layer,std::numeric_limits<MInt>::max(),
4808 std::numeric_limits<MInt>::max(),std::numeric_limits<MInt>::max()));
4809 const MInt noCandidates = std::distance(it_begin, it_end);
4812 for (
auto it = it_begin; it!=it_end;) {
4813 const MInt cellId = get<1>(*it);
4814 TERMM_IF_NOT_COND(cellId > -1 && cellId < m_tree.size(),
"");
4815 const MBool isHaloCellId = a_isHalo(cellId);
4823 TERMM_IF_COND(a_level(cellId)==level+1 && allWindows.find(a_parentId(cellId))==allWindows.end()
4824 && !a_hasProperty(a_parentId(cellId), Cell::IsPartLvlAncestor),
"");
4830 const MInt counter = a_level(cellId)==level+1 ? getAdjacentGridCells5<false,false>(cellId, nghbrList.
data())
4831 : (isHaloCellId ? getAdjacentGridCells5<true,true>(cellId, nghbrList.
data())
4832 : getAdjacentGridCells5<true,false>(cellId, nghbrList.
data(), level+1));
4836 while (cnt<noCandidates && cellId==get<1>(*it)) {
4837 ASSERT(get<0>(*it)==layer,
"Send a bug report to the C++ vendor!");
4838 const MInt nghbrDomIdx = get<2>(*it);
4839 const MInt solverId = get<3>(*it);
4841 for(
MInt n = 0; n < counter; n++) {
4842 const MInt nghbrId = nghbrList[n];
4843 ASSERT(nghbrId > -1 && nghbrId < m_tree.size(), to_string(nghbrId) +
"|" + to_string(m_tree.size()));
4844 ASSERT(a_level(nghbrId)<=level+1, to_string(a_level(nghbrId)) +
"|" + to_string(level+1));
4847 if (!treeb().solver(nghbrId, solverId))
continue;
4853 const MBool isHalo = a_isHalo(nghbrId);
4855 if (m_maxPartitionLevelShift==0) {
4856 TERMM_IF_COND(isHalo && (allWindows.find(a_parentId(nghbrId))!=allWindows.end()
4857 || allWindows.find(nghbrId)!=allWindows.end()),
"");
4862 if (!isHalo && a_level(nghbrId)<level+1)
continue;
4865 if (a_level(nghbrId)==level+1 && !a_isHalo(a_parentId(nghbrId)) && !isSolverWindowCell(nghbrDomIdx, a_parentId(nghbrId), solverId))
4870 TERMM_IF_COND(!isHalo
4871 && allWindows.find(a_parentId(nghbrId))==allWindows.end()
4872 && allWindows.find(nghbrId)!=allWindows.end()
4873 && !a_hasProperty(a_parentId(nghbrId), Cell::IsPartLvlAncestor),
"");
4876 if (m_maxPartitionLevelShift==0) {
4877 TERMM_IF_COND(a_level(nghbrId)==level+1 && allWindows.find(a_parentId(nghbrId))==allWindows.end(),
"");
4897 MInt nghbrDomIdx2 = nghbrDomIdx;
4898 if (m_maxPartitionLevelShift>0) {
4900 const MInt ndom = newNghbrDomains[nghbrDomIdx];
4902 nghbrDomIdx2 = setNeighborDomainIndex(ndom, m_haloCells, m_windowCells, m_windowLayer_);
4905 const MInt windowLayer = isHalo ? haloLayer_[nghbrDomIdx][nghbrId].get(solverId)
4906 : m_windowLayer_[nghbrDomIdx2][nghbrId].get(solverId);
4908 if (windowLayer>layer+1) {
4910 isHalo ? haloLayer_[nghbrDomIdx][nghbrId].set(solverId, layer+1)
4911 : m_windowLayer_[nghbrDomIdx2].at(nghbrId).set(solverId, layer+1);
4912 ASSERT((isHalo && haloLayer_[nghbrDomIdx][nghbrId].get(solverId)==layer+1)
4913 || (!isHalo && m_windowLayer_[nghbrDomIdx2].at(nghbrId).get(solverId)==layer+1),
"");
4915 if (layer+1<m_noSolverHaloLayers[solverId])
4916 exchangeCellList.insert({std::make_tuple(layer+1, nghbrId, nghbrDomIdx, solverId)});
4923 if (cnt==noCandidates)
break;
4929 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4930 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
4931 MInt cellId = m_windowCells[i][j];
4932 if(a_level(cellId) == level) {
4933 for(
MInt child = 0; child < m_maxNoChilds; child++) {
4934 const MInt childId = a_childId(cellId, child);
4936 if (m_windowLayer_[i].find(childId)!=m_windowLayer_[i].end()) {
4937 ASSERT(!m_windowLayer_[i].at(childId).all(),
"");
4938 refineChildIds[m_maxNoChilds * cnt + child] = 1;
4959 const std::vector<std::function<
void(
const MInt)>>& removeCellSolver) {
4970 for(
MInt i = 0; i < noNeighborDomains(); i++) {
4971 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
4972 const MInt cellId = m_haloCells[i][j];
4973 halos.insert(cellId);
4978 std::unordered_map<MInt, M32X4bit<true>> haloLayers;
4981 for (
MInt level = m_minLevel; level <= maxLevel; level++) {
4985 for (
MInt i = 0; i < noNeighborDomains(); i++) {
4986 for (
auto& item : m_windowLayer_[i]) {
4987 const MInt cellId = item.first;
4989 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
4991 if (a_level(cellId)==level || (a_level(cellId)==level-1 && !a_hasChildren(cellId, solverId))) {
4992 if (item.second.get(solverId)<=1) {
4993 ASSERT(m_tree.solver(cellId, solverId),
"Cell was identifed to be a valid windowCell for"
4994 " solver=" + to_string(solverId) +
", but does not belong to that solver");
4995 exchangeCellList.insert({std::make_tuple(0, cellId, solverId)});
5002 for (
const auto& item : haloLayers) {
5003 const MInt cellId = item.first;
5004 if (a_level(cellId)==level-1) {
5005 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5006 const MInt haloLayer = item.second.get(solverId);
5007 if (!a_hasChildren(cellId, solverId) && haloLayer<m_noSolverHaloLayers[solverId]) {
5008 exchangeCellList.insert({std::make_tuple(haloLayer, cellId, solverId)});
5027 if (m_maxPartitionLevelShift>0) {
5028 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
5029 const MInt cellId = m_haloCells[i][j];
5030 if (a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
5031 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
5032 const MInt maxNghbrDomId =
5033 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
5034 if (domainId()<minNghbrDomId || domainId()>maxNghbrDomId)
continue;
5035 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5036 if (m_tree.solver(cellId, solverId) && a_hasChildren(cellId, solverId)) {
5041 if (a_level(cellId)==level || (a_level(cellId)==level-1 && !a_hasChildren(cellId, solverId))) {
5042 exchangeCellList.insert({std::make_tuple(0, cellId, solverId)});
5045 haloLayers[cellId].set(solverId,0);
5057 for(
MInt layer = 0; layer < m_noHaloLayers; layer++) {
5059 const auto it_begin = exchangeCellList.lower_bound(std::make_tuple(layer,std::numeric_limits<MInt>::min(),
5060 std::numeric_limits<MInt>::min()));
5061 const auto it_end = exchangeCellList.upper_bound(std::make_tuple(layer,std::numeric_limits<MInt>::max(),
5062 std::numeric_limits<MInt>::min()));
5063 const MInt noCandidates = std::distance(it_begin, it_end);
5066 for (
auto it = it_begin; it!=it_end;) {
5067 const MInt cellId = get<1>(*it);
5068 ASSERT(cellId > -1 && cellId < m_tree.size(),
"");
5070 const MInt counter = a_level(cellId)==level ? getAdjacentGridCells5<false,false>(cellId, nghbrList.
data())
5071 : getAdjacentGridCells5<true,false>(cellId, nghbrList.
data(), level);
5077 while (cnt<noCandidates && cellId==get<1>(*it)) {
5078 ASSERT(get<0>(*it)==layer,
"Send a bug report to the C++ vendor!");
5079 const MInt solverId = get<2>(*it);
5082 for(
MInt n = 0; n < counter; n++) {
5083 const MInt nghbrId = nghbrList[n];
5084 ASSERT(nghbrId > -1 && nghbrId < m_tree.size(),
"");
5113 TERMM_IF_NOT_COND(a_level(nghbrId)==level,
"");
5115 TERMM_IF_NOT_COND(((halos.find(nghbrId)!=halos.end())==(findNeighborDomainId(a_globalId(nghbrId))!=domainId()))
5116 || a_hasProperty(nghbrId, Cell::IsPeriodic) || !treeb().solver(nghbrId, solverId),
"");
5120 if (!a_isHalo(nghbrId) || !treeb().solver(nghbrId, solverId))
5123 const MInt haloLayer = haloLayers[nghbrId].get(solverId);
5125 if (haloLayer>layer+1) {
5127 haloLayers[nghbrId].set(solverId, layer+1);
5128 ASSERT(haloLayers[nghbrId].get(solverId)==layer+1,
"");
5130 if (layer+1<m_noSolverHaloLayers[solverId])
5131 exchangeCellList.insert({std::make_tuple(layer+1, nghbrId, solverId)});
5137 if (cnt==noCandidates)
5145 std::unordered_map<MInt,M8X1bit<false>> validHalos;
5146 for (
auto it = haloLayers.cbegin(); it!=haloLayers.cend(); ++it) {
5147 const MInt cellId = it->first;
5148 ASSERT(validHalos.find(cellId)==validHalos.end(),
"Duplicate halo cells!");
5149 auto& flag = validHalos[cellId];
5150 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5151 if (it->second.get(solverId)<=m_noSolverHaloLayers[solverId]) {
5152 ASSERT(m_tree.solver(cellId,solverId),
"");
5153 flag.set(solverId,1);
5160 for (
const auto& item : validHalos) {
5161 MInt parentId = item.first;
5162 while (a_parentId(parentId)>-1) {
5163 parentId = a_parentId(parentId);
5164 const auto it = validHalos.find(parentId);
5168 TERMM_IF_NOT_COND(m_maxPartitionLevelShift>0 || (a_isHalo(parentId) && it!=validHalos.end()),
"");
5169 TERMM_IF_NOT_COND(m_maxPartitionLevelShift>0 || a_hasProperty(parentId, Cell::IsPeriodic) || findNeighborDomainId(a_globalId(parentId))!=domainId(),
"");
5170 TERMM_IF_NOT_COND(it!=validHalos.end() || (a_hasProperty(parentId, Cell::IsPartLvlAncestor) && !a_isHalo(parentId)),
"");
5172 if (it==validHalos.end())
break;
5174 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5175 TERMM_IF_COND(item.second.get(solverId) && !it->second.get(solverId),
" solverId=" + to_string(solverId) +
5176 ": Parent of valid halo cell is no halo!");
5186 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
5187 MInt receiveCount = 0;
5188 for (
const auto& vecWindow : m_windowCells) receiveCount+=vecWindow.size();
5190 for (
MInt i = 0, offset = 0; i < noNeighborDomains(); i++) {
5191 const MInt noWindowCells = m_windowCells[i].size();
5192 if (noWindowCells<1)
continue;
5195 m_nghbrDomains[i], mpiComm(), &recvRequests[i], AT_,
"windowBuffer[offset]");
5197 offset += noWindowCells;
5202 const MInt tmpScratchSize = m_tree.size();
5204 isHaloPartLvlAncestor.
fill(
false);
5207 if(m_maxPartitionLevelShift > 0) {
5208 for(
auto& i : m_partitionLevelAncestorIds) {
5209 ASSERT(a_hasProperty(i, Cell::IsPartLvlAncestor),
5210 "cell is not a partition level ancestor: " + std::to_string(i));
5212 if(a_hasProperty(i, Cell::IsHalo)) {
5213 isHaloPartLvlAncestor[i] =
true;
5217 for(
MInt child = 0; child < m_maxNoChilds; child++) {
5218 const MInt childId = a_childId(i, child);
5219 if(childId > -1 && a_isHalo(childId)) {
5220 isHaloPartLvlAncestor[childId] =
true;
5228 MBool operator()(
const std::pair<MInt, MInt>& m1,
const std::pair<MInt, MInt>& m2)
const {
5229 if(m1.first < m2.first) {
5231 }
else if (m1.first==m2.first) {
5232 if(m1.second < m2.second) {
5243 const MInt threesholdLvl = !duringMeshAdaptation ? 0 : m_maxUniformRefinementLevel;
5245 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
5247 for (
const auto& vecHalo : m_haloCells) sendCount+=vecHalo.size();
5250 for (
MInt i = 0, idx = 0; i < noNeighborDomains(); i++) {
5251 if (m_maxPartitionLevelShift==0) toDelete.clear();
5252 const MInt offset = idx;
5253 const MInt noHaloCells = m_haloCells[i].size();
5254 if (noHaloCells<1)
continue;
5255 std::vector<MInt> haloCells;
5256 haloCells.reserve(noHaloCells);
5259 ScratchSpace<MBool> isDuplicateHalo(m_noPeriodicCartesianDirs>0 ? m_tree.size() : 1, AT_,
"isDuplicateHalo");
5260 isDuplicateHalo.
fill(
false);
5261 if (m_noPeriodicCartesianDirs>0) {
5262 std::map<MLong,MInt> haloGlobalIds;
5263 for (
const auto cellId : m_haloCells[i]) {
5264 const MLong globalId = a_globalId(cellId);
5265 if (haloGlobalIds.find(globalId)!=haloGlobalIds.end()) {
5266 isDuplicateHalo[haloGlobalIds[globalId]] =
true;
5267 isDuplicateHalo[cellId] =
true;
5269 haloGlobalIds.insert({std::make_pair(globalId, cellId)});
5273 for (
const auto cellId : m_haloCells[i]) {
5274 const MBool isValidHalo = validHalos.find(cellId)!=validHalos.
end();
5278 const MInt minNghbrDomId1 = findNeighborDomainId(a_globalId(cellId));
5279 const MInt maxNghbrDomId1 =
5280 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
5281 if (domainId()>=minNghbrDomId1 && domainId()<=maxNghbrDomId1 && !a_hasProperty(cellId, Cell::IsPeriodic))
5282 TERMM_IF_NOT_COND(!a_hasProperty(cellId, Cell::IsPartLvlAncestor) || isValidHalo,
"Cell is partLvlAncestor, but not found as valid halo!");
5287 const M8X1bit<> solver = (a_level(cellId)<=threesholdLvl
5288 || isHaloPartLvlAncestor[cellId]
5289 || (m_noPeriodicCartesianDirs>0 && isDuplicateHalo[cellId]))
5292 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5293 if (m_tree.solver(cellId,solverId) && !solver.
get(solverId)) {
5294 auto key = std::make_pair(-a_level(cellId),cellId);
5295 toDelete[key].set(solverId,
true);
5297 if (a_level(cellId)>threesholdLvl && !isHaloPartLvlAncestor[cellId] && m_tree.solver(cellId,solverId))
5298 m_tree.solver(cellId,solverId) = solver.
get(solverId);
5300 tmp_data[idx++] = solver.
data();
5301 if (m_tree.solverBits(cellId).any() || isHaloPartLvlAncestor[cellId]) {
5302 haloCells.push_back(cellId);
5314 toDelete.insert({std::make_pair(-a_level(cellId),cellId),
M8X1bit<false>()});
5317 m_haloCells[i] = haloCells;
5318 if (m_maxPartitionLevelShift==0) {
5321 for (
const auto& item : toDelete) {
5322 const MInt cellId = item.first.second;
5323 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5324 if (!removeCellSolver.empty() && item.second.get(solverId)) {
5325 removeCellSolver[solverId](cellId);
5328 if (m_tree.solverBits(cellId).none()) {
5329 ASSERT(!isHaloPartLvlAncestor[cellId],
"");
5330 removeCell<false>(cellId);
5336 ASSERT(idx-offset==noHaloCells,
"");
5339 mpiComm(), &sendRequests[i], AT_,
"tmp_data");
5341 if (m_maxPartitionLevelShift>0) {
5342 for (
const auto& item : toDelete) {
5343 const MInt cellId = item.first.second;
5344 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5345 if (!removeCellSolver.empty() && item.second.get(solverId)) {
5346 removeCellSolver[solverId](cellId);
5349 if (m_tree.solverBits(cellId).none()) {
5350 removeCell<false>(cellId);
5356 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
5357 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
5359 for (
MInt i = 0, idx = 0; i < noNeighborDomains(); i++) {
5361 std::vector<MInt> windowCells;
5362 windowCells.reserve(m_windowCells[i].size());
5363 for (
const auto cellId : m_windowCells[i]) {
5364 ASSERT(m_windowLayer_[i].find(cellId)!=m_windowLayer_[i].end(),
"");
5366 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5367 if (!solver.
get(solverId) && isSolverWindowCell(i,cellId,solverId))
5368 m_windowLayer_[i].at(cellId).set(solverId, m_noHaloLayers+1);
5370 MBool validWindow =
false;
5371 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5372 if (isSolverWindowCell(i,cellId,solverId)) {
5373 windowCells.push_back(cellId);
5378 ASSERT(solver.
any()==validWindow,
"");
5382 const MBool ok = m_windowLayer_[i].erase(cellId);
5384 MBool isWindow =
false;
5385 for (
const auto& w : m_windowLayer_) {
5386 if (w.find(cellId)!=w.end()) {
5392 a_hasProperty(cellId, Cell::IsWindow) =
false;
5395 m_windowCells[i] = windowCells;
5398 if (!duringMeshAdaptation)
5418 std::vector<std::unordered_map<MInt, M32X4bit<true>>> haloLayer_(noNeighborDomains());
5420 ASSERT(m_windowLayer_.empty(),
"");
5421 m_windowLayer_.resize(noNeighborDomains());
5423 if(m_maxPartitionLevelShift > 0) {
5428 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
5429 if(a_isHalo(cellId) || a_isToDelete(cellId)) {
5432 bprops(cellId, 0) = (
MInt)a_hasProperty(cellId, Cell::IsPartLvlAncestor);
5433 bprops(cellId, 1) = a_noOffsprings(cellId);
5435 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
5436 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
5437 + std::to_string(bprops(cellId, 1)));
5444 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5445 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
5446 const MInt cellId = m_haloCells[i][j];
5447 ASSERT(!a_isToDelete(cellId),
"");
5448 ASSERT(bprops(cellId, 0) > -1 && bprops(cellId, 1) > 0,
5449 std::to_string(cellId) +
" " + std::to_string(bprops(cellId, 0)) +
" "
5450 + std::to_string(bprops(cellId, 1)));
5451 a_hasProperty(cellId, Cell::IsPartLvlAncestor) = (
MBool)bprops(cellId, 0);
5452 a_noOffsprings(cellId) = bprops(cellId, 1);
5458 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5459 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
5460 const MInt cellId = m_haloCells[i][j];
5461 ASSERT(a_level(cellId)==level,
"We expect all halo cells at this point to be on minLevel");
5465 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5468 exchangeCellList.insert({std::make_tuple(0, cellId, i, solverId)});
5471 if(m_maxPartitionLevelShift > 0) {
5472 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
5473 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
5474 const MInt maxNghbrDomId =
5475 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
5476 for(
MInt k = 0; k < noNeighborDomains(); k++) {
5477 if(m_nghbrDomains[k] >= minNghbrDomId && m_nghbrDomains[k] <= maxNghbrDomId) {
5480 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5483 exchangeCellList.insert({std::make_tuple(0, cellId, k, solverId)});
5493 vector<std::set<MInt>> windCellSet(noNeighborDomains());
5494 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5495 windCellSet[i].insert(m_windowCells[i].begin(), m_windowCells[i].end());
5498 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5499 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
5500 const MInt cellId = m_windowCells[i][j];
5502 if (a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
5503 const MInt minNghbrDomId = findNeighborDomainId(a_globalId(cellId));
5504 const MInt maxNghbrDomId =
5505 findNeighborDomainId(
mMin(m_noCellsGlobal - 1, a_globalId(cellId) + (
MLong)a_noOffsprings(cellId)-1));
5507 for (
MInt nD = minNghbrDomId; nD<=maxNghbrDomId; ++nD) {
5508 if (nD==domainId())
continue;
5509 MBool found =
false;
5510 for (
MInt ii = 0; ii < noNeighborDomains(); ii++) {
5511 if (m_nghbrDomains[ii]== nD) {
5516 TERMM_IF_NOT_COND(found, to_string(a_isHalo(cellId)) +
" " + to_string(a_noOffsprings(cellId)));
5519 for (
MInt solverId = 0; solverId < treeb().noSolvers(); solverId++) {
5520 if (treeb().solver(cellId, solverId)) {
5523 if(m_nghbrDomains[i] >= minNghbrDomId && m_nghbrDomains[i] <= maxNghbrDomId) {
5524 TERMM_IF_NOT_COND(windCellSet[i].find(cellId)!=windCellSet[i].end(),
"");
5525 m_windowLayer_[i][cellId].set(solverId, 0);
5526 exchangeCellList.insert({std::make_tuple(0, cellId, i, solverId)});
5538 for(
MInt layer = 0; layer < m_noHaloLayers; layer++) {
5540 const auto it_begin = exchangeCellList.lower_bound(std::make_tuple(layer,std::numeric_limits<MInt>::min(),
5541 std::numeric_limits<MInt>::min(), std::numeric_limits<MInt>::min()));
5542 const auto it_end = exchangeCellList.upper_bound(std::make_tuple(layer+1,std::numeric_limits<MInt>::min(),
5543 std::numeric_limits<MInt>::min(), std::numeric_limits<MInt>::min()));
5544 const MInt noCandidates = std::distance(it_begin, it_end);
5547 for (
auto it = it_begin; it!=it_end;) {
5548 ASSERT(get<0>(*it)==layer,
"Send a bug report to the C++ vendor!");
5549 const MInt cellId = get<1>(*it);
5552 const MInt counter = getAdjacentGridCells5<false,false>(cellId, nghbrList.
data());
5554 while (cnt<noCandidates && cellId==get<1>(*it)) {
5555 ASSERT(get<0>(*it)==layer,
"Send a bug report to the C++ vendor!");
5556 const MInt nghbrDomIdx = get<2>(*it);
5557 ASSERT((
signed)m_windowLayer_.size()>nghbrDomIdx,
"");
5558 const MInt solverId = get<3>(*it);
5560 for(
MInt n = 0; n < counter; n++) {
5561 const MInt nghbrId = nghbrList[n];
5562 ASSERT(a_level(nghbrId)==level,
"Nghbr expected to be on same level");
5568 const MBool isHalo = a_isHalo(nghbrId);
5569 if (!isHalo && !treeb().solver(nghbrId, solverId))
continue;
5572 if (!isHalo && windCellSet[nghbrDomIdx].find(nghbrId)==windCellSet[nghbrDomIdx].end() && m_maxPartitionLevelShift>0)
continue;
5574 TERMM_IF_COND(!isHalo && windCellSet[nghbrDomIdx].find(nghbrId)==windCellSet[nghbrDomIdx].end(),
"This must be a window cell!");
5577 MInt windowLayer = isHalo ? haloLayer_[nghbrDomIdx][nghbrId].get(solverId)
5578 : m_windowLayer_[nghbrDomIdx][nghbrId].get(solverId);
5579 if (windowLayer>layer+1) {
5581 isHalo ? haloLayer_[nghbrDomIdx][nghbrId].set(solverId, layer+1)
5582 : m_windowLayer_[nghbrDomIdx].at(nghbrId).set(solverId, layer+1);
5583 ASSERT((isHalo && haloLayer_[nghbrDomIdx][nghbrId].get(solverId)==layer+1)
5584 || (!isHalo && m_windowLayer_[nghbrDomIdx].at(nghbrId).get(solverId)==layer+1),
"");
5586 if (layer+1<m_noSolverHaloLayers[solverId])
5587 exchangeCellList.insert({std::make_tuple(layer+1, nghbrId, nghbrDomIdx, solverId)});
5593 if (cnt==noCandidates)
break;
5599 for (
MInt i = 0; i < noNeighborDomains(); ++i) {
5600 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
5601 const MInt cellId = m_windowCells[i][j];
5602 ASSERT(!a_isHalo(cellId),
"");
5603 if (m_windowLayer_[i].find(cellId)==m_windowLayer_[i].end()) {
5604 for (
MInt solverId = 0; solverId < treeb().noSolvers(); ++solverId)
5605 if (m_tree.solver(cellId, solverId)) {
5609 m_windowLayer_[i][cellId].set(solverId, a_hasProperty(cellId, Cell::IsPartLvlAncestor) ? 1 : (m_haloMode==2) ? m_noHaloLayers+1 : m_noSolverHaloLayers[solverId]);
5627 MBool diagonalNeighbors) {
5629 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
5631 if(a_hasNeighbor(cellId, dir0) > 0)
5632 nghbrId0 = a_neighborId(cellId, dir0);
5633 else if(a_parentId(cellId) > -1) {
5634 if(a_hasNeighbor(a_parentId(cellId), dir0) > 0) {
5635 nghbrId0 = a_neighborId(a_parentId(cellId), dir0);
5639 if(nghbrId0 < 0)
continue;
5640 if(a_noChildren(nghbrId0) > 0 && a_level(nghbrId0) <= level) {
5641 for(
MInt child = 0; child < m_maxNoChilds; child++) {
5642 if(!childCode[dir0][child])
continue;
5643 if(a_childId(nghbrId0, child) > -1) nghbrs.insert(a_childId(nghbrId0, child));
5646 nghbrs.insert(nghbrId0);
5649 if(diagonalNeighbors) {
5650 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
5651 if((dir1 / 2) == (dir0 / 2))
continue;
5653 if(a_hasNeighbor(nghbrId0, dir1) > 0)
5654 nghbrId1 = a_neighborId(nghbrId0, dir1);
5655 else if(a_parentId(nghbrId0) > -1)
5656 if(a_hasNeighbor(a_parentId(nghbrId0), dir1) > 0) nghbrId1 = a_neighborId(a_parentId(nghbrId0), dir1);
5657 if(nghbrId1 < 0)
continue;
5658 if(a_noChildren(nghbrId1) > 0 && a_level(nghbrId1) <= level) {
5659 for(
MInt child = 0; child < m_maxNoChilds; child++) {
5660 if(!childCode[dir0][child] || !childCode[dir1][child])
continue;
5661 if(a_childId(nghbrId1, child) > -1) nghbrs.insert(a_childId(nghbrId1, child));
5664 nghbrs.insert(nghbrId1);
5665 IF_CONSTEXPR(nDim == 3) {
5666 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
5667 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
5669 if(a_hasNeighbor(nghbrId1, dir2) > 0)
5670 nghbrId2 = a_neighborId(nghbrId1, dir2);
5671 else if(a_parentId(nghbrId1) > -1)
5672 if(a_hasNeighbor(a_parentId(nghbrId1), dir2) > 0) nghbrId2 = a_neighborId(a_parentId(nghbrId1), dir2);
5673 if(nghbrId2 < 0)
continue;
5674 if(a_noChildren(nghbrId2) > 0 && a_level(nghbrId2) <= level) {
5675 for(
MInt child = 0; child < m_maxNoChilds; child++) {
5676 if(!childCode[dir0][child] || !childCode[dir1][child] || !childCode[dir2][child])
continue;
5677 if(a_childId(nghbrId2, child) > -1) nghbrs.insert(a_childId(nghbrId2, child));
5680 nghbrs.insert(nghbrId2);
5689 for(
MInt nghbr : nghbrs) {
5690 ASSERT(a_level(nghbr) <= level + 1,
"");
5691 ASSERT(cnt < (
signed)adjacentCells.
size(),
"");
5692 adjacentCells[cnt] = nghbr;
5702template <MBool finer, MBool coarser>
5704 const MBool diagonalNeighbors) {
5705 static constexpr const MInt dimConverter[3][2] = {{1, 2}, {0, 2}, {0, 1}};
5708 if(diagonalNeighbors) {
5709 for(
MInt dim = 0; dim < nDim; ++dim) {
5711 getAdjacentGridCells1d5<finer, coarser>(nghbrs, cellId, dim, dimConverter[dim][0]);
5713 getAdjacentGridCells1d5<finer, coarser>(nghbrs, cellId, dim, dimConverter[dim][0], dimConverter[dim][1]);
5716 for(
MInt dim = 0; dim < nDim; ++dim) {
5717 getAdjacentGridCells1d5<finer, coarser>(nghbrs, cellId, dim);
5721 ASSERT(nghbrs.size() <= 27 * m_maxNoChilds,
"");
5723 if(!finer && !coarser) {
5725 const MInt noNghbrs = nghbrs.size();
5726 std::copy(nghbrs.begin(), nghbrs.end(), adjacentCells);
5728 }
else if(level == -1) {
5730 const MInt noNghbrs = nghbrs.size();
5731 std::copy(nghbrs.begin(), nghbrs.end(), adjacentCells);
5735 for(
auto cellId_ : nghbrs) {
5736 if(a_level(cellId_) == level) {
5737 adjacentCells[cnt++] = cellId_;
5749template <MBool finer, MBool coarser>
5751 const MInt dimNext,
const MInt dimNextNext,
5752 const uint_fast8_t childCodes) {
5755 for(
MInt dir = 2 * dim; dir < 2 * dim + 2; ++dir) {
5756 auto childCodes_ = childCodes & childCodePro[dir];
5757 if(a_hasNeighbor(cellId, dir) > 0) {
5758 const MInt nghbrId0 = a_neighborId(cellId, dir);
5759 if(finer && a_noChildren(nghbrId0) > 0) {
5761 MBool childFound =
false;
5762 for(
MInt child = 0; child < m_maxNoChilds; child++) {
5763 if( !childCode[dir][child])
continue;
5764 if(a_childId(nghbrId0, child) > -1) {
5765 const MInt childId = a_childId(nghbrId0, child);
5768 nghbrs.insert(childId);
5771 getAdjacentGridCells1d5<false, true>(nghbrs, childId, dimNext, dimNextNext, -1, childCodes_);
5772 if(dimNextNext > -1)
5773 getAdjacentGridCells1d5<false, true>(nghbrs, childId, dimNextNext, dimNext, -1, childCodes_);
5778 nghbrs.insert(nghbrId0);
5780 getAdjacentGridCells1d5<finer, coarser>(nghbrs, nghbrId0, dimNext, dimNextNext, -1, childCodes_);
5781 if(dimNextNext > -1)
5782 getAdjacentGridCells1d5<finer, coarser>(nghbrs, nghbrId0, dimNextNext, dimNext, -1, childCodes_);
5786 nghbrs.insert(nghbrId0);
5788 getAdjacentGridCells1d5<finer, coarser>(nghbrs, nghbrId0, dimNext, dimNextNext, -1, childCodes_);
5789 if(dimNextNext > -1)
5790 getAdjacentGridCells1d5<finer, coarser>(nghbrs, nghbrId0, dimNextNext, dimNext, -1, childCodes_);
5792 }
else if(coarser && a_parentId(cellId) > -1) {
5793 if(a_hasNeighbor(a_parentId(cellId), dir) > 0) {
5794 const MInt nghbrId0 = a_neighborId(a_parentId(cellId), dir);
5797 nghbrs.insert(nghbrId0);
5800 if(dimNext > -1) getAdjacentGridCells1d5<true, false>(nghbrs, nghbrId0, dimNext, dimNextNext, -1, childCodes_);
5801 if(dimNextNext > -1)
5802 getAdjacentGridCells1d5<true, false>(nghbrs, nghbrId0, dimNextNext, dimNext, -1, childCodes_);
5823 const MInt cellId,
const MLong*
const refineChildIds,
const MBool mayHaveChildren,
5824 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>>& cellOutsideSolver,
5826 static constexpr MInt noInternalConnections = (nDim == 2) ? 4 : 12;
5827 static constexpr MInt connectionDirs[12] = {1, 1, 3, 3, 1, 1, 3, 3, 5, 5, 5, 5};
5828 static constexpr MInt childs0[12] = {0, 2, 0, 1, 4, 6, 4, 5, 0, 1, 2, 3};
5829 static constexpr MInt childs1[12] = {1, 3, 2, 3, 5, 7, 6, 7, 4, 5, 6, 7};
5830 static constexpr MInt dirStencil[3][8] = {
5831 {0, 1, 0, 1, 0, 1, 0, 1}, {2, 2, 3, 3, 2, 2, 3, 3}, {4, 4, 4, 4, 5, 5, 5, 5}};
5832 static constexpr MInt sideIds[3][8] = {{0, 1, 0, 1, 0, 1, 0, 1}, {0, 0, 1, 1, 0, 0, 1, 1}, {0, 0, 0, 0, 1, 1, 1, 1}};
5833 static constexpr MInt revDir[6] = {1, 0, 3, 2, 5, 4};
5834 static constexpr MInt otherSide[2] = {1, 0};
5835 static constexpr MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
5836 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
5838 ASSERT(m_maxRfnmntLvl >= m_maxLevel,
"");
5839 if(a_level(cellId) >= m_maxRfnmntLvl)
return;
5841 const MInt childLevel = a_level(cellId) + 1;
5842 const MFloat childCellLength = cellLengthAtLevel(childLevel);
5844 MInt noOutsideChilds = 0;
5845 for(
MInt c = 0; c < m_maxNoChilds; c++) {
5849 if(!mayHaveChildren && a_childId(cellId, c) > -1) {
5853 if(a_childId(cellId, c) > -1)
continue;
5855 if(refineChildIds !=
nullptr && refineChildIds[c] < 0) {
5856 a_childId(cellId, c) = -1;
5861 for(
MInt i = 0; i < nDim; i++) {
5862 coords[i] = a_coordinate(cellId, i) + F1B2 * signStencil[c][i] * childCellLength;
5864 MInt allOutside = 0;
5865 if(!cellOutsideSolver.empty()) {
5867 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
5868 if(refineFlag[solver]) {
5869 isOutside[solver] = cellOutsideSolver[solver](coords, childLevel, cellId);
5871 isOutside[solver] = 1;
5873 allOutside =
mMin(allOutside, isOutside[solver]);
5876 if(allOutside > 0) {
5878 a_childId(cellId, c) = -1;
5883 if(m_freeIndices.size() > 0) {
5884 auto it = m_freeIndices.begin();
5886 m_freeIndices.erase(it);
5887 ASSERT(childId > -1 && childId < m_tree.size(),
"");
5889 childId = m_tree.size();
5893 for(
MInt i = 0; i < nDim; i++) {
5894 a_coordinate(childId, i) = coords[i];
5897 if(refineChildIds !=
nullptr) {
5898 a_globalId(childId) = refineChildIds[c];
5900 a_globalId(childId) = -1;
5903 treeb().resetSolver(childId);
5905 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
5906 if(refineFlag[solver] && isOutside[solver] < 1) treeb().solver(childId, solver) =
true;
5907 any = any || m_tree.solver(childId, solver);
5911 a_level(childId) = childLevel;
5913 a_childId(cellId, c) = childId;
5914 a_parentId(childId) = cellId;
5915 a_isToDelete(childId) =
false;
5916 a_resetProperties(childId);
5917 a_hasProperty(childId, Cell::IsHalo) = (refineChildIds !=
nullptr);
5921 for(
MInt k = 0; k < m_maxNoChilds; k++)
5922 a_childId(childId, k) = -1;
5923 for(
MInt d = 0; d < 2 * nDim; d++) {
5924 a_neighborId(childId, d) = -1;
5928 treeb().solver(childId, 0) =
true;
5931 treeb().resetIsLeafCell(childId);
5935 for(
MInt i = 0; i < nDim; i++) {
5936 nodeId[i] = sideIds[i][c] *
IPOW2(i);
5937 revNodeId[i] = otherSide[sideIds[i][c]] *
IPOW2(i);
5939 for(
MInt d = 0; d < nDim; d++) {
5940 const MInt dir = dirStencil[d][c];
5941 if(a_hasNeighbor(cellId, dir) == 0) {
5942 a_neighborId(childId, dir) = -1;
5943 }
else if(a_noChildren(a_neighborId(cellId, dir)) == 0) {
5944 a_neighborId(childId, dir) = -1;
5946 const MInt childNode = c - nodeId[d] + revNodeId[d];
5947 const MInt nghbrId = a_childId(a_neighborId(cellId, dir), childNode);
5949 a_neighborId(childId, dir) = -1;
5952 a_neighborId(childId, dir) = nghbrId;
5953 a_neighborId(nghbrId, revDir[dir]) = childId;
5956 a_hasProperty(childId, Cell::WasNewlyCreated) =
true;
5959 a_weight(childId) = 1.0;
5960 a_noOffsprings(childId) = 1;
5963 if(noOutsideChilds == m_maxNoChilds) {
5971 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>> cellOutsideEmpty;
5972 refineCell(cellId,
nullptr,
false, cellOutsideEmpty, refineFlag);
5977 ASSERT(noOutsideChilds < m_maxNoChilds,
5978 to_string(noOutsideChilds) +
"Check your geometry: all childs are outside or should not be refined! ");
5979 ASSERT(a_noChildren(cellId) > 0,
"");
5980 treeb().resetIsLeafCell(cellId);
5982 for(
MInt c = 0; c < noInternalConnections; c++) {
5983 const MInt dir = connectionDirs[c];
5984 const MInt child0 = a_childId(cellId, childs0[c]);
5985 const MInt child1 = a_childId(cellId, childs1[c]);
5986 if(child0 > -1 && child1 > -1) {
5987 a_neighborId(child0, dir) = child1;
5988 a_neighborId(child1, revDir[dir]) = child0;
5992 a_hasProperty(cellId, Cell::WasRefined) =
true;
6007 if(a_noChildren(cellId) <= 0) {
6008 mTerm(1, AT_,
"Unexpected situation 1 in CartesianGrid::removeChilds(MInt childId)");
6010 for(
MInt i = 0; i < m_maxNoChilds; i++) {
6011 const MInt childId = a_childId(cellId, i);
6014 removeCell<true>(childId);
6015 a_childId(cellId, i) = -1;
6018 treeb().resetIsLeafCell(cellId);
6021 a_hasProperty(cellId, Cell::WasCoarsened) =
true;
6030template <MBool removeChilds_>
6032 static constexpr MInt revDir[6] = {1, 0, 3, 2, 5, 4};
6034 ASSERT(cellId > -1 && cellId < treeb().size(),
"");
6035 ASSERT(a_noChildren(cellId) == 0,
"No children expected for child. ");
6036 ASSERT(!a_hasProperty(cellId, Cell::IsPartitionCell) || a_hasProperty(cellId, Cell::IsHalo),
6037 "Error: cannot remove non-halo partition cell");
6039 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6040 if(a_hasNeighbor(cellId, dir) > 0) {
6041 MInt nghbrId = a_neighborId(cellId, dir);
6042 if((nghbrId < 0) || (nghbrId >= treeb().size())) {
6044 "Unexpected situation 2 in CartesianGrid::removeChildIds() >> " + to_string(cellId) +
" " + to_string(dir)
6045 +
" " + to_string(nghbrId) +
" " + to_string(treeb().size()));
6047 a_neighborId(nghbrId, revDir[dir]) = -1;
6048 a_neighborId(cellId, dir) = -1;
6050 a_neighborId(cellId, dir) = -1;
6053 const MInt parentId = a_parentId(cellId);
6054 a_parentId(cellId) = -1;
6055 a_globalId(cellId) = -1;
6056 treeb().resetSolver(cellId);
6058 a_resetProperties(cellId);
6060 a_isToDelete(cellId) =
true;
6062 a_level(cellId) = -1;
6063 treeb().resetIsLeafCell(cellId);
6065 if(cellId == (treeb().size() - 1)) {
6066 treeb().size(treeb().size() - 1);
6068 m_freeIndices.insert(cellId);
6072 if(removeChilds_ || parentId == -1)
return;
6074 ASSERT(parentId < treeb().size(),
"");
6077 for(
MInt i = 0; i < m_maxNoChilds; i++) {
6078 if(a_childId(parentId, i) == cellId) {
6079 a_childId(parentId, i) = -1;
6085 treeb().resetIsLeafCell(parentId);
6086 for(
MInt solverId = 0; solverId < m_tree.noSolvers(); solverId++) {
6087 if(m_tree.solver(parentId, solverId)) {
6088 a_isLeafCell(parentId, solverId) =
6089 !a_hasChildren(parentId, solverId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor);
6110 MInt offset[6] = {2, 2, 4, 4, 6, 6};
6111 MInt offset2[4] = {2, 2, 0, 0};
6112 MInt allNeighbors[(nDim == 2) ? 8 : 12];
6113 MInt secondLevelNeighbors[8];
6115 IF_CONSTEXPR(nDim == 2) {
6116 MInt allNeighbors2D[8] = {0, 1, 2, 3, 0, 1, 2, 3};
6117 for(
MInt i = 0; i < 8; i++) {
6118 allNeighbors[i] = allNeighbors2D[i];
6122 MInt neighborCode2D[11] = {9, 0, 1, 9, 2, 6, 5, 9, 3, 7, 4};
6123 for(
MInt i = 0; i < 11; i++) {
6124 m_neighborCode[i] = neighborCode2D[i];
6128 MInt allNeighbors3D[12] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5};
6129 for(
MInt i = 0; i < 12; i++) {
6130 allNeighbors[i] = allNeighbors3D[i];
6134 MInt neighborCode3D[43] = {27, 0, 1, 27, 2, 6, 8, 27, 3, 7, 9, 27, 27, 27, 27, 27, 4, 10, 12, 27, 14, 18,
6135 22, 27, 16, 20, 24, 27, 27, 27, 27, 27, 5, 11, 13, 27, 15, 19, 23, 27, 17, 21, 25};
6136 for(
MInt i = 0; i < 43; i++) {
6137 m_neighborCode[i] = neighborCode3D[i];
6146 for(
MInt i = 0; i < nDim * 2; i++) {
6149 for(
MInt j = 0; j < (nDim * 2 - 2); j++) {
6152 for(
MInt k = 0; k < nDim * 2 - 2 - 2; k++) {
6160 mAlloc(m_paths1D, m_counter1D,
"m_paths1D", AT_);
6162 mAlloc(m_paths2D, m_counter2D, 2,
"m_paths2D", AT_);
6163 IF_CONSTEXPR(nDim == 3) {
6165 mAlloc(m_paths3D, m_counter3D, 3,
"m_paths3D", AT_);
6173 for(
MInt i = 0; i < nDim * 2; i++) {
6175 m_paths1D[m_counter1D] = allNeighbors[i];
6178 for(
MInt j = 0; j < (nDim * 2 - 2); j++) {
6180 secondLevelNeighbors[j] = allNeighbors[offset[i] + j];
6181 secondLevelNeighbors[j + nDim * 2 - 2] = allNeighbors[offset[i] + j];
6183 for(
MInt j = 0; j < (nDim * 2 - 2); j++) {
6185 m_paths2D[m_counter2D][0] = allNeighbors[i];
6186 m_paths2D[m_counter2D][1] = secondLevelNeighbors[j];
6189 IF_CONSTEXPR(nDim == 3) {
6190 MInt thirdLevelNeighbors[2];
6191 for(
MInt k = 0; k < nDim * 2 - 2 - 2; k++) {
6193 thirdLevelNeighbors[k] = secondLevelNeighbors[offset2[j] + k];
6195 m_paths3D[m_counter3D][0] = allNeighbors[i];
6196 m_paths3D[m_counter3D][1] = secondLevelNeighbors[j];
6197 m_paths3D[m_counter3D][2] = thirdLevelNeighbors[k];
6217 vector<vector<MFloat>>& sensors, vector<MFloat>& sensorWeight, vector<bitset<64>>& sensorCellFlag,
6218 vector<MInt>& sensorSolverId,
const std::vector<std::function<
void(
const MInt)>>& refineCellSolver,
6219 const std::vector<std::function<
void(
const MInt)>>& removeChildsSolver,
6220 const std::vector<std::function<
void(
const MInt)>>& removeCellSolver,
6221 const std::vector<std::function<
void(
const MInt,
const MInt)>>& swapCellsSolver,
6222 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>>& cellOutsideSolver,
6223 const std::vector<std::function<
void()>>& resizeGridMapSolver) {
6226 if(m_lowMemAdaptation) {
6227 this->meshAdaptationLowMem(sensors, sensorWeight, sensorCellFlag, sensorSolverId, refineCellSolver,
6228 removeChildsSolver, removeCellSolver, swapCellsSolver, cellOutsideSolver,
6229 resizeGridMapSolver);
6231 this->meshAdaptationDefault(sensors, sensorWeight, sensorCellFlag, sensorSolverId, refineCellSolver,
6232 removeChildsSolver, removeCellSolver, swapCellsSolver, cellOutsideSolver,
6233 resizeGridMapSolver);
6250 vector<vector<MFloat>>& sensors, vector<MFloat>& sensorWeight, vector<bitset<64>>& sensorCellFlag,
6251 vector<MInt>& sensorSolverId,
const std::vector<std::function<
void(
const MInt)>>& refineCellSolver,
6252 const std::vector<std::function<
void(
const MInt)>>& removeChildsSolver,
6253 const std::vector<std::function<
void(
const MInt)>>& removeCellSolver,
6254 const std::vector<std::function<
void(
const MInt,
const MInt)>>& swapCellsSolver,
6255 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>>& cellOutsideSolver,
6256 const std::vector<std::function<
void()>>& resizeGridMapSolver) {
6261 const MInt noCells = treeb().size();
6262 const MInt maxNoCells = m_maxNoCells;
6263 const MInt maxLevel =
mMin(m_maxRfnmntLvl, m_maxLevel + 1);
6265 const MInt noSensors = (signed)sensorWeight.size();
6266 ASSERT(sensorWeight.size() == sensors.size(),
"");
6267 ASSERT(sensorWeight.size() == sensorSolverId.size(),
"");
6272 ASSERT(m_freeIndices.empty(),
"");
6273 m_freeIndices.clear();
6275 for(
MInt c = 0; c < maxNoCells; c++) {
6276 refineFlag[c].reset();
6277 coarseFlag[c].reset();
6280 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6281 a_hasProperty(cellId, Cell::IsToDelete) =
false;
6282 a_hasProperty(cellId, Cell::WasNewlyCreated) =
false;
6283 a_hasProperty(cellId, Cell::WasCoarsened) =
false;
6284 a_hasProperty(cellId, Cell::WasRefined) =
false;
6288 a_hasProperty(cellId, Cell::IsWindow) =
false;
6296 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6297 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
6298 if(a_isToDelete(cellId))
continue;
6301 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
6305 for(
MInt s = 0; s < noSensors; s++) {
6306 if(sensorCellFlag[cellId][s]) {
6307 ASSERT(sensorWeight[s] < F0 || std::fabs(sensors[s][cellId]) < MFloatMaxSqrt,
6308 "invalid sensor value: " + std::to_string(sensors[s][cellId]));
6309 sensorCnt(s, 0) +=
POW2(sensors[s][cellId]);
6310 sensorCnt(s, 1) += F1;
6316 MPI_Allreduce(MPI_IN_PLACE, &sensorCnt(0), 2 * noSensors, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
6321 for(
MInt s = 0; s < noSensors; s++) {
6322 if(sensorWeight[s] < F0) {
6323 sensorThresholds(s, 0) = -1e-12;
6324 sensorThresholds(s, 1) = 1e-12;
6326 sensorThresholds(s, 1) = sensorWeight[s] * sqrt(
mMax(1e-14, (sensorCnt(s, 0) / sensorCnt(s, 1))));
6327 sensorThresholds(s, 0) = m_coarseRatio * sensorThresholds(s, 1);
6333 const MBool hasPartLvlShift = (m_maxPartitionLevelShift > 0);
6334 const MInt tmpScratchSize = (hasPartLvlShift) ? m_tree.size() : 1;
6338 isHaloPartLvlAncestor.
fill(
false);
6341 std::vector<std::vector<MInt>> oldWindowCells;
6342 std::vector<MInt> oldNoWindowCells;
6343 MInt totalNoWindowCells = 0;
6345 for(
MInt d = 0; d < noNeighborDomains(); d++) {
6346 oldWindowCells.push_back(m_windowCells[d]);
6347 oldNoWindowCells.push_back(noWindowCells(d));
6348 totalNoWindowCells += noWindowCells(d);
6351 MInt recvSize = (m_maxPartitionLevelShift > 0) ? totalNoWindowCells : 1;
6352 ScratchSpace<MBool> recvIsHaloPartLvlAncestor(recvSize, AT_,
"recvIsHaloPartLvlAncestor");
6354 if(m_maxPartitionLevelShift > 0) {
6355 for(
auto& i : m_partitionLevelAncestorIds) {
6356 TERMM_IF_NOT_COND(a_hasProperty(i, Cell::IsPartLvlAncestor),
6357 "cell is not a partition level ancestor: " + std::to_string(i));
6359 if(a_hasProperty(i, Cell::IsHalo)) {
6360 isHaloPartLvlAncestor[i] =
true;
6364 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6365 const MInt childId = a_childId(i, child);
6366 if(childId > -1 && a_isHalo(childId)) {
6367 isHaloPartLvlAncestor[childId] =
true;
6373 if(noNeighborDomains() > 0) {
6376 &recvIsHaloPartLvlAncestor[0]);
6378 TERMM(1,
"not working for compilation of paraview plugin");
6387 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
6388 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"");
6389 ASSERT(!a_isToDelete(cellId),
"");
6390 if(a_level(cellId) > m_maxUniformRefinementLevel) {
6391 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6392 if(!m_tree.solver(cellId, solver))
continue;
6393 if(a_hasChildren(cellId, solver))
continue;
6395 const MInt parentId = a_parentId(cellId, solver);
6396 ASSERT(parentId > -1,
"");
6398 if(a_isHalo(parentId) || a_hasProperty(parentId, Cell::IsPartLvlAncestor))
continue;
6400 for(
MInt s = 0; s < noSensors; s++) {
6401 if(sensorSolverId[s] != solver)
continue;
6402 if(sensorCellFlag[cellId][s] || sensorCellFlag[parentId][s]) {
6404 if(a_level(cellId) > m_newMinLevel && m_allowCoarsening) {
6405 coarseFlag[a_parentId(cellId)][solver] =
true;
6413 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
6414 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"");
6415 ASSERT(!a_isToDelete(cellId),
"");
6416 const MInt level = a_level(cellId);
6418 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6419 if(!m_tree.solver(cellId, solver))
continue;
6420 if(a_hasChildren(cellId, solver))
continue;
6421 const MInt parentId = a_parentId(cellId, solver);
6424 const MBool partLvlAncestorParent = (parentId > -1) ? a_hasProperty(parentId, Cell::IsPartLvlAncestor) :
false;
6427 MBool refine =
false;
6429 MBool coarsen =
true;
6432 MBool forceRefine =
false;
6433 for(
MInt s = 0; s < noSensors; s++) {
6434 if(sensorSolverId[s] != solver)
continue;
6435 if(sensorCellFlag[cellId][s]) {
6436 coarsen = coarsen && (sensors[s][cellId] < sensorThresholds(s, 0));
6438 if(level > m_maxUniformRefinementLevel && !partLvlAncestorParent && sensorCellFlag[parentId][s]) {
6439 coarsen = coarsen && (sensors[s][parentId] < sensorThresholds(s, 0));
6442 const MBool refineSensor = sensors[s][cellId] > sensorThresholds(s, 1) && sensorCellFlag[cellId][s];
6443 refine = refine || refineSensor;
6446 if(refineSensor && sensorWeight[s] < F0) {
6450 if(level < m_maxRfnmntLvl) {
6451 refineFlag[cellId][solver] = refine;
6454 if(level > m_maxUniformRefinementLevel && !partLvlAncestorParent) {
6455 coarseFlag[parentId][solver] = coarseFlag[parentId][solver] && coarsen;
6460 if((forceRefine && level < m_maxRfnmntLvl) || a_level(cellId) < m_newMinLevel) {
6461 refineFlag[cellId][solver] =
true;
6462 coarseFlag[cellId][solver] =
false;
6463 if(level > m_maxUniformRefinementLevel) {
6464 coarseFlag[parentId][solver] =
false;
6471 if(noNeighborDomains() > 0) {
6480 if(m_checkRefinementHoles !=
nullptr) {
6482 const MInt adaptationHoleLimit = nDim;
6483 MBool gridUpdated =
true;
6486 while(gridUpdated && loopCount < 25) {
6489 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6490 if(!m_checkRefinementHoles[solver])
continue;
6491 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6492 if(a_isToDelete(cellId))
continue;
6493 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
6494 if(!m_tree.solver(cellId, solver))
continue;
6495 if(a_hasChildren(cellId, solver))
continue;
6498 if(!refineFlag[cellId][solver]
6499 || (a_parentId(cellId, solver) > -1 && coarseFlag[a_parentId(cellId, solver)][solver])) {
6500 MInt checkRefinedNeighbors = 0;
6501 MInt currentHoleLimit = adaptationHoleLimit;
6502 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6503 if(a_hasNeighbor(cellId, dir, solver) > 0) {
6504 const MInt nghbrId = a_neighborId(cellId, dir, solver);
6505 if(refineFlag[nghbrId][solver] || a_hasChildren(nghbrId, solver)) {
6506 checkRefinedNeighbors += 1;
6513 if(checkRefinedNeighbors > adaptationHoleLimit) {
6514 refineFlag[cellId][solver] =
true;
6515 coarseFlag[cellId][solver] =
false;
6516 const MInt parentId = a_parentId(cellId, solver);
6517 if(parentId > -1) coarseFlag[parentId][solver] =
false;
6523 const MInt parentId = a_parentId(cellId, solver);
6524 if(parentId < 0)
continue;
6525 if(coarseFlag[parentId][solver]) {
6526 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
6527 "Partition level ancestor parent cell has coarseFlag set.");
6528 MInt checkRefinedNeighbors = 0;
6529 MInt currentHoleLimit = adaptationHoleLimit;
6530 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6531 if(a_hasNeighbor(parentId, dir, solver) > 0) {
6532 const MInt parNghbrId = a_neighborId(parentId, dir, solver);
6533 if(!coarseFlag[parNghbrId][solver]
6534 && (refineFlag[parNghbrId][solver] || a_hasChildren(parNghbrId, solver))) {
6535 checkRefinedNeighbors += 1;
6542 if(checkRefinedNeighbors > adaptationHoleLimit) {
6543 coarseFlag[parentId][solver] =
false;
6549 if(!coarseFlag[parentId][solver]) {
6550 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
6551 "Partition level ancestor parent cell has coarseFlag set.");
6552 MInt checkCoarseNeighbors = 0;
6553 MInt currentHoleLimit = adaptationHoleLimit;
6554 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6555 if(a_hasNeighbor(parentId, dir, solver) > 0) {
6556 const MInt parNghbrId = a_neighborId(parentId, dir, solver);
6557 if(coarseFlag[parNghbrId][solver]
6558 || (!refineFlag[parNghbrId][solver] && !a_hasChildren(parNghbrId, solver))) {
6559 checkCoarseNeighbors += 1;
6566 if(checkCoarseNeighbors > currentHoleLimit) {
6567 coarseFlag[parentId][solver] =
true;
6573 if(refineFlag[cellId][solver]) {
6574 MInt checkRefinedNeighbors = 0;
6575 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6576 if(a_hasNeighbor(cellId, dir, solver) > 0) {
6577 const MInt nghbrId = a_neighborId(cellId, dir, solver);
6578 if(refineFlag[nghbrId][solver] || a_hasChildren(nghbrId, solver)) {
6579 checkRefinedNeighbors += 1;
6583 if(checkRefinedNeighbors == 0) {
6584 refineFlag[cellId][solver] =
false;
6590 if(noChanges == 0) {
6591 gridUpdated =
false;
6598 if(m_diagSmoothing !=
nullptr) {
6599 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6600 if(!m_diagSmoothing[solver])
continue;
6601 for(
MInt lvl = maxLevel - 1; lvl >= minLevel(); lvl--) {
6602 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6603 if(a_level(cellId) != lvl)
continue;
6604 if(!a_isLeafCell(cellId))
continue;
6605 if(!m_tree.solver(cellId, solver))
continue;
6606 if(refineFlag[cellId][solver])
continue;
6607 for(
MInt i = 0; i < m_noDirs; i++) {
6608 const MInt nghbrId = a_neighborId(cellId, i, solver);
6609 if(nghbrId < 0)
continue;
6610 if(a_isLeafCell(nghbrId))
continue;
6611 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6612 MInt childId = a_childId(nghbrId, child, solver);
6613 if(childId < 0)
continue;
6614 if(!a_isLeafCell(childId)) {
6615 refineFlag[cellId][solver] =
true;
6616 coarseFlag[cellId][solver] =
false;
6617 MInt parentId = a_parentId(cellId, solver);
6619 coarseFlag[cellId][solver] =
false;
6624 for(
MInt j = 0; j < m_noDirs; j++) {
6625 if(j / 2 == i / 2)
continue;
6626 const MInt diagNghbrId = a_neighborId(nghbrId, j, solver);
6627 if(diagNghbrId < 0)
continue;
6628 if(a_isLeafCell(diagNghbrId))
continue;
6629 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6630 MInt childId = a_childId(diagNghbrId, child, solver);
6631 if(childId < 0)
continue;
6632 if(!a_isLeafCell(childId)) {
6633 refineFlag[cellId][solver] =
true;
6634 coarseFlag[cellId][solver] =
false;
6635 MInt parentId = a_parentId(cellId, solver);
6637 coarseFlag[cellId][solver] =
false;
6650 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6651 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
6652 if(a_isToDelete(cellId))
continue;
6654 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6655 if(!m_tree.solver(cellId, solver))
continue;
6656 if(a_hasChildren(cellId, solver))
continue;
6657 const MInt parentId = a_parentId(cellId, solver);
6658 if(refineFlag[cellId][solver] && coarseFlag[cellId][solver]) {
6659 refineFlag[cellId][solver] =
false;
6660 coarseFlag[cellId][solver] =
false;
6664 if(refineFlag[cellId][solver]) {
6666 if(coarseFlag[parentId][solver]) {
6667 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
6668 "Partition level ancestor parent cell has coarseFlag set.");
6669 coarseFlag[parentId][solver] =
false;
6670 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6671 MInt childId = a_childId(parentId, child, solver);
6673 refineFlag[childId][solver] =
false;
6684 if(m_noIdenticalSolvers > 0) {
6685 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
6686 for(
MInt pair = 0; pair < m_noIdenticalSolvers; pair++) {
6687 const MInt slaveId = m_identicalSolvers[pair * 2];
6688 const MInt masterId = m_identicalSolvers[pair * 2 + 1];
6689 if(treeb().solver(cellId, slaveId) && treeb().solver(cellId, masterId)) {
6690 if(!coarseFlag[cellId][masterId]) {
6691 coarseFlag[cellId][slaveId] = coarseFlag[cellId][masterId];
6693 if(m_identicalSolverLvlJumps[pair] == 0) {
6694 refineFlag[cellId][slaveId] = refineFlag[cellId][masterId];
6695 }
else if(m_identicalSolverLvlJumps[pair] == 1) {
6696 if(a_level(cellId) < m_identicalSolverMaxLvl[pair] && a_hasChildren(cellId, masterId)) {
6697 if(!a_hasChildren(cellId, slaveId)) {
6698 refineFlag[cellId][slaveId] =
true;
6700 coarseFlag[cellId][slaveId] =
false;
6703 if(a_level(cellId) < m_identicalSolverMaxLvl[pair] && a_hasChildren(cellId, masterId)
6704 && a_childId(cellId, 0) > -1 && treeb().solver(a_childId(cellId, 0), masterId)
6705 && a_hasChildren(a_childId(cellId, 0), masterId)) {
6706 if(!a_hasChildren(cellId, slaveId)) {
6707 refineFlag[cellId][slaveId] =
true;
6709 coarseFlag[cellId][slaveId] =
false;
6721 for(
MInt level = m_maxRfnmntLvl - 1; level >= m_maxUniformRefinementLevel; level--) {
6722 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6723 if(a_level(cellId) != level)
continue;
6724 if(a_isToDelete(cellId))
continue;
6725 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
6728 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6729 if(!m_tree.solver(cellId, solver))
continue;
6730 if(!a_hasChildren(cellId, solver))
continue;
6733 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
6734 coarseFlag[cellId][solver] =
false;
6737 if(coarseFlag[cellId][solver]) {
6738 if(!coarsenCheck(cellId, solver)) {
6739 coarseFlag[cellId][solver] =
false;
6745 if(noNeighborDomains() > 0) {
6751 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6752 if(a_level(cellId) != level)
continue;
6753 if(a_isToDelete(cellId))
continue;
6754 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
6757 if(level < m_maxRfnmntLvl - 1) {
6758 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6759 if(!m_tree.solver(cellId, solver))
continue;
6760 if(a_hasChildren(cellId, solver))
continue;
6761 if(!refineFlag[cellId][solver] && !coarseFlag[cellId][solver]) {
6762 for(
MInt dir = 0; dir < m_noDirs; dir++) {
6763 if(a_hasNeighbor(cellId, dir, solver) > 0) {
6764 MInt nghbrId = a_neighborId(cellId, dir, solver);
6765 if(m_azimuthalPer && a_hasProperty(nghbrId, Cell::IsPeriodic))
continue;
6766 if(a_hasChildren(nghbrId, solver) > 0) {
6767 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6768 if(!childCode[dir][child])
continue;
6769 MInt childId = a_childId(nghbrId, child, solver);
6770 if(childId < 0)
continue;
6771 if(refineFlag[childId][solver]) {
6772 refineFlag[cellId][solver] =
true;
6783 if(noNeighborDomains() > 0) {
6789 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6790 if(a_level(cellId) != level)
continue;
6791 if(a_isToDelete(cellId))
continue;
6792 if(m_azimuthalPer && a_hasProperty(cellId, Cell::IsPeriodic))
continue;
6795 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
6799 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6800 if(!m_tree.solver(cellId, solver))
continue;
6801 if(coarseFlag[cellId][solver]) {
6802 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6803 MInt childId = a_childId(cellId, child, solver);
6805 coarseFlag[childId][solver] =
false;
6806 refineFlag[childId][solver] =
false;
6809 if(a_hasChildren(cellId, solver)) {
6810 removeChildsSolver[solver](cellId);
6812 refineFlag[cellId][solver] =
false;
6813 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6814 MInt childId = a_childId(cellId, child);
6816 treeb().solver(childId, solver) =
false;
6824 if(a_noChildren(cellId) > 0) {
6825 MBool rmChilds =
true;
6826 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6827 if(a_hasChildren(cellId, solver)) {
6832 removeChilds(cellId);
6837 for(
MInt i = 0; i < noNeighborDomains(); i++) {
6838 std::set<MInt> deleted;
6840 if(m_haloMode > 0) {
6841 for(
auto it_ = m_windowLayer_[i].begin(); it_ != m_windowLayer_[i].end();) {
6842 if(a_isToDelete(it_->first)) {
6843 it_ = m_windowLayer_[i].erase(it_);
6846 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6847 if(it_->second.get(solver) < WINDOWLAYER_MAX
6848 && !m_tree.solver(it_->first, solver))
6849 it_->second.set(solver, WINDOWLAYER_MAX);
6850 if(it_->second.get(solver) > m_noSolverHaloLayers[solver]) it_->second.set(solver, WINDOWLAYER_MAX);
6852 if(it_->second.all()) {
6853 deleted.insert(it_->first);
6854 it_ = m_windowLayer_[i].erase(it_);
6863 std::set<MInt> windCellSet;
6864 std::set<MInt> haloCellSet;
6867 m_windowCells[i].clear();
6869 auto it = oldWindowCells[i].begin();
6871 for(it = oldWindowCells[i].begin(); it < oldWindowCells[i].end(); it++) {
6872 const MInt cellId = *it;
6873 if(!a_isToDelete(cellId) && (deleted.find(cellId) == deleted.end() || m_haloMode == 0)) {
6874 ASSERT(cellId < treeb().size(),
"");
6878 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet.find(cellId) == windCellSet.end(),
6879 "duplicate window cell: " + std::to_string(cellId));
6880 windCellSet.insert(cellId);
6883 m_windowCells[i].push_back(cellId);
6888 vector<MInt> oldHaloVec(m_haloCells[i]);
6889 m_haloCells[i].clear();
6890 for(it = oldHaloVec.begin(); it < oldHaloVec.end(); it++) {
6891 const MInt cellId = *it;
6892 if(!a_isToDelete(cellId)) {
6893 ASSERT(cellId < treeb().size(),
"");
6896 ASSERT(haloCellSet.find(cellId) == haloCellSet.end(),
"duplicate halo cell: " + std::to_string(cellId));
6897 haloCellSet.insert(cellId);
6900 if(m_tree.solverBits(cellId).any() || m_haloMode == 0) m_haloCells[i].push_back(cellId);
6916 for(
MInt level = maxLevel - 1; level >= m_maxUniformRefinementLevel; level--) {
6917 for(
MInt cellId = 0; cellId < noCells; cellId++) {
6918 if(a_isToDelete(cellId))
continue;
6919 if(!a_hasProperty(cellId, Cell::IsHalo))
continue;
6920 if(a_level(cellId) == level) {
6921 if(a_noChildren(cellId) > 0) {
6924 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
6925 if(std::find(m_partitionLevelAncestorIds.begin(), m_partitionLevelAncestorIds.end(), cellId)
6926 != m_partitionLevelAncestorIds.end()) {
6931 for(
MInt child = 0; child < m_maxNoChilds; child++) {
6932 MInt childId = a_childId(cellId, child);
6933 if(childId < 0)
continue;
6934 refineFlag[childId].reset();
6935 coarseFlag[childId].reset();
6937 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
6938 if(!m_tree.solver(cellId, solver))
continue;
6939 if(a_hasChildren(cellId, solver)) {
6940 removeChildsSolver[solver](cellId);
6943 removeChilds(cellId);
6944 coarseFlag[cellId].reset();
6945 refineFlag[cellId].reset();
6951 ScratchSpace<MBool> isWindowPartLvlAncestor_(tmpScratchSize, AT_,
"isWindowPartLvLAncestor");
6953 for(
MInt i = 0; i < noNeighborDomains(); i++) {
6954 isWindowPartLvlAncestor_.
fill(
false);
6956 if(hasPartLvlShift) {
6957 for(
MInt j = 0; j < oldNoWindowCells[i]; j++) {
6958 const MInt cellId = oldWindowCells[i][j];
6959 isWindowPartLvlAncestor_(cellId) = recvIsHaloPartLvlAncestor[cnt];
6964 m_windowCells[i].clear();
6966 auto it = oldWindowCells[i].
begin();
6967 for(it = oldWindowCells[i].begin(); it < oldWindowCells[i].end(); it++) {
6968 const MInt cellId = *it;
6971 const MBool addWindow = (hasPartLvlShift) ? isWindowPartLvlAncestor_(cellId) :
false;
6973 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addWindow) {
6974 m_windowCells[i].push_back(cellId);
6976 a_hasProperty(cellId, Cell::IsWindow) =
true;
6981 if(m_haloMode > 0) {
6982 for(
auto it_ = m_windowLayer_[i].begin(); it_ != m_windowLayer_[i].end();) {
6983 const MInt cellId = it_->first;
6986 const MBool addWindow = (hasPartLvlShift) ? isWindowPartLvlAncestor_(cellId) :
false;
6988 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addWindow)
6991 it_ = m_windowLayer_[i].erase(it_);
6995 vector<MInt> oldHaloVec(m_haloCells[i]);
6996 m_haloCells[i].clear();
6997 for(it = oldHaloVec.begin(); it < oldHaloVec.end(); it++) {
6998 const MInt cellId = *it;
7001 const MBool addHalo = (hasPartLvlShift) ? isHaloPartLvlAncestor[cellId] :
false;
7003 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addHalo) {
7004 ASSERT(cellId > -1 && cellId < treeb().size(), to_string(cellId) +
" " + to_string(treeb().size()));
7005 m_haloCells[i].push_back(cellId);
7011 if(m_azimuthalPer) {
7012 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
7013 vector<MInt> oldAzimuthalWindowVec(m_azimuthalWindowCells[i]);
7015 m_azimuthalWindowCells[i].clear();
7016 auto it = oldAzimuthalWindowVec.begin();
7017 for(
MInt j = 0; j < (signed)oldAzimuthalWindowVec.size(); j++) {
7022 const MInt cellId = oldAzimuthalWindowVec[j];
7023 MBool keepWindow =
true;
7024 if(find(m_azimuthalHigherLevelConnectivity[i].begin(), m_azimuthalHigherLevelConnectivity[i].end(), j)
7025 != m_azimuthalHigherLevelConnectivity[i].end()) {
7028 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel && keepWindow) {
7029 m_azimuthalWindowCells[i].push_back(cellId);
7030 a_hasProperty(cellId, Cell::IsWindow) =
true;
7033 oldAzimuthalWindowVec.clear();
7035 vector<MInt> oldAzimuthalHaloVec(m_azimuthalHaloCells[i]);
7036 m_azimuthalHaloCells[i].clear();
7037 for(it = oldAzimuthalHaloVec.begin(); it < oldAzimuthalHaloVec.end(); it++) {
7038 const MInt cellId = *it;
7039 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
7040 ASSERT(cellId > -1 && cellId < treeb().size(),
"");
7041 m_azimuthalHaloCells[i].push_back(cellId);
7044 oldAzimuthalHaloVec.clear();
7048 vector<MInt> oldUnmappedHaloVec(m_azimuthalUnmappedHaloCells);
7049 vector<MInt> oldUnmappedHaloDomVec(m_azimuthalUnmappedHaloDomains);
7050 m_azimuthalUnmappedHaloCells.clear();
7051 m_azimuthalUnmappedHaloDomains.clear();
7052 for(
MUint i = 0; i < oldUnmappedHaloVec.size(); i++) {
7053 MInt cellId = oldUnmappedHaloVec[i];
7054 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
7055 ASSERT(cellId > -1 && cellId < treeb().size(),
"");
7056 m_azimuthalUnmappedHaloCells.push_back(cellId);
7057 m_azimuthalUnmappedHaloDomains.push_back(oldUnmappedHaloDomVec[i]);
7060 oldUnmappedHaloVec.clear();
7061 oldUnmappedHaloDomVec.clear();
7064 vector<MInt> oldGridBndryVec(m_gridBndryCells);
7065 m_gridBndryCells.clear();
7066 for(
MUint i = 0; i < oldGridBndryVec.size(); i++) {
7067 MInt cellId = oldGridBndryVec[i];
7068 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
7069 m_gridBndryCells.push_back(cellId);
7072 oldGridBndryVec.clear();
7080 for(
MInt level = m_maxUniformRefinementLevel; level < maxLevel; level++) {
7081 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7082 if(a_level(cellId) != level)
continue;
7083 if(a_isToDelete(cellId))
continue;
7084 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7086 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7087 if(!m_tree.solver(cellId, solver))
continue;
7088 if(a_hasChildren(cellId, solver))
continue;
7089 if(refineFlag[cellId][solver]) {
7090 if(!refineCheck(cellId, solver, cellOutsideSolver)) {
7092 refineFlag[cellId][solver] = 0;
7097 if(refineFlag[cellId].any()) {
7098 refineCell(cellId,
nullptr,
false, cellOutsideSolver, refineFlag[cellId]);
7100 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7101 if(!a_hasChildren(cellId, solver) &&
false) {
7105 refineFlag[cellId][solver] =
false;
7107 if(refineFlag[cellId][solver]) {
7109 setChildSolverFlag(cellId, solver, cellOutsideSolver[solver]);
7110 refineCellSolver[solver](cellId);
7113 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7114 MInt childId = a_childId(cellId, child);
7115 if(childId > -1 && a_hasProperty(childId, Cell::WasNewlyCreated)) {
7118 coarseFlag[childId].reset();
7119 refineFlag[childId].reset();
7135 m_partitionLevelAncestorChildIds.clear();
7136 const MInt noPartLvlAncestorIds = m_partitionLevelAncestorIds.size();
7137 for(
MInt i = 0; i < noPartLvlAncestorIds; i++) {
7138 const MInt cellId = m_partitionLevelAncestorIds[i];
7140 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7141 const MInt childId = a_childId(cellId, child);
7142 const MLong childGlobalId = (childId > -1) ? a_globalId(childId) : -1;
7143 m_partitionLevelAncestorChildIds.push_back(childGlobalId);
7147 if(noDomains() > 1 || m_noPeriodicCartesianDirs > 0) {
7148 updateHaloCellCollectors();
7151 if(m_haloMode > 0) {
7152 createHigherLevelExchangeCells(level,
true, refineCellSolver, removeCellSolver, level == maxLevel - 1);
7155 createHigherLevelExchangeCells_old(level, refineCellSolver);
7158 for(
MInt i = 0; i < noNeighborDomains(); i++) {
7159 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
7160 MInt cellId = m_haloCells[i][j];
7161 if(a_level(cellId) != level)
continue;
7162 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7163 const MInt childId = a_childId(cellId, child);
7164 if(childId < 0)
continue;
7168 if(!a_isHalo(childId)) {
7169 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
7170 "child is not a partition level ancestor or a partition cell");
7171 a_hasProperty(cellId, Cell::WasRefined) =
true;
7173 coarseFlag[childId].reset();
7174 refineFlag[childId].reset();
7175 a_hasProperty(childId, Cell::WasNewlyCreated) =
true;
7176 a_hasProperty(cellId, Cell::WasRefined) =
true;
7182 if(m_azimuthalPer) {
7183 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
7184 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
7185 MInt cellId = m_azimuthalHaloCells[i][j];
7186 if(a_level(cellId) != level)
continue;
7187 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7188 const MInt childId = a_childId(cellId, child);
7189 if(childId < 0)
continue;
7190 if(!a_isHalo(childId)) {
7193 coarseFlag[childId].reset();
7194 refineFlag[childId].reset();
7195 a_hasProperty(childId, Cell::WasNewlyCreated) =
true;
7196 a_hasProperty(cellId, Cell::WasRefined) =
true;
7210 for(
auto& rgm : resizeGridMapSolver) {
7213 compactCells(swapCellsSolver);
7216 for(
auto& rgm : resizeGridMapSolver) {
7219 if(noDomains() > 1 || m_noPeriodicCartesianDirs > 0) {
7220 updateHaloCellCollectors();
7228 if(noNeighborDomains() > 0 || noAzimuthalNeighborDomains() > 0) {
7229 exchangeProperties();
7233 computeLocalBoundingBox(&m_localBoundingBox[0]);
7236 if(treeb().
noSolvers() > 1 && noNeighborDomains() > 0) {
7238 if(m_haloMode > 0) {
7239 exchangeSolverBitset(&m_tree.solverBits(0));
7245 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
7247 &m_tree.solverBits(0), m_tree.size());
7250 correctAzimuthalSolverBits();
7287 m_updatedPartitionCells =
false;
7289#ifdef MAIA_GRID_SANITY_CHECKS
7291 checkWindowHaloConsistency(
true);
7293 checkWindowLayer(
"meshAdaptation completed: ");
7297 m_wasAdapted =
true;
7317 vector<vector<MFloat>>& sensors, vector<MFloat>& sensorWeight, vector<bitset<64>>& sensorCellFlag,
7318 vector<MInt>& sensorSolverId,
const std::vector<std::function<
void(
const MInt)>>& refineCellSolver,
7319 const std::vector<std::function<
void(
const MInt)>>& removeChildsSolver,
7320 const std::vector<std::function<
void(
const MInt)>>& removeCellSolver,
7321 const std::vector<std::function<
void(
const MInt,
const MInt)>>& swapCellsSolver,
7322 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>>& cellOutsideSolver,
7323 const std::vector<std::function<
void()>>& resizeGridMapSolver) {
7328 const MInt noCells = treeb().size();
7329 const MInt maxNoCells = m_maxNoCells;
7330 const MInt maxLevel =
mMin(m_maxRfnmntLvl, m_maxLevel + 1);
7332 const MInt noSensors = (signed)sensorWeight.size();
7333 ASSERT(sensorWeight.size() == sensors.size(),
"");
7334 ASSERT(sensorWeight.size() == sensorSolverId.size(),
"");
7339 ASSERT(m_freeIndices.empty(),
"");
7340 std::set<MInt>().swap(m_freeIndices);
7342 for(
MInt c = 0; c < maxNoCells; c++) {
7343 refineFlag[c].reset();
7344 coarseFlag[c].reset();
7347 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7348 a_hasProperty(cellId, Cell::IsToDelete) =
false;
7349 a_hasProperty(cellId, Cell::WasNewlyCreated) =
false;
7350 a_hasProperty(cellId, Cell::WasCoarsened) =
false;
7351 a_hasProperty(cellId, Cell::WasRefined) =
false;
7355 a_hasProperty(cellId, Cell::IsWindow) =
false;
7363 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7364 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7365 if(a_isToDelete(cellId))
continue;
7368 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
7372 for(
MInt s = 0; s < noSensors; s++) {
7373 if(sensorCellFlag[cellId][s]) {
7374 ASSERT(sensorWeight[s] < F0 || std::fabs(sensors[s][cellId]) < MFloatMaxSqrt,
7375 "invalid sensor value: " + std::to_string(sensors[s][cellId]));
7376 sensorCnt(s, 0) +=
POW2(sensors[s][cellId]);
7377 sensorCnt(s, 1) += F1;
7383 MPI_Allreduce(MPI_IN_PLACE, &sensorCnt(0), 2 * noSensors, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
7388 for(
MInt s = 0; s < noSensors; s++) {
7389 if(sensorWeight[s] < F0) {
7390 sensorThresholds(s, 0) = -1e-12;
7391 sensorThresholds(s, 1) = 1e-12;
7393 sensorThresholds(s, 1) = sensorWeight[s] * sqrt(
mMax(1e-14, (sensorCnt(s, 0) / sensorCnt(s, 1))));
7394 sensorThresholds(s, 0) = m_coarseRatio * sensorThresholds(s, 1);
7400 const MBool hasPartLvlShift = (m_maxPartitionLevelShift > 0);
7401 const MInt tmpScratchSize = (hasPartLvlShift) ? m_tree.size() : 1;
7405 ScratchSpace<MBool> isWindowPartLvlAncestor(tmpScratchSize, noNeighborDomains(), AT_,
"isWindowPartLvlAncestor");
7407 isHaloPartLvlAncestor.
fill(
false);
7408 isWindowPartLvlAncestor.
fill(
false);
7411 if(m_maxPartitionLevelShift > 0) {
7412 MInt totalNoWindowCells = 0;
7413 for(
MInt d = 0; d < noNeighborDomains(); d++) {
7414 totalNoWindowCells += noWindowCells(d);
7416 ScratchSpace<MBool> recvIsHaloPartLvlAncestor(std::max(totalNoWindowCells, 1), AT_,
"recvIsHaloPartLvlAncestor");
7418 for(
auto& i : m_partitionLevelAncestorIds) {
7419 TERMM_IF_NOT_COND(a_hasProperty(i, Cell::IsPartLvlAncestor),
7420 "cell is not a partition level ancestor: " + std::to_string(i));
7422 if(a_hasProperty(i, Cell::IsHalo)) {
7423 isHaloPartLvlAncestor[i] =
true;
7427 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7428 const MInt childId = a_childId(i, child);
7429 if(childId > -1 && a_isHalo(childId)) {
7430 isHaloPartLvlAncestor[childId] =
true;
7436 if(noNeighborDomains() > 0) {
7439 &recvIsHaloPartLvlAncestor[0]);
7441 TERMM(1,
"not working for compilation of paraview plugin");
7446 for(
MInt d = 0; d < noNeighborDomains(); d++) {
7447 for(
MInt j = 0; j < noWindowCells(d); j++) {
7448 const MInt cellId = windowCell(d, j);
7450 isWindowPartLvlAncestor(cellId, d) = recvIsHaloPartLvlAncestor[cnt];
7460 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
7461 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"");
7462 ASSERT(!a_isToDelete(cellId),
"");
7463 if(a_level(cellId) > m_maxUniformRefinementLevel) {
7464 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7465 if(!m_tree.solver(cellId, solver))
continue;
7466 if(a_hasChildren(cellId, solver))
continue;
7468 const MInt parentId = a_parentId(cellId, solver);
7469 ASSERT(parentId > -1,
"");
7471 if(a_isHalo(parentId) || a_hasProperty(parentId, Cell::IsPartLvlAncestor))
continue;
7473 for(
MInt s = 0; s < noSensors; s++) {
7474 if(sensorSolverId[s] != solver)
continue;
7475 if(sensorCellFlag[cellId][s] || sensorCellFlag[parentId][s]) {
7477 if(a_level(cellId) > m_newMinLevel && m_allowCoarsening) {
7478 coarseFlag[a_parentId(cellId)][solver] =
true;
7486 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
7487 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"");
7488 ASSERT(!a_isToDelete(cellId),
"");
7489 const MInt level = a_level(cellId);
7491 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7492 if(!m_tree.solver(cellId, solver))
continue;
7493 if(a_hasChildren(cellId, solver))
continue;
7494 const MInt parentId = a_parentId(cellId, solver);
7497 const MBool partLvlAncestorParent = (parentId > -1) ? a_hasProperty(parentId, Cell::IsPartLvlAncestor) :
false;
7500 MBool refine =
false;
7502 MBool coarsen =
true;
7505 MBool forceRefine =
false;
7506 for(
MInt s = 0; s < noSensors; s++) {
7507 if(sensorSolverId[s] != solver)
continue;
7508 if(sensorCellFlag[cellId][s]) {
7509 coarsen = coarsen && (sensors[s][cellId] < sensorThresholds(s, 0));
7511 if(level > m_maxUniformRefinementLevel && !partLvlAncestorParent && sensorCellFlag[parentId][s]) {
7512 coarsen = coarsen && (sensors[s][parentId] < sensorThresholds(s, 0));
7515 const MBool refineSensor = sensors[s][cellId] > sensorThresholds(s, 1) && sensorCellFlag[cellId][s];
7516 refine = refine || refineSensor;
7519 if(refineSensor && sensorWeight[s] < F0) {
7523 if(level < m_maxRfnmntLvl) {
7524 refineFlag[cellId][solver] = refine;
7527 if(level > m_maxUniformRefinementLevel && !partLvlAncestorParent) {
7528 coarseFlag[parentId][solver] = coarseFlag[parentId][solver] && coarsen;
7533 if((forceRefine && level < m_maxRfnmntLvl) || a_level(cellId) < m_newMinLevel) {
7534 refineFlag[cellId][solver] =
true;
7535 coarseFlag[cellId][solver] =
false;
7536 if(level > m_maxUniformRefinementLevel) {
7537 coarseFlag[parentId][solver] =
false;
7544 if(noNeighborDomains() > 0) {
7553 if(m_checkRefinementHoles !=
nullptr) {
7555 const MInt adaptationHoleLimit = nDim;
7556 MBool gridUpdated =
true;
7559 while(gridUpdated && loopCount < 25) {
7562 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7563 if(!m_checkRefinementHoles[solver])
continue;
7564 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7565 if(a_isToDelete(cellId))
continue;
7566 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7567 if(!m_tree.solver(cellId, solver))
continue;
7568 if(a_hasChildren(cellId, solver))
continue;
7571 if(!refineFlag[cellId][solver]
7572 || (a_parentId(cellId, solver) > -1 && coarseFlag[a_parentId(cellId, solver)][solver])) {
7573 MInt checkRefinedNeighbors = 0;
7574 MInt currentHoleLimit = adaptationHoleLimit;
7575 for(
MInt dir = 0; dir < m_noDirs; dir++) {
7576 if(a_hasNeighbor(cellId, dir, solver) > 0) {
7577 const MInt nghbrId = a_neighborId(cellId, dir, solver);
7578 if(refineFlag[nghbrId][solver] || a_hasChildren(nghbrId, solver)) {
7579 checkRefinedNeighbors += 1;
7586 if(checkRefinedNeighbors > adaptationHoleLimit) {
7587 refineFlag[cellId][solver] =
true;
7588 coarseFlag[cellId][solver] =
false;
7589 const MInt parentId = a_parentId(cellId, solver);
7590 if(parentId > -1) coarseFlag[parentId][solver] =
false;
7596 const MInt parentId = a_parentId(cellId, solver);
7597 if(parentId < 0)
continue;
7598 if(coarseFlag[parentId][solver]) {
7599 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
7600 "Partition level ancestor parent cell has coarseFlag set.");
7601 MInt checkRefinedNeighbors = 0;
7602 MInt currentHoleLimit = adaptationHoleLimit;
7603 for(
MInt dir = 0; dir < m_noDirs; dir++) {
7604 if(a_hasNeighbor(parentId, dir, solver) > 0) {
7605 const MInt parNghbrId = a_neighborId(parentId, dir, solver);
7606 if(!coarseFlag[parNghbrId][solver]
7607 && (refineFlag[parNghbrId][solver] || a_hasChildren(parNghbrId, solver))) {
7608 checkRefinedNeighbors += 1;
7615 if(checkRefinedNeighbors > adaptationHoleLimit) {
7616 coarseFlag[parentId][solver] =
false;
7622 if(!coarseFlag[parentId][solver]) {
7623 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
7624 "Partition level ancestor parent cell has coarseFlag set.");
7625 MInt checkCoarseNeighbors = 0;
7626 MInt currentHoleLimit = adaptationHoleLimit;
7627 for(
MInt dir = 0; dir < m_noDirs; dir++) {
7628 if(a_hasNeighbor(parentId, dir, solver) > 0) {
7629 const MInt parNghbrId = a_neighborId(parentId, dir, solver);
7630 if(coarseFlag[parNghbrId][solver]
7631 || (!refineFlag[parNghbrId][solver] && !a_hasChildren(parNghbrId, solver))) {
7632 checkCoarseNeighbors += 1;
7639 if(checkCoarseNeighbors > currentHoleLimit) {
7640 coarseFlag[parentId][solver] =
true;
7646 if(refineFlag[cellId][solver]) {
7647 MInt checkRefinedNeighbors = 0;
7648 for(
MInt dir = 0; dir < m_noDirs; dir++) {
7649 if(a_hasNeighbor(cellId, dir, solver) > 0) {
7650 const MInt nghbrId = a_neighborId(cellId, dir, solver);
7651 if(refineFlag[nghbrId][solver] || a_hasChildren(nghbrId, solver)) {
7652 checkRefinedNeighbors += 1;
7656 if(checkRefinedNeighbors == 0) {
7657 refineFlag[cellId][solver] =
false;
7663 if(noChanges == 0) {
7664 gridUpdated =
false;
7671 if(m_diagSmoothing !=
nullptr) {
7672 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7673 if(!m_diagSmoothing[solver])
continue;
7674 for(
MInt lvl = maxLevel - 1; lvl >= minLevel(); lvl--) {
7675 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7676 if(a_level(cellId) != lvl)
continue;
7677 if(!a_isLeafCell(cellId))
continue;
7678 if(!m_tree.solver(cellId, solver))
continue;
7679 if(refineFlag[cellId][solver])
continue;
7680 for(
MInt i = 0; i < m_noDirs; i++) {
7681 const MInt nghbrId = a_neighborId(cellId, i, solver);
7682 if(nghbrId < 0)
continue;
7683 if(a_isLeafCell(nghbrId))
continue;
7684 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7685 MInt childId = a_childId(nghbrId, child, solver);
7686 if(childId < 0)
continue;
7687 if(!a_isLeafCell(childId)) {
7688 refineFlag[cellId][solver] =
true;
7689 coarseFlag[cellId][solver] =
false;
7690 MInt parentId = a_parentId(cellId, solver);
7692 coarseFlag[cellId][solver] =
false;
7697 for(
MInt j = 0; j < m_noDirs; j++) {
7698 if(j / 2 == i / 2)
continue;
7699 const MInt diagNghbrId = a_neighborId(nghbrId, j, solver);
7700 if(diagNghbrId < 0)
continue;
7701 if(a_isLeafCell(diagNghbrId))
continue;
7702 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7703 MInt childId = a_childId(diagNghbrId, child, solver);
7704 if(childId < 0)
continue;
7705 if(!a_isLeafCell(childId)) {
7706 refineFlag[cellId][solver] =
true;
7707 coarseFlag[cellId][solver] =
false;
7708 MInt parentId = a_parentId(cellId, solver);
7710 coarseFlag[cellId][solver] =
false;
7723 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7724 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7725 if(a_isToDelete(cellId))
continue;
7727 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7728 if(!m_tree.solver(cellId, solver))
continue;
7729 if(a_hasChildren(cellId, solver))
continue;
7730 const MInt parentId = a_parentId(cellId, solver);
7731 if(refineFlag[cellId][solver] && coarseFlag[cellId][solver]) {
7732 refineFlag[cellId][solver] =
false;
7733 coarseFlag[cellId][solver] =
false;
7737 if(refineFlag[cellId][solver]) {
7739 if(coarseFlag[parentId][solver]) {
7740 ASSERT(!a_isHalo(parentId) && !a_hasProperty(parentId, Cell::IsPartLvlAncestor),
7741 "Partition level ancestor parent cell has coarseFlag set.");
7742 coarseFlag[parentId][solver] =
false;
7743 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7744 MInt childId = a_childId(parentId, child, solver);
7746 refineFlag[childId][solver] =
false;
7757 if(m_noIdenticalSolvers > 0) {
7758 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
7759 for(
MInt pair = 0; pair < m_noIdenticalSolvers; pair++) {
7760 const MInt slaveId = m_identicalSolvers[pair * 2];
7761 const MInt masterId = m_identicalSolvers[pair * 2 + 1];
7762 if(treeb().solver(cellId, slaveId) && treeb().solver(cellId, masterId)) {
7763 if(!coarseFlag[cellId][masterId]) {
7764 coarseFlag[cellId][slaveId] = coarseFlag[cellId][masterId];
7766 if(m_identicalSolverLvlJumps[pair] == 0) {
7767 refineFlag[cellId][slaveId] = refineFlag[cellId][masterId];
7768 }
else if(m_identicalSolverLvlJumps[pair] == 1) {
7769 if(a_level(cellId) < m_identicalSolverMaxLvl[pair] && a_hasChildren(cellId, masterId)) {
7770 if(!a_hasChildren(cellId, slaveId)) {
7771 refineFlag[cellId][slaveId] =
true;
7773 coarseFlag[cellId][slaveId] =
false;
7776 if(a_level(cellId) < m_identicalSolverMaxLvl[pair] && a_hasChildren(cellId, masterId)
7777 && a_childId(cellId, 0) > -1 && treeb().solver(a_childId(cellId, 0), masterId)
7778 && a_hasChildren(a_childId(cellId, 0), masterId)) {
7779 if(!a_hasChildren(cellId, slaveId)) {
7780 refineFlag[cellId][slaveId] =
true;
7782 coarseFlag[cellId][slaveId] =
false;
7794 for(
MInt level = m_maxRfnmntLvl - 1; level >= m_maxUniformRefinementLevel; level--) {
7795 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7796 if(a_level(cellId) != level)
continue;
7797 if(a_isToDelete(cellId))
continue;
7798 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7801 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7802 if(!m_tree.solver(cellId, solver))
continue;
7803 if(!a_hasChildren(cellId, solver))
continue;
7806 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
7807 coarseFlag[cellId][solver] =
false;
7810 if(coarseFlag[cellId][solver]) {
7811 if(!coarsenCheck(cellId, solver)) {
7812 coarseFlag[cellId][solver] =
false;
7818 if(noNeighborDomains() > 0) {
7824 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7825 if(a_level(cellId) != level)
continue;
7826 if(a_isToDelete(cellId))
continue;
7827 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
7830 if(level < m_maxRfnmntLvl - 1) {
7831 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7832 if(!m_tree.solver(cellId, solver))
continue;
7833 if(a_hasChildren(cellId, solver))
continue;
7834 if(!refineFlag[cellId][solver] && !coarseFlag[cellId][solver]) {
7835 for(
MInt dir = 0; dir < m_noDirs; dir++) {
7836 if(a_hasNeighbor(cellId, dir, solver) > 0) {
7837 MInt nghbrId = a_neighborId(cellId, dir, solver);
7838 if(m_azimuthalPer && a_hasProperty(nghbrId, Cell::IsPeriodic))
continue;
7839 if(a_hasChildren(nghbrId, solver) > 0) {
7840 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7841 if(!childCode[dir][child])
continue;
7842 MInt childId = a_childId(nghbrId, child, solver);
7843 if(childId < 0)
continue;
7844 if(refineFlag[childId][solver]) {
7845 refineFlag[cellId][solver] =
true;
7856 if(noNeighborDomains() > 0) {
7862 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7863 if(a_level(cellId) != level)
continue;
7864 if(a_isToDelete(cellId))
continue;
7865 if(m_azimuthalPer && a_hasProperty(cellId, Cell::IsPeriodic))
continue;
7868 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
7872 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7873 if(!m_tree.solver(cellId, solver))
continue;
7874 if(coarseFlag[cellId][solver]) {
7875 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7876 MInt childId = a_childId(cellId, child, solver);
7878 coarseFlag[childId][solver] =
false;
7879 refineFlag[childId][solver] =
false;
7882 if(a_hasChildren(cellId, solver)) {
7883 removeChildsSolver[solver](cellId);
7885 refineFlag[cellId][solver] =
false;
7886 for(
MInt child = 0; child < m_maxNoChilds; child++) {
7887 MInt childId = a_childId(cellId, child);
7889 treeb().solver(childId, solver) =
false;
7897 if(a_noChildren(cellId) > 0) {
7898 MBool rmChilds =
true;
7899 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7900 if(a_hasChildren(cellId, solver)) {
7905 removeChilds(cellId);
7910 for(
MInt i = 0; i < noNeighborDomains(); i++) {
7911 std::set<MInt> deleted;
7913 if(m_haloMode > 0) {
7914 for(
auto it_ = m_windowLayer_[i].begin(); it_ != m_windowLayer_[i].end();) {
7915 if(a_isToDelete(it_->first)) {
7916 it_ = m_windowLayer_[i].erase(it_);
7919 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
7920 if(it_->second.get(solver) < WINDOWLAYER_MAX
7921 && !m_tree.solver(it_->first, solver))
7922 it_->second.set(solver, WINDOWLAYER_MAX);
7923 if(it_->second.get(solver) > m_noSolverHaloLayers[solver]) it_->second.set(solver, WINDOWLAYER_MAX);
7925 if(it_->second.all()) {
7926 deleted.insert(it_->first);
7927 it_ = m_windowLayer_[i].erase(it_);
7935 vector<MInt> oldWindowVec(m_windowCells[i]);
7937 std::set<MInt> windCellSet;
7938 std::set<MInt> haloCellSet;
7941 std::vector<MInt>().swap(m_windowCells[i]);
7942 auto it = oldWindowVec.begin();
7943 for(it = oldWindowVec.begin(); it < oldWindowVec.end(); it++) {
7944 const MInt cellId = *it;
7945 if(!a_isToDelete(cellId) && (deleted.find(cellId) == deleted.end() || m_haloMode == 0)) {
7946 ASSERT(cellId < treeb().size(),
"");
7950 ASSERT(m_noPeriodicCartesianDirs > 0 || windCellSet.find(cellId) == windCellSet.end(),
7951 "duplicate window cell: " + std::to_string(cellId));
7952 windCellSet.insert(cellId);
7955 m_windowCells[i].push_back(cellId);
7958 oldWindowVec.clear();
7961 vector<MInt> oldHaloVec(m_haloCells[i]);
7962 std::vector<MInt>().swap(m_haloCells[i]);
7963 for(it = oldHaloVec.begin(); it < oldHaloVec.end(); it++) {
7964 const MInt cellId = *it;
7965 if(!a_isToDelete(cellId)) {
7966 ASSERT(cellId < treeb().size(),
"");
7969 ASSERT(haloCellSet.find(cellId) == haloCellSet.end(),
"duplicate halo cell: " + std::to_string(cellId));
7970 haloCellSet.insert(cellId);
7973 if(m_tree.solverBits(cellId).any() || m_haloMode == 0) m_haloCells[i].push_back(cellId);
7989 for(
MInt level = maxLevel - 1; level >= m_maxUniformRefinementLevel; level--) {
7990 for(
MInt cellId = 0; cellId < noCells; cellId++) {
7991 if(a_isToDelete(cellId))
continue;
7992 if(!a_hasProperty(cellId, Cell::IsHalo))
continue;
7993 if(a_level(cellId) == level) {
7994 if(a_noChildren(cellId) > 0) {
7997 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsPartitionCell)) {
7998 if(std::find(m_partitionLevelAncestorIds.begin(), m_partitionLevelAncestorIds.end(), cellId)
7999 != m_partitionLevelAncestorIds.end()) {
8004 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8005 MInt childId = a_childId(cellId, child);
8006 if(childId < 0)
continue;
8007 refineFlag[childId].reset();
8008 coarseFlag[childId].reset();
8010 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
8011 if(!m_tree.solver(cellId, solver))
continue;
8012 if(a_hasChildren(cellId, solver)) {
8013 removeChildsSolver[solver](cellId);
8016 removeChilds(cellId);
8017 coarseFlag[cellId].reset();
8018 refineFlag[cellId].reset();
8023 for(
MInt i = 0; i < noNeighborDomains(); i++) {
8024 vector<MInt> oldWindowVec(m_windowCells[i]);
8025 std::vector<MInt>().swap(m_windowCells[i]);
8026 auto it = oldWindowVec.begin();
8027 for(it = oldWindowVec.begin(); it < oldWindowVec.end(); it++) {
8028 const MInt cellId = *it;
8031 const MBool addWindow = (hasPartLvlShift) ? isWindowPartLvlAncestor(cellId, i) :
false;
8033 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addWindow) {
8034 m_windowCells[i].push_back(cellId);
8036 a_hasProperty(cellId, Cell::IsWindow) =
true;
8039 oldWindowVec.clear();
8042 if(m_haloMode > 0) {
8043 for(
auto it_ = m_windowLayer_[i].begin(); it_ != m_windowLayer_[i].end();) {
8044 const MInt cellId = it_->first;
8047 const MBool addWindow = (hasPartLvlShift) ? isWindowPartLvlAncestor(cellId, i) :
false;
8049 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addWindow)
8052 it_ = m_windowLayer_[i].erase(it_);
8056 vector<MInt> oldHaloVec(m_haloCells[i]);
8057 std::vector<MInt>().swap(m_haloCells[i]);
8058 for(it = oldHaloVec.begin(); it < oldHaloVec.end(); it++) {
8059 const MInt cellId = *it;
8062 const MBool addHalo = (hasPartLvlShift) ? isHaloPartLvlAncestor[cellId] :
false;
8064 if((a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) || addHalo) {
8065 ASSERT(cellId > -1 && cellId < treeb().size(), to_string(cellId) +
" " + to_string(treeb().size()));
8066 m_haloCells[i].push_back(cellId);
8072 if(m_azimuthalPer) {
8073 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
8074 vector<MInt> oldAzimuthalWindowVec(m_azimuthalWindowCells[i]);
8076 m_azimuthalWindowCells[i].clear();
8077 auto it = oldAzimuthalWindowVec.begin();
8078 for(
MInt j = 0; j < (signed)oldAzimuthalWindowVec.size(); j++) {
8083 const MInt cellId = oldAzimuthalWindowVec[j];
8084 MBool keepWindow =
true;
8085 if(find(m_azimuthalHigherLevelConnectivity[i].begin(), m_azimuthalHigherLevelConnectivity[i].end(), j)
8086 != m_azimuthalHigherLevelConnectivity[i].end()) {
8089 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel && keepWindow) {
8090 m_azimuthalWindowCells[i].push_back(cellId);
8091 a_hasProperty(cellId, Cell::IsWindow) =
true;
8094 oldAzimuthalWindowVec.clear();
8096 vector<MInt> oldAzimuthalHaloVec(m_azimuthalHaloCells[i]);
8097 m_azimuthalHaloCells[i].clear();
8098 for(it = oldAzimuthalHaloVec.begin(); it < oldAzimuthalHaloVec.end(); it++) {
8099 const MInt cellId = *it;
8100 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
8101 ASSERT(cellId > -1 && cellId < treeb().size(),
"");
8102 m_azimuthalHaloCells[i].push_back(cellId);
8105 oldAzimuthalHaloVec.clear();
8109 vector<MInt> oldUnmappedHaloVec(m_azimuthalUnmappedHaloCells);
8110 vector<MInt> oldUnmappedHaloDomVec(m_azimuthalUnmappedHaloDomains);
8111 m_azimuthalUnmappedHaloCells.clear();
8112 m_azimuthalUnmappedHaloDomains.clear();
8113 for(
MUint i = 0; i < oldUnmappedHaloVec.size(); i++) {
8114 MInt cellId = oldUnmappedHaloVec[i];
8115 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
8116 ASSERT(cellId > -1 && cellId < treeb().size(),
"");
8117 m_azimuthalUnmappedHaloCells.push_back(cellId);
8118 m_azimuthalUnmappedHaloDomains.push_back(oldUnmappedHaloDomVec[i]);
8121 oldUnmappedHaloVec.clear();
8122 oldUnmappedHaloDomVec.clear();
8125 vector<MInt> oldGridBndryVec(m_gridBndryCells);
8126 m_gridBndryCells.clear();
8127 for(
MUint i = 0; i < oldGridBndryVec.size(); i++) {
8128 MInt cellId = oldGridBndryVec[i];
8129 if(a_level(cellId) > -1 && a_level(cellId) <= m_maxUniformRefinementLevel) {
8130 m_gridBndryCells.push_back(cellId);
8133 oldGridBndryVec.clear();
8141 for(
MInt level = m_maxUniformRefinementLevel; level < maxLevel; level++) {
8142 for(
MInt cellId = 0; cellId < noCells; cellId++) {
8143 if(a_level(cellId) != level)
continue;
8144 if(a_isToDelete(cellId))
continue;
8145 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
8147 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
8148 if(!m_tree.solver(cellId, solver))
continue;
8149 if(a_hasChildren(cellId, solver))
continue;
8150 if(refineFlag[cellId][solver]) {
8151 if(!refineCheck(cellId, solver, cellOutsideSolver)) {
8152 refineFlag[cellId][solver] = 0;
8157 if(refineFlag[cellId].any()) {
8158 refineCell(cellId,
nullptr,
false, cellOutsideSolver, refineFlag[cellId]);
8160 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
8161 if(!a_hasChildren(cellId, solver) &&
false) {
8165 refineFlag[cellId][solver] =
false;
8167 if(refineFlag[cellId][solver]) {
8169 setChildSolverFlag(cellId, solver, cellOutsideSolver[solver]);
8170 refineCellSolver[solver](cellId);
8173 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8174 MInt childId = a_childId(cellId, child);
8175 if(childId > -1 && a_hasProperty(childId, Cell::WasNewlyCreated)) {
8178 coarseFlag[childId].reset();
8179 refineFlag[childId].reset();
8195 m_partitionLevelAncestorChildIds.clear();
8196 const MInt noPartLvlAncestorIds = m_partitionLevelAncestorIds.size();
8197 for(
MInt i = 0; i < noPartLvlAncestorIds; i++) {
8198 const MInt cellId = m_partitionLevelAncestorIds[i];
8200 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8201 const MInt childId = a_childId(cellId, child);
8202 const MLong childGlobalId = (childId > -1) ? a_globalId(childId) : -1;
8203 m_partitionLevelAncestorChildIds.push_back(childGlobalId);
8207 if(noDomains() > 1 || m_noPeriodicCartesianDirs > 0) {
8208 updateHaloCellCollectors();
8211 if(m_haloMode > 0) {
8212 createHigherLevelExchangeCells(level,
true, refineCellSolver, removeCellSolver, level == maxLevel - 1);
8215 createHigherLevelExchangeCells_old(level, refineCellSolver);
8218 for(
MInt i = 0; i < noNeighborDomains(); i++) {
8219 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
8220 MInt cellId = m_haloCells[i][j];
8221 if(a_level(cellId) != level)
continue;
8222 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8223 const MInt childId = a_childId(cellId, child);
8224 if(childId < 0)
continue;
8228 if(!a_isHalo(childId)) {
8229 ASSERT(a_hasProperty(childId, Cell::IsPartLvlAncestor) || a_hasProperty(childId, Cell::IsPartitionCell),
8230 "child is not a partition level ancestor or a partition cell");
8231 a_hasProperty(cellId, Cell::WasRefined) =
true;
8233 coarseFlag[childId].reset();
8234 refineFlag[childId].reset();
8235 a_hasProperty(childId, Cell::WasNewlyCreated) =
true;
8236 a_hasProperty(cellId, Cell::WasRefined) =
true;
8242 if(m_azimuthalPer) {
8243 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
8244 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
8245 MInt cellId = m_azimuthalHaloCells[i][j];
8246 if(a_level(cellId) != level)
continue;
8247 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8248 const MInt childId = a_childId(cellId, child);
8249 if(childId < 0)
continue;
8250 if(!a_isHalo(childId)) {
8253 coarseFlag[childId].reset();
8254 refineFlag[childId].reset();
8255 a_hasProperty(childId, Cell::WasNewlyCreated) =
true;
8256 a_hasProperty(cellId, Cell::WasRefined) =
true;
8270 for(
auto& rgm : resizeGridMapSolver) {
8273 compactCells(swapCellsSolver);
8276 for(
auto& rgm : resizeGridMapSolver) {
8279 if(noDomains() > 1 || m_noPeriodicCartesianDirs > 0) {
8280 updateHaloCellCollectors();
8288 if(noNeighborDomains() > 0 || noAzimuthalNeighborDomains() > 0) {
8289 exchangeProperties();
8293 computeLocalBoundingBox(&m_localBoundingBox[0]);
8296 if(treeb().
noSolvers() > 1 && noNeighborDomains() > 0) {
8298 if(m_haloMode > 0) {
8299 exchangeSolverBitset(&m_tree.solverBits(0));
8305 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
8307 &m_tree.solverBits(0), m_tree.size());
8310 correctAzimuthalSolverBits();
8347 m_updatedPartitionCells =
false;
8349#ifdef MAIA_GRID_SANITY_CHECKS
8351 checkWindowHaloConsistency(
true);
8353 checkWindowLayer(
"meshAdaptation completed: ");
8357 m_wasAdapted =
true;
8371 for(
MInt cellId = m_noInternalCells; cellId < m_tree.size(); cellId++) {
8372 ASSERT(a_hasProperty(cellId, Cell::IsHalo),
"not a halo cell");
8373 isPeriodic[cellId - m_noInternalCells] = a_hasProperty(cellId, Cell::IsPeriodic);
8377 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
8379 &m_tree.properties(0), m_tree.size());
8381 for(
MInt cellId = m_noInternalCells; cellId < m_tree.size(); cellId++) {
8382 a_hasProperty(cellId, Cell::IsHalo) =
true;
8383 a_hasProperty(cellId, Cell::IsWindow) =
false;
8384 a_hasProperty(cellId, Cell::IsPeriodic) = isPeriodic[cellId - m_noInternalCells];
8398 const std::vector<std::function<
void(
const MInt,
const MInt)>>& swapCellsSolver) {
8403 for(
auto& i : m_freeIndices) {
8406 std::set<MInt>().swap(m_freeIndices);
8410 m_noInternalCells = 0;
8412 for(
MInt cellId = 0; cellId < treeb().size(); cellId++) {
8413 if(isToDelete(cellId))
continue;
8414 oldCellId(cellId) = cellId;
8415 if(!a_hasProperty(cellId, Cell::IsHalo)) m_noInternalCells++;
8420 MInt otherId = treeb().size() - 1;
8421 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
8422 if(isToDelete(cellId) || a_hasProperty(cellId, Cell::IsHalo)) {
8423 while(isToDelete(otherId) || a_hasProperty(otherId, Cell::IsHalo)) {
8426 ASSERT(cellId < otherId,
"");
8427 swapCells(cellId, otherId);
8428 for(
auto& swp : swapCellsSolver) {
8429 swp(cellId, otherId);
8431 std::swap(oldCellId(cellId), oldCellId(otherId));
8432 std::swap(isToDelete(cellId), isToDelete(otherId));
8433 ASSERT(!a_hasProperty(cellId, Cell::IsHalo),
"");
8434 ASSERT(isToDelete(otherId) || a_hasProperty(otherId, Cell::IsHalo),
"");
8436 ASSERT(!a_hasProperty(cellId, Cell::IsHalo) && !isToDelete(cellId),
"");
8437 ASSERT(a_level(cellId) > -1,
"");
8442 otherId = treeb().size() - 1;
8443 for(
MInt cellId = m_noInternalCells; cellId < noCells; cellId++) {
8444 if(isToDelete(cellId)) {
8445 while(isToDelete(otherId)) {
8448 ASSERT(cellId < otherId,
"");
8449 ASSERT(otherId >= noCells,
"");
8450 ASSERT(a_hasProperty(otherId, Cell::IsHalo) && !isToDelete(otherId),
"");
8451 swapCells(cellId, otherId);
8452 for(
auto& swp : swapCellsSolver) {
8453 swp(cellId, otherId);
8455 std::swap(oldCellId(cellId), oldCellId(otherId));
8456 std::swap(isToDelete(cellId), isToDelete(otherId));
8458 ASSERT(a_hasProperty(cellId, Cell::IsHalo) && !isToDelete(cellId),
"");
8459 ASSERT(a_level(cellId) > -1,
"");
8463 treeb().size(noCells);
8466 for(
MInt cellId = 0; cellId < noCells; cellId++) {
8467 if(oldCellId(cellId) < 0)
continue;
8468 newCellId(oldCellId(cellId)) = cellId;
8470 for(
MInt i = 0; i < noNeighborDomains(); i++) {
8471 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
8472 MInt cellId = m_haloCells[i][j];
8473 if(newCellId(cellId) > -1) {
8474 m_haloCells[i][j] = newCellId(cellId);
8477 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
8478 MInt cellId = m_windowCells[i][j];
8479 if(newCellId(cellId) > -1) {
8480 m_windowCells[i][j] = newCellId(cellId);
8485 if(m_haloMode > 0) {
8486 std::unordered_map<MInt, M32X4bit<true>> windowLayerBak_(m_windowLayer_[i]);
8487 m_windowLayer_[i].clear();
8488 for(
auto m : windowLayerBak_) {
8489 if(newCellId(m.first) > -1) {
8490 m_windowLayer_[i].insert({newCellId(m.first), m.second});
8496 if(m_azimuthalPer) {
8497 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
8498 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
8499 MInt cellId = m_azimuthalHaloCells[i][j];
8500 if(newCellId(cellId) > -1) {
8501 m_azimuthalHaloCells[i][j] = newCellId(cellId);
8504 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
8505 MInt cellId = m_azimuthalWindowCells[i][j];
8506 if(newCellId(cellId) > -1) {
8507 m_azimuthalWindowCells[i][j] = newCellId(cellId);
8511 for(
MInt c = 0; c < noAzimuthalUnmappedHaloCells(); c++) {
8512 MInt cellId = azimuthalUnmappedHaloCell(c);
8513 if(newCellId(cellId) > -1) {
8514 m_azimuthalUnmappedHaloCells[c] = newCellId(cellId);
8521 std::vector<MInt> oldPartLevelAncestorIds(m_partitionLevelAncestorIds);
8522 const MInt noPartLvlAncestorIds = oldPartLevelAncestorIds.size();
8526 std::vector<MInt>().swap(m_partitionLevelAncestorIds);
8527 std::vector<MInt>().swap(m_partitionLevelAncestorNghbrDomains);
8528 std::vector<std::vector<MInt>>().swap(m_partitionLevelAncestorHaloCells);
8529 std::vector<std::vector<MInt>>().swap(m_partitionLevelAncestorWindowCells);
8530 m_noHaloPartitionLevelAncestors = 0;
8533 for(
MInt i = 0; i < noPartLvlAncestorIds; i++) {
8534 const MInt oldId = oldPartLevelAncestorIds[i];
8535 const MInt newId = newCellId(oldId);
8536 m_partitionLevelAncestorIds.push_back(newId);
8560 static constexpr MInt revDir[6] = {1, 0, 3, 2, 5, 4};
8561 if(cellId1 == cellId0)
return;
8562 ASSERT(cellId1 > -1 && cellId0 > -1 && cellId1 < treeb().size() && cellId0 < treeb().size(),
8563 "Invalid cell range " << cellId1 <<
" " << cellId0 <<
" " << treeb().size());
8567 MInt parentId0 = a_parentId(cellId0);
8568 MInt parentId1 = a_parentId(cellId1);
8571 if(parentId0 > -1) {
8572 for(
MInt k = 0; k < m_maxNoChilds; k++) {
8573 if(a_childId(parentId0, k) == cellId0) {
8579 if(parentId1 > -1) {
8580 for(
MInt k = 0; k < m_maxNoChilds; k++) {
8581 if(a_childId(parentId1, k) == cellId1) {
8587 for(
MInt k = 0; k < m_maxNoChilds; k++) {
8588 if(a_childId(cellId0, k) > -1) {
8589 ASSERT(a_parentId(a_childId(cellId0, k)) == cellId0,
"Wrong parent!");
8590 a_parentId(a_childId(cellId0, k)) = cellId1;
8593 for(
MInt k = 0; k < m_maxNoChilds; k++) {
8594 if(a_childId(cellId1, k) > -1) {
8595 ASSERT(a_parentId(a_childId(cellId1, k)) == cellId1,
"Wrong parent!");
8596 a_parentId(a_childId(cellId1, k)) = cellId0;
8599 if(child0 > -1) a_childId(parentId0, child0) = cellId1;
8600 if(child1 > -1) a_childId(parentId1, child1) = cellId0;
8602 for(
MInt k = 0; k < m_maxNoChilds; k++) {
8603 std::swap(a_childId(cellId1, k), a_childId(cellId0, k));
8605 std::swap(a_parentId(cellId0), a_parentId(cellId1));
8609 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8610 MInt nghbrId0 = a_neighborId(cellId0, dir);
8611 MInt nghbrId1 = a_neighborId(cellId1, revDir[dir]);
8613 ASSERT(a_neighborId(nghbrId0, revDir[dir]) == cellId0,
"Reverse link dead");
8614 a_neighborId(nghbrId0, revDir[dir]) = cellId1;
8617 ASSERT(a_neighborId(nghbrId1, dir) == cellId1,
"Reverse link dead");
8618 a_neighborId(nghbrId1, dir) = cellId0;
8621 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8622 std::swap(a_neighborId(cellId1, dir), a_neighborId(cellId0, dir));
8627 std::swap(a_level(cellId1), a_level(cellId0));
8628 std::swap(m_tree.properties(cellId0), m_tree.properties(cellId1));
8629 std::swap(m_tree.solverBits(cellId0), m_tree.solverBits(cellId1));
8630 std::swap(a_globalId(cellId1), a_globalId(cellId0));
8631 std::swap(m_tree.leafCellBits(cellId1), m_tree.leafCellBits(cellId0));
8632 std::swap(a_weight(cellId1), a_weight(cellId0));
8633 std::swap(a_workload(cellId1), a_workload(cellId0));
8634 std::swap(a_noOffsprings(cellId1), a_noOffsprings(cellId0));
8635 for(
MInt i = 0; i < nDim; i++) {
8636 std::swap(a_coordinate(cellId1, i), a_coordinate(cellId0, i));
8662 MBool extendCheckTo2ndNeighbor = m_lbGridChecks;
8663 MBool restrictDiagonalLevelJumps = m_lbGridChecks;
8664 MBool lbBndCheck = m_lbGridChecks;
8666 ASSERT(m_tree.solver(cellId, solver),
"");
8674 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8675 if(!a_hasNeighbor(cellId, dir, solver))
8677 MInt cartesianNeighbor = a_neighborId(cellId, dir, solver);
8678 if(a_noChildren(cartesianNeighbor) != m_maxNoChilds && a_noChildren(cartesianNeighbor) != 0)
return false;
8680 MInt d1 = (d0 + 1) % nDim;
8681 for(
MInt p = 0; p < 2; p++) {
8682 MInt dir1 = 2 * d1 + p;
8683 if(!a_hasNeighbor(cartesianNeighbor, dir1, solver))
continue;
8684 MInt diagonalNeighbor = a_neighborId(cartesianNeighbor, dir1, solver);
8685 if(a_noChildren(diagonalNeighbor) != m_maxNoChilds && a_noChildren(diagonalNeighbor) != 0)
return false;
8686 IF_CONSTEXPR(nDim == 3) {
8687 MInt d2 = (d1 + 1) % nDim;
8688 for(
MInt q = 0; q < 2; q++) {
8689 MInt dir2 = 2 * d2 + q;
8690 if(!a_hasNeighbor(diagonalNeighbor, dir2, solver))
continue;
8691 MInt cornerNeighbor = a_neighborId(diagonalNeighbor, dir2, solver);
8692 if(a_noChildren(cornerNeighbor) != m_maxNoChilds && a_noChildren(cornerNeighbor) != 0)
return false;
8701 for(
MInt child = 0; child < m_maxNoChilds; child++) {
8702 MInt childId = a_childId(cellId, child, solver);
8704 if(childId < 0)
continue;
8705 if(a_hasChildren(childId, solver))
return false;
8706 for(
MInt i = 0; i < m_noDirs; i++) {
8707 if(childCode[i][child])
continue;
8708 if(a_hasNeighbor(childId, i, solver) > 0) {
8710 if(a_hasChildren(a_neighborId(childId, i, solver), solver) > 0) {
8715 if(extendCheckTo2ndNeighbor) {
8716 if(a_hasNeighbor(a_neighborId(childId, i, solver), i, solver)) {
8717 if(a_hasChildren(a_neighborId(a_neighborId(childId, i, solver), i, solver)) > 0) {
8726 if(restrictDiagonalLevelJumps) {
8727 for(
MInt j = 0; j < m_noDirs; j++) {
8728 if(j / 2 == i / 2)
continue;
8729 if(a_hasNeighbor(a_neighborId(childId, i, solver), j, solver) > 0) {
8730 if(a_hasChildren(a_neighborId(a_neighborId(childId, i, solver), j, solver), solver)) {
8735 if(extendCheckTo2ndNeighbor) {
8736 MInt diagNeighbor = a_neighborId(a_neighborId(childId, i, solver), j, solver);
8737 if(a_hasNeighbor(diagNeighbor, i, solver) > 0) {
8739 if(a_hasChildren(a_neighborId(diagNeighbor, i, solver), solver))
return false;
8741 if(a_hasNeighbor(a_neighborId(diagNeighbor, i, solver), j, solver) > 0) {
8742 if(a_hasChildren(a_neighborId(a_neighborId(diagNeighbor, i, solver), j, solver), solver)) {
8749 IF_CONSTEXPR(nDim == 3) {
8750 for(
MInt k = 0; k < m_noDirs; k++) {
8753 if(k / 2 == i / 2)
continue;
8754 if(a_hasNeighbor(a_neighborId(a_neighborId(childId, i, solver), j, solver), k, solver) > 0) {
8755 if(a_hasChildren(a_neighborId(a_neighborId(a_neighborId(childId, i, solver), j, solver), k, solver),
8762 if(extendCheckTo2ndNeighbor) {
8763 MInt cornerNeighbor =
8764 a_neighborId(a_neighborId(a_neighborId(childId, i, solver), j, solver), k, solver);
8765 if(a_hasNeighbor(cornerNeighbor, i, solver) > 0) {
8767 if(a_hasChildren(a_neighborId(cornerNeighbor, i, solver), solver))
return false;
8769 if(a_hasNeighbor(a_neighborId(cornerNeighbor, i, solver), j, solver) > 0) {
8771 if(a_hasChildren(a_neighborId(a_neighborId(cornerNeighbor, i, solver), j, solver), solver))
8774 if(a_hasNeighbor(a_neighborId(a_neighborId(cornerNeighbor, i, solver), j, solver), k, solver)
8776 if(a_hasChildren(a_neighborId(
8777 a_neighborId(a_neighborId(cornerNeighbor, i, solver), j, solver), k, solver)))
8795 if(!m_lbGridChecks) {
8799 if(!m_allowInterfaceRefinement)
8800 for(
MInt i = 0; i < m_noDirs; i++)
8801 if(!a_hasNeighbor(cellId, i, solver))
return false;
8816 const MInt cellId,
const MInt solver,
8817 const std::vector<std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>>& cellOutsideSolver) {
8819 MBool restrictDiagonalLevelJumps = m_lbGridChecks;
8820 MBool extendCheckTo2ndNeighbor = m_lbGridChecks;
8822 ASSERT(m_tree.solver(cellId, solver),
"");
8823 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8824 if(a_hasNeighbor(cellId, dir, solver)) {
8825 if(restrictDiagonalLevelJumps) {
8827 MInt d1 = (d0 + 1) % nDim;
8828 for(
MInt p = 0; p < 2; p++) {
8829 MInt dir1 = 2 * d1 + p;
8830 if(a_hasNeighbor(a_neighborId(cellId, dir, solver), dir1, solver) == 0) {
8836 MInt firstDiagNghbor;
8837 if(extendCheckTo2ndNeighbor) {
8838 firstDiagNghbor = a_neighborId(a_neighborId(cellId, dir, solver), dir1, solver);
8839 if(a_hasNeighbor(firstDiagNghbor, dir, solver)) {
8840 if(a_hasNeighbor(a_neighborId(firstDiagNghbor, dir, solver), dir1, solver) == 0) {
8849 IF_CONSTEXPR(nDim == 3) {
8850 MInt d2 = (d1 + 1) % nDim;
8851 for(
MInt q = 0; q < 2; q++) {
8852 MInt dir2 = 2 * d2 + q;
8853 if(a_hasNeighbor(a_neighborId(a_neighborId(cellId, dir, solver), dir1, solver), dir2, solver) == 0) {
8859 MInt firstCornerNeighbor =
8860 a_neighborId(a_neighborId(a_neighborId(cellId, dir, solver), dir1, solver), dir2, solver);
8861 if(extendCheckTo2ndNeighbor) {
8862 if(a_hasNeighbor(firstCornerNeighbor, dir, solver)) {
8863 if(a_hasNeighbor(a_neighborId(firstCornerNeighbor, dir, solver), dir1, solver)) {
8864 if(a_hasNeighbor(a_neighborId(a_neighborId(firstCornerNeighbor, dir, solver), dir1, solver), dir2,
8880 }
else if(m_allowInterfaceRefinement && hasCutOff()) {
8885 MInt parentId = a_parentId(cellId, solver);
8886 if(parentId > -1 && !a_hasNeighbor(parentId, dir, solver)) {
8888 }
else if(parentId > -1) {
8892 }
else if(m_allowInterfaceRefinement) {
8894 for(
MInt k = 0; k < nDim; k++) {
8895 coords[k] = a_coordinate(cellId, k);
8897 coords[dir / 2] += ((dir % 2 == 0) ? -F1 : F1) * cellLengthAtCell(cellId);
8898 MInt isOutside = cellOutsideSolver[solver](coords, a_level(cellId), cellId);
8899 if(isOutside == 0) {
8901 }
else if(isOutside == -1) {
8902 MInt parentId = a_parentId(cellId, solver);
8903 while(parentId > -1) {
8904 if(a_hasNeighbor(parentId, dir, solver)) {
8907 parentId = a_parentId(parentId, solver);
8931 for(
MInt i = 0; i < m_tree.size(); i++) {
8932 if(a_isToDelete(i))
continue;
8933 if(a_hasProperty(i, Cell::IsHalo))
continue;
8934 m_maxLevel = (m_maxLevel < a_level(i)) ? a_level(i) : m_maxLevel;
8937 MPI_Allreduce(MPI_IN_PLACE, &m_maxLevel, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"m_maxLevel");
8939 if(m_minLevel < 0 || m_maxLevel < m_minLevel || m_maxLevel > 31 || m_minLevel > m_maxLevel) {
8940 mTerm(1, AT_,
"Inconsistent min/max levels: " + to_string(m_minLevel) +
"/" + to_string(m_maxLevel));
8951 if(m_tree.size() == 0) {
8952 mTerm(1, AT_,
" Error in CartesianGrid::deleteCell(), collector is empty.");
8954 if(
id >= m_tree.size()) {
8955 mTerm(1, AT_,
" Error in CartesianGrid::deleteCell(), cell out of range.");
8958 a_resetProperties(
id);
8961 const MInt lastId = m_tree.size() - 1;
8962 const MInt returnValue = (lastId <=
id) ? -1 : lastId;
8965 m_tree.removeAndFill(
id);
8984 const MFloat*
const center,
8986 const MInt baseLevel)
const {
8988 ASSERT(length0 > 0.0,
"length needs to be > 0.");
8991 for(
MInt i = 0; i < nDim; i++) {
8992 x[i] = (coords[i] - center[i] + 1e-12 + F1B2 * length0) / length0;
8993 ASSERT(x[i] > F0 && x[i] < F1,
8994 "Normalized coordinate outside of range (0,1): " + std::to_string(x[i])
8995 +
"; length0 = " + std::to_string(length0) +
"; baseLevel = " + std::to_string(baseLevel)
8996 +
"; coord = " + std::to_string(coords[i]) +
"; center = " + std::to_string(center[i]));
8998 const MLong hilbertId = maia::grid::hilbert::index<nDim>(&x[0], (
MLong)baseLevel);
8999 ASSERT(hilbertId > -1,
"Invalid hilbert id");
9006 const std::vector<std::vector<MInt>>& windowCells,
9007 const std::vector<std::vector<MInt>>& azimuthalHaloCells,
9008 const std::vector<MInt>& azimuthalUnmappedHaloCells,
9009 const std::vector<std::vector<MInt>>& azimuthalWindowCells,
MInt* recalcIdTree) {
9012 windowCells, azimuthalHaloCells, azimuthalUnmappedHaloCells,
9013 azimuthalWindowCells, recalcIdTree);
9020 if(m_newMinLevel < 0) {
9022 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells,
9023 m_azimuthalWindowCells, recalcIdTree);
9029 if(m_newMinLevel == m_targetGridMinLevel && noDomains() == 1) {
9031 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells,
9032 m_azimuthalWindowCells, recalcIdTree);
9033 }
else if(noDomains() > 1) {
9034 MInt backup = m_newMinLevel;
9037 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells,
9038 m_azimuthalWindowCells, recalcIdTree);
9039 m_newMinLevel = backup;
9043 MInt noUnrefinedMinCells = 0;
9044 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
9045 if(a_isHalo(cellId))
continue;
9046 if(a_level(cellId) < m_newMinLevel) {
9047 if(a_noChildren(cellId) < 1) noUnrefinedMinCells++;
9051 MPI_Allreduce(MPI_IN_PLACE, &noUnrefinedMinCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
9052 "noUnrefinedMinCells");
9055 if(noUnrefinedMinCells > 0) {
9056 MInt backup = m_newMinLevel;
9057 if(domainId() == 0) {
9058 cerr <<
"Mincells not yet sufficiently refined for minLevel increase from " << m_minLevel <<
" to "
9059 << m_newMinLevel <<
"!" << endl;
9063 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells,
9064 m_azimuthalWindowCells, recalcIdTree);
9065 m_newMinLevel = backup;
9070 MInt backupMinLevel = m_newMinLevel;
9072 m_targetGridMinLevel = m_minLevel;
9073 std::stringstream s;
9074 s <<
"restartGrid_backup_" <<
globalTimeStep << ParallelIo::fileExt();
9075 MString newGridFileName = s.str();
9078 *
this, (m_outputDir + newGridFileName).c_str(),
static_cast<Collector<void>*
>(
nullptr), m_haloCells,
9079 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells, m_azimuthalWindowCells, recalcIdTree);
9081 m_newMinLevel = backupMinLevel;
9082 m_targetGridMinLevel = m_newMinLevel;
9084 if(domainId() == 0) {
9085 cerr <<
"Increasing minLevel from " << m_minLevel <<
" to " << m_newMinLevel << endl;
9088 MInt backupUniform = m_maxUniformRefinementLevel;
9089 if(m_maxUniformRefinementLevel < m_newMinLevel) {
9090 if(domainId() == 0) {
9091 cerr <<
"Increasing maxUniformRefinementLevel from " << m_maxUniformRefinementLevel <<
" to "
9092 << m_newMinLevel << endl;
9094 m_maxUniformRefinementLevel = m_newMinLevel;
9098 m_windowCells, m_azimuthalHaloCells, m_azimuthalUnmappedHaloCells,
9099 m_azimuthalWindowCells, recalcIdTree);
9101 m_maxUniformRefinementLevel = backupUniform;
9130 ASSERT(m_globalToLocalId.size() > 0,
"Error: m_globalToLocalId is empty.");
9131 auto it = m_globalToLocalId.find(globalId);
9132 if(it != m_globalToLocalId.end()) {
9135 TERMM_IF_COND(termIfNotExisting,
"Mapping from global to local id not found.");
9149 a_resetProperties(cellId);
9150 m_tree.resetSolver(cellId);
9151 m_tree.resetIsLeafCell(cellId);
9152 a_parentId(cellId) = -1;
9153 a_globalId(cellId) = -1;
9154 a_level(cellId) = -1;
9155 a_noOffsprings(cellId) = 0;
9156 a_weight(cellId) = F1;
9157 a_workload(cellId) = F0;
9158 fill(&a_childId(cellId, 0), &a_childId(cellId, 0) + m_maxNoChilds, -1);
9159 fill(&a_neighborId(cellId, 0), &a_neighborId(cellId, 0) + m_maxNoNghbrs, -1);
9196 if(!Context::getBasicProperty<MBool>(
"createGridMap", AT_)) {
9201 const MString donorGridFileName = Context::getBasicProperty<MString>(
"donorGridFileName", AT_);
9204 MString gridMapFileName = m_outputDir +
"gridmap.Netcdf";
9205 gridMapFileName = Context::getBasicProperty<MString>(
"gridMapFileName", AT_, &gridMapFileName);
9219 MBool regenerate =
true;
9220 regenerate = Context::getBasicProperty<MBool>(
"forceGridMapGeneration", AT_, ®enerate);
9221 if(regenerate || !ParallelIo::fileExists(gridMapFileName, mpiComm())) {
9222 createGridMap(donorGridFileName, gridMapFileName);
9237 MBool savePartition =
false;
9238 savePartition = Context::getBasicProperty<MBool>(
"saveDonorGridPartition", AT_, &savePartition);
9241 MString gridPartitionFileName = Context::getBasicProperty<MString>(
"gridPartitionFileName", AT_);
9244 saveDonorGridPartition(gridMapFileName, gridPartitionFileName);
9275 m_log <<
"Creating grid map from donor grid " << donorGridFileName <<
" to target grid " << m_gridInputFileName
9276 <<
" and writing the results to " << gridMapFileName <<
"..." << endl;
9283 using namespace parallel_io;
9284 ParallelIo donorGrid(donorGridFileName, PIO_READ, mpiComm());
9287 array<MFloat, nDim> donorCenter;
9290 donorGrid.getAttribute(&donorCenter[0],
"centerOfGravity", nDim);
9291 MFloat donorLengthLevel0 = NAN;
9293 donorGrid.getAttribute(&donorLengthLevel0,
"lengthLevel0");
9294 const array<MString, 3> dirs = {{
"x",
"y",
"z"}};
9295 for(
MInt dir = 0; dir < nDim; dir++) {
9296 const array<MFloat, 2> donorExtent = {
9297 {donorCenter[dir] - 0.5 * donorLengthLevel0, donorCenter[dir] + 0.5 * donorLengthLevel0}};
9298 const array<MFloat, 2> targetExtent = {
9299 {m_centerOfGravity[dir] - 0.5 * lengthLevel0(), m_centerOfGravity[dir] + 0.5 * lengthLevel0()}};
9300 if(donorExtent[0] < targetExtent[0]) {
9301 TERMM(1,
"Donor grid extents exceed target grid in negative " + dirs[dir] +
"-direction");
9303 if(donorExtent[1] > targetExtent[1]) {
9304 TERMM(1,
"Donor grid extents exceed target grid in positive " + dirs[dir] +
"-direction");
9311 const MFloat eps = 1.0 /
FPOW2(30) * m_lengthLevel0;
9314 MInt donorMinLevel = 0;
9316 donorGrid.getAttribute(&donorMinLevel,
"minLevel");
9317 const MFloat donorMinLevelLength = donorLengthLevel0 *
FFPOW2(donorMinLevel);
9318 const MFloat targetMinLevelLength = cellLengthAtLevel(minLevel());
9319 if(fabs(donorMinLevelLength - targetMinLevelLength) > eps) {
9321 "Length of min level cells do not match between donor and target "
9323 + to_string(donorMinLevelLength) +
"; target: " + to_string(targetMinLevelLength));
9328 for(
MInt dir = 0; dir < nDim; dir++) {
9329 const MFloat displacement = fabs(donorCenter[dir] - m_centerOfGravity[dir]);
9330 const MFloat quotient = displacement / targetMinLevelLength;
9332 TERMM(1,
"The grid centers are displaced in the " + dirs[dir]
9333 +
"-direction by a non-integer multiple of the length of a "
9335 + to_string(quotient));
9346 MInt noPartitionCells = 0;
9347 donorGrid.getAttribute(&noPartitionCells,
"noPartitionCells");
9350 donorGrid.setOffset(isMpiRoot() ? noPartitionCells : 0, 0);
9360 donorGrid.getAttribute(&hasDiff,
"maxPartitionLevelShift");
9362 TERMM(1,
"partition level shifts not supported but level difference found");
9367 MIntScratchSpace partitionCellsId(noPartitionCells, AT_,
"partitionCellsId");
9372 MFloatScratchSpace partitionCellsWorkLoad(noPartitionCells, AT_,
"partitionCellsWorkLoad");
9374 donorGrid.readArray(&partitionCellsWorkLoad[0],
"partitionCellsWorkload");
9375 if(isMpiRoot() && noDomains() > 1) {
9384 donorGrid.readArray(&partitionCellsId[0],
"partitionCellsGlobalId");
9385 if(isMpiRoot() && noDomains() > 1) {
9395 "partitionCellsId[0]");
9404 const MInt noCells = m_noInternalCells;
9409 MInt globalCount = 0;
9410 donorGrid.getAttribute(&globalCount,
"noCells");
9411 const MInt globalIdOffset = globalIdOffsets[domainId()];
9412 const MInt localCount = (domainId() == noDomains() - 1)
9413 ? globalCount - globalIdOffsets[domainId()]
9414 : globalIdOffsets[domainId() + 1] - globalIdOffsets[domainId()];
9423 MLongScratchSpace minLevelCellsTreeId(noPartitionCells, AT_,
"minLevelCellsTreeId");
9425 donorGrid.setOffset(noPartitionCells, 0);
9426 donorGrid.readArray(minLevelCellsTreeId.
data(),
"minLevelCellsTreeId");
9430 fill(hilbertIds.
begin(), hilbertIds.
end(), -1);
9431 for(
MInt i = 0; i < noPartitionCells; i++) {
9433 const MInt globalId = partitionCellsId[i];
9434 if(globalId < globalIdOffset || globalId >= globalIdOffset + localCount) {
9439 array<MFloat, nDim> x;
9440 const MInt localCellId = globalId - globalIdOffset;
9441 maia::grid::hilbert::treeIdToCoordinates<nDim>(&coordinates[localCellId * nDim], minLevelCellsTreeId[i],
9442 (
MLong)m_minLevel, &donorCenter[0], donorLengthLevel0);
9443 for(
MInt j = 0; j < nDim; j++) {
9444 x[j] = (coordinates[localCellId * nDim + j] - m_centerOfGravity[j] + 0.5 * lengthLevel0()) / lengthLevel0();
9448 hilbertIds[i] = maia::grid::hilbert::index<nDim>(&x[0], minLevel());
9452 for(
MInt cellId = 0; cellId < noCells; cellId++) {
9454 if(a_level(cellId) != minLevel()) {
9459 array<MFloat, nDim> x;
9460 for(
MInt j = 0; j < nDim; j++) {
9461 x[j] = (a_coordinate(cellId, j) - m_centerOfGravity[j] + 0.5 * lengthLevel0()) / lengthLevel0();
9465 localHilbertIds[cellId] = maia::grid::hilbert::index<nDim>(&x[0], minLevel());
9477 const MInt noCellsFound = count_if(hilbertIds.
begin(), hilbertIds.
end(), [](
const MInt a) { return a != -1; });
9478 dataCount[domainId()] = noCellsFound;
9482 displacements[0] = 0;
9483 for(
MInt i = 1; i < noDomains(); i++) {
9484 displacements[i] = displacements[i - 1] + dataCount[i - 1];
9489 for(
MInt count = 0, i = 0; i < noPartitionCells; i++) {
9490 if(hilbertIds[i] == -1) {
9493 sendBuffer[count++] = partitionCellsId[i];
9497 "sendBuffer[0]",
"partitionCellsId[0]");
9500 for(
MInt count = 0, i = 0; i < noPartitionCells; i++) {
9501 if(hilbertIds[i] == -1) {
9504 sendBuffer[count++] = hilbertIds[i];
9519 for(
MInt i = 0; i < noPartitionCells; i++) {
9520 s[i][0] = hilbertIds[i];
9521 s[i][1] = partitionCellsId[i];
9523 sort(s.
begin(), s.
end(), [](
const array<MInt, 2>&
a,
const array<MInt, 2>&
b) { return a[0] < b[0]; });
9524 for(
MInt i = 0; i < noPartitionCells; i++) {
9525 hilbertIds[i] = s[i][0];
9526 partitionCellsId[i] = s[i][1];
9531 fill(gridMap.
begin(), gridMap.
end(), -1);
9533 MInt firstMappedPartitionCellId = std::numeric_limits<MInt>::max();
9534 MInt noMappedPartitionCells = 0;
9538 for(
MInt cellId = 0; cellId < noCells; cellId++) {
9540 if(a_level(cellId) != minLevel()) {
9545 const MInt hilbertId = localHilbertIds[cellId];
9546 MInt*
const lower = lower_bound(hilbertIds.
data(), (hilbertIds.
data() + hilbertIds.
size()), hilbertId);
9549 if(lower == (hilbertIds.
data() + hilbertIds.
size()) || *lower != hilbertId) {
9554 const MInt partitionCellId = distance(hilbertIds.
data(), lower);
9555 gridMap[cellId] = partitionCellsId[partitionCellId];
9558 firstMappedPartitionCellId = min(firstMappedPartitionCellId, partitionCellId);
9561 noMappedPartitionCells++;
9565 const MInt firstMappedCellId = (noMappedPartitionCells > 0) ? partitionCellsId[firstMappedPartitionCellId] : 0;
9568 MInt noDonorCells = 0;
9571 MIntScratchSpace partitionCellsNoOffsprings(max(noMappedPartitionCells, 1), AT_,
"partitionCellsNoOffsprings");
9572 MIntScratchSpace partitionCellsId2(noPartitionCells, AT_,
"partitionCellsId2");
9577 donorGrid.setOffset(noPartitionCells, 0);
9578 donorGrid.readArray(&partitionCellsId2[0],
"partitionCellsGlobalId");
9580 donorGrid.getAttribute(&globalCount,
"noCells");
9581 for(
MInt i = 0; i < noMappedPartitionCells; i++) {
9582 MInt id = firstMappedPartitionCellId + i;
9583 MInt nextId = (
id == noPartitionCells - 1) ? globalCount : partitionCellsId2[
id + 1];
9584 partitionCellsNoOffsprings[i] = nextId - partitionCellsId2[
id];
9585 ASSERT(partitionCellsNoOffsprings[i] > 0,
"");
9589 for(
MInt i = 0; i < noMappedPartitionCells; i++) {
9590 noDonorCells += partitionCellsNoOffsprings[i];
9595 ParallelIo::size_type offset, totalCount;
9596 ParallelIo::calcOffset(noDonorCells, &offset, &totalCount, mpiComm());
9600 donorGrid.setOffset(noDonorCells, offset);
9602 vector<MUchar> cellInfo(noDonorCells);
9603 donorGrid.readArray(cellInfo.data(),
"cellInfo");
9604 for(
MInt i = 0; i < noDonorCells; i++) {
9605 const MUint childCnt =
static_cast<MUint>(cellInfo[i]) & 15u;
9606 noChildIds[i] = (
MInt)childCnt;
9611 fill(gridMapNoOffspring.
begin(), gridMapNoOffspring.
end(), 0);
9617 auto getNoOffspring = [](
const MInt cellId,
const MInt*
const noChilds) {
9619 MInt noOffspring = noChilds[cellId];
9624 MInt offspringId = 1;
9625 while(offspringId <= noOffspring) {
9626 noOffspring += noChilds[cellId + offspringId];
9633 MInt noOneToMultipleMappings = 0;
9634 for(
MInt cellId = 0; cellId < noCells;) {
9638 MInt donorGlobalCellId = gridMap[cellId];
9639 if(donorGlobalCellId == -1) {
9645 if(a_noChildren(cellId) == 0) {
9648 const MInt donorLocalCellId = donorGlobalCellId - firstMappedCellId;
9649 gridMapNoOffspring[cellId] = getNoOffspring(donorLocalCellId, &noChildIds[0]);
9657 const MInt partitionCellLevel = a_level(cellId);
9660 MInt currentCellId = cellId + 1;
9662 while(currentCellId < noCells && a_level(currentCellId) > partitionCellLevel) {
9663 MInt donorLocalCellId = donorGlobalCellId - firstMappedCellId;
9665 if(noChildIds[donorLocalCellId] == 0) {
9667 gridMap[cellId] = donorGlobalCellId;
9668 const MInt parentLevel = a_level(cellId);
9675 while(cellId < noCells && a_level(cellId) > parentLevel) {
9676 gridMap[cellId] = donorGlobalCellId;
9678 gridMapNoOffspring[cellId] = -1;
9679 noOneToMultipleMappings++;
9685 donorGlobalCellId++;
9687 if(a_noChildren(cellId) == 0) {
9689 gridMap[cellId] = donorGlobalCellId;
9692 donorLocalCellId = donorGlobalCellId - firstMappedCellId;
9693 const MInt noOffspring = getNoOffspring(donorLocalCellId, &noChildIds[0]);
9694 gridMapNoOffspring[cellId] = noOffspring;
9697 donorGlobalCellId += noOffspring + 1;
9700 gridMap[cellId] = donorGlobalCellId;
9701 donorGlobalCellId++;
9708 currentCellId = cellId;
9714 ParallelIo gridMapFile(gridMapFileName, PIO_REPLACE, mpiComm());
9715 gridMapFile.setAttribute(donorGridFileName,
"donorGridFileName");
9716 gridMapFile.setAttribute(m_gridInputFileName,
"gridFile");
9717 gridMapFile.defineScalar(PIO_INT,
"noCells");
9718 gridMapFile.defineArray(PIO_INT,
"cellIds", m_domainOffsets[noDomains()]);
9719 gridMapFile.defineArray(PIO_INT,
"noOffspring", m_domainOffsets[noDomains()]);
9720 gridMapFile.setOffset(noCells, m_domainOffsets[domainId()]);
9721 gridMapFile.writeScalar(m_domainOffsets[noDomains()],
"noCells");
9722 gridMapFile.writeArray(&gridMap[0],
"cellIds");
9723 gridMapFile.writeArray(&gridMapNoOffspring[0],
"noOffspring");
9725 m_log <<
"Created & saved grid map file." << endl;
9726 if(noOneToMultipleMappings > 0) {
9727 m_log <<
"WARNING: There were " << noOneToMultipleMappings
9728 <<
" cells on the target grid that are finer than the "
9729 "corresponding donor cell."
9753 ParallelIo gridMapFile(gridMapFileName, PIO_READ, mpiComm());
9755 gridMapFile.getAttribute(&donorGridFileName,
"donorGridFileName");
9756 gridMapFile.setOffset(m_noInternalCells, m_domainOffsets[domainId()]);
9758 gridMapFile.readArray(&gridMap[0],
"cellIds");
9760 m_log <<
"Saving grid partition for donor grid " << donorGridFileName <<
" and writing the results to "
9761 << gridPartitionFileName <<
"..." << endl;
9764 auto c = find_if(gridMap.
begin(), gridMap.
end(), [](
const MInt a) { return a != -1; });
9765 const MInt cellId = (c == end(gridMap)) ? -1 : *c;
9768 ParallelIo file(gridPartitionFileName, PIO_REPLACE, mpiComm());
9769 file.setAttribute(m_gridInputFileName,
"targetGridFileName");
9770 file.setAttribute(donorGridFileName,
"gridFile");
9771 file.defineArray(PIO_INT,
"firstCellIds", noDomains());
9772 file.setOffset(1, domainId());
9773 file.writeArray(&cellId,
"firstCellIds");
9775 m_log <<
"Saved grid partition file." << endl;
9797 MLongScratchSpace partitionCellOffsets(noDomains() + 1, AT_,
"partitionCellOffsets");
9799 if(domainId() == 0) {
9800 MString gridPartitionFileName = m_outputDir +
"partition.Netcdf";
9801 gridPartitionFileName = Context::getBasicProperty<MString>(
"gridPartitionFileName", AT_, &gridPartitionFileName);
9805 ParallelIo file(gridPartitionFileName, PIO_READ, MPI_COMM_SELF);
9806 const MInt noTargetDomains = file.getArraySize(
"firstCellIds");
9807 file.setOffset(noTargetDomains, 0);
9809 file.readArray(&firstCellIds[0],
"firstCellIds");
9813 for(
auto&& first : firstCellIds) {
9820 if(first < previous) {
9821 TERMM(1,
"Cell ids not monotonically increasing: " + to_string(first) +
" < " + to_string(previous)
9822 +
". Did you forget to set 'targetGridFileName' when "
9823 "generating the donor grid file?");
9833 const MLong* first = partitionCellsId;
9834 const MLong*
const last = first + noPartitionCells;
9835 MInt donorDomainId = 0;
9836 for(
MInt d = 0; d < noTargetDomains; d++) {
9838 const MInt firstCellId = firstCellIds[d];
9839 if(firstCellId == -1) {
9844 const auto bound = lower_bound(first, last, firstCellId);
9845 if(distance(bound, last) == 0) {
9848 TERMM(1,
"partition cell not found, this should not happen. Go fix your code!");
9852 partitionCellOffsets[donorDomainId] = distance(partitionCellsId, bound);
9862 partitionCellOffsets[noDomains()] = noPartitionCells;
9863 m_log <<
"Cartesian grid loaded grid partition from " << gridPartitionFileName << endl;
9865 m_domainOffsets[0] = 0;
9866 for(
MInt i = 1; i < noDomains(); i++) {
9867 m_domainOffsets[i] = partitionCellsId[partitionCellOffsets[i]];
9869 m_domainOffsets[noDomains()] = m_noCellsGlobal;
9873 if(donorDomainId != noDomains()) {
9874 TERMM(1,
"mismatch between number of donor domains in partition file and "
9879 MPI_Bcast(partitionCellOffsets.
data(), noDomains() + 1, MPI_LONG, 0, mpiComm(), AT_,
"partitionCellOffsets.data()");
9880 MPI_Bcast(m_domainOffsets, noDomains() + 1, MPI_LONG, 0, mpiComm(), AT_,
"m_domainOffsets");
9881 m_noPartitionCells = partitionCellOffsets[domainId() + 1] - partitionCellOffsets[domainId()];
9882 m_localPartitionCellOffsets[0] =
9883 partitionCellOffsets[domainId()];
9884 m_localPartitionCellOffsets[1] = partitionCellOffsets[domainId() + 1];
9885 m_localPartitionCellOffsets[2] =
9886 m_noPartitionCellsGlobal;
9887 m_noInternalCells = m_domainOffsets[domainId() + 1] - m_domainOffsets[domainId()];
9896 std::map<MLong, MInt>().swap(m_globalToLocalId);
9897 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
9900 if(a_hasProperty(cellId, Cell::IsPeriodic))
continue;
9902 if(a_hasProperty(cellId, Cell::IsToDelete))
continue;
9904 if(a_globalId(cellId) > -1) {
9905 ASSERT(m_globalToLocalId.count(a_globalId(cellId)) == 0,
9906 "Global id already in map: " + std::to_string(a_globalId(cellId)) +
" " + std::to_string(cellId) +
" "
9907 + std::to_string(m_globalToLocalId[a_globalId(cellId)]));
9908 m_globalToLocalId[a_globalId(cellId)] = cellId;
9909 }
else if(!a_isToDelete(cellId)) {
9911 "Error: invalid global id for cell #" + std::to_string(cellId) +
": " + std::to_string(a_globalId(cellId)));
9929 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
9931 for(
MInt childId = 0; childId < m_maxNoChilds; childId++) {
9932 if(a_childId(cellId, childId) == -1) {
9936 if(m_globalToLocalId.count(a_childId(cellId, childId)) > 0) {
9937 a_childId(cellId, childId) = m_globalToLocalId[a_childId(cellId, childId)];
9939 a_childId(cellId, childId) = -1;
9955 for(
MInt dirId = 0; dirId < m_noDirs; dirId++) {
9956 if(a_neighborId(cellId, dirId) > -1) {
9957 if(m_globalToLocalId.count(a_neighborId(cellId, dirId)) > 0) {
9958 a_neighborId(cellId, dirId) = m_globalToLocalId[a_neighborId(cellId, dirId)];
9960 a_neighborId(cellId, dirId) = -1;
9966 if(a_parentId(cellId) == -1) {
9967 a_parentId(cellId) = -1;
9969 if(m_globalToLocalId.count(a_parentId(cellId)) > 0) {
9970 a_parentId(cellId) = m_globalToLocalId[a_parentId(cellId)];
9972 a_parentId(cellId) = -1;
9985 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
9986 if(a_parentId(cellId) > -1) {
9987 a_parentId(cellId) = a_globalId(
static_cast<MInt>(a_parentId(cellId)));
9990 for(
MInt i = 0; i < m_noDirs; i++) {
9991 if(a_hasNeighbor(cellId, i)) {
9992 a_neighborId(cellId, i) = a_globalId(
static_cast<MInt>(a_neighborId(cellId, i)));
9997 if(a_childId(cellId, i) > -1) {
9998 a_childId(cellId, i) = a_globalId(
static_cast<MInt>(a_childId(cellId, i)));
10011template <MInt nDim>
10014 storeMinLevelCells();
10017 m_noInternalCells = 0;
10018 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
10019 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
10020 if(a_isToDelete(cellId))
continue;
10021 m_noInternalCells++;
10025 const MInt noCells = m_noInternalCells;
10028 mpiComm(), AT_,
"noCells",
"noCellsPerDomain[0]");
10029 ASSERT(noCellsPerDomain[domainId()] == noCells,
"Local number of cells does not match.");
10031 if(m_domainOffsets ==
nullptr) {
10032 mAlloc(m_domainOffsets, noDomains() + 1,
"m_domainOffsets", 0L, AT_);
10036 m_domainOffsets[0] = m_32BitOffset;
10037 for(
MInt d = 0; d < noDomains(); d++) {
10038 m_domainOffsets[d + 1] = m_domainOffsets[d] +
static_cast<MLong>(noCellsPerDomain[d]);
10041 m_noCellsGlobal = m_domainOffsets[noDomains()] - m_32BitOffset;
10044 const MInt firstMinLvlCell = m_minLevelCells[0];
10052 if(a_hasProperty(firstMinLvlCell, Cell::IsPartLvlAncestor) && a_hasProperty(firstMinLvlCell, Cell::IsHalo)) {
10053 descendStoreGlobalId(firstMinLvlCell, localCnt);
10058 for(
MUint i = std::max(0, std::min(1, localCnt)); i < m_minLevelCells.size(); i++) {
10059 const MInt cellId = m_minLevelCells[i];
10063 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
10064 descendStoreGlobalId(cellId, localCnt);
10068 if(noNeighborDomains() > 0) {
10070 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10071 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
10072 MInt cellId = m_windowCells[i][j];
10073 globalId(cellId) = a_globalId(cellId);
10074 ASSERT(globalId(cellId) >= m_domainOffsets[domainId()] && globalId(cellId) < m_domainOffsets[domainId() + 1],
10080 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10081 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
10082 MInt cellId = m_haloCells[i][j];
10083 a_globalId(cellId) = globalId(cellId);
10088 if(m_azimuthalPer && noAzimuthalNeighborDomains() > 0) {
10090 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
10091 for(
MInt j = 0; j < (signed)m_azimuthalWindowCells[i].size(); j++) {
10092 MInt cellId = m_azimuthalWindowCells[i][j];
10093 globalId(cellId) = a_globalId(cellId);
10094 ASSERT(globalId(cellId) >= m_domainOffsets[domainId()] && globalId(cellId) < m_domainOffsets[domainId() + 1],
10100 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
10101 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
10102 MInt cellId = m_azimuthalHaloCells[i][j];
10103 a_globalId(cellId) = globalId(cellId);
10109 createGlobalToLocalIdMapping();
10113 TERMM_IF_NOT_COND(m_noPartitionCells > 0 || m_updatingPartitionCells,
10114 "Error: number of partition cells needs to be at least 1.");
10116 updatePartitionCellInformation();
10121template <MInt nDim>
10124 MInt noLocalPartitionCells = 0;
10125 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
10126 if(a_isToDelete(cellId)) {
10129 if(a_hasProperty(cellId, Cell::IsHalo)) {
10133 if(a_hasProperty(cellId, Cell::IsPartitionCell)) {
10134 m_localPartitionCellGlobalIds[noLocalPartitionCells] = a_globalId(cellId);
10135 noLocalPartitionCells++;
10139 if(noLocalPartitionCells == 0 && !m_updatingPartitionCells) {
10140 TERMM(1,
"noLocalPartitionCells == 0");
10144 if(noLocalPartitionCells != m_noPartitionCells) {
10145 TERMM(-1,
"Mismatch in partitionCells " + to_string(m_noPartitionCells) +
"/" + to_string(noLocalPartitionCells));
10149 sort(m_localPartitionCellGlobalIds, m_localPartitionCellGlobalIds + noLocalPartitionCells);
10152 MIntScratchSpace localPartitionCellCounts(noDomains(), AT_,
"localPartitionCellCounts");
10153 MPI_Allgather(&noLocalPartitionCells, 1, MPI_INT, &localPartitionCellCounts[0], 1, MPI_INT, mpiComm(), AT_,
10154 "noLocalPartitionCells",
"localPartitionCellCounts[0]");
10158 for(
MInt dId = 0; dId < domainId(); dId++) {
10159 offset += localPartitionCellCounts[dId];
10163 m_localPartitionCellOffsets[0] = offset;
10164 m_localPartitionCellOffsets[1] = m_localPartitionCellOffsets[0] + noLocalPartitionCells;
10165 m_localPartitionCellOffsets[2] = m_noPartitionCellsGlobal;
10168 for(
MInt i = 0; i < m_noPartitionCells; i++) {
10169 m_localPartitionCellLocalIds[i] = globalIdToLocalId(m_localPartitionCellGlobalIds[i]);
10184template <MInt nDim>
10187 if(!a_hasProperty(cellId, Cell::IsHalo)) {
10188 ASSERT(localCnt < m_noInternalCells,
"");
10189 a_globalId(cellId) = m_domainOffsets[domainId()] + localCnt++;
10190 ASSERT(a_globalId(cellId) >= m_domainOffsets[domainId()] && a_globalId(cellId) < m_domainOffsets[domainId() + 1],
10191 "Error: global id outside of global id range for this domain.");
10195 for(
MInt child = 0; child <
ipow(2, nDim); child++) {
10196 if(a_childId(cellId, child) < 0) {
10199 descendStoreGlobalId(a_childId(cellId, child), localCnt);
10207template <MInt nDim>
10209 ASSERT(!a_hasProperty(cellId, Cell::IsPartLvlAncestor),
"not supposed to be called for a partition level ancestor");
10210 a_noOffsprings(cellId) = 1;
10211 a_workload(cellId) = a_weight(cellId);
10212 if(a_noChildren(cellId) > 0) {
10213 for(
MInt child = 0; child <
ipow(2, nDim); child++) {
10214 if(a_childId(cellId, child) < 0)
continue;
10215 MLong childId = a_childId(cellId, child) - offset;
10216 descendNoOffsprings(childId, offset);
10217 a_noOffsprings(cellId) += a_noOffsprings(childId);
10218 a_workload(cellId) += a_workload(childId);
10228template <MInt nDim>
10231 m_minLevelCells.clear();
10232 map<MLong, MInt> minLevelCells;
10233 const MInt minLevel = updateMinlevel ? m_newMinLevel : m_minLevel;
10234 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
10235 if(a_hasProperty(cellId, Cell::IsHalo))
continue;
10236 if(a_isToDelete(cellId))
continue;
10237 if(a_level(cellId) == minLevel) {
10238 const MLong hilbertId =
10239 updateMinlevel ? generateHilbertIndex(cellId, m_newMinLevel) : generateHilbertIndex(cellId);
10240 TERMM_IF_COND(minLevelCells.count(hilbertId),
"Error: duplicate hilbertId.");
10241 minLevelCells.insert(pair<MLong, MInt>(hilbertId, cellId));
10245 MBool found =
false;
10246 MInt minLvlHaloPartLvlAncestor = -1;
10247 for(
auto& i : m_partitionLevelAncestorIds) {
10248 TERMM_IF_NOT_COND(a_hasProperty(i, Cell::IsPartLvlAncestor),
10249 "cell is not a partition level ancestor: " + std::to_string(i));
10250 TERMM_IF_COND(a_isToDelete(i),
"Error: partition level ancestor marked for deletion.");
10254 if(a_level(i) == minLevel && a_hasProperty(i, Cell::IsHalo)) {
10255 TERMM_IF_COND(found,
"there should only be a single min-level halo partition level ancestor "
10256 "in the list of partitionLevelAncestorIds! Other halo cells with "
10257 "these properties shouldnt be in that list!");
10258 const MInt hilbertId = updateMinlevel ? generateHilbertIndex(i, m_newMinLevel) : generateHilbertIndex(i);
10259 TERMM_IF_COND(minLevelCells.count(hilbertId),
"duplicate hilbertId.");
10260 minLevelCells.insert(pair<MInt, MInt>(hilbertId, i));
10261 minLvlHaloPartLvlAncestor = i;
10270 for(
auto& minLevelCell : minLevelCells) {
10271 m_minLevelCells.push_back(minLevelCell.second);
10275 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
10278 if(found && cellId == minLvlHaloPartLvlAncestor)
continue;
10280 if(a_level(cellId) == minLevel && a_hasProperty(cellId, Cell::IsHalo)) {
10281 TERMM_IF_COND(a_isToDelete(cellId),
"Error: min-level halo marked for deletion.");
10282 m_minLevelCells.push_back(cellId);
10292template <MInt nDim>
10294 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
10295 m_tree.resetIsLeafCell(cellId);
10297 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
10298 for(
MInt solverId = 0; solverId < m_tree.noSolvers(); solverId++) {
10299 if(m_tree.solver(cellId, solverId)) {
10300 a_isLeafCell(cellId, solverId) =
10301 !a_hasChildren(cellId, solverId) && !a_hasProperty(cellId, Cell::IsPartLvlAncestor);
10306 if(noNeighborDomains() > 0) {
10311 if(m_azimuthalPer) {
10312 if(noAzimuthalNeighborDomains() > 0) {
10314 &m_tree.leafCellBits(0), m_tree.size());
10319 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
10320 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
10321 MInt cellId = azimuthalHaloCell(i, j);
10322 for(
MInt solverId = 0; solverId < m_tree.noSolvers(); solverId++) {
10323 if(m_tree.solver(cellId, solverId)) {
10324 a_isLeafCell(cellId, solverId) =
10325 !a_hasChildren(cellId, solverId) && !a_hasProperty(cellId, Cell::IsPartLvlAncestor);
10330 for(
MInt i = 0; i < noAzimuthalUnmappedHaloCells(); i++) {
10331 MInt cellId = azimuthalUnmappedHaloCell(i);
10332 for(
MInt solverId = 0; solverId < m_tree.noSolvers(); solverId++) {
10333 if(m_tree.solver(cellId, solverId)) {
10334 a_isLeafCell(cellId, solverId) =
10335 !a_hasChildren(cellId, solverId) && !a_hasProperty(cellId, Cell::IsPartLvlAncestor);
10347template <MInt nDim>
10349 const MInt*
const noCellsToSendByDomain,
10350 const MInt*
const sortedCellId,
10351 const MLong*
const partitionCellOffsets,
10352 const MLong*
const globalIdOffsets) {
10355 const MInt noCells = m_tree.size();
10356 const MInt receiveSize = noCellsToReceiveByDomain[noDomains()];
10369 for(
MInt i = 0; i < noCells; i++) {
10371 const MUint noChilds = (
MUint)a_noChildren(i);
10372 const MUint isMinLevel = (a_level(i) == m_minLevel);
10373 const MInt parent = m_globalToLocalId[a_parentId(i)];
10374 MUint position = 0;
10376 for(
MUint j = 0; j < (unsigned)m_maxNoChilds; j++) {
10377 if(a_childId(parent, j) == a_globalId(i)) {
10382 const MUint tmpBit = noChilds | (position << 4) | (isMinLevel << 7);
10383 cellInfoSend[i] = tmpBit;
10388 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &cellInfoRecv[0]);
10390 for(
MInt i = 0; i < receiveSize; i++) {
10392 cellInfo[i] =
static_cast<MUchar>(cellInfoRecv[i]);
10417 coordinates.
fill(-1.0);
10425 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &parentId[0]);
10427 noCellsToSendByDomain, noCellsToReceiveByDomain,
IPOW2(nDim), &childIds[0]);
10429 noCellsToSendByDomain, noCellsToReceiveByDomain, m_noDirs, &nghbrIds[0]);
10431 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &level[0]);
10433 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &globalId[0]);
10435 noCellsToSendByDomain, noCellsToReceiveByDomain, nDim, &coordinates[0]);
10437 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &weight[0]);
10439 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &solver[0]);
10442 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &properties[0]);
10444 std::map<MLong, MInt>().swap(m_globalToLocalId);
10450 vector<MInt> localMinLevelCells(0);
10451 vector<MLong> minLevelCellsTreeId(0);
10453 localMinLevelId.
fill(-1);
10455 vector<MLong> partitionCells(0);
10458 for(
MInt i = 0; i < receiveSize; i++) {
10460 const MInt cellId = m_tree.size();
10461 if(globalIdOffsets[domainId()] + (
MLong)cellId != globalId(i)) {
10463 "Global id mismatch." + to_string(m_domainOffsets[domainId()] + (
MLong)cellId) +
" "
10464 + to_string(globalId(i)));
10469 a_parentId(cellId) = parentId(i);
10470 for(
MInt j = 0; j <
IPOW2(nDim); j++) {
10471 a_childId(cellId, j) = childIds(i, j);
10473 for(
MInt j = 0; j < m_noDirs; j++) {
10474 a_neighborId(cellId, j) = nghbrIds(i, j);
10476 a_globalId(cellId) = globalId(i);
10477 a_level(cellId) = level(i);
10478 for(
MInt j = 0; j < nDim; j++) {
10479 a_coordinate(cellId, j) = coordinates(i, j);
10481 a_weight(cellId) = weight(i);
10482 m_tree.solverBits(cellId) = solver(i);
10485 a_noOffsprings(cellId) = 0;
10486 a_workload(cellId) = F0;
10489 if(a_level(cellId) == m_minLevel) {
10490 localMinLevelId[i] = (
MInt)localMinLevelCells.
size();
10491 localMinLevelCells.push_back(i);
10494 maia::grid::hilbert::coordinatesToTreeId<nDim>(treeId, &a_coordinate(cellId, 0), (
MLong)m_targetGridMinLevel,
10495 m_targetGridCenterOfGravity, m_targetGridLengthLevel0);
10496 minLevelCellsTreeId.push_back(treeId);
10503 m_tree.resetProperties(cellId);
10504 a_hasProperty(cellId, Cell::IsPartitionCell) = isPartitionCell;
10505 a_hasProperty(cellId, Cell::IsPartLvlAncestor) = isPartLvlAncestor;
10508 if(isPartitionCell) {
10509 partitionCells.push_back(globalId(i));
10512 m_noInternalCells = m_tree.size();
10514 m_log <<
"Partition level shift: level diff of first cell is " << a_level(0) - m_minLevel << std::endl;
10516 std::cerr << domainId() <<
" Partition level shift: level diff of first cell is " << a_level(0) - m_minLevel
10520 std::vector<MInt>().swap(m_minLevelCells);
10523 std::copy_n(&globalIdOffsets[0], noDomains() + 1, &m_domainOffsets[0]);
10525 m_localPartitionCellOffsets[0] = partitionCellOffsets[domainId()];
10526 m_localPartitionCellOffsets[1] = partitionCellOffsets[domainId() + 1];
10527 m_localPartitionCellOffsets[2] = m_noPartitionCellsGlobal;
10528 m_noPartitionCells = partitionCellOffsets[domainId() + 1] - partitionCellOffsets[domainId()];
10530 const MLong noCellsCheck = globalIdOffsets[domainId() + 1] - globalIdOffsets[domainId()];
10531 if(noCellsCheck != m_noInternalCells) {
10532 TERMM(1,
"Wrong number of internal cells: " + std::to_string(m_noInternalCells)
10533 +
" != " + std::to_string(noCellsCheck));
10536 TERMM_IF_COND(m_noPartitionCells <= 0,
"Cannot allocate array with " + to_string(m_noPartitionCells) +
" elements.");
10540 mAlloc(m_localPartitionCellGlobalIds, m_noPartitionCells,
"m_localPartitionCellGlobalIds",
static_cast<MLong>(-1),
10543 mAlloc(m_localPartitionCellLocalIds, m_noPartitionCells,
"m_localPartitionCellLocalIds", -1, AT_);
10545 const MInt maxPartLvl = m_minLevel + m_maxPartitionLevelShift;
10548 for(
MInt i = 0; i < m_noPartitionCells; i++) {
10549 auto cellId = (
MInt)(partitionCells[i] - m_domainOffsets[domainId()]);
10550 const MInt partLevel = a_level(cellId);
10551 TERMM_IF_NOT_COND(a_hasProperty(cellId, Cell::IsPartitionCell),
"Partition cell flag not set.");
10552 TERMM_IF_COND(partitionCells[i] != a_globalId(cellId),
"Error: partition level cell global id mismatch.");
10553 TERMM_IF_COND(partLevel < m_minLevel || partLevel > maxPartLvl,
"Invalid level for partition cell.");
10555 m_localPartitionCellGlobalIds[i] = partitionCells[i];
10557 descendNoOffsprings(cellId, m_domainOffsets[domainId()]);
10565 createGlobalToLocalIdMapping();
10567 const MInt noMinLevelCells = localMinLevelCells.size();
10568 if(noMinLevelCells == 0) {
10569 localMinLevelCells.push_back(-1);
10570 minLevelCellsTreeId.push_back(-1);
10576 *
this, noMinLevelCells, &localMinLevelCells[0], &localMinLevelId[0], &minLevelCellsTreeId[0], &cellInfo[0]);
10578 for(
MInt i = m_noInternalCells; i < m_tree.size(); ++i) {
10579 ASSERT(a_hasProperty(i, Cell::IsPartLvlAncestor),
"Cell is not a partition level ancestor.");
10580 a_hasProperty(i, Cell::IsHalo) =
true;
10587 createGlobalToLocalIdMapping();
10588 changeGlobalToLocalIds();
10591 setupWindowHaloCellConnectivity();
10597 computeGlobalIds();
10600 computeLocalBoundingBox(&m_localBoundingBox[0]);
10603 m_wasBalancedAtLeastOnce =
true;
10604 m_wasBalanced =
true;
10606#ifdef MAIA_GRID_SANITY_CHECKS
10607 gridSanityChecks();
10617template <MInt nDim>
10621 m_neighborBackup.clear();
10625 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10626 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
10627 MInt cellId = m_haloCells[i][j];
10628 if(!a_hasProperty(cellId, Cell::IsPeriodic))
continue;
10629 if(!saveBackup) a_globalId(cellId) = -1;
10630 for(
MInt dir = 0; dir < m_noDirs; dir++) {
10631 if(a_hasNeighbor(cellId, dir) == 0)
continue;
10632 MInt nghbrId = a_neighborId(cellId, dir);
10633 if(!a_hasProperty(nghbrId, Cell::IsHalo)) {
10634 if(saveBackup) m_neighborBackup.push_back(make_tuple(cellId, nghbrId, dir));
10635 a_neighborId(cellId, dir) = -1;
10636 a_neighborId(nghbrId,
m_revDir[dir]) = -1;
10642 if(m_azimuthalPer) {
10643 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
10644 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
10645 MInt cellId = m_azimuthalHaloCells[i][j];
10646 ASSERT(a_hasProperty(cellId, Cell::IsPeriodic),
"");
10647 if(!saveBackup) a_globalId(cellId) = -1;
10648 for(
MInt dir = 0; dir < m_noDirs; dir++) {
10649 if(a_hasNeighbor(cellId, dir) == 0)
continue;
10650 MInt nghbrId = a_neighborId(cellId, dir);
10651 if(!a_hasProperty(nghbrId, Cell::IsHalo)) {
10652 if(saveBackup) m_neighborBackup.push_back(make_tuple(cellId, nghbrId, dir));
10653 a_neighborId(cellId, dir) = -1;
10654 a_neighborId(nghbrId,
m_revDir[dir]) = -1;
10669template <MInt nDim>
10673 for(
MUint i = 0; i < m_neighborBackup.size(); i++) {
10674 MInt cellId = get<0>(m_neighborBackup[i]);
10675 MInt nghbrId = get<1>(m_neighborBackup[i]);
10676 MInt dir = get<2>(m_neighborBackup[i]);
10677 a_neighborId(cellId, dir) = nghbrId;
10678 a_neighborId(nghbrId,
m_revDir[dir]) = cellId;
10680 m_neighborBackup.clear();
10698template <MInt nDim>
10699template <
typename CELLTYPE>
10702 vector<vector<MInt>> partitionLevelAncestorHaloCells;
10703 vector<vector<MInt>> partitionLevelAncestorWindowCells;
10705 if(m_maxPartitionLevelShift > 0) {
10706 determinePartLvlAncestorHaloWindowCells(partitionLevelAncestorHaloCells, partitionLevelAncestorWindowCells);
10708 partitionLevelAncestorHaloCells.resize(noNeighborDomains());
10709 partitionLevelAncestorWindowCells.resize(noNeighborDomains());
10713 *
this, input_cells, input_noCells, m_haloCells, m_windowCells, partitionLevelAncestorWindowCells,
10714 partitionLevelAncestorHaloCells);
10718template <MInt nDim>
10720 const MFloat*
const partitionCellsWorkload,
10721 const MLong*
const partitionCellsGlobalId,
const MFloat totalWorkload,
10722 MLong* partitionCellOffsets,
MLong* globalIdOffsets,
10723 MBool computeOnlyPartition) {
10725 partitionCellsGlobalId, totalWorkload, partitionCellOffsets,
10726 globalIdOffsets, computeOnlyPartition);
10732template <MInt nDim>
10733template <MBool t_correct>
10736 ASSERT(solverId >= -1 && solverId < treeb().
noSolvers(),
"Invalid solver id " + to_string(solverId));
10739 const MInt noLocalPartitionCells = m_localPartitionCellOffsets[1] - m_localPartitionCellOffsets[0];
10742 for(
MInt i = 0; i < noLocalPartitionCells; i++) {
10743 const MInt curId = m_localPartitionCellLocalIds[i];
10745 MBool isInCell = pointWthCell<t_correct, false>(coord, curId, correctCellCoord);
10752 if(a_solver(curId, solverId)) {
10766template <MInt nDim>
10768 const MFloat*
const sphereCenter,
MFloat const radius) {
10770 for(
MInt n = 0; n < nDim; n++) {
10771 if(sphereCenter[n] < bMin[n]) {
10772 dmin += pow((sphereCenter[n] - bMin[n]), 2);
10773 }
else if(sphereCenter[n] > bMax[n]) {
10774 dmin += pow((sphereCenter[n] - bMax[n]), 2);
10777 return (dmin <= pow(radius, 2));
10783template <MInt nDim>
10785 const MFloat*
const sphereCenter,
MFloat const radius) {
10787 MBool face =
false;
10788 for(
MInt i = 0; i < nDim; i++) {
10789 if(sphereCenter[i] < bMin[i]) {
10791 dmin += pow(sphereCenter[i] - bMin[i], 2);
10792 }
else if(sphereCenter[i] > bMax[i]) {
10794 dmin += pow(sphereCenter[i] - bMax[i], 2);
10795 }
else if(sphereCenter[i] - bMin[i] <= radius) {
10797 }
else if(bMax[i] - sphereCenter[i] <= radius) {
10801 return (face && (dmin <= pow(radius, 2)));
10804template <MInt nDim>
10806 const MInt noLocalPartitionCells = m_localPartitionCellOffsets[1] - m_localPartitionCellOffsets[0];
10810 MBool intersectsACell =
false;
10811 MInt intersectingCellId = -1;
10812 for(
MInt i = 0; i < noLocalPartitionCells; i++) {
10813 const MInt curId = m_localPartitionCellLocalIds[i];
10814 const MFloat _halfCellLength = halfCellLength(curId);
10815 const MFloat* cCoord = m_tree.coordinate(curId);
10817 for(
MInt n = 0; n < nDim; n++) {
10818 bMin[n] = cCoord[n] - _halfCellLength;
10819 bMax[n] = cCoord[n] + _halfCellLength;
10822 intersectsACell = boxSphereIntersection(bMin, bMax, center, radius);
10824 if(intersectsACell) {
10825 intersectingCellId = curId;
10828 return intersectingCellId;
10831template <MInt nDim>
10833 MBool onlyPartition) {
10834 MBool intersectsACell =
false;
10835 MInt intersectingCellId = -1;
10836 std::vector<MFloat> bMin(nDim);
10837 std::vector<MFloat> bMax(nDim);
10839 for(
MInt i = 0; i < noHaloCells(domainId); i++) {
10840 const MInt curId = haloCell(domainId, i);
10842 if(onlyPartition && !a_hasProperty(curId, Cell::IsPartitionCell)) {
10846 const MFloat _halfCellLength = halfCellLength(curId);
10847 const MFloat* cCoord = m_tree.coordinate(curId);
10849 for(
MInt n = 0; n < nDim; n++) {
10851 bMin[n] = cCoord[n] - _halfCellLength;
10852 bMax[n] = cCoord[n] + _halfCellLength;
10855 intersectsACell = boxSphereIntersection(bMin.data(), bMax.data(), center, radius);
10856 if(intersectsACell) {
10857 intersectingCellId = curId;
10861 return intersectingCellId;
10864template <MInt nDim>
10866 const MFloat* bMin = &m_localBoundingBox[0];
10867 const MFloat* bMax = &m_localBoundingBox[nDim];
10869 MBool intersecting = boxSphereIntersection(bMin, bMax, center, radius);
10870 return intersecting;
10873template <MInt nDim>
10875 TERMM(1,
"function not used anywhere, check this code!");
10877 if(a_hasProperty(cellId, Cell::IsPartitionCell)) {
10881 MInt parentId = a_parentId(cellId);
10882 while(!a_hasProperty(parentId, Cell::IsPartitionCell)) {
10883 parentId = a_parentId(parentId);
10888template <MInt nDim>
10891 for(
MInt n = 0; n < noNeighborDomains(); n++) {
10892 for(
MInt i = 0; i < noHaloCells(n); i++) {
10893 const MInt curId = haloCell(n, i);
10895 if(!a_hasProperty(curId, Cell::IsPartitionCell)) {
10899 MBool isInCell =
true;
10901 const MFloat* cellCoords = m_tree.coordinate(curId);
10902 const MFloat _halfCellLength = halfCellLength(curId);
10904 for(
MInt dimId = 0; dimId < nDim; dimId++) {
10905 if(coord[dimId] < cellCoords[dimId] - _halfCellLength or coord[dimId] >= cellCoords[dimId] + _halfCellLength) {
10916 if(a_solver(curId, solverId)) {
10928template <MInt nDim>
10929template <MBool t_correct>
10931 MBool onlyPartitionCells,
10933 ASSERT(solverId >= -1 && solverId < treeb().
noSolvers(),
"Invalid solver id " + to_string(solverId));
10936 for(
MInt i = 0; i < noHaloCells(n); i++) {
10937 const MInt curId = haloCell(n, i);
10939 if(onlyPartitionCells && !a_hasProperty(curId, Cell::IsPartitionCell)) {
10943 MBool isInCell = pointWthCell<t_correct, false>(coord, curId, correctCellCoord);
10950 if(a_solver(curId, solverId)) {
10978template <MInt nDim>
10979template <MBool t_correct>
10985 if(!pointInLocalBoundingBox(coord)) {
10989 ASSERT(solverId >= -1 && solverId < treeb().
noSolvers(),
"Invalid solver id " + to_string(solverId));
10991 const MBool global = (solverId < 0);
10993 MInt cellId = findContainingPartitionCell<t_correct>(coord, solverId, correctCellCoord);
11001 while((global) ? a_hasChildren(cellId) : a_hasChildren(cellId, solverId)) {
11003 for(; childId <
IPOW2(nDim); childId++) {
11004 const MInt childCellId = (global) ? a_childId(cellId, childId) : a_childId(cellId, childId, solverId);
11005 if(childCellId < 0)
continue;
11006 MBool isInCell = pointWthCell<t_correct, false>(coord, childCellId, correctCellCoord);
11008 cellId = childCellId;
11012 if(childId ==
IPOW2(nDim)) {
11013 mTerm(1, AT_,
"No matching child during loop down!");
11018 ASSERT(m_tree.isLeafCell(cellId),
"No leaf cell... " + std::to_string(cellId));
11020 ASSERT(!a_hasChildren(cellId, solverId),
"No leaf cell... " + std::to_string(cellId));
11046template <MInt nDim>
11047template <MBool t_correct>
11050 const MInt solverId,
const MBool allowNonLeafHalo) {
11054 const MBool global = (solverId < 0);
11056 MInt cellId = startId;
11057 array<MFloat, nDim> tmp;
11059 auto findExistingNghbr = [&](
const MInt _cellId,
const MInt _dir,
const MInt _solverId) {
11060 MInt curId = _cellId;
11061 if(_solverId < 0) {
11062 while(curId > -1 && a_neighborId(_cellId, _dir) < 0) {
11063 curId = a_parentId(_cellId);
11066 while(curId > -1 && a_neighborId(curId, _dir, _solverId) < 0) {
11067 curId = a_parentId(curId, _solverId);
11070 if(curId > -1 && solverId > -1) {
11071 return a_neighborId(curId, _dir, _solverId);
11072 }
else if(curId > -1 && solverId < 0) {
11073 return a_neighborId(_cellId, _dir);
11075 return static_cast<MLong>(-1);
11079 set<MInt> checkedCells;
11081 while(!pointWthCell<t_correct, true>(coord, cellId, correctCellCoord)) {
11083 const MFloat* tmpCoord = m_tree.coordinate(cellId);
11084 const MFloat* cellCoords = t_correct ? (correctCellCoord)(cellId, &tmp[0]) : tmpCoord;
11085 const MFloat halfCellLength = cellLengthAtLevel(a_level(cellId) + 1);
11087 checkedCells.insert(cellId);
11089 MInt direction = -1;
11092 for(
MInt i = 0; i < nDim; i++) {
11093 const MFloat difference = coord[i] - cellCoords[i];
11094 const MFloat absDifference = fabs(difference);
11095 if(absDifference > halfCellLength) {
11096 const MInt temp = 2 * i + ((difference > 0.0) ? 1 : 0);
11097 const MLong neighborId = findExistingNghbr(cellId, temp, solverId);
11098 if(neighborId > -1) {
11100 cellId = neighborId;
11102 }
else if(a_parentId(cellId) > -1
11103 && pointWthCell<t_correct, true>(coord, a_parentId(cellId), correctCellCoord)) {
11111 if(direction == -1) {
11115 return findContainingLeafCell<t_correct>(coord, correctCellCoord, solverId);
11120 if(checkedCells.find(cellId) != checkedCells.end())
break;
11124 while((global) ? a_hasChildren(cellId) : a_hasChildren(cellId, solverId)) {
11126 for(; childId <
IPOW2(nDim); childId++) {
11127 const MInt childCellId = (global) ? a_childId(cellId, childId) : a_childId(cellId, childId, solverId);
11128 if(childCellId < 0) {
11132 const MFloat* cellCoords = m_tree.coordinate(childCellId);
11135 const MFloat constHalfCellLength = halfCellLength(childCellId);
11137 for(
MInt dimId = 0; dimId < nDim; dimId++) {
11138 MFloat dist = coord[dimId] - cellCoords[dimId];
11139 if(coord[dimId] >= cellCoords[dimId] - constHalfCellLength
11140 && coord[dimId] < cellCoords[dimId] + constHalfCellLength) {
11143 const MFloat increaseOrderOfMagnitude = 10.0;
11144 if(
approx(fabs(
dist), constHalfCellLength, increaseOrderOfMagnitude * MFloatEps)) {
11146 if(a_neighborId(childCellId, dimId + dir) > -1) {
11147 if(a_parentId(a_neighborId(childCellId, dimId + dir)) != a_parentId(childCellId)) {
11165 cellId = childCellId;
11169 if(childId ==
IPOW2(nDim)) {
11170 if(!a_isHalo(cellId)) {
11171 mTerm(1, AT_,
"No matching child during loop down!");
11173 if(!allowNonLeafHalo) {
11174 cout <<
"dom: " << domainId() <<
" no matching child during loop down" << endl;
11184 ASSERT(m_tree.isLeafCell(cellId),
"No leaf cell... " + std::to_string(cellId));
11186 ASSERT(!a_hasChildren(cellId, solverId),
"No leaf cell... " + std::to_string(cellId));
11209template <MInt nDim>
11213 m_log <<
"running distance propagation for distance " <<
dist << endl;
11215 for(
const auto gridCellId : list)
11216 propagationStep(gridCellId, 0, distMem.
data(),
dist);
11218 if(noNeighborDomains() > 0) {
11219 MIntScratchSpace recvMemOffset(noNeighborDomains() + 1, AT_,
"recvMemOffset");
11220 recvMemOffset.
fill(0);
11222 for(
MInt dom = 0; dom < noNeighborDomains(); dom++) {
11223 allRecv += (signed)m_haloCells[dom].size();
11224 recvMemOffset[dom + 1] = allRecv;
11227 MInt checkHalos = 1;
11229 m_log <<
"checking halos" << endl;
11230 while(checkHalos) {
11233 exchangeNotInPlace(distMem.
data(), recvMem.
data());
11235 for(
MInt dom = 0; dom < noNeighborDomains(); dom++) {
11236 for(
MInt cell = 0; cell < (signed)m_haloCells[dom].size(); cell++) {
11237 MInt windowDist = recvMem[recvMemOffset[dom] + cell];
11238 MInt haloDist = distMem[m_haloCells[dom][cell]];
11239 if(windowDist < haloDist) {
11240 propagationStep(m_haloCells[dom][cell], windowDist, distMem.
data(),
dist);
11245 MPI_Allreduce(MPI_IN_PLACE, &checkHalos, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"checkHalos");
11248 m_log <<
"checking halos again " << nmbrComm << endl;
11266template <MInt nDim>
11269 if(
dist < distMem[cellId]) {
11270 distMem[cellId] =
dist;
11271 if(
dist < endDist) {
11272 for(
MInt i = 0; i < 2 * nDim; i++) {
11273 const MInt nghbrId = a_neighborId(cellId, i);
11274 if(nghbrId > -1) propagationStep(nghbrId,
dist + 1, distMem, endDist);
11290template <MInt nDim>
11291template <
typename DATATYPE>
11297template <MInt nDim>
11298template <
typename DATATYPE>
11300 MInt* domSend,
const MInt* noCellsSendPerDom,
const MInt* cellIdsSend,
11301 MInt noDomRecv,
MInt* domRecv,
const MInt* noCellsRecvPerDom,
11302 const MInt* cellIdsRecv) {
11307 recvMemOffset.
fill(0);
11309 for(
MInt dom = 0; dom < noDomRecv; dom++) {
11310 allRecv += noCellsRecvPerDom[dom];
11311 recvMemOffset[dom + 1] = allRecv;
11317 sendMemOffset.
fill(0);
11319 for(
MInt dom = 0; dom < noDomSend; dom++) {
11320 allSend += noCellsSendPerDom[dom];
11321 sendMemOffset[dom + 1] = allSend;
11325 DATATYPE* ptr = &(exchangeVar[0][0]);
11327 for(
MInt i = 0; i < noVars; i++) {
11328 MInt var = vars[i];
11331 for(
MInt j = 0; j < allSend; j++)
11332 sendMem[j] = ptr[cellIdsSend[j] * noVars + var];
11337 for(
MInt dom = 0; dom < noDomSend; dom++)
11338 MPI_Issend(&(sendMem[sendMemOffset[dom]]), noCellsSendPerDom[dom] *
sizeof(DATATYPE), MPI_CHAR, domSend[dom], 0,
11339 mpiComm(), &mpi_request_[dom], AT_,
"(sendMem[sendMemOffset[dom]])");
11341 MPI_Status status_;
11342 for(
MInt dom = 0; dom < noDomRecv; dom++)
11343 MPI_Recv(&(recvMem[recvMemOffset[dom]]), noCellsRecvPerDom[dom] *
sizeof(DATATYPE), MPI_CHAR, domRecv[dom], 0,
11344 mpiComm(), &status_, AT_,
"(recvMem[recvMemOffset[dom]])");
11346 for(
MInt dom = 0; dom < noDomSend; dom++)
11347 MPI_Wait(&mpi_request_[dom], &status_, AT_);
11350 for(
MInt j = 0; j < allRecv; j++)
11351 ptr[cellIdsRecv[j] * noVars + var] = recvMem[j];
11362template <MInt nDim>
11366 createGridSlice(axis, intercept, fileName, -1,
nullptr,
nullptr,
nullptr,
nullptr);
11405template <MInt nDim>
11409 const MInt solverId,
11410 MInt*
const noSliceCellIds,
11411 MInt*
const sliceCellIds,
11412 MInt*
const noSliceHilbertIds,
11413 MInt*
const sliceHilbertInfo,
11414 MInt*
const noSliceContHilbertIds,
11415 MInt*
const sliceContiguousHilbertInfo) {
11419 if(m_minLevel == m_maxLevel) {
11420 if(domainId() == 0) {
11422 std::cerr <<
"Warning: CartesianGrid::createGridSlice minLevel and maxLevel grid are equal! "
11423 <<
"(hang-up might occur)" << std::endl;
11428 IF_CONSTEXPR(nDim != 3) { TERMM(1,
"Can not create a 2D slice from a 2D grid."); }
11430 m_log <<
"Creating 2D slice from grid... ";
11433 const MInt nDimSlice = 2;
11438 array<MInt, nDimSlice> coordArray{};
11441 coordArray = {{1, 2}};
11442 }
else if(axis ==
"y") {
11444 coordArray = {{0, 2}};
11445 }
else if(axis ==
"z") {
11447 coordArray = {{0, 1}};
11449 TERMM(1,
"Unknown axis! Check your property file.");
11452 MBool isAtCenterOfGravity =
false;
11454 if(
approx(intercept, m_targetGridCenterOfGravity[axisNum], MFloatEps)) {
11455 isAtCenterOfGravity =
true;
11463 std::array<MFloat, nDimSlice> centerOfGravity{};
11464 centerOfGravity[0] = m_centerOfGravity[coordArray[0]];
11465 centerOfGravity[1] = m_centerOfGravity[coordArray[1]];
11467 std::array<MFloat, nDimSlice> targetGridCenterOfGravity{};
11468 targetGridCenterOfGravity[0] = m_targetGridCenterOfGravity[coordArray[0]];
11469 targetGridCenterOfGravity[1] = m_targetGridCenterOfGravity[coordArray[1]];
11472 MInt noSlicePartitionCells = 0;
11473 MInt noSliceMinLevelCells = 0;
11474 MInt noSliceCells = 0;
11475 MLong noLeafCells = 0;
11480 for(
MInt i = 0; i < m_noInternalCells; i++) {
11481 sliceCellCollector[i].
fill(0);
11484 const MInt noLocalPartitionCells = m_localPartitionCellOffsets[1] - m_localPartitionCellOffsets[0];
11487 MIntScratchSpace localPartitionCellGlobalIds(noLocalPartitionCells + 1, AT_,
"localPartitionCellGlobalIds");
11488 copy_n(&m_localPartitionCellGlobalIds[0], noLocalPartitionCells, &localPartitionCellGlobalIds[0]);
11491 localPartitionCellGlobalIds[noLocalPartitionCells] = m_noInternalCells + m_domainOffsets[domainId()];
11494 std::map<MInt, MInt> hilbertIdCount;
11495 std::map<MInt, MInt> hilbertIdCountSolver;
11497 for(
MInt i = 0, cellId = 0; i < noLocalPartitionCells; i++) {
11499 const MInt partitionCellId = localPartitionCellGlobalIds[i] - m_domainOffsets[domainId()];
11500 MInt isPartitionCell = 0;
11503 if(isAtCenterOfGravity) {
11506 if(fabs((intercept + eps) - a_coordinate(partitionCellId, axisNum)) < halfCellLength(partitionCellId)) {
11507 isPartitionCell = 1;
11508 noSlicePartitionCells++;
11511 cellId = partitionCellId + a_noOffsprings(partitionCellId);
11515 const MInt nextPartitionCell = localPartitionCellGlobalIds[i + 1] - m_domainOffsets[domainId()];
11516 while(cellId < nextPartitionCell) {
11518 if(!(fabs((intercept + eps) - a_coordinate(cellId, axisNum)) < halfCellLength(cellId))) {
11524 if(cellId == partitionCellId) {
11525 sliceCellCollector[noSliceCells][2] = isPartitionCell;
11526 isPartitionCell = 0;
11530 const MFloat*
const sliceCoord = &a_coordinate(cellId, 0);
11532 array<MFloat, 2> normedSliceCoord{};
11533 normedSliceCoord[0] =
11534 (sliceCoord[coordArray[0]] - targetGridCenterOfGravity[0] + 1e-12 + m_targetGridLengthLevel0 * 0.5)
11535 / m_targetGridLengthLevel0;
11536 normedSliceCoord[1] =
11537 (sliceCoord[coordArray[1]] - targetGridCenterOfGravity[1] + 1e-12 + m_targetGridLengthLevel0 * 0.5)
11538 / m_targetGridLengthLevel0;
11539 const MLong sliceHilbertId =
11540 maia::grid::hilbert::index<2>(&normedSliceCoord[0],
static_cast<MLong>(m_targetGridMinLevel));
11542 hilbertIdCount[sliceHilbertId]++;
11543 sliceCellCollector[noSliceCells][1] = sliceHilbertId;
11546 if(solverId > -1 && a_solver(cellId, solverId)) hilbertIdCountSolver[sliceHilbertId]++;
11549 if(a_level(cellId) == m_minLevel) {
11550 sliceCellCollector[noSliceCells][3] = 1;
11551 noSliceMinLevelCells++;
11555 if(a_isLeafCell(cellId)) {
11559 sliceCellCollector[noSliceCells][0] = cellId;
11572 MIntScratchSpace slicePartitionCells(noSlicePartitionCells + 1, AT_,
"slicePartitionCells");
11574 MIntScratchSpace sliceMinLevelCells(noSliceMinLevelCells, AT_,
"sliceMinLevelCells");
11580 std::map<MInt, MInt> hilbertIdMinLevelCellsCount;
11581 std::map<MInt, MInt> hilbertIdPartitionCellsCount;
11583 if(noSliceCells > 0) {
11585 MInt noHilbertIds = 0;
11586 for(
auto const& ent1 : hilbertIdCount) {
11587 hIdKeys[noHilbertIds] = ent1.first;
11592 std::stable_sort(sliceCellCollector.
begin(), sliceCellCollector.
begin() + noSliceCells,
11593 [](
const array<MInt, 4>&
a,
const array<MInt, 4>&
b) { return a[1] < b[1]; });
11596 for(
MInt i = 0, j = 0, k = 0; i < noSliceCells; i++) {
11597 cellIdsInSlice[i] = sliceCellCollector[i][0];
11599 if(sliceCellCollector[i][2] == 1) {
11600 slicePartitionCells[j] = sliceCellCollector[i][0];
11601 hilbertIdPartitionCellsCount[sliceCellCollector[i][1]]++;
11605 if(sliceCellCollector[i][3] == 1) {
11606 sliceMinLevelCells[k] = sliceCellCollector[i][0];
11607 hilbertIdMinLevelCellsCount[sliceCellCollector[i][1]]++;
11612 slicePartitionCells[noSlicePartitionCells] = cellIdsInSlice[noSliceCells - 1] + 1;
11617 if(noSliceCellIds !=
nullptr) {
11618 *noSliceCellIds = noSliceCells;
11620 if(sliceCellIds !=
nullptr && noSliceCells > 0) {
11621 std::copy_n(&cellIdsInSlice[0], noSliceCells, sliceCellIds);
11625 MIntScratchSpace cellIdsInSliceSolver(noSliceCells, AT_,
"cellIdsInSliceSolver");
11626 MInt noSliceCellsSolver = 0;
11627 for(
MInt i = 0; i < noSliceCells; i++) {
11628 if(a_solver(cellIdsInSlice[i], solverId)) {
11629 cellIdsInSliceSolver[noSliceCellsSolver] = cellIdsInSlice[i];
11630 noSliceCellsSolver++;
11635 if(noSliceCellIds !=
nullptr) {
11636 *noSliceCellIds = noSliceCellsSolver;
11638 if(sliceCellIds !=
nullptr && noSliceCellsSolver > 0) {
11639 std::copy_n(&cellIdsInSliceSolver[0], noSliceCellsSolver, sliceCellIds);
11648 MPI_Comm mpiCommSlice = MPI_COMM_NULL;
11653 if(noSliceCells > 0) {
11654 MPI_Comm_rank(mpiComm(), &rank);
11658 "rank",
"sliceRanks[0]");
11661 const MInt noRelDomains = count_if(sliceRanks.
begin(), sliceRanks.
end(), [](
const MInt a) { return a != -1; });
11664 map<MInt, MInt> domainMap;
11666 for(
auto&& slice : sliceRanks) {
11668 relDomains[position] = slice;
11669 domainMap[slice] = position;
11674 MPI_Group globalGroup, localGroup;
11676 MPI_Group_incl(globalGroup, noRelDomains, &relDomains[0], &localGroup, AT_);
11679 MPI_Comm_create(mpiComm(), localGroup, &mpiCommSlice, AT_,
"mpiCommSlice");
11685 if(noSliceCells < 1) {
11699 MInt noSliceDomains = -1;
11700 MPI_Comm_size(mpiCommSlice, &noSliceDomains);
11702 MInt sliceDomain = -1;
11703 MPI_Comm_rank(mpiCommSlice, &sliceDomain);
11706 MIntScratchSpace noLocalHilbertIds(noSliceDomains, AT_,
"noLocalHilbertIds");
11707 noLocalHilbertIds[sliceDomain] = hilbertIdCount.
size();
11710 MPI_Allgather(MPI_IN_PLACE, 1, MPI_INT, &noLocalHilbertIds[0], 1, MPI_INT, mpiCommSlice, AT_,
"MPI_IN_PLACE",
11711 "noLocalHilbertIds[0]");
11715 offsetsRecvData[0] = 0;
11716 for(
MInt i = 1; i < noSliceDomains; i++) {
11717 offsetsRecvData[i] = offsetsRecvData[i - 1] + noLocalHilbertIds[i - 1] * 6;
11719 MInt noTotalRecvData = offsetsRecvData[noSliceDomains - 1] + noLocalHilbertIds[noSliceDomains - 1] * 6;
11724 MIntScratchSpace sendHilbertData(noLocalHilbertIds[sliceDomain] * 6, AT_,
"sendHilbertData");
11725 for(
MUlong i = 0; i < hIdKeys.
size(); i++) {
11726 sendHilbertData[i * 6] = hIdKeys[i];
11727 sendHilbertData[i * 6 + 1] = domainId();
11728 sendHilbertData[i * 6 + 2] = hilbertIdCount[hIdKeys[i]];
11729 sendHilbertData[i * 6 + 3] = hilbertIdPartitionCellsCount[hIdKeys[i]];
11730 sendHilbertData[i * 6 + 4] = hilbertIdMinLevelCellsCount[hIdKeys[i]];
11731 sendHilbertData[i * 6 + 5] = hilbertIdCountSolver[hIdKeys[i]];
11735 MIntScratchSpace recvHilbertData(noTotalRecvData, AT_,
"recvHilbertData");
11736 MInt noSendData = sendHilbertData.
size();
11738 for(
MInt i = 0; i < noSliceDomains; i++) {
11739 noRecvData[i] = noLocalHilbertIds[i] * 6;
11741 MPI_Allgatherv(&sendHilbertData[0], noSendData, MPI_INT, &recvHilbertData[0], &noRecvData[0], &offsetsRecvData[0],
11742 MPI_INT, mpiCommSlice, AT_,
"sendHilbertData[0]",
"recvHilbertData[0]");
11747 for(
MInt i = 0; i < noTotalRecvData / 6; i++) {
11748 sliceGlobalHilbertInfo[i][0] = recvHilbertData[i * 6];
11749 sliceGlobalHilbertInfo[i][1] = recvHilbertData[i * 6 + 1];
11750 sliceGlobalHilbertInfo[i][2] = recvHilbertData[i * 6 + 2];
11751 sliceGlobalHilbertInfo[i][3] = recvHilbertData[i * 6 + 3];
11752 sliceGlobalHilbertInfo[i][4] = recvHilbertData[i * 6 + 4];
11753 sliceGlobalHilbertInfo[i][5] = recvHilbertData[i * 6 + 5];
11757 std::stable_sort(sliceGlobalHilbertInfo.
begin(), sliceGlobalHilbertInfo.
end(),
11758 [](
const array<MInt, 6>&
a,
const array<MInt, 6>&
b) { return a[1] < b[1]; });
11760 std::stable_sort(sliceGlobalHilbertInfo.
begin(), sliceGlobalHilbertInfo.
end(),
11761 [](
const array<MInt, 6>&
a,
const array<MInt, 6>&
b) { return a[0] < b[0]; });
11767 MInt maxNoHilbertIds = *std::max_element(noLocalHilbertIds.
begin(), noLocalHilbertIds.
end());
11768 MIntScratchSpace hilbertDomainOffset(maxNoHilbertIds, AT_,
"hilbertDomainOffset");
11769 hilbertDomainOffset.
fill(0);
11770 MIntScratchSpace hilbertPartitionDomainOffset(maxNoHilbertIds, AT_,
"hilbertDomainOffset");
11771 hilbertPartitionDomainOffset.
fill(0);
11772 MIntScratchSpace hilbertMinLevelDomainOffset(maxNoHilbertIds, AT_,
"hilbertDomainOffset");
11773 hilbertMinLevelDomainOffset.
fill(0);
11776 MIntScratchSpace hilbertDomainOffsetSolver(maxNoHilbertIds, AT_,
"hilbertDomainOffsetSolver");
11777 hilbertDomainOffsetSolver.
fill(0);
11793 for(
MInt i = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
11794 MInt offset = 0, offsetPart = 0, offsetMin = 0, offsetSolver = 0, j = 0;
11796 while(sliceGlobalHilbertInfo[j][0] < hIdKeys[i]) {
11797 offset += sliceGlobalHilbertInfo[j][2];
11798 offsetPart += sliceGlobalHilbertInfo[j][3];
11799 offsetMin += sliceGlobalHilbertInfo[j][4];
11800 offsetSolver += sliceGlobalHilbertInfo[j][5];
11804 while(sliceGlobalHilbertInfo[j][1] < domainId()) {
11805 offset += sliceGlobalHilbertInfo[j][2];
11806 offsetPart += sliceGlobalHilbertInfo[j][3];
11807 offsetMin += sliceGlobalHilbertInfo[j][4];
11808 offsetSolver += sliceGlobalHilbertInfo[j][5];
11811 hilbertDomainOffset[i] = offset;
11812 hilbertPartitionDomainOffset[i] = offsetPart;
11813 hilbertMinLevelDomainOffset[i] = offsetMin;
11815 if(solverId > -1) {
11816 hilbertDomainOffsetSolver[i] = offsetSolver;
11825 mpiCommSlice, AT_,
"noSliceCells",
"domainOffset[0]");
11828 for(
MInt i = 0, offset = 0, tmp = 0; i < (noSliceDomains + 1); i++) {
11829 tmp = domainOffset[i];
11830 domainOffset[i] = offset;
11834 MInt noLocalHilbertIdsSolver = 0;
11838 if(noSliceHilbertIds !=
nullptr) {
11839 *noSliceHilbertIds = noLocalHilbertIds[sliceDomain];
11842 if(sliceHilbertInfo !=
nullptr) {
11843 MIntScratchSpace hilbertInfo(noLocalHilbertIds[sliceDomain] * 3, AT_,
"hilbertInfo");
11844 for(
MInt i = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
11845 hilbertInfo[i * 3] = hIdKeys[i];
11846 hilbertInfo[i * 3 + 1] = hilbertIdCount[hIdKeys[i]];
11847 hilbertInfo[i * 3 + 2] = hilbertDomainOffset[i];
11849 std::copy_n(&hilbertInfo[0], noLocalHilbertIds[sliceDomain] * 3, sliceHilbertInfo);
11852 TERMM_IF_COND(noSliceHilbertIds ==
nullptr || sliceHilbertInfo ==
nullptr,
11853 "Error: solverId given, pointers need to be != nullptr.");
11855 MIntScratchSpace hilbertInfoSolver(noLocalHilbertIds[sliceDomain] * 3, AT_,
"hilbertInfo");
11856 MInt noHIdsSolver = 0;
11857 for(
MInt i = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
11858 if(hilbertIdCountSolver[hIdKeys[i]] > 0) {
11859 hilbertInfoSolver[noHIdsSolver * 3] = hIdKeys[i];
11860 hilbertInfoSolver[noHIdsSolver * 3 + 1] = hilbertIdCountSolver[hIdKeys[i]];
11861 hilbertInfoSolver[noHIdsSolver * 3 + 2] = hilbertDomainOffsetSolver[i];
11866 noLocalHilbertIdsSolver = noHIdsSolver;
11868 *noSliceHilbertIds = noHIdsSolver;
11870 std::copy_n(&hilbertInfoSolver[0], noHIdsSolver * 3, sliceHilbertInfo);
11882 array<MInt, nDimSlice * 2> nghbrArray{};
11884 nghbrArray = {{2, 3, 4, 5}};
11885 }
else if(axis ==
"y") {
11886 nghbrArray = {{0, 1, 4, 5}};
11887 }
else if(axis ==
"z") {
11888 nghbrArray = {{0, 1, 2, 3}};
11892 std::set<MInt> relatedDomains;
11895 for(
MInt i = 0; i < noSliceMinLevelCells; i++) {
11897 for(
MInt j = 0; j < (nDimSlice * 2); j++) {
11899 if(!a_hasNeighbor(sliceMinLevelCells[i], nghbrArray[j])) {
11903 MInt nId = a_neighborId(sliceMinLevelCells[i], nghbrArray[j]);
11904 const MInt nghbrDomainId = findNeighborDomainId(a_globalId(nId));
11905 if(domainId() != nghbrDomainId) {
11906 relatedDomains.insert(nghbrDomainId);
11912 MInt partitionLevelShift = 0;
11913 for(
MInt i = 0; i < noSlicePartitionCells; ++i) {
11914 const MInt levelDiff = a_level(slicePartitionCells[i]) - m_minLevel;
11915 partitionLevelShift =
mMax(levelDiff, partitionLevelShift);
11919 set<MLong> partitionLevelAncestorIds;
11920 for(
MInt i = 0; i < noSliceCells; i++) {
11921 const MInt cellId = cellIdsInSlice[i];
11922 if(a_hasProperty(cellId, Cell::IsPartLvlAncestor) && !a_hasProperty(cellId, Cell::IsHalo)) {
11923 partitionLevelAncestorIds.insert(cellId);
11933 map<MInt, MInt> idMap;
11937 for(
MInt i = 0, j = 0, h = 0; i < noSliceCells; i++, j++) {
11939 if(j == hilbertIdCount[hIdKeys[h]]) {
11943 idMap[cellIdsInSlice[i] + m_domainOffsets[domainId()]] = j + hilbertDomainOffset[h];
11947 if(!relatedDomains.empty()) {
11949 std::vector<MInt> sliceRelatedDomains(relatedDomains.begin(), relatedDomains.end());
11953 MInt noRecvCells = 0;
11954 MIntScratchSpace relDomainOffsets(sliceRelatedDomains.size() + 1, AT_,
"relDomainOffsets");
11955 for(
MUlong i = 0; i < sliceRelatedDomains.size(); i++) {
11956 relDomainOffsets[i] = noRecvCells;
11958 domainOffset[domainMap[sliceRelatedDomains[i]] + 1] - domainOffset[domainMap[sliceRelatedDomains[i]]];
11961 relDomainOffsets[sliceRelatedDomains.size()] = noRecvCells;
11969 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
11971 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
11974 for(
MUlong i = 0; i < sliceRelatedDomains.size(); i++) {
11975 MInt d = sliceRelatedDomains[i];
11976 MPI_Irecv(&recvIds[relDomainOffsets[i]], domainOffset[domainMap[d] + 1] - domainOffset[domainMap[d]],
11978 "recvIds[relDomainOffsets[i]]");
11982 for(
MUlong i = 0; i < sliceRelatedDomains.size(); i++) {
11984 domainMap[domainId()], mpiCommSlice, &sendRequests[i], AT_,
"cellIdsInSlice[0]");
11988 MPI_Waitall(sliceRelatedDomains.size(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
11991 MPI_Waitall(sliceRelatedDomains.size(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
11994 for(
MUlong j = 0; j < sliceRelatedDomains.size(); j++) {
11995 MInt d = sliceRelatedDomains[j];
11996 std::vector<MInt> hId(noLocalHilbertIds[domainMap[d]]);
11997 std::vector<MInt> hCount(noLocalHilbertIds[domainMap[d]]);
11998 std::vector<MInt> hOffsets(noLocalHilbertIds[domainMap[d]]);
12001 for(
MUlong k = 0, i = 0; i < hId.size(); k++) {
12002 if(sliceGlobalHilbertInfo[k][1] == d) {
12003 hId[i] = sliceGlobalHilbertInfo[k][0];
12004 hCount[i] = sliceGlobalHilbertInfo[k][2];
12008 while(sliceGlobalHilbertInfo[m][0] < hId[i]) {
12009 offset += sliceGlobalHilbertInfo[m][2];
12012 while(sliceGlobalHilbertInfo[m][1] < d) {
12013 offset += sliceGlobalHilbertInfo[m][2];
12016 hOffsets[i] = offset;
12022 for(
MInt i = 0, n = 0, h = 0; i < (relDomainOffsets[j + 1] - relDomainOffsets[j]); i++, n++) {
12023 if(n == hCount[h]) {
12027 idMap[recvIds[i + relDomainOffsets[j]] + m_domainOffsets[d]] = n + hOffsets[h];
12033 MBool onlySliceCells =
false;
12034 if(noSlicePartitionCells < 1) {
12035 onlySliceCells =
true;
12040 if(noSlicePartitionCells > 0) {
12041 std::map<MInt, MInt>::iterator it;
12042 MInt lastKeyId = hIdKeys.
size() - 1;
12043 MInt val = hilbertIdCount[hIdKeys[lastKeyId]] + hilbertDomainOffset[lastKeyId];
12045 it = idMap.find(slicePartitionCells[noSlicePartitionCells] + m_domainOffsets[domainId()]);
12047 auto result = std::find_if(idMap.begin(), idMap.end(), [val](
const auto& mo) { return mo.second == val; });
12049 if(it == idMap.end() && result == idMap.end()) {
12050 idMap[slicePartitionCells[noSlicePartitionCells] + m_domainOffsets[domainId()]] =
12051 hilbertIdCount[hIdKeys[lastKeyId]] + hilbertDomainOffset[lastKeyId];
12052 }
else if(result != idMap.end()) {
12053 MInt foundKey = result->first;
12054 slicePartitionCells[noSlicePartitionCells] = foundKey - m_domainOffsets[domainId()];
12063 const MUint noChildInRef = pow(2, nDimSlice);
12066 MIntScratchSpace partitionCellsId(noSlicePartitionCells, AT_,
"partitionCellsId");
12067 MFloatScratchSpace partitionCellsWorkload(noSlicePartitionCells, AT_,
"partitionCellsWorkLoad");
12068 MInt maxNoOffsprings = 0;
12069 MFloat maxWorkload = 0.0;
12070 MFloat totalWorkload = 0.0;
12072 for(
MInt i = 0, c = 0, partitionCellNoOffsprings = 0; i < noSlicePartitionCells; i++) {
12073 partitionCellsId[i] = idMap[slicePartitionCells[i] + m_domainOffsets[domainId()]];
12075 partitionCellNoOffsprings = 1;
12078 while(idMap[a_globalId(cellIdsInSlice[c])] < idMap[slicePartitionCells[i + 1] + m_domainOffsets[domainId()]]) {
12080 if(a_level(cellIdsInSlice[c]) > a_level(slicePartitionCells[i])) {
12081 partitionCellNoOffsprings++;
12084 if(c == noSliceCells) {
12090 partitionCellsWorkload[i] = partitionCellNoOffsprings;
12092 totalWorkload += partitionCellsWorkload[i];
12094 maxNoOffsprings =
mMax(partitionCellNoOffsprings, maxNoOffsprings);
12096 maxWorkload =
mMax(partitionCellsWorkload[i], maxWorkload);
12100 MLong totalNoPartitionLevelAncestors = 0;
12101 MLong localPartitionLevelAncestorCount = (signed)partitionLevelAncestorIds.size();
12102 MPI_Allreduce(&localPartitionLevelAncestorCount, &totalNoPartitionLevelAncestors, 1, MPI_LONG, MPI_SUM, mpiCommSlice,
12103 AT_,
"localPartitionLevelAncestorCount",
"totalNoPartitionLevelAncestors");
12105 MInt maxPartitionLevelShift = -1;
12106 MPI_Allreduce(&partitionLevelShift, &maxPartitionLevelShift, 1, MPI_INT, MPI_MAX, mpiCommSlice, AT_,
12107 "partitionLevelShift",
"maxPartitionLevelShift");
12110 MPI_Allreduce(MPI_IN_PLACE, &maxNoOffsprings, 1, MPI_INT, MPI_MAX, mpiCommSlice, AT_,
"MPI_IN_PLACE",
12111 "maxNoOffsprings");
12113 MPI_Allreduce(MPI_IN_PLACE, &totalWorkload, 1, MPI_DOUBLE, MPI_SUM, mpiCommSlice, AT_,
"MPI_IN_PLACE",
12115 MPI_Allreduce(MPI_IN_PLACE, &maxWorkload, 1, MPI_DOUBLE, MPI_MAX, mpiCommSlice, AT_,
"MPI_IN_PLACE",
"maxWorkload");
12116 MFloat maxNoCPUs = totalWorkload / maxWorkload;
12124 array<MInt, 8> childArray{};
12126 childArray = {{0, 0, 1, 1, 2, 2, 3, 3}};
12127 }
else if(axis ==
"y") {
12128 childArray = {{0, 1, 0, 1, 2, 3, 2, 3}};
12129 }
else if(axis ==
"z") {
12130 childArray = {{0, 1, 2, 3, 0, 1, 2, 3}};
12134 const array<MFloat, nDimSlice* 2> boundingBox = {{m_boundingBox[coordArray[0]], m_boundingBox[coordArray[1]],
12135 m_boundingBox[coordArray[0] + 3],
12136 m_boundingBox[coordArray[1] + 3]}};
12137 const array<MFloat, nDimSlice* 2> targetGridBoundingBox = {
12138 {m_targetGridBoundingBox[coordArray[0]], m_targetGridBoundingBox[coordArray[1]],
12139 m_targetGridBoundingBox[coordArray[0] + 3], m_targetGridBoundingBox[coordArray[1] + 3]}};
12140 array<MFloat, nDimSlice * 2> geometryExtents{};
12141 MInt decisiveDirection = 0;
12142 for(
MInt dir = 0; dir < nDimSlice; dir++) {
12143 geometryExtents[dir] = targetGridBoundingBox[dir + nDimSlice] - targetGridBoundingBox[dir];
12144 decisiveDirection = geometryExtents[dir] > geometryExtents[decisiveDirection] ? dir : decisiveDirection;
12148 MLongScratchSpace sliceMinLevelCellsTreeId(noSliceMinLevelCells, AT_,
"sliceMinLevelCellsTreeId");
12149 for(
MInt i = 0; i < noSliceMinLevelCells; ++i) {
12150 std::array<MFloat, nDimSlice> coord = {
12151 {a_coordinate(sliceMinLevelCells[i], coordArray[0]), a_coordinate(sliceMinLevelCells[i], coordArray[1])}};
12152 maia::grid::hilbert::coordinatesToTreeId<nDimSlice>(sliceMinLevelCellsTreeId[i], &coord[0],
12153 (
MLong)m_targetGridMinLevel, &targetGridCenterOfGravity[0],
12154 m_targetGridLengthLevel0);
12158 MLongScratchSpace sliceMinLevelCellsNghbrIds(noSliceMinLevelCells, 2 * nDimSlice, AT_,
"sliceMinLevelCellsNghbrIds");
12159 for(
MInt i = 0; i < noSliceMinLevelCells; ++i) {
12160 for(
MInt j = 0; j < (nDimSlice * 2); j++) {
12161 MInt nghbrId = a_neighborId(sliceMinLevelCells[i], nghbrArray[j]);
12162 if(nghbrId == -1) {
12163 sliceMinLevelCellsNghbrIds(i, j) = -1;
12165 sliceMinLevelCellsNghbrIds(i, j) = idMap[a_globalId(nghbrId)];
12175 MInt maxLevel = -1;
12178 for(
MInt i = 0; i < noSliceCells; ++i) {
12179 MLong cellId = cellIdsInSlice[i];
12180 MUint noChilds = 0;
12181 MUint curChildPos = 0;
12183 for(
MInt j = 0; j < pow(2, nDim) && curChildPos < noChildInRef; j++) {
12184 if(a_childId(cellIdsInSlice[i], j) != -1) {
12186 if(fabs(intercept - a_coordinate(a_childId(cellIdsInSlice[i], j), axisNum))
12187 > halfCellLength(a_childId(cellIdsInSlice[i], j))) {
12196 if(a_parentId(cellId) > -1) {
12197 MInt parentId = a_parentId(cellId);
12198 for(
MUint j = 0; j < (unsigned)m_maxNoChilds; j++) {
12199 if(a_childId(parentId, j) == cellId) {
12200 pos = childArray[j];
12205 MUint isMinLvl = 0;
12206 if(a_level(cellId) == m_minLevel) {
12207 isMinLvl = (
MUint)1;
12209 MUint tmpBit = noChilds | (pos << 4) | (isMinLvl << 7);
12210 sliceCellInfo[i] =
static_cast<MUchar>(tmpBit);
12213 if(a_level(cellId) > maxLevel) {
12214 maxLevel = a_level(cellId);
12227 const MString gridFileName = fileName + ParallelIo::fileExt();
12228 ParallelIo file(gridFileName, PIO_REPLACE, mpiCommSlice);
12231 ParallelIo::size_type sliceCellsOffset, noTotalCells;
12232 ParallelIo::calcOffset(noSliceCells, &sliceCellsOffset, &noTotalCells, mpiCommSlice);
12235 if(onlySliceCells) {
12236 noSlicePartitionCells = 0;
12239 ParallelIo::size_type partitionOffset, noPartitionCells;
12240 ParallelIo::calcOffset(noSlicePartitionCells, &partitionOffset, &noPartitionCells, mpiCommSlice);
12242 ParallelIo::size_type minLevelCellsOffset, noTotalMinLevelCells;
12243 ParallelIo::calcOffset(noSliceMinLevelCells, &minLevelCellsOffset, &noTotalMinLevelCells, mpiCommSlice);
12245 MFloat avgWorkload = totalWorkload / ((
MFloat)noPartitionCells);
12249 file.defineArray(PIO_LONG,
"partitionCellsGlobalId", noPartitionCells);
12250 file.defineArray(PIO_FLOAT,
"partitionCellsWorkload", noPartitionCells);
12251 file.defineArray(PIO_LONG,
"minLevelCellsTreeId", noTotalMinLevelCells);
12252 file.defineArray(PIO_LONG,
"minLevelCellsNghbrIds", 2 * nDimSlice * noTotalMinLevelCells);
12253 file.defineArray(PIO_UCHAR,
"cellInfo", noTotalCells);
12259 file.defineArray(PIO_UCHAR,
"solver", noTotalCells);
12261 for(
MInt i = 0; i < noSliceCells; ++i) {
12262 const MLong cellId = cellIdsInSlice[i];
12265 if(m_tree.solver(cellId, solver)) {
12266 tmpBit |= (1 << solver);
12269 solverBits[i] =
static_cast<MUchar>(tmpBit);
12275 MPI_Allreduce(MPI_IN_PLACE, &maxLevel, 1, MPI_INT, MPI_MAX, mpiCommSlice, AT_,
"MPI_IN_PLACE",
"maxLevel");
12277 MPI_Allreduce(MPI_IN_PLACE, &noLeafCells, 1, MPI_LONG, MPI_SUM, mpiCommSlice, AT_,
"MPI_IN_PLACE",
"noLeafCells");
12282 MLong solverCount = 0;
12283 for(
MInt i = 0; i < noSliceCells; i++) {
12284 const MLong cellId = cellIdsInSlice[i];
12285 if(m_tree.solver(cellId,
b) ==
true) {
12289 MPI_Allreduce(MPI_IN_PLACE, &solverCount, 1, MPI_LONG, MPI_SUM, mpiCommSlice, AT_,
"MPI_IN_PLACE",
"solverCount");
12290 file.setAttributes(&solverCount,
"noCells_" + std::to_string(
b), 1);
12295 file.setAttributes(&nDimSlice,
"nDim", 1);
12296 file.setAttributes(&
noSolvers,
"noSolvers", 1);
12297 file.setAttributes(&tstep,
"globalTimeStep", 1);
12298 file.setAttributes(&noTotalCells,
"noCells", 1);
12299 file.setAttributes(&noLeafCells,
"noLeafCells", 1);
12300 file.setAttributes(&noTotalMinLevelCells,
"noMinLevelCells", 1);
12301 file.setAttributes(&noPartitionCells,
"noPartitionCells", 1);
12302 file.setAttributes(&totalNoPartitionLevelAncestors,
"noPartitionLevelAncestors", 1);
12303 file.setAttributes(&m_minLevel,
"minLevel", 1);
12304 file.setAttributes(&maxLevel,
"maxLevel", 1);
12305 file.setAttributes(&m_maxUniformRefinementLevel,
"maxUniformRefinementLevel", 1);
12306 file.setAttributes(&maxPartitionLevelShift,
"maxPartitionLevelShift", 1);
12307 file.setAttributes(&m_lengthLevel0,
"lengthLevel0", 1);
12308 file.setAttributes(¢erOfGravity[0],
"centerOfGravity", nDimSlice);
12309 file.setAttributes(&boundingBox[0],
"boundingBox", 2 * nDimSlice);
12312 if(m_hasMultiSolverBoundingBox) {
12313 file.setAttributes(&m_targetGridLengthLevel0,
"multiSolverLengthLevel0", 1);
12314 file.setAttributes(&m_targetGridMinLevel,
"multiSolverMinLevel", 1);
12315 file.setAttributes(&targetGridCenterOfGravity[0],
"multiSolverCenterOfGravity", nDimSlice);
12316 file.setAttributes(&targetGridBoundingBox[0],
"multiSolverBoundingBox", 2 * nDimSlice);
12319 file.setAttributes(&m_reductionFactor,
"reductionFactor", 1);
12320 file.setAttributes(&decisiveDirection,
"decisiveDirection", 1);
12321 file.setAttributes(&totalWorkload,
"totalWorkload", 1);
12322 file.setAttributes(&maxWorkload,
"partitionCellMaxWorkload", 1);
12323 file.setAttributes(&avgWorkload,
"partitionCellAverageWorkload", 1);
12324 file.setAttributes(&maxNoOffsprings,
"partitionCellMaxNoOffspring", 1);
12325 file.setAttributes(&avgOffspring,
"partitionCellAverageNoOffspring", 1);
12326 file.setAttributes(&m_partitionCellWorkloadThreshold,
"partitionCellWorkloadThreshold", 1);
12327 file.setAttributes(&m_partitionCellOffspringThreshold,
"partitionCellOffspringThreshold", 1);
12328 file.setAttributes(&maxNoCPUs,
"maxNoBalancedCPUs", 1);
12331 file.setAttribute(axis,
"sliceAxis");
12332 file.setAttribute(intercept,
"sliceIntercept");
12334 MBool optimizedSliceIo =
true;
12335 optimizedSliceIo = Context::getBasicProperty<MBool>(
"optimizedSliceIo", AT_, &optimizedSliceIo);
12338 if(optimizedSliceIo) {
12339 std::vector<MInt> contHilbertIdsPartitionCounts{};
12340 std::vector<MInt> contHilbertIdsPartitionOffset{};
12342 std::vector<MInt> contHilbertIdCount{};
12343 std::vector<MInt> contHilbertIdOffset{};
12345 std::vector<MInt> contHilbertIdMinCellCount{};
12346 std::vector<MInt> contHilbertIdMinCellOffset{};
12349 MInt contHIdMinCellCount = -1;
12350 std::vector<MInt> minCellCount{};
12351 std::vector<MInt> minCellOffset{};
12353 for(
MInt i = 0, localMinOffset = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
12354 const MInt count = hilbertIdMinLevelCellsCount[hIdKeys[i]];
12355 const MInt offset = hilbertMinLevelDomainOffset[i];
12356 if(localMinOffset < noSliceMinLevelCells) {
12358 minCellCount.push_back(count);
12359 minCellOffset.push_back(offset);
12362 localMinOffset += count;
12365 contHIdMinCellCount = (noSliceMinLevelCells > 0) ? minCellCount[0] : -1;
12366 if(noSliceMinLevelCells == 1) {
12367 contHilbertIdMinCellCount.push_back(contHIdMinCellCount);
12368 contHilbertIdMinCellOffset.push_back(minCellOffset[0]);
12372 for(
MInt h = 1, i = 0; h < noSliceMinLevelCells; h++) {
12373 if(minCellCount[h - 1] + minCellOffset[h - 1] == minCellOffset[h]) {
12374 contHIdMinCellCount += minCellCount[h];
12376 contHilbertIdMinCellCount.push_back(contHIdMinCellCount);
12377 contHilbertIdMinCellOffset.push_back(minCellOffset[i]);
12380 contHIdMinCellCount = minCellCount[h];
12384 if(h == noSliceMinLevelCells - 1) {
12385 contHilbertIdMinCellCount.push_back(contHIdMinCellCount);
12386 contHilbertIdMinCellOffset.push_back(minCellOffset[i]);
12392 MInt contHIdPartitionCellCount = hilbertIdPartitionCellsCount[hIdKeys[0]];
12393 MInt contHIdCount = hilbertIdCount[hIdKeys[0]];
12395 if(noLocalHilbertIds[sliceDomain] == 1) {
12396 contHilbertIdsPartitionCounts.push_back(contHIdPartitionCellCount);
12397 contHilbertIdsPartitionOffset.push_back(hilbertPartitionDomainOffset[0]);
12399 contHilbertIdCount.push_back(contHIdCount);
12400 contHilbertIdOffset.push_back(hilbertDomainOffset[0]);
12404 for(
MInt h = 1, i = 0; h < noLocalHilbertIds[sliceDomain]; h++) {
12406 if(hilbertIdPartitionCellsCount[hIdKeys[h - 1]] + hilbertPartitionDomainOffset[h - 1]
12407 == hilbertPartitionDomainOffset[h]) {
12408 TERMM_IF_NOT_COND(hilbertIdCount[hIdKeys[h - 1]] + hilbertDomainOffset[h - 1] == hilbertDomainOffset[h],
12409 "Error: cells not contiguous");
12410 contHIdPartitionCellCount += hilbertIdPartitionCellsCount[hIdKeys[h]];
12411 contHIdCount += hilbertIdCount[hIdKeys[h]];
12414 contHilbertIdsPartitionCounts.push_back(contHIdPartitionCellCount);
12415 contHilbertIdsPartitionOffset.push_back(hilbertPartitionDomainOffset[i]);
12417 contHilbertIdCount.push_back(contHIdCount);
12418 contHilbertIdOffset.push_back(hilbertDomainOffset[i]);
12421 contHIdPartitionCellCount = hilbertIdPartitionCellsCount[hIdKeys[h]];
12422 contHIdCount = hilbertIdCount[hIdKeys[h]];
12426 if(h == noLocalHilbertIds[sliceDomain] - 1) {
12427 contHilbertIdsPartitionCounts.push_back(contHIdPartitionCellCount);
12428 contHilbertIdsPartitionOffset.push_back(hilbertPartitionDomainOffset[i]);
12430 contHilbertIdCount.push_back(contHIdCount);
12431 contHilbertIdOffset.push_back(hilbertDomainOffset[i]);
12435 const MInt noContHilbertIds = contHilbertIdsPartitionCounts.size();
12437 if(solverId > -1 && noSliceContHilbertIds !=
nullptr) {
12438 TERMM_IF_COND(sliceContiguousHilbertInfo ==
nullptr,
12439 "Error: sliceContiguousHilbertInfo is a nullptr but noSliceContHilbertIds is not.");
12441 std::vector<MInt> hIdCountSolver;
12442 std::vector<MInt> hDomainOffsetSolver;
12443 for(
MInt i = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
12444 if(hilbertIdCountSolver[hIdKeys[i]] > 0) {
12445 hIdCountSolver.push_back(hilbertIdCountSolver[hIdKeys[i]]);
12446 hDomainOffsetSolver.push_back(hilbertDomainOffsetSolver[i]);
12450 std::vector<MInt> contHilbertIdCountSolver{};
12451 std::vector<MInt> contHilbertIdOffsetSolver{};
12454 MInt contHIdCountSolver = (hIdCountSolver.size() > 0) ? hIdCountSolver[0] : 0;
12456 if(noLocalHilbertIdsSolver == 1) {
12457 contHilbertIdCountSolver.push_back(contHIdCountSolver);
12458 contHilbertIdOffsetSolver.push_back(hDomainOffsetSolver[0]);
12462 for(
MInt h = 1, i = 0; h < noLocalHilbertIdsSolver; h++) {
12464 if(hIdCountSolver[h - 1] + hDomainOffsetSolver[h - 1] == hDomainOffsetSolver[h]) {
12465 contHIdCountSolver += hIdCountSolver[h];
12468 contHilbertIdCountSolver.push_back(contHIdCountSolver);
12469 contHilbertIdOffsetSolver.push_back(hDomainOffsetSolver[i]);
12472 contHIdCountSolver = hIdCountSolver[h];
12476 if(h == noLocalHilbertIdsSolver - 1) {
12477 contHilbertIdCountSolver.push_back(contHIdCountSolver);
12478 contHilbertIdOffsetSolver.push_back(hDomainOffsetSolver[i]);
12482 const MInt noContHilbertIdsSolver = contHilbertIdCountSolver.size();
12483 *noSliceContHilbertIds = noContHilbertIdsSolver;
12485 if(noContHilbertIdsSolver > 0) {
12486 MIntScratchSpace contHilbertInfo(noContHilbertIdsSolver * 3, AT_,
"contHilbertInfo");
12487 for(
MInt i = 0; i < noContHilbertIdsSolver; i++) {
12488 contHilbertInfo[i * 3] = -1;
12489 contHilbertInfo[i * 3 + 1] = contHilbertIdCountSolver[i];
12490 contHilbertInfo[i * 3 + 2] = contHilbertIdOffsetSolver[i];
12492 std::copy_n(&contHilbertInfo[0], noContHilbertIdsSolver * 3, sliceContiguousHilbertInfo);
12494 }
else if(solverId < 0) {
12496 if(noSliceContHilbertIds !=
nullptr) {
12497 *noSliceContHilbertIds = noContHilbertIds;
12500 if(sliceContiguousHilbertInfo !=
nullptr) {
12501 MIntScratchSpace contHilbertInfo(noContHilbertIds * 3, AT_,
"contHilbertInfo");
12502 for(
MInt i = 0; i < noContHilbertIds; i++) {
12503 contHilbertInfo[i * 3] = -1;
12504 contHilbertInfo[i * 3 + 1] = contHilbertIdCount[i];
12505 contHilbertInfo[i * 3 + 2] = contHilbertIdOffset[i];
12507 std::copy_n(&contHilbertInfo[0], noContHilbertIds * 3, sliceContiguousHilbertInfo);
12512 for(
MInt i = 0, localOffset = 0, localPartOffset = 0; i < hilbertDomainOffset.
size0(); i++) {
12514 if(i < noContHilbertIds) {
12516 file.setOffset(contHilbertIdsPartitionCounts[i], contHilbertIdsPartitionOffset[i]);
12517 file.writeArray(&partitionCellsId[0] + localPartOffset,
"partitionCellsGlobalId");
12518 file.writeArray(&partitionCellsWorkload[0] + localPartOffset,
"partitionCellsWorkload");
12519 localPartOffset += contHilbertIdsPartitionCounts[i];
12522 file.setOffset(contHilbertIdCount[i], contHilbertIdOffset[i]);
12523 file.writeArray(&sliceCellInfo[0] + localOffset,
"cellInfo");
12526 file.writeArray(&solverBits[0] + localOffset,
"solver");
12528 localOffset += contHilbertIdCount[i];
12531 file.setOffset(0, 0);
12532 file.writeArray(&partitionCellsId[0],
"partitionCellsGlobalId");
12533 file.writeArray(&partitionCellsWorkload[0],
"partitionCellsWorkload");
12535 file.writeArray(&sliceCellInfo[0],
"cellInfo");
12537 file.writeArray(&solverBits[0],
"solver");
12542 const MInt noContMinCells = contHilbertIdMinCellCount.size();
12543 for(
MInt i = 0, localMinOffset = 0; i < hilbertDomainOffset.
size0(); i++) {
12545 if(i < noContMinCells) {
12547 file.setOffset(contHilbertIdMinCellCount[i], contHilbertIdMinCellOffset[i]);
12548 file.writeArray(&sliceMinLevelCellsTreeId[0] + localMinOffset,
"minLevelCellsTreeId");
12550 file.setOffset(contHilbertIdMinCellCount[i] * 2 * nDimSlice, contHilbertIdMinCellOffset[i] * 2 * nDimSlice);
12551 file.writeArray(&sliceMinLevelCellsNghbrIds[0] + localMinOffset * 2 * nDimSlice,
"minLevelCellsNghbrIds");
12552 localMinOffset += contHilbertIdMinCellCount[i];
12555 file.setOffset(0, 0);
12556 file.writeArray(&partitionCellsId[0],
"minLevelCellsTreeId");
12557 file.writeArray(&partitionCellsId[0],
"minLevelCellsNghbrIds");
12562 if(sliceDomain == 0) std::cerr <<
"Slice grid " << gridFileName <<
" write time: " << writeTimeTotal << std::endl;
12570 if(noSliceContHilbertIds !=
nullptr || sliceContiguousHilbertInfo !=
nullptr) {
12571 TERMM(1,
"Error: using non-optimized slice IO but contiguous Hilbert info requested by passing non-nullptr as "
12577 for(
MInt i = 0, localOffset = 0, localPartOffset = 0, localMinOffset = 0; i < hilbertDomainOffset.
size0(); i++) {
12578 if(i < noLocalHilbertIds[sliceDomain]) {
12582 file.setOffset(hilbertIdPartitionCellsCount[hIdKeys[i]], hilbertPartitionDomainOffset[i]);
12583 file.writeArray(&partitionCellsId[0] + localPartOffset,
"partitionCellsGlobalId");
12584 file.writeArray(&partitionCellsWorkload[0] + localPartOffset,
"partitionCellsWorkload");
12585 localPartOffset += hilbertIdPartitionCellsCount[hIdKeys[i]];
12591 file.setOffset(hilbertIdCount[hIdKeys[i]], hilbertDomainOffset[i]);
12592 file.writeArray(&sliceCellInfo[0] + localOffset,
"cellInfo");
12596 file.writeArray(&solverBits[0] + localOffset,
"solver");
12600 if(localMinOffset < noSliceMinLevelCells) {
12602 file.setOffset(hilbertIdMinLevelCellsCount[hIdKeys[i]], hilbertMinLevelDomainOffset[i]);
12603 file.writeArray(&sliceMinLevelCellsTreeId[0] + localMinOffset,
"minLevelCellsTreeId");
12605 file.setOffset(hilbertIdMinLevelCellsCount[hIdKeys[i]] * 2 * nDimSlice,
12606 hilbertMinLevelDomainOffset[i] * 2 * nDimSlice);
12607 file.writeArray(&sliceMinLevelCellsNghbrIds[0] + localMinOffset * 2 * nDimSlice,
"minLevelCellsNghbrIds");
12610 file.setOffset(0, 0);
12611 file.writeArray(&partitionCellsId[0],
"minLevelCellsTreeId");
12612 file.writeArray(&partitionCellsId[0],
"minLevelCellsNghbrIds");
12614 localMinOffset += hilbertIdMinLevelCellsCount[hIdKeys[i]];
12616 localOffset += hilbertIdCount[hIdKeys[i]];
12620 file.setOffset(0, 0);
12621 file.writeArray(&partitionCellsId[0],
"partitionCellsGlobalId");
12622 file.writeArray(&partitionCellsWorkload[0],
"partitionCellsWorkload");
12624 file.writeArray(&partitionCellsId[0],
"minLevelCellsTreeId");
12625 file.writeArray(&partitionCellsId[0],
"minLevelCellsNghbrIds");
12627 file.writeArray(&sliceCellInfo[0],
"cellInfo");
12629 file.writeArray(&solverBits[0],
"solver");
12634 if(sliceDomain == 0) std::cerr <<
"Slice grid " << gridFileName <<
" write time: " << writeTimeTotal << std::endl;
12643 m_log <<
"done!" << endl;
12654template <MInt nDim>
12656 std::vector<MInt>& mappedLeafCells,
MBool allChilds) {
12659 mappedLeafCells.clear();
12661 std::stack<MInt> cellStack;
12664 if(a_solver(gridCellId, donorSolverId)) {
12666 cellStack.push(gridCellId);
12670 while(!cellStack.empty()) {
12672 const MInt cellId = cellStack.top();
12676 if(a_isLeafCell(cellId, donorSolverId)) {
12678 mappedLeafCells.push_back(cellId);
12681 for(
MInt childId = 0; childId < m_maxNoChilds; childId++) {
12682 if(a_hasChild(cellId, childId, donorSolverId)) {
12683 cellStack.push(a_childId(cellId, childId, donorSolverId));
12685 mappedLeafCells.push_back(a_childId(cellId, childId, donorSolverId));
12694 MBool foundMappedParent =
false;
12695 MInt parentId = gridCellId;
12696 while(!foundMappedParent && a_hasParent(parentId)) {
12697 parentId = a_parentId(parentId);
12698 if(a_solver(parentId, donorSolverId) && a_isLeafCell(parentId, donorSolverId)) {
12699 foundMappedParent =
true;
12703 if(foundMappedParent) {
12704 mappedLeafCells.push_back(parentId);
12709 std::sort(mappedLeafCells.begin(), mappedLeafCells.end());
12722template <MInt nDim>
12724 MLong*
const partitionCellOffsets) {
12727 const MLong localNoPartitionCells = m_noPartitionCells;
12733 partitionCellOffsets[0] = 0;
12736 for(
MInt i = 1; i < noDomains() + 1; i++) {
12737 partitionCellOffsets[i] = partitionCellOffsets[i - 1] + noPartitionCells[i - 1];
12741 if(partitionCellOffsets[noDomains()] != m_noPartitionCellsGlobal) {
12742 TERMM(1,
"determineNoPartitionCellsAndOffsets(): Partition cell count does not match: "
12743 + std::to_string(partitionCellOffsets[noDomains()])
12744 +
" != " + std::to_string(m_noPartitionCellsGlobal));
12755template <MInt nDim>
12761 stringstream partitionFileName;
12762 partitionFileName << m_outputDir << partitionFileNameBase << ParallelIo::fileExt();
12765 ParallelIo file(partitionFileName.str(), PIO_REPLACE, mpiComm());
12767 const MLong noPartitionCells = m_noPartitionCellsGlobal;
12768 file.setAttributes(&noPartitionCells,
"noPartitionCells", 1);
12770 file.defineArray(PIO_LONG,
"partitionCellOffset", noDomains());
12771 file.setOffset(1, domainId());
12772 file.writeArray(&partitionCellOffset,
"partitionCellOffset");
12774 m_log <<
"Saved partition to file '" << partitionFileName.str() <<
"'." << endl;
12781template <MInt nDim>
12785 stringstream fileName;
12786 fileName <<
"partition_n" << noDomains() <<
"_" <<
globalTimeStep;
12788 savePartitionFile(fileName.str(), m_localPartitionCellOffsets[0]);
12793template <MInt nDim>
12799 if(domainId() == 0) {
12801 ParallelIo file(partitionFileName, PIO_READ, MPI_COMM_SELF);
12803 MLong noPartitionCells = -1;
12804 file.getAttribute(&noPartitionCells,
"noPartitionCells");
12805 TERMM_IF_NOT_COND(noPartitionCells == m_noPartitionCellsGlobal,
"global number of partition cell mismatch");
12807 if(file.getArraySize(
"partitionCellOffset", 0) != noDomains()) {
12808 TERMM(1,
"array size does not match number of domains");
12810 file.setOffset(noDomains(), 0);
12811 file.readArray(partitionCellOffsets,
"partitionCellOffset");
12816 "partitionCellOffsets");
12818 m_log <<
"Loaded partition from file '" << partitionFileName <<
"'." << endl;
12823template <MInt nDim>
12826 using namespace parallel_io;
12828 ParallelIo parallelIo(m_restartDir + gridInputFileName(), PIO_APPEND, mpiComm());
12831 const MInt noLocalPartitionCells = m_noPartitionCells;
12832 parallelIo.setOffset(noLocalPartitionCells, m_localPartitionCellOffsets[0]);
12835 ScratchSpace<MFloat> partitionCellsWorkload(noLocalPartitionCells, AT_,
"partitionCellsWorkload");
12836 MFloat totalWorkload = 0.0;
12837 for(
MInt i = 0; i < noLocalPartitionCells; i++) {
12838 const MInt partitionCellId = m_localPartitionCellLocalIds[i];
12839 partitionCellsWorkload[i] = a_workload(partitionCellId);
12840 totalWorkload += a_workload(partitionCellId);
12843 MPI_Allreduce(MPI_IN_PLACE, &totalWorkload, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"totalWorkload");
12845 parallelIo.setAttributes(&totalWorkload,
"totalWorkload", 1);
12846 parallelIo.writeArray(&partitionCellsWorkload[0],
"partitionCellsWorkload");
12850template <MInt nDim>
12851template <MBool t_correct, MBool ins
ideLimit>
12854 array<MFloat, nDim> tmp;
12855 const MFloat* tmpCoord = m_tree.coordinate(cellId);
12856 const MFloat* cellCenter = t_correct ? (correctCellCoord)(cellId, &tmp[0]) : tmpCoord;
12857 const MFloat _halfCellLength = halfCellLength(cellId);
12858 MBool isInCell =
true;
12861 IF_CONSTEXPR(nDim == 3) {
12862 return fabs(cellCenter[0] - coord[0]) <= _halfCellLength && fabs(cellCenter[1] - coord[1]) <= _halfCellLength
12863 && fabs(cellCenter[2] - coord[2]) <= _halfCellLength;
12865 return fabs(cellCenter[0] - coord[0]) <= _halfCellLength && fabs(cellCenter[1] - coord[1]) <= _halfCellLength;
12867 for(
MInt dimId = 0; dimId < nDim; dimId++) {
12868 if(coord[dimId] < cellCenter[dimId] - _halfCellLength || coord[dimId] >= cellCenter[dimId] + _halfCellLength) {
12879template <MInt nDim>
12883 for(
MInt i = 0; i < nDim; i++) {
12884 bbox[i] = numeric_limits<MFloat>::max();
12885 bbox[nDim + i] = numeric_limits<MFloat>::lowest();
12888 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
12889 if(a_hasProperty(cellId, Cell::IsHalo)) {
12893 const MFloat halfCellLength = F1B2 * cellLengthAtLevel(a_level(cellId));
12894 for(
MInt i = 0; i < nDim; i++) {
12895 bbox[i] =
mMin(bbox[i], a_coordinate(cellId, i) - halfCellLength);
12896 bbox[nDim + i] =
mMax(bbox[nDim + i], a_coordinate(cellId, i) + halfCellLength);
12900 const MFloat halfLength0 = 0.5 * ((F1 + F1 /
FPOW2(30)) * m_lengthLevel0);
12901 for(
MInt i = 0; i < nDim; i++) {
12902 ASSERT(bbox[i] > m_centerOfGravity[i] - halfLength0 && bbox[nDim + i] < m_centerOfGravity[i] + halfLength0,
12903 "local bounding box error");
12906 m_localBoundingBoxInit =
true;
12910template <MInt nDim>
12913 if(!m_localBoundingBoxInit) {
12917 const MFloat eps = 1e-12;
12918 for(
MInt i = 0; i < nDim; i++) {
12919 if(coord[i] < m_localBoundingBox[i] - eps || coord[i] > m_localBoundingBox[nDim + i] + eps) {
12928template <MInt nDim>
12930 m_log <<
"Performing grid sanity checks... ";
12932 const MInt noCells = m_tree.size();
12935 TERMM_IF_NOT_COND(m_noInternalCells == m_domainOffsets[domainId() + 1] - m_domainOffsets[domainId()],
12936 "Error: number of internal cells does not match with interval between domain offsets.");
12941 isPartitionCell.
fill(
false);
12943 MLong lastGlobalId = -1;
12944 for(
MInt i = 0; i < m_noPartitionCells; i++) {
12945 const MInt localId = m_localPartitionCellLocalIds[i];
12946 const MLong globalId = m_localPartitionCellGlobalIds[i];
12949 TERMM_IF_NOT_COND(a_hasProperty(localId, Cell::IsPartitionCell),
"Error: Cell is not a partition cell.");
12951 TERMM_IF_NOT_COND(globalId == a_globalId(localId),
"Error: partition cell global id mismatch.");
12953 TERMM_IF_NOT_COND(globalId > lastGlobalId,
"Error: partition cells not sorted by global id.");
12955 isPartitionCell[localId] =
true;
12956 lastGlobalId = a_globalId(localId);
12960 for(
MInt i = 0; i < noCells; i++) {
12961 if(isPartitionCell[i] || a_isToDelete(i) || a_isHalo(i))
continue;
12962 TERMM_IF_COND(a_hasProperty(i, Cell::IsPartitionCell),
12963 "Error: cell marked as partition cell but not in partition cell list " + std::to_string(i));
12966 TERMM_IF_NOT_COND(m_localPartitionCellOffsets[2] == m_noPartitionCellsGlobal,
12967 "Error: global number of partition cells mismatch.");
12969 MLongScratchSpace localPartitionCellCounts(noDomains(), AT_,
"localPartitionCellCounts");
12970 MLongScratchSpace localPartitionCellOffsets(noDomains() + 1, AT_,
"localPartitionCellOffsets");
12972 determineNoPartitionCellsAndOffsets(&localPartitionCellCounts[0], &localPartitionCellOffsets[0]);
12974 TERMM_IF_NOT_COND(m_localPartitionCellOffsets[0] == localPartitionCellOffsets[domainId()],
12975 "Error: partition cell offset mismatch.");
12976 TERMM_IF_NOT_COND(m_localPartitionCellOffsets[1] == localPartitionCellOffsets[domainId() + 1],
12977 "Error: next partition cell offset mismatch.");
12981 for(
MInt i = 0; i < noCells; i++) {
12982 if(a_isToDelete(i) || a_hasProperty(i, Cell::IsPeriodic))
continue;
12983 TERMM_IF_NOT_COND(m_globalToLocalId[a_globalId(i)] == i,
12984 "Error in global to local id mapping: l" + to_string(i) +
" g" + to_string(a_globalId(i)) +
" g2l"
12985 + to_string(m_globalToLocalId[a_globalId(i)]));
12991 isPartLvlAncestor.
fill(
false);
12993 MInt noLocalPartLvlAncestors = 0;
12995 for(
auto& i : m_partitionLevelAncestorIds) {
12996 TERMM_IF_NOT_COND(a_hasProperty(i, Cell::IsPartLvlAncestor),
"Error: cell is not a partition level ancestor.");
12997 TERMM_IF_COND(a_isToDelete(i),
"Error: partition level ancestor marked for deletion.");
12998 isPartLvlAncestor[i] =
true;
13001 for(
MInt child = 0; child < m_maxNoChilds; child++) {
13002 const MInt childId = a_childId(i, child);
13003 const MLong childGlobalId = (childId > -1) ? a_globalId(childId) : -1;
13004 const MInt index = count * m_maxNoChilds + child;
13005 TERMM_IF_NOT_COND(m_partitionLevelAncestorChildIds[index] == childGlobalId,
13006 "Error: partition level ancestor child id mismatch. "
13007 + std::to_string(m_partitionLevelAncestorChildIds[index])
13008 +
" != " + std::to_string(childGlobalId) +
"; " + std::to_string(i) +
"; "
13009 + std::to_string(child));
13014 noLocalPartLvlAncestors++;
13019 TERMM_IF_NOT_COND(noLocalPartLvlAncestors == m_noPartitionLevelAncestors,
13020 "Error: number of local partition level ancestors mismatch.");
13023 for(
MInt i = 0; i < noCells; i++) {
13024 if(isPartLvlAncestor[i] || a_isToDelete(i) || a_isHalo(i))
continue;
13025 TERMM_IF_COND(a_hasProperty(i, Cell::IsPartLvlAncestor),
13026 "Error: cell marked as partition level ancestor but is not in corresponding list.");
13035 isMinLevelCell.
fill(
false);
13037 for(
auto& minLevelCell : m_minLevelCells) {
13038 TERMM_IF_NOT_COND(a_level(minLevelCell) == m_minLevel,
"Error: level of min-level cell mismatch.");
13039 isMinLevelCell[minLevelCell] =
true;
13042 for(
MInt i = 0; i < noCells; i++) {
13043 if(isMinLevelCell[i] || a_isToDelete(i))
continue;
13044 TERMM_IF_COND(a_level(i) <= m_minLevel,
"Error: non-min-level cell has level <= minLevel");
13048 m_log <<
"done" << std::endl;
13055template <MInt nDim>
13062 m_log <<
"checkWindowHaloConsistency... ";
13065 if(m_haloMode > 0) {
13068 isWindowCell.
fill(
false);
13069 isHaloCell.
fill(
false);
13074 for(
MInt solver = 0; solver < treeb().noSolvers(); ++solver) {
13079 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
13080 MIntScratchSpace noWindowCellsRecv(std::max(1, noNeighborDomains()), AT_,
"noWindowCellsRecv");
13081 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13082 noWindowCellsRecv[d] = -1;
13084 mpiComm(), &recvRequests[d], AT_,
"noWindowCellsRecv[d]");
13088 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
13089 MIntScratchSpace noWindowCellsSend(std::max(1, noNeighborDomains()), AT_,
"noWindowCellsSend");
13090 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13092 noWindowCellsSend[d] = noSolverWindowCells(d, solver);
13094 &sendRequests[d], AT_,
"noWindowCellsSend[d]");
13098 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
13099 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
13102 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13103 if(noWindowCellsRecv[d] != noSolverHaloCells(d, solver,
true) ) {
13104 TERMM(1,
"Cartesian Grid : Number of window cells from domain " + to_string(neighborDomain(d))
13105 +
" does not match local number of halo cells; window: " + to_string(noWindowCellsRecv[d])
13106 +
" ,halo: " + to_string(noSolverHaloCells(d, solver,
true) ) +
" " +
a
13107 +
" d=" + to_string(domainId()) +
" solver=" + to_string(solver));
13116 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
13118 MInt totalNoWindowCellsRecv = 0;
13119 for(
MInt d = 0; d < noNeighborDomains(); d++)
13120 totalNoWindowCellsRecv += noHaloCells(d);
13122 MIntScratchSpace windowCellsRecv(max(1, totalNoWindowCellsRecv), AT_,
"windowCellsRecv");
13123 fill(windowCellsRecv.
begin(), windowCellsRecv.
end(), -1);
13124 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13125 if(noHaloCells(d) > 0) {
13127 neighborDomain(d), mpiComm(), &recvRequests[d], AT_,
"windowCellsRecv[offset]");
13129 offset += noHaloCells(d);
13133 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
13135 MInt totalNoWindowCellsSend = 0;
13136 for(
MInt d = 0; d < noNeighborDomains(); d++)
13137 totalNoWindowCellsSend += noWindowCells(d);
13138 MIntScratchSpace windowCellsSend(max(1, totalNoWindowCellsSend), AT_,
"windowCellsSend");
13140 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13141 for(
MInt c = 0; c < noWindowCells(d) ; c++) {
13143 windowCellsSend[offset + c] = a_globalId(windowCell(d, c));
13144 isWindowCell(windowCell(d, c)) =
true;
13146 if(noWindowCells(d) > 0) {
13148 domainId(), mpiComm(), &sendRequests[d], AT_,
"windowCellsSend[offset]");
13150 offset += noWindowCells(d);
13154 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
13155 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
13158 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13159 for(
MInt c = 0; c < noHaloCells(d); c++) {
13160 const MInt cellId = haloCell(d, c);
13161 TERMM_IF_NOT_COND(a_isHalo(cellId),
"not a halo cell");
13162 isHaloCell(haloCell(d, c)) =
true;
13163 const MInt globalId = a_globalId(cellId);
13165 if(windowCellsRecv[offset + c] != globalId && !(a_hasProperty(cellId, Cell::IsPeriodic) && globalId == -1)) {
13166 TERMM(1,
a +
"Global id of window cell " + to_string(c) +
" from domain " + to_string(neighborDomain(d))
13167 +
" does not match local halo cell gobal id (" + to_string(windowCellsRecv[offset + c]) +
" vs. "
13168 + to_string(a_globalId(haloCell(d, c))) +
")");
13171 offset += noHaloCells(d);
13175 if(m_azimuthalPer) {
13176 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
13177 for(
MInt c = 0; c < noAzimuthalWindowCells(d); c++) {
13178 isWindowCell(azimuthalWindowCell(d, c)) =
true;
13180 for(
MInt c = 0; c < noAzimuthalHaloCells(d); c++) {
13181 isHaloCell(azimuthalHaloCell(d, c)) =
true;
13184 for(
MInt c = 0; c < noAzimuthalUnmappedHaloCells(); c++) {
13185 isHaloCell(azimuthalUnmappedHaloCell(c)) =
true;
13189 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
13191 if(!isWindowCell(cellId)) {
13192 TERMM_IF_NOT_COND(!a_hasProperty(cellId, Cell::IsWindow),
13193 "cell is marked as window but not in m_windowCells: " + std::to_string(cellId) +
a);
13196 if(!isHaloCell(cellId) && !a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
13197 TERMM_IF_NOT_COND(!a_isHalo(cellId),
13198 "cell is marked as halo but not in m_haloCells: " + std::to_string(cellId));
13207 MIntScratchSpace noWindowCellsRecv(std::max(1, noNeighborDomains()), AT_,
"noWindowCellsRecv");
13208 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13209 noWindowCellsRecv[d] = -1;
13211 &recvRequests[d], AT_,
"noWindowCellsRecv[d]");
13216 MIntScratchSpace noWindowCellsSend(std::max(1, noNeighborDomains()), AT_,
"noWindowCellsSend");
13217 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13218 noWindowCellsSend[d] = noWindowCells(d);
13220 &sendRequests[d], AT_,
"noWindowCellsSend[d]");
13224 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
13225 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
13228 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13229 if(noWindowCellsRecv[d] != noHaloCells(d)) {
13230 TERMM(1,
"Cartesian Grid : Number of window cells from domain " + to_string(neighborDomain(d))
13231 +
" does not match local number of halo cells; window: " + to_string(noWindowCellsRecv[d])
13232 +
" ,halo: " + to_string(noHaloCells(d)));
13240 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
13241 const MInt totalNoWindowCellsRecv = accumulate(noWindowCellsRecv.
begin(), noWindowCellsRecv.
end(), 0);
13243 MLongScratchSpace windowCellsRecv(max(1, totalNoWindowCellsRecv), AT_,
"windowCellsRecv");
13244 fill(windowCellsRecv.
begin(), windowCellsRecv.
end(), -1);
13245 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13246 if(noHaloCells(d) > 0) {
13248 neighborDomain(d), mpiComm(), &recvRequests[d], AT_,
"windowCellsRecv[offset]");
13250 offset += noHaloCells(d);
13254 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
13255 const MInt totalNoWindowCellsSend = accumulate(noWindowCellsSend.
begin(), noWindowCellsSend.
end(), 0);
13256 MLongScratchSpace windowCellsSend(max(1, totalNoWindowCellsSend), AT_,
"windowCellsSend");
13260 isWindowCell.
fill(
false);
13261 isHaloCell.
fill(
false);
13263 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13264 for(
MInt c = 0; c < noWindowCellsSend[d]; c++) {
13265 TERMM_IF_NOT_COND(a_hasProperty(windowCell(d, c), Cell::IsWindow),
"not a window cell");
13266 windowCellsSend[offset + c] = a_globalId(windowCell(d, c));
13267 isWindowCell(windowCell(d, c)) =
true;
13269 if(noWindowCells(d) > 0) {
13271 domainId(), mpiComm(), &sendRequests[d], AT_,
"windowCellsSend[offset]");
13273 offset += noWindowCells(d);
13277 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
13278 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
13281 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
13282 for(
MInt c = 0; c < noHaloCells(d); c++) {
13283 const MInt cellId = haloCell(d, c);
13284 TERMM_IF_NOT_COND(a_isHalo(cellId),
"not a halo cell");
13285 isHaloCell(haloCell(d, c)) =
true;
13286 const MLong globalId = a_globalId(cellId);
13288 if(windowCellsRecv[offset + c] != globalId && !(a_hasProperty(cellId, Cell::IsPeriodic) && globalId == -1)) {
13289 TERMM(1,
"Global id of window cell " + to_string(c) +
" from domain " + to_string(neighborDomain(d))
13290 +
" does not match local halo cell gobal id (" + to_string(windowCellsRecv[offset + c]) +
" vs. "
13291 + to_string(a_globalId(haloCell(d, c))) +
")");
13294 offset += noHaloCells(d);
13298 if(m_azimuthalPer) {
13299 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
13300 for(
MInt c = 0; c < noAzimuthalWindowCells(d); c++) {
13301 isWindowCell(azimuthalWindowCell(d, c)) =
true;
13303 for(
MInt c = 0; c < noAzimuthalHaloCells(d); c++) {
13304 isHaloCell(azimuthalHaloCell(d, c)) =
true;
13307 for(
MInt c = 0; c < noAzimuthalUnmappedHaloCells(); c++) {
13308 isHaloCell(azimuthalUnmappedHaloCell(c)) =
true;
13312 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
13314 if(!isWindowCell(cellId)) {
13315 TERMM_IF_NOT_COND(!a_hasProperty(cellId, Cell::IsWindow),
13316 "cell is marked as window but not in m_windowCells: " + std::to_string(cellId));
13319 if(!isHaloCell(cellId) && !a_hasProperty(cellId, Cell::IsPartLvlAncestor)) {
13320 TERMM_IF_NOT_COND(!a_isHalo(cellId),
13321 "cell is marked as halo but not in m_haloCells: " + std::to_string(cellId));
13329 if(fullCheck && noNeighborDomains() > 0) {
13332 parentData.
fill(-1);
13333 childData.
fill(-1);
13335 for(
MInt cellId = 0; cellId < m_noInternalCells; cellId++) {
13336 TERMM_IF_COND(a_isHalo(cellId),
"cell is a halo" +
a);
13337 const MInt parentId = a_parentId(cellId);
13338 parentData[cellId] = (parentId > -1) ? a_globalId(parentId) : -1;
13340 for(
MInt j = 0; j < m_maxNoChilds; j++) {
13341 const MInt childId = a_childId(cellId, j);
13342 childData(cellId, j) = (childId > -1) ? a_globalId(childId) : -1;
13351 for(
MInt d = 0; d < noNeighborDomains(); d++) {
13352 for(
MInt c = 0; c < noHaloCells(d); c++) {
13353 const MInt cellId = haloCell(d, c);
13354 TERMM_IF_NOT_COND(a_isHalo(cellId),
"not a halo cell");
13355 const MInt parentId = a_parentId(cellId);
13356 if(parentId > -1) {
13357 TERMM_IF_NOT_COND(a_globalId(parentId) == parentData[cellId],
13358 "Halo cell parent global id mismatch: cell" + std::to_string(cellId) +
" parent"
13359 + std::to_string(parentId) +
"; " + std::to_string(a_globalId(parentId))
13360 +
" != " + std::to_string(parentData[cellId]));
13363 for(
MInt j = 0; j < m_maxNoChilds; j++) {
13364 const MInt childId = a_childId(cellId, j);
13366 TERMM_IF_NOT_COND(a_globalId(childId) == childData(cellId, j),
13367 "Halo cell child global id mismatch: cell" + std::to_string(cellId) +
" child"
13368 + std::to_string(childId) +
"; " + std::to_string(a_globalId(childId))
13369 +
" != " + std::to_string(childData(cellId, j)));
13376 m_log <<
"done" << std::endl;
13378 if(m_azimuthalPer) {
13379 checkAzimuthalWindowHaloConsistency();
13385template <MInt nDim>
13388 logfile.open(name +
"_" + std::to_string(domainId()));
13390 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
13391 logfile << cellId <<
" g" << a_globalId(cellId) <<
" l" << a_level(cellId) <<
" p" << a_parentId(cellId);
13392 for(
MUint j = 0; j < (unsigned)m_maxNoChilds; j++) {
13393 logfile <<
" c" << a_childId(cellId, j);
13395 for(
MInt dirId = 0; dirId < m_noDirs; dirId++) {
13396 logfile <<
" n" << a_neighborId(cellId, dirId);
13398 logfile <<
" " << a_propertiesToString(cellId);
13399 logfile <<
" w" << a_weight(cellId);
13400 logfile <<
" o" << a_noOffsprings(cellId) << std::endl;
13402 logfile << std::endl;
13404 for(
MUint i = 0; i < m_minLevelCells.size(); i++) {
13405 logfile <<
"m" << i <<
" " << m_minLevelCells[i] << std::endl;
13407 logfile << std::endl;
13409 for(
MInt i = 0; i < m_noPartitionCells; i++) {
13410 logfile <<
"p" << i <<
" g" << m_localPartitionCellGlobalIds[i] <<
" l" << m_localPartitionCellLocalIds[i]
13411 <<
" level" << a_level(m_localPartitionCellLocalIds[i]) << std::endl;
13413 logfile << std::endl;
13416 for(
auto&
id : m_globalToLocalId) {
13417 logfile <<
"g2l" << count++ <<
" g" <<
id.first <<
" l" <<
id.second << std::endl;
13419 logfile << std::endl;
13421 for(
MInt i = 0; i < noNeighborDomains(); i++) {
13422 logfile <<
"window " << i <<
" " << m_nghbrDomains[i] <<
" " << m_windowCells[i].size() << std::endl;
13423 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
13424 logfile <<
"window " << m_nghbrDomains[i] <<
" " << j <<
" w" << m_windowCells[i][j] <<
" g"
13425 << a_globalId(m_windowCells[i][j]) << std::endl;
13427 logfile << std::endl;
13429 logfile <<
"halo " << i <<
" " << m_nghbrDomains[i] <<
" " << m_haloCells[i].size() << std::endl;
13430 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); j++) {
13431 logfile <<
"halo " << m_nghbrDomains[i] <<
" " << j <<
" h" << m_haloCells[i][j]
13433 <<
" g" << a_globalId(m_haloCells[i][j]) << std::endl;
13435 logfile << std::endl;
13446template <MInt nDim>
13449 m_log <<
"Update partition cells: offspringThreshold=" << offspringThreshold
13450 <<
"; workloadThreshold=" << workloadThreshold << std::endl;
13452 MBool partitionCellChange =
false;
13459 std::vector<MInt> tmpMinLevelCells;
13460 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
13461 if(a_level(cellId) == m_minLevel && !a_hasProperty(cellId, Cell::IsPeriodic)) {
13462 ASSERT(a_parentId(cellId) == -1,
"");
13463 tmpMinLevelCells.push_back(cellId);
13467 std::vector<MInt> partitionCellsFiltered;
13469 partitionCellsFiltered.clear();
13470 std::vector<MInt> tmpPartitionCells(tmpMinLevelCells);
13473 while(!tmpPartitionCells.empty()) {
13474 const MInt cellId = tmpPartitionCells.front();
13475 tmpPartitionCells.erase(tmpPartitionCells.begin());
13478 MBool isSolverLeafCell =
false;
13479 for(
MInt b = 0;
b < treeb().noSolvers();
b++) {
13480 if(a_isLeafCell(cellId,
b)) {
13481 isSolverLeafCell =
true;
13487 if((a_noOffsprings(cellId) > offspringThreshold || a_workload(cellId) > workloadThreshold) && !isSolverLeafCell) {
13490 for(
MInt j = 0; j <
IPOW2(nDim); ++j) {
13491 if(a_childId(cellId, j) > -1) {
13492 tmpPartitionCells.insert(tmpPartitionCells.begin() + cnt, a_childId(cellId, j));
13496 }
else if(!a_isHalo(cellId)) {
13498 partitionCellsFiltered.push_back(cellId);
13502 MLong globalNoNewPartitionCells = partitionCellsFiltered.size();
13504 "MPI_IN_PLACE",
"globalNoNewPartitionCells");
13505 cerr0 <<
"Found " << globalNoNewPartitionCells <<
" new partition cells." << std::endl;
13506 m_log <<
"Found " << globalNoNewPartitionCells <<
" new partition cells." << std::endl;
13510 if(globalNoNewPartitionCells < noDomains()) {
13511 offspringThreshold /= 2;
13512 workloadThreshold *= 0.5;
13513 cerr0 <<
"Error: too few partition cells; Repeating filtering of partition cells with "
13514 "lowered thresholds..."
13521 const MInt oldNoPartCells = m_noPartitionCells;
13522 const MInt newNoPartCells = partitionCellsFiltered.size();
13524 sort(partitionCellsFiltered.begin(), partitionCellsFiltered.end());
13526 if(oldNoPartCells != newNoPartCells) {
13528 partitionCellChange =
true;
13531 for(
MInt i = 0; i < newNoPartCells; i++) {
13532 const MInt newPartCellId = partitionCellsFiltered[i];
13533 if(!a_hasProperty(newPartCellId, Cell::IsPartitionCell)) {
13534 partitionCellChange =
true;
13540 MInt globalPartitionCellChange = partitionCellChange;
13542 "MPI_IN_PLACE",
"globalPartitionCellChange");
13545 if(!globalPartitionCellChange) {
13546 cerr0 <<
"Partition cells did not change." << std::endl;
13547 m_log <<
"Partition cells did not change." << std::endl;
13552 m_updatingPartitionCells =
true;
13556 const MInt firstMinLvlCell = m_minLevelCells[0];
13557 MInt minLvlHaloPartLvlAncestor = -1;
13558 if(a_hasProperty(firstMinLvlCell, Cell::IsPartLvlAncestor) && a_hasProperty(firstMinLvlCell, Cell::IsHalo)) {
13559 minLvlHaloPartLvlAncestor = firstMinLvlCell;
13563 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
13564 a_hasProperty(cellId, Cell::IsPartitionCell) =
false;
13565 a_hasProperty(cellId, Cell::IsPartLvlAncestor) =
false;
13569 MInt maxLevelDiff = 0;
13570 for(
MInt i = 0; i < newNoPartCells; i++) {
13571 const MInt newPartCellId = partitionCellsFiltered[i];
13572 a_hasProperty(newPartCellId, Cell::IsPartitionCell) =
true;
13574 maxLevelDiff = std::max(maxLevelDiff, a_level(newPartCellId) - m_minLevel);
13577 m_noPartitionCells = newNoPartCells;
13579 m_noPartitionCellsGlobal = m_noPartitionCells;
13581 "MPI_IN_PLACE",
"m_noPartitionCellsGlobal");
13585 cerr0 <<
"New maximum partition level shift: " << maxLevelDiff << std::endl;
13586 m_log <<
"New maximum partition level shift: " << maxLevelDiff << std::endl;
13587 m_maxPartitionLevelShift = maxLevelDiff;
13592 mAlloc(m_localPartitionCellGlobalIds, std::max(m_noPartitionCells, 1),
"m_localPartitionCellGlobalIds",
13593 static_cast<MLong>(-1), AT_);
13595 mAlloc(m_localPartitionCellLocalIds, std::max(m_noPartitionCells, 1),
"m_localPartitionCellLocalIds", -1, AT_);
13597 MIntScratchSpace isPartitionLevelAncestor(m_noInternalCells, AT_,
"isPartitionLevelAncestor");
13598 isPartitionLevelAncestor.
fill(0);
13600 MInt noPartitionLevelAncestorsLocal = 0;
13602 for(
MInt i = 0; i < newNoPartCells; i++) {
13603 const MInt cellId = partitionCellsFiltered[i];
13604 MInt parentId = a_parentId(cellId);
13607 while(parentId > -1) {
13608 a_hasProperty(parentId, Cell::IsPartLvlAncestor) =
true;
13610 if(!a_isHalo(parentId)) {
13611 noPartitionLevelAncestorsLocal++;
13614 for(
MInt b = 0;
b < treeb().noSolvers();
b++) {
13615 TERMM_IF_COND(a_isLeafCell(parentId,
b),
"Error: partition level ancestor is the leaf cell of a solver.");
13618 parentId = a_parentId(parentId);
13622 m_noPartitionLevelAncestors = noPartitionLevelAncestorsLocal;
13624 m_noPartitionLevelAncestorsGlobal = m_noPartitionLevelAncestors;
13626 AT_,
"MPI_IN_PLACE",
"noPartitionLevelAncestorsGlobal");
13628 std::vector<MInt>().swap(m_partitionLevelAncestorIds);
13629 std::vector<MLong>().swap(m_partitionLevelAncestorChildIds);
13633 if(minLvlHaloPartLvlAncestor > -1) {
13634 TERMM_IF_NOT_COND(a_isHalo(minLvlHaloPartLvlAncestor),
"Error: not a halo cell.");
13635 a_hasProperty(minLvlHaloPartLvlAncestor, Cell::IsPartLvlAncestor) =
true;
13636 m_partitionLevelAncestorIds.push_back(minLvlHaloPartLvlAncestor);
13640 updatePartitionCellInformation();
13643 exchangeProperties();
13645 m_updatingPartitionCells =
false;
13647 m_updatedPartitionCells =
true;
13654template <MInt nDim>
13656 std::vector<std::vector<MInt>>& partLvlAncestorHaloCells,
13657 std::vector<std::vector<MInt>>& partLvlAncestorWindowCells) {
13660 partLvlAncestorHaloCells.clear();
13661 partLvlAncestorWindowCells.clear();
13663 partLvlAncestorHaloCells.resize(noNeighborDomains());
13664 partLvlAncestorWindowCells.resize(noNeighborDomains());
13666 for(
MInt i = 0; i < noNeighborDomains(); i++) {
13667 for(
MInt j = 0; j < (signed)m_haloCells[i].size(); ++j) {
13668 if(a_hasProperty(m_haloCells[i][j], Cell::IsPartLvlAncestor)) {
13669 partLvlAncestorHaloCells[i].push_back(m_haloCells[i][j]);
13672 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); ++j) {
13673 if(a_hasProperty(m_windowCells[i][j], Cell::IsPartLvlAncestor)) {
13674 partLvlAncestorWindowCells[i].push_back(m_windowCells[i][j]);
13681template <MInt nDim>
13683 const MInt cellId,
const MInt solver,
13684 const std::function<
MInt(
const MFloat*,
const MInt,
const MInt)>& cellOutsideSolver) {
13687 static constexpr MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
13688 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
13690 const MInt childLevel = a_level(cellId) + 1;
13691 const MFloat childCellLength = cellLengthAtLevel(childLevel);
13693 for(
MInt c = 0; c < m_maxNoChilds; c++) {
13694 MInt childId = a_childId(cellId, c);
13696 if(childId < 0)
continue;
13697 if(treeb().solver(childId, solver))
continue;
13700 for(
MInt i = 0; i < nDim; i++) {
13701 coords[i] = a_coordinate(cellId, i) + F1B2 * signStencil[c][i] * childCellLength;
13703 MInt isOutside = cellOutsideSolver(coords, childLevel, cellId);
13705 if(isOutside < 1) {
13706 treeb().solver(childId, solver) =
true;
13716template <MInt nDim>
13722 for(
MInt d = 0; d < nDim; d++) {
13723 if(m_periodicCartesianDir[d] == 0) {
13724 coordsCyl[nDim - 1] = coords[d];
13726 radius += pow((coords[d] - m_azimuthalPerCenter[d]), 2);
13729 radius = sqrt(radius);
13732 if(coords[m_azimuthalPeriodicDir[0]] >= F0) {
13737 MFloat phi = fac * acos(coords[m_azimuthalPeriodicDir[1]] / radius);
13739 coordsCyl[0] = radius;
13740 coordsCyl[1] = phi;
13747template <MInt nDim>
13753 for(
MInt d = 0; d < nDim; d++) {
13754 tmpCoords[d] = coords[d] - m_azimuthalPerCenter[d];
13757 coords[m_azimuthalPeriodicDir[0]] =
13758 tmpCoords[m_azimuthalPeriodicDir[0]] * cos(angle) - tmpCoords[m_azimuthalPeriodicDir[1]] * sin(angle);
13759 coords[m_azimuthalPeriodicDir[1]] =
13760 tmpCoords[m_azimuthalPeriodicDir[0]] * sin(angle) + tmpCoords[m_azimuthalPeriodicDir[1]] * cos(angle);
13762 for(
MInt d = 0; d < nDim; d++) {
13763 coords[d] += m_azimuthalPerCenter[d];
13772template <MInt nDim>
13774 vector<MLong>& recvChildIds,
13778 if(noAzimuthalNeighborDomains() == 0)
return;
13780 static constexpr MFloat cornerStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
13781 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
13783 MFloat childCoords[3] = {F0, F0, F0};
13784 MFloat coordsCyl[3] = {F0, F0, F0};
13785 MFloat dxCyl = m_azimuthalAngle;
13787 MInt noCells = treeb().size();
13789 gridBndryCells.
fill(
false);
13790 for(
auto it = m_gridBndryCells.begin(); it != m_gridBndryCells.end(); it++) {
13792 gridBndryCells[cellId] =
true;
13795 MInt windowCnt = 0;
13797 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13798 windowCnt += m_azimuthalWindowCells[i].
size();
13799 haloCnt += m_azimuthalHaloCells[i].size();
13802 refineChildIds.resize(windowCnt * m_maxNoChilds);
13803 recvChildIds.resize(haloCnt * m_maxNoChilds);
13806 refinedWindows.
fill(0);
13808 refineCandidates.
fill(0);
13814 MIntScratchSpace windowRefineCnt(noAzimuthalNeighborDomains(), AT_,
"windowRefineCnt");
13815 windowRefineCnt.
fill(0);
13816 MInt windowRefineCntTotal = 0;
13817 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13818 for(
MInt j = 0; j < noAzimuthalWindowCells(i); j++) {
13819 MInt cellId = m_azimuthalWindowCells[i][j];
13821 MBool refine =
false;
13822 if(a_level(cellId) == level) {
13823 if(a_noChildren(cellId) > 0) {
13829 refinedWindows[cnt] = 1;
13830 windowRefineCnt[i]++;
13831 windowRefineCntTotal++;
13839 windowRefineCntTotal = 0;
13840 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13841 for(
MInt j = 0; j < noAzimuthalWindowCells(i); j++) {
13842 if(refinedWindows[cnt] > 0) {
13843 MInt cellId = m_azimuthalWindowCells[i][j];
13844 windowMap[windowRefineCntTotal] = cellId;
13845 windowRefineCntTotal++;
13856 MInt haloRefineCntTotal = 0;
13857 MIntScratchSpace haloRefineCnt(noAzimuthalNeighborDomains(), AT_,
"haloRefineCnt");
13858 haloRefineCnt.
fill(0);
13859 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13860 for(
MInt j = 0; j < noAzimuthalHaloCells(i); j++) {
13861 if(refineCandidates[cnt] > 0) {
13862 haloRefineCnt[i]++;
13863 haloRefineCntTotal++;
13872 haloRefineCntTotal = 0;
13873 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13874 for(
MInt j = 0; j < noAzimuthalHaloCells(i); j++) {
13875 MInt cellId = m_azimuthalHaloCells[i][j];
13876 refineHalo[cellId] = refineCandidates[cnt];
13877 if(refineCandidates[cnt] > 0) {
13878 haloMap[haloRefineCntTotal] = cellId;
13879 haloRefineCntTotal++;
13887 for(
MInt cellId = 0; cellId < noCells; cellId++) {
13888 if(a_isHalo(cellId)) {
13891 if(a_level(cellId) != level) {
13894 for(
MInt d = 0; d < m_noDirs; d++) {
13895 MInt nghbrId = a_neighborId(cellId, d);
13896 if(nghbrId <= -1) {
13899 if(!a_isHalo(nghbrId)) {
13902 layerId[nghbrId] = 1;
13904 MInt addLayer =
true;
13905 if(!a_hasProperty(nghbrId, Cell::IsPeriodic)) {
13906 if(a_noChildren(nghbrId) != 0) {
13910 if(refineHalo[nghbrId] > 0) {
13915 for(
MInt d2 = 0; d2 < m_noDirs; d2++) {
13916 if(!addLayer && d == d2) {
13919 MInt nghbrId2 = a_neighborId(nghbrId, d2);
13920 if(nghbrId2 <= -1) {
13923 if(a_isHalo(nghbrId2) && layerId[nghbrId2] <= -1) {
13924 layerId[nghbrId2] = 2;
13926 for(
MInt d3 = 0; d3 < m_noDirs; d3++) {
13927 if(d3 == d || d3 == d2) {
13930 MInt nghbrId3 = a_neighborId(nghbrId2, d3);
13931 if(nghbrId3 <= -1) {
13934 if(a_isHalo(nghbrId3) && layerId[nghbrId3] <= -1) {
13935 layerId[nghbrId3] = 3;
13942 MLongScratchSpace haloChildIds(2 * haloRefineCntTotal * m_maxNoChilds, AT_,
"haloChildIds");
13944 ASSERT(m_noHaloLayers == 2,
"");
13945 for(
MInt i = 0; i < haloRefineCntTotal; i++) {
13946 MInt cellId = haloMap[i];
13948 MBool refine =
false;
13951 if(a_level(cellId) == level) {
13952 if(layerId[cellId] > 0) {
13958 fill(&haloChildIds[i * 2 * m_maxNoChilds], &haloChildIds[i * 2 * m_maxNoChilds] + (2 * m_maxNoChilds), -2);
13962 MInt parentId = cellId;
13963 for(
MInt lvl = level; lvl > m_minLevel; lvl--) {
13964 parentId = a_parentId(parentId);
13967 cartesianToCylindric(&a_coordinate(parentId, 0), coordsCyl);
13968 MInt side = m_azimuthalBbox.azimuthalSide(coordsCyl[1]);
13971 MFloat hLength = F1B2 * cellLengthAtLevel(a_level(cellId));
13972 for(
MInt child = 0; child < m_maxNoChilds; child++) {
13973 for(
MInt d = 0; d < nDim; d++) {
13974 childCoords[d] = a_coordinate(cellId, d) + cornerStencil[child][d] * F1B2 * hLength;
13976 rotateCartesianCoordinates(childCoords, side * dxCyl);
13979 hilbertIndexGeneric(&childCoords[0], m_targetGridCenterOfGravity, m_targetGridLengthLevel0, level + 1);
13980 haloChildIds[i * 2 * m_maxNoChilds + 2 * child] = hilbertId;
13981 hilbertId = hilbertIndexGeneric(&childCoords[0], m_targetGridCenterOfGravity, m_targetGridLengthLevel0, level);
13982 haloChildIds[i * 2 * m_maxNoChilds + 2 * child + 1] = hilbertId;
13988 mpi_send_req.
fill(MPI_REQUEST_NULL);
13989 mpi_recv_req.
fill(MPI_REQUEST_NULL);
13991 MLongScratchSpace windowChildIds(2 * windowRefineCntTotal * m_maxNoChilds, AT_,
"windowChildIds");
13993 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
13994 if(windowRefineCnt[i] > 0) {
13995 MInt bufSize = 2 * m_maxNoChilds * windowRefineCnt[i];
13996 MPI_Irecv(&windowChildIds[cnt], bufSize, MPI_LONG, m_azimuthalNghbrDomains[i], 2, mpiComm(), &mpi_recv_req[i],
13997 AT_,
"windowChildIds[cnt]");
14003 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14004 if(haloRefineCnt[i] > 0) {
14005 MInt bufSize = 2 * m_maxNoChilds * haloRefineCnt[i];
14006 MPI_Isend(&haloChildIds[cnt], bufSize, MPI_LONG, m_azimuthalNghbrDomains[i], 2, mpiComm(), &mpi_send_req[i], AT_,
14007 "haloChildIds[cnt]");
14012 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14013 if(windowRefineCnt[i] > 0)
MPI_Wait(&mpi_recv_req[i], MPI_STATUSES_IGNORE, AT_);
14014 if(haloRefineCnt[i] > 0)
MPI_Wait(&mpi_send_req[i], MPI_STATUSES_IGNORE, AT_);
14018 for(
MInt i = 0; i < windowRefineCntTotal; i++) {
14019 MInt cellId = windowMap[i];
14021 MBool gridBndry = gridBndryCells[cellId];
14022 MBool noRefine =
false;
14024 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14025 MLong haloHilbertId_L1 = windowChildIds[i * 2 * m_maxNoChilds + 2 * child];
14026 MLong haloHilbertId_L0 = windowChildIds[i * 2 * m_maxNoChilds + 2 * child + 1];
14027 windowChildIds[i * 2 * m_maxNoChilds + 2 * child] = -2;
14028 windowChildIds[i * 2 * m_maxNoChilds + 2 * child + 1] = -2;
14030 if(haloHilbertId_L1 < -1) {
14031 windowChildIds[i * m_maxNoChilds + child] = -2;
14035 MBool found =
false;
14037 for(
MInt child2 = 0; child2 < m_maxNoChilds; child2++) {
14038 MInt childId = a_childId(cellId, child2);
14039 if(childId < 0)
continue;
14041 MLong hilbertId = hilbertIndexGeneric(&a_coordinate(childId, 0), m_targetGridCenterOfGravity,
14042 m_targetGridLengthLevel0, level + 1);
14044 if(hilbertId == haloHilbertId_L1) {
14045 windowChildIds[i * m_maxNoChilds + child] = a_globalId(childId);
14051 if(found)
continue;
14057 const MInt counter = getAdjacentGridCells(cellId, nghbrList, level);
14058 for(
MInt n = 0; n < counter; n++) {
14059 MInt nghbrId = nghbrList[n];
14060 if(nghbrId < 0)
continue;
14061 if(a_level(nghbrId) == level + 1) {
14062 MLong hilbertId = hilbertIndexGeneric(&a_coordinate(nghbrId, 0), m_targetGridCenterOfGravity,
14063 m_targetGridLengthLevel0, level + 1);
14064 if(hilbertId == haloHilbertId_L1) {
14065 windowChildIds[i * m_maxNoChilds + child] = a_globalId(nghbrId);
14070 }
else if(a_level(nghbrId) == level) {
14071 MLong hilbertId = hilbertIndexGeneric(&a_coordinate(nghbrId, 0), m_targetGridCenterOfGravity,
14072 m_targetGridLengthLevel0, level);
14074 if(hilbertId == haloHilbertId_L0) {
14075 windowChildIds[i * m_maxNoChilds + child] = a_globalId(nghbrId);
14088 windowChildIds[i * m_maxNoChilds + child] = -1;
14096 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14097 windowChildIds[i * m_maxNoChilds + child] = -2;
14103 windowRefineCntTotal = 0;
14104 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14105 for(
MInt j = 0; j < noAzimuthalWindowCells(i); j++) {
14106 if(refinedWindows[cnt] > 0) {
14107 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14108 refineChildIds[cnt * m_maxNoChilds + child] = windowChildIds[windowRefineCntTotal * m_maxNoChilds + child];
14110 windowRefineCntTotal++;
14112 auto it = refineChildIds.
begin() + (cnt * m_maxNoChilds);
14113 fill(it, it + m_maxNoChilds, -1);
14119 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14120 mpi_send_req[i] = MPI_REQUEST_NULL;
14121 mpi_recv_req[i] = MPI_REQUEST_NULL;
14126 haloChildIds.
fill(-2);
14127 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14128 if(haloRefineCnt[i] > 0) {
14129 MInt bufSize = m_maxNoChilds * haloRefineCnt[i];
14130 MPI_Irecv(&haloChildIds[cnt], bufSize, MPI_DOUBLE, m_azimuthalNghbrDomains[i], 2, mpiComm(), &mpi_recv_req[i],
14131 AT_,
"haloChildIds[cnt]");
14137 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14138 if(windowRefineCnt[i] > 0) {
14139 MInt bufSize = m_maxNoChilds * windowRefineCnt[i];
14140 MPI_Isend(&windowChildIds[cnt], bufSize, MPI_DOUBLE, m_azimuthalNghbrDomains[i], 2, mpiComm(), &mpi_send_req[i],
14141 AT_,
"windowChildIds[cnt]");
14146 MPI_Waitall(noAzimuthalNeighborDomains(), &mpi_recv_req[0], MPI_STATUSES_IGNORE, AT_);
14147 MPI_Waitall(noAzimuthalNeighborDomains(), &mpi_send_req[0], MPI_STATUSES_IGNORE, AT_);
14151 haloRefineCntTotal = 0;
14152 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14153 for(
MInt j = 0; j < noAzimuthalHaloCells(i); j++) {
14154 if(refineCandidates[cnt] > 0) {
14155 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14156 recvChildIds[cnt * m_maxNoChilds + child] = haloChildIds[haloRefineCntTotal * m_maxNoChilds + child];
14158 haloRefineCntTotal++;
14160 auto it = recvChildIds.
begin() + (cnt * m_maxNoChilds);
14161 fill(it, it + m_maxNoChilds, -2);
14173template <MInt nDim>
14175 unordered_multimap<MLong, MInt>& hilbertToLocal,
const MFloat* bbox,
14176 MInt*
const noHalos, vector<vector<MInt>>& halos,
14177 vector<vector<MLong>>& hilbertIds) {
14178 static constexpr MInt revDir[6] = {1, 0, 3, 2, 5, 4};
14179 const MFloat cellLength = cellLengthAtCell(cellId);
14186 for(
MInt i = 0; i < nDim; i++) {
14187 coords[i] = a_coordinate(cellId, i);
14189 coords[dir / 2] += ((dir % 2) == 0 ? -F1 : F1) * cellLength;
14191 if(!m_periodicCartesianDir[dir / 2] && (coords[dir / 2] < bbox[dir / 2] || coords[dir / 2] > bbox[nDim + dir / 2])) {
14195 MBool isPeriodic =
false;
14197 for(
MInt i = 0; i < nDim; i++) {
14198 dummyCoords[i] = coords[i];
14201 cartesianToCylindric(coords, coordsCyl);
14202 dxCyl = m_azimuthalAngle;
14204 if(coordsCyl[1] < m_azimuthalBbox.azimuthalBoundary(coords, -1) - MFloatEps) {
14206 rotateCartesianCoordinates(dummyCoords, -dxCyl);
14207 }
else if(coordsCyl[1] > m_azimuthalBbox.azimuthalBoundary(coords, 1) + MFloatEps) {
14209 rotateCartesianCoordinates(dummyCoords, dxCyl);
14210 }
else if(
approx(dxCyl, 0.5 * PI, pow(10, -12))) {
14211 if(m_azimuthalBbox.azimuthalCenter() > F0 && m_azimuthalBbox.azimuthalCenter() < 0.5 * PI) {
14212 if(dir / 2 == 1 && coords[1] < bbox[1]) {
14214 rotateCartesianCoordinates(dummyCoords, -dxCyl);
14216 if(dir / 2 == 2 && coords[2] < bbox[2]) {
14218 rotateCartesianCoordinates(dummyCoords, dxCyl);
14221 mTerm(1, AT_,
"Do some implementing!");
14225 if(!isPeriodic)
return -1;
14227 const MInt hilbertIndex = hilbertIndexGeneric(&dummyCoords[0]);
14230 while(hilbertIndex >= hilbertOffsets[ndom + 1]) {
14232 if(ndom == noDomains() - 1)
break;
14234 ASSERT(ndom > -1,
"");
14235 ASSERT(hilbertIndex >= hilbertOffsets[ndom] && hilbertIndex < hilbertOffsets[ndom + 1],
14236 to_string(hilbertIndex) +
" " + to_string(hilbertOffsets[ndom]) +
" " + to_string(hilbertOffsets[ndom + 1]));
14238 const MInt haloCellId = m_tree.size();
14241 for(
MInt i = 0; i < nDim; i++) {
14242 a_level(haloCellId) = a_level(cellId);
14245 for(
MInt i = 0; i < nDim; i++) {
14246 a_coordinate(haloCellId, i) = coords[i];
14249 hilbertToLocal.insert(make_pair(hilbertIndex, haloCellId));
14251 for(
MInt i = 0; i < m_noDirs; i++) {
14252 a_neighborId(haloCellId, i) = -1;
14254 for(
MInt i = 0; i < m_maxNoChilds; i++) {
14255 a_childId(haloCellId, i) = -1;
14257 a_parentId(haloCellId) = -1;
14259 a_neighborId(cellId, dir) = haloCellId;
14260 a_neighborId(haloCellId, revDir[dir]) = cellId;
14261 for(
MInt otherDir = 0; otherDir < m_noDirs; otherDir++) {
14262 if(otherDir / 2 == dir / 2)
continue;
14263 if(a_hasNeighbor(cellId, otherDir) == 0)
continue;
14264 MInt nghbrId = a_neighborId(cellId, otherDir);
14265 if(a_hasNeighbor(nghbrId, dir) > 0) {
14266 nghbrId = a_neighborId(nghbrId, dir);
14267 a_neighborId(nghbrId, revDir[otherDir]) = haloCellId;
14268 a_neighborId(haloCellId, otherDir) = nghbrId;
14272 for(
MInt ndir = 0; ndir < m_noDirs; ndir++) {
14273 if(a_hasNeighbor(haloCellId, ndir) > 0)
continue;
14274 for(
MInt i = 0; i < nDim; i++) {
14275 dummyCoords[i] = a_coordinate(haloCellId, i);
14277 dummyCoords[ndir / 2] += ((ndir % 2) == 0 ? -F1 : F1) * cellLength;
14278 for(
MInt i = 0; i < nDim; i++) {
14279 dcoords[i] = dummyCoords[i];
14281 MLong nghbrHilbertId = hilbertIndexGeneric(&dummyCoords[0]);
14283 auto range = hilbertToLocal.equal_range(nghbrHilbertId);
14284 for(
auto it = range.first; it != range.second; ++it) {
14286 for(
MInt i = 0; i < nDim; i++) {
14287 dist +=
POW2(a_coordinate(it->second, i) - dcoords[i]);
14290 if(
dist < 0.001 * cellLength) {
14291 if(nghbrId > -1) cerr <<
"duplicate " << hilbertToLocal.count(nghbrHilbertId) << endl;
14292 nghbrId = it->second;
14296 a_neighborId(nghbrId, revDir[ndir]) = haloCellId;
14297 a_neighborId(haloCellId, ndir) = nghbrId;
14299 for(
MInt i = 0; i < nDim; i++) {
14300 ASSERT(fabs(a_coordinate(nghbrId, i) - a_coordinate(haloCellId, i)) < cellLength * 1.0001,
"");
14306 for(
MInt i = 0; i < nDim; i++) {
14307 cartesianToCylindric(dummyCoords, coordsCyl);
14308 dxCyl = m_azimuthalAngle;
14309 if(coordsCyl[1] < m_azimuthalBbox.azimuthalBoundary(coords, -1)) {
14310 rotateCartesianCoordinates(dummyCoords, -dxCyl);
14311 }
else if(coordsCyl[1] > m_azimuthalBbox.azimuthalBoundary(coords, 1)) {
14312 rotateCartesianCoordinates(dummyCoords, dxCyl);
14315 nghbrHilbertId = hilbertIndexGeneric(&dummyCoords[0]);
14317 range = hilbertToLocal.equal_range(nghbrHilbertId);
14318 for(
auto it = range.first; it != range.second; ++it) {
14320 for(
MInt i = 0; i < nDim; i++) {
14321 dist +=
POW2(a_coordinate(it->second, i) - dcoords[i]);
14324 if(
dist < 0.001 * cellLength) {
14325 if(nghbrId > -1) cerr <<
"duplicate " << hilbertToLocal.count(nghbrHilbertId) << endl;
14326 nghbrId = it->second;
14330 a_neighborId(nghbrId, revDir[ndir]) = haloCellId;
14331 a_neighborId(haloCellId, ndir) = nghbrId;
14333 for(
MInt i = 0; i < nDim; i++) {
14334 ASSERT(fabs(a_coordinate(nghbrId, i) - a_coordinate(haloCellId, i)) < cellLength * 1.0001,
"");
14340 a_resetProperties(haloCellId);
14341 a_hasProperty(haloCellId, Cell::IsHalo) =
true;
14342 a_hasProperty(haloCellId, Cell::IsPeriodic) = isPeriodic;
14344 MInt idx = setAzimuthalNeighborDomainIndex(ndom, halos, hilbertIds);
14345 ASSERT(idx > -1,
"");
14346 halos[idx].push_back(haloCellId);
14347 hilbertIds[idx].push_back(hilbertIndex);
14357template <MInt nDim>
14359 vector<MLong>& haloChildIds,
14360 vector<MInt>& haloDomainIds,
14364 static constexpr MFloat cornerStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
14365 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
14366 MFloat childCoords[3] = {F0, F0, F0};
14367 MFloat coordsCyl[3] = {F0, F0, F0};
14368 MFloat dxCyl = m_azimuthalAngle;
14371 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
14372 if(a_level(cellId) != level + 1)
continue;
14373 if(a_isHalo(cellId))
continue;
14377 unordered_multimap<MLong, MInt> hilbertToLocal;
14378 hilbertToLocal.reserve(cellCnt * 1.5);
14380 MLong minHilbertIndex = std::numeric_limits<MLong>::max();
14381 for(
MInt cellId = 0; cellId < m_tree.size(); cellId++) {
14382 if(a_isHalo(cellId))
continue;
14383 MLong hilbertId = hilbertIndexGeneric(&a_coordinate(cellId, 0), m_targetGridCenterOfGravity,
14384 m_targetGridLengthLevel0, m_minLevel);
14385 minHilbertIndex =
mMin(minHilbertIndex, hilbertId);
14386 if(a_level(cellId) != level + 1)
continue;
14388 hilbertIndexGeneric(&a_coordinate(cellId, 0), m_targetGridCenterOfGravity, m_targetGridLengthLevel0, level + 1);
14389 hilbertToLocal.insert(make_pair(hilbertId, cellId));
14391 MPI_Allgather(&minHilbertIndex, 1, MPI_LONG, &hilbertOffsets[0], 1, MPI_LONG, mpiComm(), AT_,
"minHilbertIndex",
14392 "hilbertOffsets[0]");
14393 hilbertOffsets[0] = 0;
14394 hilbertOffsets[noDomains()] = std::numeric_limits<MLong>::max();
14396 if(m_noHaloLayers != 2)
mTerm(1, AT_,
"Only working with noHaloLayers=2");
14399 noSndHilberts.
fill(0);
14401 shiftWindows.resize(noDomains());
14403 haloDomainIds.resize(m_maxNoChilds * noAzimuthalUnmappedHaloCells());
14404 fill(haloDomainIds.begin(), haloDomainIds.end(), -1);
14405 haloChildIds.resize(m_maxNoChilds * noAzimuthalUnmappedHaloCells());
14406 fill(haloChildIds.begin(), haloChildIds.end(), -1);
14408 MIntScratchSpace candidateMap(noAzimuthalUnmappedHaloCells(), AT_,
"candidateMap");
14409 candidateMap.
fill(-1);
14410 MLongScratchSpace candidateHilbertIds(m_maxNoChilds * noAzimuthalUnmappedHaloCells(), AT_,
"candidateHilbertIds");
14411 candidateHilbertIds.
fill(-1);
14412 MInt noRefineCandidates = 0;
14416 for(
MInt i = 0; i < noAzimuthalUnmappedHaloCells(); i++) {
14417 MInt cellId = azimuthalUnmappedHaloCell(i);
14418 if(a_level(cellId) != level)
continue;
14420 MBool refine =
false;
14421 const MInt counter = getAdjacentGridCells(cellId, nghbrList, (level - 1),
true);
14422 for(
MInt n = 0; n < counter; n++) {
14423 MInt nghbrId = nghbrList[n];
14424 if(nghbrId < 0)
continue;
14425 if(a_isHalo(nghbrId))
continue;
14426 if(a_noChildren(nghbrId) > 0) {
14437 candidateMap[noRefineCandidates] = i;
14439 MInt parentId = cellId;
14440 for(
MInt lvl = level; lvl > m_minLevel; lvl--) {
14441 parentId = a_parentId(parentId);
14445 cartesianToCylindric(&a_coordinate(parentId, 0), coordsCyl);
14446 MInt side = m_azimuthalBbox.azimuthalSide(coordsCyl[1]);
14448 MFloat hLength = F1B2 * cellLengthAtLevel(a_level(cellId));
14449 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14450 for(
MInt d = 0; d < nDim; d++) {
14451 childCoords[d] = a_coordinate(cellId, d) + cornerStencil[child][d] * F1B2 * hLength;
14453 rotateCartesianCoordinates(childCoords, side * dxCyl);
14456 hilbertIndexGeneric(childCoords, m_targetGridCenterOfGravity, m_targetGridLengthLevel0, m_minLevel);
14459 for(
MInt d = 0; d < noDomains(); d++) {
14460 if(hilbertOffsets[d + 1] > hilbertId) {
14466 hilbertId = hilbertIndexGeneric(childCoords, m_targetGridCenterOfGravity, m_targetGridLengthLevel0, level + 1);
14468 haloDomainIds[i * m_maxNoChilds + child] = dom;
14469 candidateHilbertIds[noRefineCandidates * m_maxNoChilds + child] = hilbertId;
14470 noSndHilberts[dom]++;
14472 noRefineCandidates++;
14474 fill(&haloChildIds[i * m_maxNoChilds], &haloChildIds[i * m_maxNoChilds] + m_maxNoChilds, -2);
14482 for(
MInt d = 0; d < noDomains(); d++) {
14483 sndOffsets[d + 1] = sndOffsets[d] + noSndHilberts[d];
14484 noSndHilberts[d] = 0;
14487 MLongScratchSpace sndHilbertIds(m_maxNoChilds * noRefineCandidates, AT_,
"sndHilbertIds");
14488 for(
MInt i = 0; i < noRefineCandidates; i++) {
14489 MInt candidateId = candidateMap[i];
14490 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14491 MInt dom = haloDomainIds[candidateId * m_maxNoChilds + child];
14492 sndHilbertIds[sndOffsets[dom] + noSndHilberts[dom]] = candidateHilbertIds[i * m_maxNoChilds + child];
14493 noSndHilberts[dom]++;
14499 MPI_Alltoall(&noSndHilberts[0], 1, MPI_INT, &noRcvHilberts[0], 1, MPI_INT, mpiComm(), AT_,
"noSndHilberts[0]",
14500 "noRcvHilberts[0]");
14503 MInt rcvHilbertsTotal = 0;
14506 for(
MInt d = 0; d < noDomains(); d++) {
14507 rcvOffsets[d + 1] = rcvOffsets[d] + noRcvHilberts[d];
14508 rcvHilbertsTotal += noRcvHilberts[d];
14514 sendReq.
fill(MPI_REQUEST_NULL);
14516 for(
MInt i = 0; i < noDomains(); i++) {
14517 if(noSndHilberts[i] == 0)
continue;
14519 &sendReq[i], AT_,
"sndHilbertIds[sndOffsets[i]");
14522 for(
MInt i = 0; i < noDomains(); i++) {
14523 if(noRcvHilberts[i] == 0)
continue;
14525 MPI_STATUS_IGNORE, AT_,
"rcvHilbertIds[rcvOffsets[i]]");
14528 for(
MInt i = 0; i < noDomains(); i++) {
14529 if(noSndHilberts[i] == 0)
continue;
14530 MPI_Wait(&sendReq[i], MPI_STATUSES_IGNORE, AT_);
14535 for(
MInt i = 0; i < noDomains(); i++) {
14536 for(
MInt j = 0; j < noRcvHilberts[i]; j++) {
14537 MLong hilbertId = rcvHilbertIds[rcvOffsets[i] + j];
14539 MInt windowId = -1;
14540 auto range = hilbertToLocal.equal_range(hilbertId);
14541 for(
auto it = range.first; it != range.second; ++it) {
14542 if(!a_hasProperty(it->second, Cell::IsPeriodic) && !a_hasProperty(it->second, Cell::IsHalo)) {
14543 windowId = it->second;
14546 ASSERT(windowId > -2, to_string(windowId) +
" " + to_string(m_noInternalCells));
14548 if(windowId > -1) {
14549 rcvHilbertIds[rcvOffsets[i] + j] = a_globalId(windowId);
14550 shiftWindows[i].push_back(rcvHilbertIds[rcvOffsets[i] + j]);
14552 rcvHilbertIds[rcvOffsets[i] + j] = -1;
14558 sendReq.
fill(MPI_REQUEST_NULL);
14560 for(
MInt i = 0; i < noDomains(); i++) {
14561 if(noRcvHilberts[i] == 0)
continue;
14563 &sendReq[i], AT_,
"rcvHilbertIds[rcvOffsets[i]]");
14566 for(
MInt i = 0; i < noDomains(); i++) {
14567 if(noSndHilberts[i] == 0)
continue;
14569 MPI_STATUS_IGNORE, AT_,
"sndHilbertIds[sndOffsets[i]");
14572 for(
MInt i = 0; i < noDomains(); i++) {
14573 if(noRcvHilberts[i] == 0)
continue;
14574 MPI_Wait(&sendReq[i], MPI_STATUSES_IGNORE, AT_);
14577 for(
MInt d = 0; d < noDomains(); d++) {
14578 noSndHilberts[d] = 0;
14581 for(
MInt i = 0; i < noRefineCandidates; i++) {
14582 MInt candidateId = candidateMap[i];
14583 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14584 MInt dom = haloDomainIds[candidateId * m_maxNoChilds + child];
14585 haloChildIds[candidateId * m_maxNoChilds + child] = sndHilbertIds[sndOffsets[dom] + noSndHilberts[dom]++];
14594template <MInt nDim>
14601 m_log <<
"checkWindowHaloConsistency azimuthal... ";
14608 MIntScratchSpace noWindowCellsRecv(std::max(1, noAzimuthalNeighborDomains()), AT_,
"noWindowCellsRecv");
14609 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
14610 noWindowCellsRecv[d] = -1;
14612 azimuthalNeighborDomain(d), mpiComm(), &recvRequests[d], AT_,
"noWindowCellsRecv[d]");
14617 MIntScratchSpace noWindowCellsSend(std::max(1, noAzimuthalNeighborDomains()), AT_,
"noWindowCellsSend");
14618 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
14619 noWindowCellsSend[d] = noAzimuthalWindowCells(d);
14621 &sendRequests[d], AT_,
"noWindowCellsSend[d]");
14625 MPI_Waitall(noAzimuthalNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
14626 MPI_Waitall(noAzimuthalNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
14629 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
14630 if(noWindowCellsRecv[d] != noAzimuthalHaloCells(d)) {
14631 TERMM(1,
"Cartesian Grid : Number of azimuthal window cells from domain " + to_string(azimuthalNeighborDomain(d))
14632 +
" does not match local number of azimuthal halo cells; window: " + to_string(noWindowCellsRecv[d])
14633 +
" ,halo: " + to_string(noAzimuthalHaloCells(d)));
14641 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
14642 const MInt totalNoWindowCellsRecv = accumulate(noWindowCellsRecv.
begin(), noWindowCellsRecv.
end(), 0);
14644 MIntScratchSpace windowCellsRecv(max(1, totalNoWindowCellsRecv), AT_,
"windowCellsRecv");
14645 fill(windowCellsRecv.
begin(), windowCellsRecv.
end(), -1);
14646 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
14647 if(noAzimuthalHaloCells(d) > 0) {
14649 azimuthalNeighborDomain(d), azimuthalNeighborDomain(d), mpiComm(), &recvRequests[d], AT_,
14650 "windowCellsRecv[offset]");
14652 offset += noAzimuthalHaloCells(d);
14656 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
14657 const MInt totalNoWindowCellsSend = accumulate(noWindowCellsSend.
begin(), noWindowCellsSend.
end(), 0);
14658 MIntScratchSpace windowCellsSend(max(1, totalNoWindowCellsSend), AT_,
"windowCellsSend");
14660 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
14661 for(
MInt c = 0; c < noWindowCellsSend[d]; c++) {
14662 TERMM_IF_NOT_COND(a_hasProperty(azimuthalWindowCell(d, c), Cell::IsWindow),
"not a window cell");
14663 windowCellsSend[offset + c] = a_globalId(azimuthalWindowCell(d, c));
14665 if(noAzimuthalWindowCells(d) > 0) {
14667 azimuthalNeighborDomain(d), domainId(), mpiComm(), &sendRequests[d], AT_,
"windowCellsSend[offset]");
14669 offset += noAzimuthalWindowCells(d);
14673 MPI_Waitall(noAzimuthalNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
14674 MPI_Waitall(noAzimuthalNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
14677 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
14678 for(
MInt c = 0; c < noAzimuthalHaloCells(d); c++) {
14679 const MInt cellId = azimuthalHaloCell(d, c);
14680 TERMM_IF_NOT_COND(a_isHalo(cellId),
"not a halo cell");
14681 const MInt globalId = a_globalId(cellId);
14683 if(windowCellsRecv[offset + c] != globalId && !(a_hasProperty(cellId, Cell::IsPeriodic) && globalId == -1)) {
14684 TERMM(1,
"Global id of window cell " + to_string(c) +
" from domain " + to_string(azimuthalNeighborDomain(d))
14685 +
" does not match local halo cell gobal id (" + to_string(windowCellsRecv[offset + c]) +
" vs. "
14686 + to_string(a_globalId(azimuthalHaloCell(d, c))) +
")");
14689 offset += noAzimuthalHaloCells(d);
14692 m_log <<
"done" << std::endl;
14702template <MInt nDim>
14706 MInt maxLvl =
mMin(m_maxRfnmntLvl, m_maxLevel);
14707 for(
MInt level = m_maxUniformRefinementLevel; level < maxLvl; level++) {
14708 for(
MInt i = 0; i < noAzimuthalNeighborDomains(); i++) {
14709 for(
MInt j = 0; j < (signed)m_azimuthalHaloCells[i].size(); j++) {
14710 MInt cellId = m_azimuthalHaloCells[i][j];
14711 if(a_level(cellId) != level)
continue;
14712 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
14713 if(m_tree.solver(cellId, solver)) {
14714 MBool noRefine =
false;
14715 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14716 MInt childId = a_childId(cellId, child);
14717 if(childId == -1)
continue;
14718 if(!m_tree.solver(childId, solver)) {
14724 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14725 MInt childId = a_childId(cellId, child);
14726 if(childId == -1)
continue;
14727 m_tree.solver(childId, solver) =
false;
14731 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14732 MInt childId = a_childId(cellId, child);
14733 if(childId == -1)
continue;
14734 m_tree.solver(childId, solver) =
false;
14742 for(
MInt i = 0; i < (signed)m_azimuthalUnmappedHaloCells.size(); i++) {
14743 MInt cellId = m_azimuthalUnmappedHaloCells[i];
14744 if(a_level(cellId) != level)
continue;
14745 for(
MInt solver = 0; solver < treeb().noSolvers(); solver++) {
14746 if(m_tree.solver(cellId, solver)) {
14747 MBool noRefine =
false;
14748 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14749 MInt childId = a_childId(cellId, child);
14750 if(childId == -1)
continue;
14751 if(!m_tree.solver(childId, solver)) {
14757 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14758 MInt childId = a_childId(cellId, child);
14759 if(childId == -1)
continue;
14760 m_tree.solver(childId, solver) =
false;
14764 for(
MInt child = 0; child < m_maxNoChilds; child++) {
14765 MInt childId = a_childId(cellId, child);
14766 if(childId == -1)
continue;
14767 m_tree.solver(childId, solver) =
false;
14779template <MInt nDim>
14783 TERMM_IF_COND((
signed)m_windowLayer_.size() < noNeighborDomains(), text);
14785 for(
MInt d = 0; d < noNeighborDomains(); ++d) {
14786 for(
const auto item : m_windowLayer_[d]) {
14787 const MInt cellId = item.first;
14788 TERMM_IF_NOT_COND(cellId > -1 && cellId < m_tree.size(),
"");
14789 TERMM_IF_COND(item.second.all(),
"This entry is unnecessary!");
14791 for(
MInt solver = 0; solver < treeb().noSolvers(); ++solver) {
14792 TERMM_IF_COND(item.second.get(solver) <= m_noSolverHaloLayers[solver]
14793 && !m_tree.solver(cellId, solver),
14800 for(
MInt i = 0; i < noNeighborDomains(); i++) {
14801 std::set<MInt> allWs(m_windowCells[i].begin(), m_windowCells[i].end());
14802 for(
MInt j = 0; j < (signed)m_windowCells[i].size(); j++) {
14803 const MInt cellId = m_windowCells[i][j];
14804 if(m_windowLayer_[i].find(cellId) == m_windowLayer_[i].end()) {
14806 ss <<
" domainId=" << domainId() <<
": i=" << i <<
" j=" << j <<
" cellId=" << cellId
14807 <<
" globalId=" << a_globalId(cellId) <<
" nghbrDom=" << m_nghbrDomains[i] << endl;
14808 TERMM(1, text + ss.str());
14813 std::set<std::pair<MInt, MInt>> del;
14814 for(
auto m : m_windowLayer_[i]) {
14815 if(allWs.find(m.first) == allWs.end()) {
14818 std::stringstream ss;
14819 ss << text <<
" d=" << domainId() <<
" nghbrDom=" << m_nghbrDomains[i] <<
"(" << i
14820 <<
") minLevel=" << m_minLevel <<
" cell_level=" << a_level(m.first) <<
" isHalo=" << a_isHalo(m.first)
14821 <<
" cellId=" << m.first <<
" cellLayer=" << m.second.get(0) <<
"|" << m.second.get(1)
14822 <<
" parentId=" << a_parentId(m.first) <<
" parentIsHalo=" << a_isHalo(std::max(0, (
int)a_parentId(m.first)))
14823 <<
" " << isSolverWindowCell(i, m.first, 0);
14824 TERMM(1, ss.str());
14827 for(
auto d : del) {
14828 m_windowLayer_[d.first].erase(m_windowLayer_[d.first].find(d.second));
14831 if(m_noPeriodicCartesianDirs == 0) TERMM_IF_NOT_COND(m_windowCells[i].size() == m_windowLayer_[i].size(), text);
MLong allocatedBytes()
Return the number of allocated bytes.
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
void refineCell(const MInt cellId, const MLong *const refineChildIds=nullptr, const MBool mayHaveChildren=false, const std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> > &=std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> >(), const std::bitset< maia::grid::tree::Tree< nDim >::maxNoSolvers()> refineFlag=std::bitset< maia::grid::tree::Tree< nDim >::maxNoSolvers()>(1ul))
MInt createAzimuthalHaloCell(const MInt, const MInt, const MLong *, std::unordered_multimap< MLong, MInt > &, const MFloat *, MInt *const, std::vector< std::vector< MInt > > &, std::vector< std::vector< MLong > > &)
Create a new azimuthal halo cell as neighbor of cellId in direction dir and find matching neighbor do...
void getAdjacentGridCells1d5(std::set< MInt > &, const MInt, const MInt, const MInt dimNext=-1, const MInt dimNextNext=-1, const uint_fast8_t childCodes=(uint_fast8_t)~0)
MBool hollowBoxSphereIntersection(const MFloat *bMin, const MFloat *bMax, const MFloat *const sphereCenter, MFloat const radius)
MInt findIndex(ITERATOR, ITERATOR, const U &)
Find index in array [first,last) with matching entry 'val'.
void tagActiveWindowsOnLeafLvl3(const MInt maxLevel, const MBool duringMeshAdaptation, const std::vector< std::function< void(const MInt)> > &=std::vector< std::function< void(const MInt)> >())
Don't touch this function, because you don't know what you are doing NOTE: Actually the most clever w...
void rotateCartesianCoordinates(MFloat *, MFloat)
Rotate caresian coordinates by angle. Azimuthal periodic center is used.
void restorePeriodicConnection()
Delete the Connection of periodic-Halo-Cells at the bounding box.
void calculateNoOffspringsAndWorkload(Collector< CELLTYPE > *input_cells, MInt input_noCells)
Caluclate the number of offsprings and the workload for each cell.
void checkWindowHaloConsistency(const MBool fullCheck=false, const MString a="")
Checks consistency of window/halo cells.
void tagAzimuthalUnmappedHaloCells(std::vector< std::vector< MLong > > &, std::vector< MLong > &, std::vector< MInt > &, MInt)
Tag azimuthal halo cells for refinement.
void computeGlobalIds()
Update number of internal cells, recalculate domain offsets, recalculate global ids for all internal ...
void meshAdaptation(std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt, const MInt)> > &, const std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> > &, const std::vector< std::function< void()> > &)
MInt ancestorPartitionCellId(const MInt cellId) const
Return the cell Id of the partition cell that has the given cellId as a descendant.
void loadGridFile(const MInt, const MInt)
Load grid from disk and setup communication.
void updateHaloCellCollectors()
Fill m_nghbrDomains, m_haloCells and m_windowCells with data from temporary buffers.
void determineNoPartitionCellsAndOffsets(MLong *const noPartitionCells, MLong *const partitionCellOffsets)
Determine the number of partition cells on each domain and the corresponding offsets.
MBool pointInLocalBoundingBox(const MFloat *coord)
Check if the given point lies in the local bounding box.
MInt globalIdToLocalId(const MLong &globalId, const MBool termIfNotExisting=false)
Global to local id mapping.
void savePartitionCellWorkloadsGridFile()
Update the partition cell workloads in the grid file.
void descendStoreGlobalId(MInt cellId, MInt &localCnt)
Recursively descend subtree to reset global id for internal cells.
MInt findContainingPartitionCell(const MFloat *const coord, const MInt solverId=-1, std::function< MFloat *(MInt, MFloat *const)> correctCellCoord=nullptr)
Return the cell Id of the partition cell containing the coords.
void meshAdaptationDefault(std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt, const MInt)> > &, const std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> > &, const std::vector< std::function< void()> > &)
Performs mesh adaptation and continuously updates the window/halo cells.
void tagActiveWindows(std::vector< MLong > &, MInt)
Flag m_noHaloLayers layers of halo cells adjacent to internal cells on this domain.
MLong hilbertIndexGeneric(const MFloat *const coords, const MFloat *const center, const MFloat length0, const MInt baseLevel) const
Return the hilbert index for the given coordinates in 2D/3D.
MBool intersectingWithLocalBoundingBox(MFloat *const center, MFloat const radius)
MBool pointWthCell(const std::array< MFloat, nDim > &coord, const MInt cellId, std::function< MFloat *(MInt, MFloat *const)> correctCellCoord=nullptr) const
void determinePartLvlAncestorHaloWindowCells(std::vector< std::vector< MInt > > &partLvlAncestorHaloCells, std::vector< std::vector< MInt > > &partLvlAncestorWindowCells)
Store partition level ancestor window/halo cells.
void tagActiveWindowsAtMinLevel(const MInt)
Actually the most clever way of tagging is to go from highest level to lower levels,...
void compactCells(const std::vector< std::function< void(const MInt, const MInt)> > &=std::vector< std::function< void(const MInt, const MInt)> >())
Removes all holes in the cell collector and moves halo cells to the back of the collector.
void computeLocalBoundingBox(MFloat *const bbox)
Compute the bounding box of all local cells.
MInt findNeighborDomainId(const MLong globalId)
void saveGrid(const MChar *, const std::vector< std::vector< MInt > > &, const std::vector< std::vector< MInt > > &, const std::vector< std::vector< MInt > > &, const std::vector< MInt > &, const std::vector< std::vector< MInt > > &, MInt *recalcIdTree=nullptr)
void exchangeNotInPlace(DATATYPE *exchangeVar, DATATYPE *recvMem)
communicates a variable from windows to halos but does not overwrite halo values. Window values are s...
void changeGlobalToLocalIds()
Change global child/neighbor/parent cell ids into local cell ids. Requires that m_globalToLocalId con...
void saveDonorGridPartition(const MString &gridMapFileName, const MString &gridPartitionFileName)
Create and store donor grid partition for volume-coupled simulations.
void balance(const MInt *const noCellsToReceiveByDomain, const MInt *const noCellsToSendByDomain, const MInt *const sortedCellId, const MLong *const offset, const MLong *const globalIdOffsets)
Balance the grid according to the given cell send/recv counts.
void setGridInputFilename(MBool=false)
Read grid file name from properties or restart files.
void createMinLevelExchangeCells()
Create window-halo-connectivity based on hilbertIndex matching for regular and periodic exchange cell...
MInt findContainingHaloCell(const MFloat *const coord, const MInt solverId, MInt domainId, MBool onlyPartitionCells, std::function< MFloat *(MInt, MFloat *const)> correctCellCoord=nullptr)
Return the cell id of the halo partition cell containing the coords.
void correctAzimuthalSolverBits()
Corrects solver bits on azimuthal halo cells Ensure that azimuthal halo cells have all children or ar...
void createHigherLevelExchangeCells_old(const MInt onlyLevel=-1, const std::vector< std::function< void(const MInt)> > &=std::vector< std::function< void(const MInt)> >())
Iteratively create window and halo cells on levels m_minLevel+1...m_maxLevel, starting from m_minLeve...
void createPaths()
Necessary for extractPointIdsFromGrid function.
void descendNoOffsprings(const MLong cellId, const MLong offset=0)
void generalExchange(MInt noVars, const MInt *vars, DATATYPE **exchangeVar, MInt noDomSend, MInt *domSend, const MInt *noCellsSendPerDom, const MInt *cellIdsSend, MInt noDomRecv, MInt *domRecv, const MInt *noCellsRecvPerDom, const MInt *cellIdsRecv)
void exchangeProperties()
Exchange properties of window/halo cells.
MBool coarsenCheck(const MInt cellId, const MInt solverId)
checks if the given cell's children may be removed
MBool boxSphereIntersection(const MFloat *bMin, const MFloat *bMax, const MFloat *const sphereCenter, MFloat const radius)
void propagateDistance(std::vector< MInt > &list, MIntScratchSpace &distMem, MInt dist)
propagates a given distance from a given list of cells on equal level neighbours
void savePartitionFile()
Save current grid partitioning to file.
void storeMinLevelCells(const MBool updateMinlevel=false)
Store cell ids of all min-level cells.
MInt intersectingWithHaloCells(MFloat *const center, MFloat const radius, MInt domainId, MBool onlyPartition)
void removeChilds(const MInt cellId)
removes the children of the given cell
MInt setNeighborDomainIndex(const MInt, std::vector< TA > &, std::vector< TB > &, std::vector< TC > &)
Find neighbor domain index or create new if not existing.
void setLevel()
Set minimum und maximum cell levels.
void setupWindowHaloCellConnectivity()
Create window and halo cell connectivity between domains.
void tagActiveWindows2_(std::vector< MLong > &, const MInt)
NOTE: Actually the most clever way of tagging is to go from highest level to lower levels,...
MInt getAdjacentGridCells5(const MInt, MInt *const, const MInt level=-1, const MBool diagonalNeighbors=true)
void cartesianToCylindric(const MFloat *, MFloat *)
Transform cartesian cell coordinate to cylindrcal coordinats using the / using the azimuthal periodic...
MInt intersectingWithPartitioncells(MFloat *const center, MFloat const radius)
MInt findContainingHaloPartitionCell(const MFloat *const coors, const MInt solverId=-1)
Return the cell id of the halo partition cell containing the coords.
MBool updatePartitionCells(MInt offspringThreshold, MFloat workloadThreshold)
Determine new partition cells (i.e. in/decrease the partition level shifts) and change the grid accor...
void meshAdaptationLowMem(std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt)> > &, const std::vector< std::function< void(const MInt, const MInt)> > &, const std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> > &, const std::vector< std::function< void()> > &)
Performs mesh adaptation and continuously updates the window/halo cells.
void propagationStep(MInt cellId, MInt dist, MInt *distMem, MInt endDist)
starts the propagation on a cell and continues calling the function for the neighbours
void setChildSolverFlag(const MInt cellId, const MInt solver, const std::function< MInt(const MFloat *, const MInt, const MInt)> &cellOutsideSolver)
void deletePeriodicConnection(const MBool=true)
Delete the Connection of periodic-Halo-Cells at the bounding box.
void partitionParallel(const MInt tmpCount, const MLong tmpOffset, const MFloat *const partitionCellsWorkload, const MLong *const partitionCellsGlobalId, const MFloat totalWorkload, MLong *partitionCellOffsets, MLong *globalIdOffsets, MBool computeOnlyPartition=false)
MInt createAdjacentHaloCell(const MInt, const MInt, const MLong *, std::unordered_multimap< MLong, MInt > &, const MFloat *, MInt *const, std::vector< std::vector< MInt > > &, std::vector< std::vector< MLong > > &)
Create a new halo cell (candidate) as neighbor of cellId in direction dir and find matching neighbor ...
void createGridMap(const MString &donorGridFileName, const MString &gridMapFileName)
Create file that contains mapping from donor to target cell.
MBool refineCheck(const MInt cellId, const MInt solverId, const std::vector< std::function< MInt(const MFloat *, const MInt, const MInt)> > &cellOutsideSolver)
checks if the given cell may be refined
MInt deleteCell(const MInt cellId)
Deletes a cell (without collector fragmentation) and returns new collector size.
void createGridSlice(const MString &axis, const MFloat intercept, const MString &fileName)
Overload method of createGridSlice to provide usage with or without return of cellIds which are in th...
void exchangeSolverBitset(std::bitset< N > *const data, const MBool defaultVal=false)
MInt findContainingLeafCell(const MFloat *coord, std::function< MFloat *(MInt, MFloat *const)> correctCellCoord=nullptr, const MInt solverId=-1)
Return the cell Id of the leaf cell containing the coords.
void computeLeafLevel()
Compute distance to leaf level.
void dumpCellData(const MString name)
Write the cell data of the local tree to some file for debugging purposes.
void checkAzimuthalWindowHaloConsistency()
Checks consistency of aimuthal window/halo cells.
void removeCell(const MInt cellId)
removes the children of the given cell
MInt getAdjacentGridCells(MInt, MIntScratchSpace &, MInt, MBool diagonalNeighbors=true)
Retrieves all direct and diagonal neighboring cells of the given cell on the child level if available...
void swapCells(const MInt cellId, const MInt otherId)
swap two cells; the window/halo cell arrays have to be update elsewhere for performance reasons
void createGlobalToLocalIdMapping()
Create the mapping from global to local cell ids.
void tagAzimuthalHigherLevelExchangeCells(std::vector< MLong > &, std::vector< MLong > &, MInt)
Tag azimuthal halo cells for refinement.
void gridSanityChecks()
Perform grid sanity checks.
void localToGlobalIds()
Convert parent ids, neighbor ids, and child ids from local to global cell ids.
void resetCell(const MInt &cellId)
Reset cell to default values.
CartesianGrid(MInt maxCells, const MFloat *const bBox, const MPI_Comm comm, const MString &fileName="")
void loadDonorGridPartition(const MLong *const partitionCellsId, const MInt noPartitionCells)
Return partition cell offsets based on grid partition file.
void updatePartitionCellInformation()
Update the partition cell local/global ids and the partition cell global offsets.
MInt setAzimuthalNeighborDomainIndex(const MInt, std::vector< std::vector< MInt > > &, std::vector< std::vector< MInt > > &)
Find azimuthal neighbor domain index or create new if not existing.
void createLeafCellMapping(const MInt donorSolverId, const MInt gridCellId, std::vector< MInt > &mappedLeafCells, MBool allChilds=false)
Identify all leaf cells of one solver which are mapped to a given grid cell.
void createHigherLevelExchangeCells(const MInt onlyLevel=-1, const MBool duringMeshAdaptation=false, const std::vector< std::function< void(const MInt)> > &=std::vector< std::function< void(const MInt)> >(), const std::vector< std::function< void(const MInt)> > &=std::vector< std::function< void(const MInt)> >(), const MBool forceLeafLvlCorrection=false)
Iteratively create window and halo cells on levels m_minLevel+1...m_maxLevel, starting from m_minLeve...
void loadGrid(const MString &fileName)
Load a grid file writen with saveGridDomainPar.
void checkWindowLayer(const MString a)
Checks variable m_windowLayer_.
void loadPartitionFile(const MString &partitionFileName, MLong *partitionCellOffsets)
Load a grid partitioning from a file.
static MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
MInt get(const MInt index) const
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
void fill(T val)
fill the scratch with a given value
Class that represents grid tree and contains all relevant per-node data.
static constexpr MInt maxNoSolvers()
Return maximum number of supported solvers.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool fileExists(const MString &fileName)
Returns true if the file fileName exists, false otherwise.
MBool isApproxInt(const T &, const T)
constexpr Real POW2(const Real x)
MBool approx(const T &, const U &, const T)
constexpr T mMin(const T &x, const T &y)
MInt ipow(MInt base, MInt exp)
Integer exponent function for non-negative exponents.
constexpr T mMax(const T &x, const T &y)
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
MInt globalNoDomains()
Return global number of domains.
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
std::basic_string< char > MString
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
int MPI_Comm_free(MPI_Comm *comm, const MString &name, const MString &varname)
same as MPI_Comm_free, but updates the number of MPI communicators
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm, const MString &name, const MString &varname)
same as MPI_Comm_create, but updates the number of MPI communicators
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group *newgroup, const MString &name)
same as MPI_Group_incl
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group, const MString &name, const MString &varname)
same as MPI_Comm_group
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoall
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
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
int MPI_Group_free(MPI_Group *group, const MString &name)
same as MPI_Group_free
void const MInt const MInt const MInt const MInt maxNoCells
constexpr std::underlying_type< GridCell >::type p(const GridCell property)
Converts property name to underlying integer value.
maia::grid::cell::BitsetType PropertyBitsetType
Underlying bitset type for property storage.
std::bitset< MAIA_MULTISOLVER_MAX_NO_SOLVERS > SolverBitsetType
Underlying bitset type for solver use storage (Note: If there are more solvers, change size here)
void partitionCellToGlobalOffsets(const IdType *const partitionCellOffsets, const IdType *const partitionCellToGlobalIds, const IdType noDomains, IdType *const globalIdOffsets)
Translates a list of partition cell offsets to global offsets.
WeightType optimalPartitioningSerial(const WeightType *const weights, const IdType noWeights, const IdType noPartitions, IdType *const offsets)
Serial algorithm to find the optimal (not ideal) partitioning with given workloads based on a probing...
void exchangeScattered(const std::vector< MInt > &nghbrDomains, std::vector< MInt > &sendDomainIndices, std::vector< U > &sendData, const MPI_Comm comm, std::vector< MInt > &recvOffsets, std::vector< U > &recvBuffer, const MInt noDat=1)
Generic exchange of data.
void communicateData(const DataType *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, DataType *const buffer)
Assemble given data in send buffer and communicate.
void exchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const, const MInt *const noWindowCells, const MInt **const windowCells, const MPI_Comm comm, const U *const data, U *const haloBuffer, const MInt noDat=1)
Generic exchange of data.
void exchangeBuffer(const MInt noExDomains, const MInt *const exDomainId, const MInt *const recvSize, const MInt *const sendSize, const MPI_Comm comm, U *const receiveBuffer, const U *const sendBuffer, const MInt noDat=1)
Generic exchange of data.
void communicateBitsetData(const std::bitset< N > *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, std::bitset< N > *const buffer)
void reverseExchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const haloCells, const MInt *const noWindowCells, const MInt **const, const MPI_Comm comm, const U *const data, U *const windowBuffer, const MInt noDat=1)
Generic reverse exchange of data.
void exchangeBitset(const std::vector< MInt > &nghbrDomains, const std::vector< std::vector< MInt > > &haloCellVec, const std::vector< std::vector< MInt > > &windowCellVec, const MPI_Comm comm, std::bitset< N > *const data, const MInt noCells, const MInt noDat=1)
Generic exchange of data.
Namespace for auxiliary functions/classes.
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
void logDuration_(const MFloat timeStart, const MString module, const MString comment, const MPI_Comm comm, const MInt domainId, const MInt noDomains)
Output the min/max/average duration of a code section over the ranks in a communicator Note: only use...