23 : m_solverId(solverId), m_grid(grid_), m_tree(solverId, grid_.treeb()), m_geometry(&geometry_) {
24 if(
raw().addSolverToGrid()) {
25 MBool useSolverGeometry =
false;
26 useSolverGeometry = Context::getSolverProperty<MBool>(
"useSolverGeometry",
solverId, AT_, &useSolverGeometry);
36 if(!
raw().paraViewPlugin()) {
40 TERMM(1,
"Error: property maxRfnmntLvl is smaller than the maxLevel in the grid for solver #"
46 const MInt testNoDomains = Context::getBasicProperty<MInt>(
"noDomains", AT_, 0);
53 cerr0 <<
"noDomain > number of used mpi ranks! Therefore, increasing maxNoCells: " <<
m_maxNoCells << std::endl;
61 : m_solverId(solverId), m_grid(grid_), m_tree(solverId, grid_.treeb()) {
64 if(!
raw().paraViewPlugin()) {
65 TERMM(1,
"This constructor should only be called by the ParaView plugin");
74 if(m_mpiComm != MPI_COMM_NULL && m_mpiComm != MPI_COMM_WORLD) {
92 updateParallelizationInfo();
101 m_tree.update(*
this);
107 if(!raw().paraViewPlugin()) {
119 updateParallelizationInfo();
127 m_tree.update(*
this);
140 m_tree.m_solver2grid.resize(solverSize, -1);
141 m_tree.m_grid2solver.resize(raw().treeb().size() + 1, -1);
144 m_tree.m_grid2solver[0] = -1;
153 m_tree.m_solver2grid.assign(raw().treeb().noNodesBySolver(solverId()), -1);
156 m_tree.m_solver2grid.assign(raw().treeb().noNodesBySolver(0), -1);
158 m_tree.m_grid2solver.assign(raw().treeb().size() + 1, -1);
159 m_tree.m_grid2solver[0] = -1;
168 if(azimuthalPeriodicity()) correctAzimuthalHaloCells();
172 m_tree.m_solver2grid.assign(raw().treeb().noNodesBySolver(solverId()), -1);
175 m_tree.m_solver2grid.assign(raw().treeb().noNodesBySolver(0), -1);
177 m_tree.m_grid2solver.assign(raw().treeb().size() + 1, -1);
180 if(m_tree.m_solver2grid.size() > 0) {
182 raw().treeb().nodesBySolver(solverId(), m_tree.m_solver2grid.data());
185 raw().treeb().nodesBySolver(0, m_tree.m_solver2grid.data());
190 for(
MInt cellId = 0; cellId < static_cast<MInt>(m_tree.m_solver2grid.size()); cellId++) {
191 const MInt gridCellId = m_tree.m_solver2grid[cellId];
192 m_tree.m_grid2solver[gridCellId + 1] = cellId;
202 m_noInternalCells = 0;
203 for(
MInt i = 0; i < raw().noInternalCells(); i++) {
204 m_noInternalCells += (m_tree.grid2solver(i) > -1);
208 if(m_mpiComm != MPI_COMM_NULL && m_mpiComm != MPI_COMM_WORLD) {
213 MIntScratchSpace noInternalCells_(raw().noDomains(), AT_,
"noInternalCells_");
214 noInternalCells_[raw().domainId()] = noInternalCells();
216 raw().mpiComm(), AT_,
"MPI_IN_PLACE",
"noInternalCells_[0]");
221 for(
MInt d = 0; d < raw().noDomains(); d++) {
222 if(noInternalCells_[d] > 0) {
223 domains[noDomains_] = d;
229 MPI_Group globalGroup, localGroup;
230 MPI_Comm_group(raw().mpiComm(), &globalGroup, AT_,
"globalGroup");
237 MPI_Group_incl(globalGroup, noDomains_, &domains[0], &localGroup, AT_);
243 MPI_Comm_create(raw().mpiComm(), localGroup, &m_mpiComm, AT_,
"m_mpiComm");
248 if(noDomains_ == raw().noDomains()) {
249 m_hasInactiveRanks =
false;
251 m_hasInactiveRanks =
true;
255 if(noInternalCells() > 0) {
257 MPI_Comm_rank(mpiComm(), &m_domainId);
258 MPI_Comm_size(mpiComm(), &m_noDomains);
260 if(noDomains() != noDomains_) {
261 TERMM(1,
"an error occurred while creating the solver-specific MPI communicator");
266 cout <<
"Solver " << solverId() <<
": Global domain " <<
globalDomainId()
267 <<
" is the root domain of a new solver-specific communicator with the following " << noDomains_
268 <<
" domain(s): " << domains[0];
269 for(
MInt i = 1; i < noDomains_; i++) {
270 cout <<
", " << domains[i];
283 m_noInternalCells = -1;
284 std::vector<MLong>().swap(m_domainOffsets);
285 std::vector<MInt>().swap(m_neighborDomains);
286 std::vector<MInt>().swap(m_neighborDomainIndex);
288 std::vector<std::vector<MInt>>().swap(m_windowCells);
289 std::vector<std::vector<MInt>>().swap(m_haloCells);
290 std::map<MInt, MInt>().swap(m_global2solver);
297 m_domainOffsets.assign(noDomains() + 1, -1);
299 m_domainOffsets[0] = bitOffset();
300 for(
MInt d = 1; d < noDomains() + 1; d++) {
301 m_domainOffsets[d] = m_domainOffsets[d - 1] + (
MLong)noInternalCells_[domains[d - 1]];
306 checkOffsetConsistency();
310 std::map<MInt, MInt>().swap(m_global2solver);
311 for(
MInt d = 0; d < noDomains(); d++) {
312 m_global2solver[domains[d]] = d;
316 for(
MInt d = 0; d < noDomains(); d++) {
317 ASSERT(m_global2solver[d] == d,
"");
323 std::map<MInt, MInt> neighborDomains;
324 for(
MInt d = 0; d < raw().noNeighborDomains(); d++) {
326 if(m_global2solver.count(raw().neighborDomain(d)) == 0) {
331 for(
MInt c = 0; c < raw().noWindowCells(d); c++) {
332 if((raw().haloMode() == 0 && m_tree.grid2solver(raw().windowCell(d, c)) > -1)
333 || (raw().haloMode() > 0 && m_tree.grid2solver(raw().windowCell(d, c)) > -1
334 && raw().isSolverWindowCell(d, raw().windowCell(d, c), solverId()))) {
335 const MInt position = neighborDomains.size();
336 neighborDomains[d] = position;
342 if(neighborDomains.count(d) > 0) {
347 for(
MInt c = 0; c < raw().noHaloCells(d); c++) {
348 if(m_tree.grid2solver(raw().haloCell(d, c)) > -1) {
349 const MInt position = neighborDomains.size();
350 neighborDomains[d] = position;
355 m_neighborDomains.assign(neighborDomains.size(), -1);
356 m_neighborDomainIndex.assign(noDomains(), -1);
357 for(
auto&& m : neighborDomains) {
359 m_neighborDomains[m.second] = raw().neighborDomain(m.first);
363 for(
MInt d = 0; d < noNeighborDomains(); d++) {
364 m_neighborDomains[d] = m_global2solver[m_neighborDomains[d]];
365 m_neighborDomainIndex[m_neighborDomains[d]] = d;
370 checkNeighborConsistency();
373 setupWindowHaloConnectivityOnLeafLvl(neighborDomains);
377 checkWindowHaloConsistency();
382 m_azimuthalNeighborDomains.clear();
383 if(azimuthalPeriodicity()) {
384 neighborDomains.clear();
389 for(
MInt d = 0; d < raw().noAzimuthalNeighborDomains(); d++) {
391 if(m_global2solver.count(raw().azimuthalNeighborDomain(d)) == 0) {
392 windowCnt += raw().noAzimuthalWindowCells(d);
393 haloCnt += raw().noAzimuthalHaloCells(d);
399 for(
MInt c = 0; c < raw().noAzimuthalWindowCells(d); c++) {
400 if(m_tree.grid2solver(raw().azimuthalWindowCell(d, c)) > -1 && m_isOutsideWindow[tmpCnt] ==
false) {
401 const MInt position = neighborDomains.size();
402 neighborDomains[d] = position;
407 windowCnt += raw().noAzimuthalWindowCells(d);
410 if(neighborDomains.count(d) > 0) {
411 haloCnt += raw().noAzimuthalHaloCells(d);
417 for(
MInt c = 0; c < raw().noAzimuthalHaloCells(d); c++) {
418 if(m_tree.grid2solver(raw().azimuthalHaloCell(d, c)) > -1 && m_isOutsideHalo[tmpCnt] ==
false) {
419 const MInt position = neighborDomains.size();
420 neighborDomains[d] = position;
425 haloCnt += raw().noAzimuthalHaloCells(d);
427 m_azimuthalNeighborDomains.assign(neighborDomains.size(), -1);
428 m_azimuthalNeighborDomainIndex.assign(noDomains(), -1);
429 for(
auto&& m : neighborDomains) {
431 m_azimuthalNeighborDomains[m.second] = raw().azimuthalNeighborDomain(m.first);
435 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
436 m_azimuthalNeighborDomains[d] = m_global2solver[m_azimuthalNeighborDomains[d]];
437 m_azimuthalNeighborDomainIndex[m_azimuthalNeighborDomains[d]] = d;
442 checkNeighborConsistencyAzimuthal();
445 m_azimuthalWindowCells.clear();
446 m_azimuthalWindowCells.resize(noAzimuthalNeighborDomains());
447 m_azimuthalHaloCells.clear();
448 m_azimuthalHaloCells.resize(noAzimuthalNeighborDomains());
449 m_azimuthalUnmappedHaloCells.clear();
450 m_azimuthalUnmappedHaloDomains.clear();
455 for(
MInt d = 0; d < raw().noAzimuthalNeighborDomains(); d++) {
456 if(m_global2solver.count(raw().azimuthalNeighborDomain(d)) == 0) {
457 windowCnt += raw().noAzimuthalWindowCells(d);
458 haloCnt += raw().noAzimuthalHaloCells(d);
463 const MInt oldDomainPosition = d;
464 const MInt newDomainPosition = m_azimuthalNeighborDomainIndex[m_global2solver[raw().azimuthalNeighborDomain(d)]];
465 if(newDomainPosition < 0) {
466 windowCnt += raw().noAzimuthalWindowCells(d);
467 haloCnt += raw().noAzimuthalHaloCells(d);
473 std::vector<MInt> windowCells;
474 windowCells.reserve(raw().noAzimuthalWindowCells(oldDomainPosition));
475 for(
MInt c = 0; c < raw().noAzimuthalWindowCells(oldDomainPosition); c++) {
476 const MInt windowCellId = m_tree.grid2solver(raw().azimuthalWindowCell(oldDomainPosition, c));
477 if(windowCellId > -1 && m_isOutsideWindow[tmpCnt] ==
false) {
478 windowCells.push_back(windowCellId);
482 m_azimuthalWindowCells[newDomainPosition] = windowCells;
483 windowCnt += raw().noAzimuthalWindowCells(d);
487 std::vector<MInt> haloCells;
488 haloCells.reserve(raw().noAzimuthalHaloCells(oldDomainPosition));
489 for(
MInt c = 0; c < raw().noAzimuthalHaloCells(oldDomainPosition); c++) {
490 const MInt haloCellId = m_tree.grid2solver(raw().azimuthalHaloCell(oldDomainPosition, c));
491 if(haloCellId > -1) {
492 if(m_isOutsideHalo[tmpCnt] ==
false) {
493 haloCells.push_back(haloCellId);
495 m_azimuthalUnmappedHaloCells.push_back(haloCellId);
496 m_azimuthalUnmappedHaloDomains.push_back(m_global2solver[raw().azimuthalNeighborDomain(d)]);
501 m_azimuthalHaloCells[newDomainPosition] = haloCells;
502 haloCnt += raw().noAzimuthalHaloCells(d);
505 for(
MInt c = 0; c < raw().noAzimuthalUnmappedHaloCells(); c++) {
506 const MInt haloCellId = m_tree.grid2solver(raw().azimuthalUnmappedHaloCell(c));
507 if(haloCellId > -1) {
508 m_azimuthalUnmappedHaloCells.push_back(haloCellId);
509 m_azimuthalUnmappedHaloDomains.push_back(m_global2solver[raw().azimuthalUnmappedHaloDomain(c)]);
515 checkWindowHaloConsistencyAzimuthal();
567 std::vector<std::vector<MInt>>().swap(m_leafWindowCells);
568 m_leafWindowCells.resize(noNeighborDomains());
569 std::vector<std::vector<MInt>>().swap(m_leafHaloCells);
570 m_leafHaloCells.resize(noNeighborDomains());
575 std::vector<MInt>().swap(m_leafSendNeighborDomains);
576 std::vector<MInt>().swap(m_leafRecvNeighborDomains);
578 if(noNeighborDomains() == 0) {
585 sendReq.
fill(MPI_REQUEST_NULL);
586 recvReq.
fill(MPI_REQUEST_NULL);
589 MInt noWindowSums = 0;
590 for(
MInt d = 0; d < noNeighborDomains(); d++) {
591 noHaloSums += noHaloCells(d);
592 noWindowSums += noWindowCells(d);
598 receiveBuffer.
fill(-1);
602 for(
MInt i = 0; i < noNeighborDomains(); i++) {
603 std::vector<MInt> leafHaloCells;
604 leafHaloCells.reserve(noHaloCells(i));
606 for(
MInt j = 0; j < noHaloCells(i); j++) {
607 const MInt cellId = haloCell(i, j);
608 if(!tree().isLeafCell(cellId)) {
612 leafHaloCells.push_back(cellId);
613 sendBuffer[haloId++] = cellId;
615 m_leafHaloCells[i] = leafHaloCells;
616 if(!leafHaloCells.empty()) {
617 m_leafRecvNeighborDomains.push_back(i);
624 for(
MInt i = 0; i < noNeighborDomains(); i++) {
625 const MInt bufSize = noHaloCells(i);
629 MPI_Issend(&sendBuffer[sendOffset], bufSize, MPI_INT, neighborDomain(i), 0, mpiComm(), &sendReq[i], AT_,
630 "sendBuffer[sendOffset]");
631 sendOffset += bufSize;
635 MInt receiveOffset = 0;
636 for(
MInt i = 0; i < noNeighborDomains(); i++) {
637 const MInt bufSize = noWindowCells(i);
641 MPI_Recv(&receiveBuffer[receiveOffset], bufSize, MPI_INT, neighborDomain(i), 0, mpiComm(), MPI_STATUS_IGNORE, AT_,
642 "receiveBuffer[receiveOffset]");
643 receiveOffset += bufSize;
646 MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
651 for(
MInt i = 0; i < noNeighborDomains(); i++) {
652 std::vector<MInt> leafWindowCells;
653 leafWindowCells.reserve(noWindowCells(i));
655 for(
MInt j = 0; j < noWindowCells(i); j++) {
656 if(receiveBuffer[windowId++] != -1) {
657 ASSERT(windowCell(i, j) > -1,
"");
658 leafWindowCells.push_back(windowCell(i, j));
661 m_leafWindowCells[i] = leafWindowCells;
662 if(!leafWindowCells.empty()) {
663 m_leafSendNeighborDomains.push_back(i);
668 for(
MInt n = 0; n < noLeafRecvNeighborDomains(); n++) {
669 const MInt d = leafRecvNeighborDomain(n);
670 m_leafRecvSize += noLeafHaloCells(d);
673 for(
MInt n = 0; n < noLeafSendNeighborDomains(); n++) {
674 const MInt d = leafSendNeighborDomain(n);
675 m_leafSendSize += noLeafWindowCells(d);
689 m_tree.m_globalIds.assign(noCells(), -1);
692 const MInt firstGridMinCell = raw().minCell(0);
698 if(raw().a_hasProperty(firstGridMinCell, Cell::IsPartLvlAncestor)
699 && raw().a_hasProperty(firstGridMinCell, Cell::IsHalo)) {
700 descendStoreGlobalId(firstGridMinCell, localCnt);
705 for(
MInt i = std::max(0, std::min(1, localCnt)); i < raw().noMinCells(); i++) {
706 const MInt gridCellId = raw().minCell(i);
709 if(!solverFlag(gridCellId, solverId()))
continue;
710 if(raw().a_hasProperty(gridCellId, Cell::IsHalo))
continue;
711 descendStoreGlobalId(gridCellId, localCnt);
715 if(m_neighborDomains.size() > 0) {
716 mpi::exchangeData(m_neighborDomains, m_haloCells, m_windowCells, mpiComm(), m_tree.m_globalIds.data());
718 if(m_azimuthalNeighborDomains.size() > 0) {
719 mpi::exchangeData(m_azimuthalNeighborDomains, m_azimuthalHaloCells, m_azimuthalWindowCells, mpiComm(),
720 m_tree.m_globalIds.data());
727 for(
MInt i = 0; i < noInternalCells(); i++) {
728 ASSERT(m_tree.m_globalIds[i] == raw().a_globalId(i),
729 std::to_string(domainId()) +
" globalId mismatch: " + std::to_string(i) +
", "
730 + std::to_string(m_tree.m_globalIds[i]) +
" != " + std::to_string(raw().a_globalId(i)));
734 m_tree.createGlobalToLocalIdMapping();
744 if(!solverFlag(gridCellId, solverId()))
return;
747 if(!raw().a_hasProperty(gridCellId, Cell::IsHalo)) {
748 ASSERT(solverFlag(gridCellId, solverId()),
"");
749 ASSERT(localCnt < noInternalCells(),
"");
751 const MInt solverCellId = m_tree.grid2solver(gridCellId);
752 m_tree.m_globalIds[solverCellId] = m_domainOffsets[domainId()] + localCnt++;
754 ASSERT(m_tree.m_globalIds[solverCellId] >= m_domainOffsets[domainId()]
755 && m_tree.m_globalIds[solverCellId] < m_domainOffsets[domainId() + 1]
756 && m_tree.m_globalIds[solverCellId] < m_domainOffsets[domainId()] + noInternalCells(),
761 for(
MInt child = 0; child <
ipow(2, nDim); child++) {
762 if(raw().a_childId(gridCellId, child) < 0)
continue;
763 if(!solverFlag(gridCellId, solverId()))
continue;
764 descendStoreGlobalId(raw().a_childId(gridCellId, child), localCnt);
774 const MInt domain = raw().findNeighborDomainId(globalId, noDomains(), &m_domainOffsets[0]);
776 ASSERT(domain == raw().findNeighborDomainId(globalId),
"");
793 for(
MInt i = 0; i < noInternalCells(); i++) {
794 m_maxLevel = max(m_maxLevel, m_tree.level(i));
799 if(minLevel() < 0 || minLevel() > m_maxLevel) {
800 mTerm(1, AT_,
"Inconsistent min/max levels: " + to_string(minLevel()) +
"/" + to_string(m_maxLevel));
820 if(m_domainOffsets[0] != bitOffset()) {
821 TERMM(1,
"Domain offset for domain 0 must be equal to the 32-Bit-Offset (0)!");
825 for(
MInt i = 1; i < noDomains() + 1; i++) {
826 if(m_domainOffsets[i] <= m_domainOffsets[i - 1]) {
827 TERMM(1,
"Domain offsets are not strictly monotonically increasing");
833 copy(m_domainOffsets.begin(), m_domainOffsets.end(), rootOffsets.
begin());
835 for(
MInt i = 0; i < noDomains() + 1; i++) {
836 if(m_domainOffsets[i] != rootOffsets[i]) {
837 TERMM(1,
"Domain offsets differ from root domain");
842 for(
MInt i = 1; i < noDomains() + 1; i++) {
843 ASSERT(m_domainOffsets[i] == raw().domainOffset(i),
"");
863 if(!std::is_sorted(m_neighborDomains.begin(), m_neighborDomains.end())) {
864 TERMM(1,
"Neighbor domains are not sorted in ascending order.");
869 fill(isNeighborDomain.
begin(), isNeighborDomain.
end(), 0);
870 for(
MInt d = 0; d < noNeighborDomains(); d++) {
871 isNeighborDomain[neighborDomain(d)] = 1;
876 AT_,
"MPI_IN_PLACE",
"isNeighborDomain[0]");
879 for(
MInt d = 0; d < noNeighborDomains(); d++) {
880 if(!isNeighborDomain[neighborDomain(d)]) {
881 TERMM(1,
"Domain " + to_string(domainId()) +
" has domain " + to_string(neighborDomain(d))
882 +
" as a neighbor but not the other way around.");
897 std::vector<std::vector<MInt>>().swap(m_windowCells);
898 std::vector<std::vector<MInt>>().swap(m_haloCells);
901 if(raw().haloMode() > 0) {
903 m_windowCells.resize(noNeighborDomains());
904 m_haloCells.resize(noNeighborDomains());
905 for(
auto&& m : neighborDomains) {
907 const MInt oldDomainPosition = m.first;
908 const MInt newDomainPosition = m.second;
912 std::vector<MInt> windowCells;
913 windowCells.reserve(raw().noWindowCells(oldDomainPosition));
914 for(
MInt c = 0; c < raw().noWindowCells(oldDomainPosition); c++) {
915 const MInt windowCellId = m_tree.grid2solver(raw().windowCell(oldDomainPosition, c));
916 if(windowCellId > -1) {
917 ASSERT(m_tree.solver2grid(windowCellId) == raw().windowCell(oldDomainPosition, c),
918 std::to_string(raw().windowCell(oldDomainPosition, c)) +
"|" + std::to_string(windowCellId) +
"|"
919 + std::to_string(m_tree.solver2grid(windowCellId)));
920 if(raw().isSolverWindowCell(oldDomainPosition, raw().windowCell(oldDomainPosition, c), solverId())) {
921 windowCells.push_back(windowCellId);
925 m_windowCells[newDomainPosition] = windowCells;
932 std::vector<MInt> haloCells;
933 haloCells.reserve(raw().noHaloCells(oldDomainPosition));
934 for(
MInt c = 0; c < raw().noHaloCells(oldDomainPosition); c++) {
935 const MInt haloCellId = m_tree.grid2solver(raw().haloCell(oldDomainPosition, c));
936 ASSERT((haloCellId > -1) == raw().a_solver(raw().haloCell(oldDomainPosition, c), m_solverId),
937 "Shut down your PC!");
939 if(haloCellId > -1 && raw().a_solver(raw().haloCell(oldDomainPosition, c), m_solverId)) {
940 ASSERT(m_tree.solver2grid(haloCellId) == raw().haloCell(oldDomainPosition, c),
"");
941 haloCells.push_back(haloCellId);
944 m_haloCells[newDomainPosition] = haloCells;
945 ASSERT((
signed)m_haloCells[newDomainPosition].size()
946 == raw().noSolverHaloCells(oldDomainPosition, m_solverId,
true),
947 std::to_string(m_haloCells[newDomainPosition].size()) +
" "
948 + std::to_string(raw().noSolverHaloCells(oldDomainPosition, m_solverId,
true)));
952 m_windowCells.resize(noNeighborDomains());
953 m_haloCells.resize(noNeighborDomains());
954 for(
auto&& m : neighborDomains) {
956 const MInt oldDomainPosition = m.first;
957 const MInt newDomainPosition = m.second;
961 std::vector<MInt> windowCells;
962 windowCells.reserve(raw().noWindowCells(oldDomainPosition));
963 for(
MInt c = 0; c < raw().noWindowCells(oldDomainPosition); c++) {
964 const MInt windowCellId = m_tree.grid2solver(raw().windowCell(oldDomainPosition, c));
965 if(windowCellId > -1) {
966 windowCells.push_back(windowCellId);
969 m_windowCells[newDomainPosition] = windowCells;
972 std::vector<MInt> haloCells;
973 haloCells.reserve(raw().noHaloCells(oldDomainPosition));
974 for(
MInt c = 0; c < raw().noHaloCells(oldDomainPosition); c++) {
975 const MInt haloCellId = m_tree.grid2solver(raw().haloCell(oldDomainPosition, c));
976 if(haloCellId > -1) {
977 haloCells.push_back(haloCellId);
980 m_haloCells[newDomainPosition] = haloCells;
1006 MIntScratchSpace noWindowCellsRecv(max(1, noNeighborDomains()), AT_,
"noWindowCellsRecv");
1007 for(
MInt d = 0; d < noNeighborDomains(); d++) {
1008 noWindowCellsRecv[d] = -1;
1010 &recvRequests[d], AT_,
"noWindowCellsRecv[d]");
1015 MIntScratchSpace noWindowCellsSend(max(1, noNeighborDomains()), AT_,
"noWindowCellsSend");
1016 for(
MInt d = 0; d < noNeighborDomains(); d++) {
1017 noWindowCellsSend[d] = noWindowCells(d);
1019 &sendRequests[d], AT_,
"noWindowCellsSend[d]");
1023 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
1024 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
1027 for(
MInt d = 0; d < noNeighborDomains(); d++) {
1028 if(noWindowCellsRecv[d] != noHaloCells(d)) {
1029 TERMM(1,
"Solver " + to_string(m_solverId) +
" d=" + to_string(domainId())
1030 +
": Number of window cells from domain " + to_string(neighborDomain(d))
1031 +
" does not match local number of halo cells; window: " + to_string(noWindowCellsRecv[d])
1032 +
" ,halo: " + to_string(noHaloCells(d)));
1040 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
1041 const MInt totalNoWindowCellsRecv = accumulate(noWindowCellsRecv.
begin(), noWindowCellsRecv.
end(), 0);
1042 MIntScratchSpace windowCellsRecv(max(1, totalNoWindowCellsRecv), AT_,
"windowCellsRecv");
1043 fill(windowCellsRecv.
begin(), windowCellsRecv.
end(), -1);
1044 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
1045 if(noHaloCells(d) > 0) {
1047 neighborDomain(d), mpiComm(), &recvRequests[d], AT_,
"windowCellsRecv[offset]");
1049 offset += noHaloCells(d);
1053 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
1054 const MInt totalNoWindowCellsSend = accumulate(noWindowCellsSend.
begin(), noWindowCellsSend.
end(), 0);
1055 MIntScratchSpace windowCellsSend(max(1, totalNoWindowCellsSend), AT_,
"windowCellsSend");
1056 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
1057 for(
MInt c = 0; c < noWindowCellsSend[d]; c++) {
1058 windowCellsSend[offset + c] = raw().treeb().globalId(m_tree.solver2grid(windowCell(d, c)));
1060 if(noWindowCells(d) > 0) {
1062 mpiComm(), &sendRequests[d], AT_,
"windowCellsSend[offset]");
1064 offset += noWindowCells(d);
1068 MPI_Waitall(noNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
1069 MPI_Waitall(noNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
1072 for(
MInt d = 0, offset = 0; d < noNeighborDomains(); d++) {
1073 for(
MInt c = 0; c < noHaloCells(d); c++) {
1074 const MInt cellId = m_tree.solver2grid(haloCell(d, c));
1075 const MInt globalId = raw().treeb().globalId(cellId);
1077 if(windowCellsRecv[offset + c] != globalId
1078 && !(raw().treeb().hasProperty(cellId, Cell::IsPeriodic) && globalId == -1)) {
1079 TERMM(1,
"Global id of window cell " + to_string(c) +
" from domain " + to_string(neighborDomain(d))
1080 +
" does not match local halo cell gobal id (" + to_string(windowCellsRecv[offset + c]) +
" vs. "
1081 + to_string(raw().treeb().globalId(m_tree.solver2grid(haloCell(d, c)))) +
")");
1084 offset += noHaloCells(d);
1096 const MInt*
const polyDegs,
1097 const MInt*
const dataOffsets) {
1098 std::vector<MInt> dataSizeSend(noNeighborDomains(), 0);
1099 std::vector<MInt> dataSizeRecv(noNeighborDomains(), 0);
1100 MInt totalSendSize = 0;
1101 MInt totalRecvSize = 0;
1103 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1104 const MInt noWindowSend = noWindowCells(nghbrId);
1105 const MInt noHaloRecv = noHaloCells(nghbrId);
1108 MInt noDOFsSend = 0;
1109 for(
MInt i = 0; i < noWindowSend; i++) {
1110 noDOFsSend +=
ipow(polyDegs[windowCell(nghbrId, i)] + 1, nDim);
1112 dataSizeSend[nghbrId] = noDOFsSend;
1113 totalSendSize += noDOFsSend;
1116 MInt noDOFsRecv = 0;
1117 for(
MInt i = 0; i < noHaloRecv; i++) {
1118 noDOFsRecv +=
ipow(polyDegs[haloCell(nghbrId, i)] + 1, nDim);
1120 dataSizeRecv[nghbrId] = noDOFsRecv;
1121 totalRecvSize += noDOFsRecv;
1125 std::vector<MFloat> windowData(totalSendSize, std::numeric_limits<MFloat>::infinity());
1128 MInt sendBufCtr = 0;
1129 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1130 const MInt noWindowSend = noWindowCells(nghbrId);
1132 for(
MInt i = 0; i < noWindowSend; i++) {
1133 const MInt cellId = windowCell(nghbrId, i);
1134 const MInt noDOFs =
ipow(polyDegs[cellId] + 1, nDim);
1136 std::copy(&data[dataOffsets[cellId]], &data[dataOffsets[cellId] + noDOFs], &windowData[sendBufCtr]);
1138 sendBufCtr += noDOFs;
1142 if(sendBufCtr != totalSendSize) {
1143 TERMM(1,
"Send buffer counter does not match total send size.");
1147 std::vector<MFloat> haloData(totalRecvSize, std::numeric_limits<MFloat>::infinity());
1150 &dataSizeSend[0], &dataSizeRecv[0], &haloData[0]);
1153 MInt haloDataOffset = 0;
1154 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1155 const MInt noHaloRecv = noHaloCells(nghbrId);
1158 for(
MInt i = 0; i < noHaloRecv; i++) {
1159 const MInt haloCellId = haloCell(nghbrId, i);
1160 const MInt noDOFsHalo =
ipow(polyDegs[haloCellId] + 1, nDim);
1161 std::copy_n(&haloData[haloDataOffset], noDOFsHalo, &data[dataOffsets[haloCellId]]);
1162 haloDataOffset += noDOFsHalo;
1174 const MInt*
const noNodes1D,
1175 const MInt*
const dataOffsets) {
1176 std::vector<MInt> dataSizeSend(noNeighborDomains(), 0);
1177 std::vector<MInt> dataSizeRecv(noNeighborDomains(), 0);
1178 MInt totalSendSize = 0;
1179 MInt totalRecvSize = 0;
1181 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1182 const MInt noWindowSend = noWindowCells(nghbrId);
1183 const MInt noHaloRecv = noHaloCells(nghbrId);
1186 MInt noDOFsSend = 0;
1187 for(
MInt i = 0; i < noWindowSend; i++) {
1188 noDOFsSend +=
ipow(noNodes1D[windowCell(nghbrId, i)], nDim);
1190 dataSizeSend[nghbrId] = noDOFsSend;
1191 totalSendSize += noDOFsSend;
1194 MInt noDOFsRecv = 0;
1195 for(
MInt i = 0; i < noHaloRecv; i++) {
1196 noDOFsRecv +=
ipow(noNodes1D[haloCell(nghbrId, i)], nDim);
1198 dataSizeRecv[nghbrId] = noDOFsRecv;
1199 totalRecvSize += noDOFsRecv;
1203 std::vector<MFloat> windowData(totalSendSize, std::numeric_limits<MFloat>::infinity());
1206 MInt sendBufCtr = 0;
1207 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1208 const MInt noWindowSend = noWindowCells(nghbrId);
1210 for(
MInt i = 0; i < noWindowSend; i++) {
1211 const MInt cellId = windowCell(nghbrId, i);
1212 const MInt noDOFs =
ipow(noNodes1D[cellId], nDim);
1214 std::copy(&data[dataOffsets[cellId]], &data[dataOffsets[cellId] + noDOFs], &windowData[sendBufCtr]);
1216 sendBufCtr += noDOFs;
1220 if(sendBufCtr != totalSendSize) {
1221 TERMM(1,
"Send buffer counter does not match total send size.");
1225 std::vector<MFloat> haloData(totalRecvSize, std::numeric_limits<MFloat>::infinity());
1228 &dataSizeSend[0], &dataSizeRecv[0], &haloData[0]);
1231 MInt haloDataOffset = 0;
1232 for(
MInt nghbrId = 0; nghbrId < noNeighborDomains(); nghbrId++) {
1233 const MInt noHaloRecv = noHaloCells(nghbrId);
1236 for(
MInt i = 0; i < noHaloRecv; i++) {
1237 const MInt haloCellId = haloCell(nghbrId, i);
1238 const MInt noDOFsHalo =
ipow(noNodes1D[haloCellId], nDim);
1239 std::copy_n(&haloData[haloDataOffset], noDOFsHalo, &data[dataOffsets[haloCellId]]);
1240 haloDataOffset += noDOFsHalo;
1255 raw().cartesianToCylindric(coords, coordsCyl);
1257 side = raw().m_azimuthalBbox.azimuthalSide( coordsCyl[1]);
1271 m_tree.m_isCutOffCell.assign(noCells(), -1);
1289 for(
MInt i = 0; i < noCutOffDirections; i++) {
1290 const MInt dir = Context::getSolverProperty<MInt>(
"cutOffDirections", solverId(), AT_, i);
1292 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
1293 if(tree().hasNeighbor(cellId, dir) != 0)
continue;
1294 if(!tree().isLeafCell(cellId))
continue;
1295 if(tree().parent(cellId) > -1) {
1296 if(tree().hasNeighbor(tree().parent(cellId), dir) != 0)
continue;
1298 if(m_tree.m_isCutOffCell[cellId] < 0) {
1299 m_tree.m_isCutOffCell[cellId] = dir;
1300 isCutOff[cellId] = dir;
1305 m_tree.m_isCutOffCell[cellId] += dir;
1306 isCutOff[cellId] += dir;
1312 if(m_neighborDomains.size() > 0) {
1313 mpi::exchangeData(m_neighborDomains, m_haloCells, m_windowCells, mpiComm(), &isCutOff[0], 1);
1325 static constexpr MInt maxNoNeighbors = (nDim == 2) ? 8 : 26;
1327 m_log <<
"detecting neighbors for " << noCells() <<
" cells ... ";
1330 m_log <<
"allocating new array (" << noCells() <<
" entries)...";
1332 mAlloc(m_neighborList, noCells(), maxNoNeighbors,
"m_neighborList", -1, AT_);
1333 m_log <<
" allocated... ";
1335 static constexpr MInt twoPowers[6] = {1, 2, 4, 8, 16, 32};
1337 IF_CONSTEXPR(nDim == 2) {
1339#pragma omp parallel for
1341 for(
MInt id = 0;
id < noCells();
id++) {
1345 for(
MInt i = 0; i < raw().m_counter2D; i++) {
1349 if(tree().hasNeighbor(current, raw().m_paths2D[i][0]) == 1) {
1351 MInt currentGlobal = tree().neighbor(current, raw().m_paths2D[i][0]);
1353 MInt nCode = raw().m_neighborCode[twoPowers[raw().m_paths2D[i][0]]];
1355 m_neighborList[
id][nCode] = currentGlobal;
1357 if(currentGlobal == -1) {
1362 if(idsAreGlobal && raw().m_globalToLocalId.find(currentGlobal) == raw().m_globalToLocalId.end()) {
1367 current = idsAreGlobal ? raw().m_globalToLocalId.at(tree().neighbor(current, raw().m_paths2D[i][0]))
1368 : tree().neighbor(current, raw().m_paths2D[i][0]);
1371 if(tree().hasNeighbor(current, raw().m_paths2D[i][1]) == 1) {
1373 nCode = raw().m_neighborCode[twoPowers[raw().m_paths2D[i][0]] + twoPowers[raw().m_paths2D[i][1]]];
1374 m_neighborList[
id][nCode] = tree().neighbor(current, raw().m_paths2D[i][1]);
1382 if(raw().m_lbGridChecks) {
1383 MInt posPosMap[4] = {3, 2, 1, 0};
1386 MInt posDiagNghbrMap[4] = {6, 5, 7, 4};
1389 MInt parentPaths[4][2][2] = {{{0, 2}, {2, 0}}, {{1, 2}, {2, 1}}, {{0, 3}, {3, 0}}, {{1, 3}, {3, 1}}};
1390 MInt numberOfPossiblePaths = 2;
1393 if(tree().level(
id) > maxUniformRefinementLevel()) {
1394 MInt parent = tree().parent(
id);
1398 for(
MInt dim = 0; dim < 2; dim++) {
1399 if(tree().coordinate(
id, dim) < tree().coordinate(parent, dim)) {
1402 position +=
IPOW2(dim);
1407 for(
MInt j = 0; j < numberOfPossiblePaths; j++) {
1408 if(m_neighborList[
id][posDiagNghbrMap[position]] == -1) {
1410 if(tree().hasNeighbor(parent, parentPaths[position][j][0]) == 1) {
1411 MInt firstParentNghbrGlobal = tree().neighbor(parent, parentPaths[position][j][0]);
1412 if(firstParentNghbrGlobal == -1)
continue;
1414 && raw().m_globalToLocalId.find(firstParentNghbrGlobal) == raw().m_globalToLocalId.end())
1416 MInt firstParentNghbr =
1417 idsAreGlobal ? raw().m_globalToLocalId.at(tree().neighbor(parent, parentPaths[position][j][0]))
1418 : tree().neighbor(parent, parentPaths[position][j][0]);
1421 if(tree().hasNeighbor(firstParentNghbr, parentPaths[position][j][1]) == 1) {
1422 MInt secondParentNghbrGlobal = tree().neighbor(firstParentNghbr, parentPaths[position][j][1]);
1423 if(secondParentNghbrGlobal == -1)
continue;
1425 && raw().m_globalToLocalId.find(secondParentNghbrGlobal) == raw().m_globalToLocalId.end())
1427 MInt secondParentNghbr =
1429 ? raw().m_globalToLocalId.at(tree().neighbor(firstParentNghbr, parentPaths[position][j][1]))
1430 : tree().neighbor(firstParentNghbr, parentPaths[position][j][1]);
1431 if(tree().hasChildren(secondParentNghbr)) {
1432 if(tree().child(secondParentNghbr, posPosMap[position]) != -1) {
1433 MInt nCode = posDiagNghbrMap[position];
1434 m_neighborList[
id][nCode] = tree().child(secondParentNghbr, posPosMap[position]);
1448#pragma omp parallel for
1450 for(
MInt id = 0;
id < noCells();
id++) {
1454 for(
MInt i = 0; i < raw().m_counter3D; i++) {
1457 if(tree().hasNeighbor(current, raw().m_paths3D[i][0]) == 1) {
1459 MInt currentGlobal = tree().neighbor(current, raw().m_paths3D[i][0]);
1461 MInt nCode = raw().m_neighborCode[twoPowers[raw().m_paths3D[i][0]]];
1463 m_neighborList[
id][nCode] = currentGlobal;
1465 if(currentGlobal == -1) {
1470 if(idsAreGlobal && raw().m_globalToLocalId.find(currentGlobal) == raw().m_globalToLocalId.end()) {
1475 current = idsAreGlobal ? raw().m_globalToLocalId.at(tree().neighbor(current, raw().m_paths3D[i][0]))
1476 : tree().neighbor(current, raw().m_paths3D[i][0]);
1479 if(tree().hasNeighbor(current, raw().m_paths3D[i][1]) == 1) {
1481 currentGlobal = tree().neighbor(current, raw().m_paths3D[i][1]);
1483 nCode = raw().m_neighborCode[twoPowers[raw().m_paths3D[i][0]] + twoPowers[raw().m_paths3D[i][1]]];
1485 m_neighborList[
id][nCode] = currentGlobal;
1487 if(currentGlobal == -1) {
1492 if(idsAreGlobal && raw().m_globalToLocalId.find(currentGlobal) == raw().m_globalToLocalId.end()) {
1497 current = idsAreGlobal ? raw().m_globalToLocalId.at(tree().neighbor(current, raw().m_paths3D[i][1]))
1498 : tree().neighbor(current, raw().m_paths3D[i][1]);
1501 if(tree().hasNeighbor(current, raw().m_paths3D[i][2]) == 1) {
1504 nCode = raw().m_neighborCode[twoPowers[raw().m_paths3D[i][0]] + twoPowers[raw().m_paths3D[i][1]]
1505 + twoPowers[raw().m_paths3D[i][2]]];
1506 m_neighborList[
id][nCode] = tree().neighbor(current, raw().m_paths3D[i][2]);
1515 if(raw().m_lbGridChecks) {
1516 MInt posDiagNghbrMap[8][4] = {{6, 10, 14, 18}, {8, 12, 14, 22}, {7, 10, 16, 20}, {9, 12, 16, 24},
1517 {6, 11, 15, 19}, {8, 13, 15, 23}, {7, 11, 17, 21}, {9, 13, 17, 25}};
1520 MInt posPosMap[8][4] = {{3, 5, 6, 7}, {2, 4, 7, 6}, {1, 7, 4, 5}, {0, 6, 5, 4},
1521 {7, 1, 2, 3}, {6, 0, 3, 2}, {5, 3, 0, 1}, {4, 2, 1, 0}};
1525 MInt diagNghbrPathMap[20][4][3] = {
1526 {{2, 0, -1}, {0, 2, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{3, 0, -1}, {0, 3, -1}, {-1, -1, -1}, {-1, -1, -1}},
1527 {{2, 1, -1}, {1, 2, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{3, 1, -1}, {1, 3, -1}, {-1, -1, -1}, {-1, -1, -1}},
1528 {{4, 0, -1}, {0, 4, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{5, 0, -1}, {0, 5, -1}, {-1, -1, -1}, {-1, -1, -1}},
1529 {{4, 1, -1}, {1, 4, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{5, 1, -1}, {1, 5, -1}, {-1, -1, -1}, {-1, -1, -1}},
1530 {{4, 2, -1}, {2, 4, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{5, 2, -1}, {2, 5, -1}, {-1, -1, -1}, {-1, -1, -1}},
1531 {{4, 3, -1}, {3, 4, -1}, {-1, -1, -1}, {-1, -1, -1}}, {{5, 3, -1}, {3, 5, -1}, {-1, -1, -1}, {-1, -1, -1}},
1532 {{0, 2, 4}, {2, 0, 4}, {4, 2, 0}, {4, 0, 2}}, {{0, 2, 5}, {2, 0, 5}, {5, 0, 2}, {5, 2, 0}},
1533 {{0, 3, 4}, {3, 0, 4}, {4, 0, 3}, {4, 3, 0}}, {{0, 3, 5}, {3, 0, 5}, {5, 0, 3}, {5, 3, 0}},
1534 {{1, 2, 4}, {2, 1, 4}, {4, 1, 2}, {4, 2, 1}}, {{1, 2, 5}, {2, 1, 5}, {5, 1, 2}, {5, 2, 1}},
1535 {{1, 3, 4}, {3, 1, 4}, {4, 1, 3}, {4, 3, 1}}, {{1, 3, 5}, {3, 1, 5}, {5, 1, 3}, {5, 3, 1}}};
1538 if(tree().level(
id) > maxUniformRefinementLevel()) {
1539 MInt parent = tree().parent(
id);
1543 for(
MInt dim = 0; dim < nDim; dim++) {
1544 if(tree().coordinate(
id, dim) < tree().coordinate(parent, dim)) {
1547 position +=
IPOW2(dim);
1552 for(
MInt i = 0; i < 4; i++) {
1553 MInt neighbor = posDiagNghbrMap[position][i];
1556 if(m_neighborList[
id][neighbor] == -1) {
1560 for(
MInt j = 0; j < 4; j++) {
1562 if(diagNghbrPathMap[neighbor - 6][j][0] == -1)
continue;
1565 if(tree().hasNeighbor(parent, diagNghbrPathMap[neighbor - 6][j][0]) == 1) {
1566 MInt firstParentNghbrGlobal = tree().neighbor(parent, diagNghbrPathMap[neighbor - 6][j][0]);
1567 if(firstParentNghbrGlobal == -1)
continue;
1569 && raw().m_globalToLocalId.find(firstParentNghbrGlobal) == raw().m_globalToLocalId.end())
1571 MInt firstParentNghbr =
1573 ? raw().m_globalToLocalId.at(tree().neighbor(parent, diagNghbrPathMap[neighbor - 6][j][0]))
1574 : tree().neighbor(parent, diagNghbrPathMap[neighbor - 6][j][0]);
1577 if(tree().hasNeighbor(firstParentNghbr, diagNghbrPathMap[neighbor - 6][j][1]) == 1) {
1578 MInt secondParentNghbrGlobal =
1579 tree().neighbor(firstParentNghbr, diagNghbrPathMap[neighbor - 6][j][1]);
1580 if(secondParentNghbrGlobal == -1)
continue;
1582 && raw().m_globalToLocalId.find(secondParentNghbrGlobal) == raw().m_globalToLocalId.end())
1584 MInt secondParentNghbr =
1585 idsAreGlobal ? raw().m_globalToLocalId.at(
1586 tree().neighbor(firstParentNghbr, diagNghbrPathMap[neighbor - 6][j][1]))
1587 : tree().neighbor(firstParentNghbr, diagNghbrPathMap[neighbor - 6][j][1]);
1590 if(diagNghbrPathMap[neighbor - 6][j][2] != -1) {
1591 if(tree().hasNeighbor(secondParentNghbr, diagNghbrPathMap[neighbor - 6][j][2]) == 1) {
1592 MInt thirdParentNghbrGlobal =
1593 tree().neighbor(secondParentNghbr, diagNghbrPathMap[neighbor - 6][j][2]);
1594 if(thirdParentNghbrGlobal == -1)
continue;
1596 && raw().m_globalToLocalId.find(thirdParentNghbrGlobal) == raw().m_globalToLocalId.end())
1598 MInt thirdParentNghbr =
1599 idsAreGlobal ? raw().m_globalToLocalId.at(
1600 tree().neighbor(secondParentNghbr, diagNghbrPathMap[neighbor - 6][j][2]))
1601 : tree().neighbor(secondParentNghbr, diagNghbrPathMap[neighbor - 6][j][2]);
1602 if(tree().hasChildren(thirdParentNghbr)) {
1603 if(tree().child(thirdParentNghbr, posPosMap[position][i]) != -1) {
1604 MInt nCode = neighbor;
1605 m_neighborList[
id][nCode] = tree().child(thirdParentNghbr, posPosMap[position][i]);
1611 if(tree().hasChildren(secondParentNghbr)) {
1612 if(tree().child(secondParentNghbr, posPosMap[position][i]) != -1) {
1613 MInt nCode = neighbor;
1614 m_neighborList[
id][nCode] = tree().child(secondParentNghbr, posPosMap[position][i]);
1644 if(m_storeNghbrIds !=
nullptr) {
1647 mAlloc(m_storeNghbrIds, m_noDirs *
IPOW2(nDim) * noCells(),
"m_storeNghbrIds", -1, AT_);
1649 if(m_identNghbrIds !=
nullptr) {
1652 mAlloc(m_identNghbrIds, m_noDirs * noCells() + 1,
"m_identNghbrIds", -1, AT_);
1657 for(
MInt cellId = 0; cellId < noCells(); cellId++) {
1658 for(
MInt dirId = 0; dirId < m_noDirs; dirId++) {
1659 m_identNghbrIds[cellId * m_noDirs + dirId] = pos;
1661 if(!tree().isLeafCell(cellId))
continue;
1662 for(
MInt dirId = 0; dirId < m_noDirs; dirId++) {
1663 const MInt spaceId = dirId / 2;
1664 const MInt sideId = dirId % 2;
1665 const MInt nghbrSideId = (sideId + 1) % 2;
1669 m_identNghbrIds[cellId * m_noDirs + dirId] = pos;
1679 if(tree().hasNeighbor(cellId, dirId) > 0) {
1682 MInt nghbrId = tree().neighbor(cellId, dirId);
1683 const MInt nghbrLvl = tree().level(nghbrId);
1691 if(tree().isLeafCell(nghbrId)) {
1693 m_storeNghbrIds[pos] = nghbrId;
1700 MInt tempNghbrs[16];
1701 MInt tempNghbrs1[16];
1702 tempNghbrs[0] = nghbrId;
1703 MBool nghbrsFound =
false;
1710 while(nghbrsFound ==
false) {
1717 for(
MInt index = 0; index < maxIndex; index++) {
1719 ASSERT(index > -1 && index < 16,
"");
1720 nghbrId = tempNghbrs[index];
1731 for(
MInt childId = 0; childId <
IPOW2(nDim); childId++) {
1732 const MInt nghbrChildId = tree().child(nghbrId, childId);
1733 if(nghbrChildId < 0)
continue;
1734 if((tree().coordinate(nghbrChildId, spaceId) - tree().coordinate(nghbrId, spaceId))
1735 * ((
MFloat)nghbrSideId - 0.5)
1737 if(tree().isLeafCell(nghbrChildId)) {
1739 m_storeNghbrIds[pos] = nghbrChildId;
1748 cerr <<
"Large neighbor count " << k <<
" " << nghbrLvl <<
" " << tree().level(nghbrChildId)
1751 tempNghbrs1[k] = nghbrChildId;
1764 for(
MInt l = 0; l < k; l++) {
1765 ASSERT(l > -1 && l < 16,
"");
1766 tempNghbrs[l] = tempNghbrs1[l];
1773 MInt currentCellId = cellId;
1774 MBool nghbrExist =
false;
1777 while(nghbrExist ==
false) {
1778 const MInt parentId = tree().parent(currentCellId);
1780 if(parentId < 0 || parentId >= noCells())
break;
1785 if((tree().coordinate(currentCellId, spaceId) - tree().coordinate(parentId, spaceId)) * ((
float)sideId - 0.5)
1791 currentCellId = parentId;
1794 if(tree().hasNeighbor(currentCellId, dirId) > 0) {
1796 const MInt nghbrId = tree().neighbor(currentCellId, dirId);
1798 if(tree().isLeafCell(nghbrId)) {
1799 m_storeNghbrIds[pos] = nghbrId;
1807 m_identNghbrIds[noCells() * m_noDirs] = pos;
1821 ASSERT(cellId >= 0,
"ERROR: Invalid cellId!");
1822 ASSERT(m_storeNghbrIds !=
nullptr,
"");
1823 ASSERT(m_identNghbrIds !=
nullptr,
"");
1825 nghbrList.push_back(cellId);
1828 auto uniqueAdd = [&](
MInt newElement) {
1829 auto it = find(nghbrList.begin(), nghbrList.end(), newElement);
1830 if(it == nghbrList.end() && newElement >= 0) {
1831 nghbrList.push_back(newElement);
1840 static constexpr MInt diagDirs[4]{3, 2, 0, 1};
1841 for(
MInt dir = 0; dir < 2 * nDim; dir++) {
1843 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + dir]; j < m_identNghbrIds[2 * cellId * nDim + dir + 1]; j++) {
1844 const MInt nghbrId = m_storeNghbrIds[j];
1848 for(
MInt t = m_identNghbrIds[2 * nghbrId * nDim + diagDirs[dir]];
1849 t < m_identNghbrIds[2 * nghbrId * nDim + diagDirs[dir] + 1];
1851 const MInt diagNghbr = m_storeNghbrIds[t];
1852 uniqueAdd(diagNghbr);
1862 IF_CONSTEXPR(nDim == 3) {
1863 for(
MInt dirZ = 4; dirZ < 6; dirZ++) {
1864 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + dirZ]; j < m_identNghbrIds[2 * cellId * nDim + dirZ + 1]; j++) {
1865 const MInt nghbrIdZ = m_storeNghbrIds[j];
1866 for(
MInt dir = 0; dir < 4; dir++) {
1867 for(
MInt t = m_identNghbrIds[2 * nghbrIdZ * nDim + dir]; t < m_identNghbrIds[2 * nghbrIdZ * nDim + dir + 1];
1869 const MInt nghbrId = m_storeNghbrIds[t];
1872 for(
MInt v = m_identNghbrIds[2 * nghbrId * nDim + diagDirs[dir]];
1873 v < m_identNghbrIds[2 * nghbrId * nDim + diagDirs[dir] + 1];
1875 const MInt triDiagNghbrId = m_storeNghbrIds[v];
1876 uniqueAdd(triDiagNghbrId);
1896 ASSERT(layer > 0,
"ERROR: Invalid layer!");
1897 ASSERT(cellId >= 0,
"ERROR: Invalid cellId!");
1898 ASSERT(m_storeNghbrIds !=
nullptr,
"");
1899 ASSERT(m_identNghbrIds !=
nullptr,
"");
1902 auto uniqueAdd = [&](
MInt newElement) {
1903 auto it = find(nghbrList.begin(), nghbrList.end(), newElement);
1904 if(it == nghbrList.end() && newElement >= 0) {
1905 nghbrList.push_back(newElement);
1911 vector<MInt> tempNghbrCollection{};
1916 findDirectNghbrs(cellId, nghbrList);
1921 for(
MInt currEx = 1; currEx < layer; currEx++) {
1923 for(
auto& nghbr : nghbrList) {
1924 findDirectNghbrs(nghbr, tempNghbrCollection);
1928 for(
auto& nghbr : tempNghbrCollection) {
1929 if(uniqueAdd(nghbr) && currEx + 1 < layer) {
1931 nghbrList.push_back(nghbr);
1941 static constexpr MInt cornerIndices[8][3] = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1},
1942 {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};
1943 MFloat corner[3] = {0, 0, 0};
1944 MFloat cellHalfLength = raw().halfCellLength(gridId);
1949 for(
MInt dim = 0; dim < nDim; dim++) {
1950 corner[dim] = raw().a_coordinate(gridId, dim) + cornerIndices[i][dim] * cellHalfLength;
1953 if(!m_geometry->pointIsInside(corner)) {
1958 if(!m_geometry->pointIsInside2(corner)) {
1965 MInt outside =
false;
1978 MInt diagonalNeighbors) {
1979 MInt noDirs = 2 * nDim;
1981 std::array<std::array<MInt, 4>, nDim> tmpNghbrs;
1984 nghbrs.insert(cellId);
1985 for(
MInt layer = 1; layer <= noLayers; layer++) {
1986 set<MInt> nextLayer;
1987 for(
auto& nghbrId : nghbrs) {
1988 for(
MInt dir0 = 0; dir0 < noDirs; dir0++) {
1989 const MInt cnt0 = getNghbrCells(nghbrId, level, &tmpNghbrs[0][0], dir0);
1990 for(
MInt c0 = 0; c0 < cnt0; c0++) {
1991 nextLayer.insert(tmpNghbrs[0][c0]);
1993 if(diagonalNeighbors > 0) {
1994 for(
MInt dir1 = 0; dir1 < noDirs; dir1++) {
1995 if((dir1 / 2) == (dir0 / 2))
continue;
1996 const MInt cnt1 = getNghbrCells(tmpNghbrs[0][c0], level, &tmpNghbrs[1][0], dir1, dir0);
1997 for(
MInt c1 = 0; c1 < cnt1; c1++) {
1998 nextLayer.insert(tmpNghbrs[1][c1]);
2000 if(nDim == 3 && diagonalNeighbors == 2) {
2001 for(
MInt dir2 = 0; dir2 < noDirs; dir2++) {
2002 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
2003 const MInt cnt2 = getNghbrCells(tmpNghbrs[1][c1], level, &tmpNghbrs[2][0], dir2, dir1, dir0);
2004 for(
MInt c2 = 0; c2 < cnt2; c2++) {
2005 nextLayer.insert(tmpNghbrs[2][c2]);
2015 for(
MInt it : nextLayer) {
2019 nghbrs.erase(cellId);
2022 for(
MInt nghbr : nghbrs) {
2023 ASSERT(tree().level(nghbr) <= level + 1,
"");
2024 ASSERT(cnt < (
signed)adjacentCells.
size(), to_string(nghbrs.size()) +
" " + to_string(adjacentCells.
size()));
2025 adjacentCells[cnt] = nghbr;
2036 if(tree().hasNeighbor(cellId, dir0) > 0) {
2037 nghbrId0 = tree().neighbor(cellId, dir0);
2038 }
else if(tree().parent(cellId) > -1) {
2039 if(tree().hasNeighbor(tree().parent(cellId), dir0) > 0) {
2040 nghbrId0 = tree().neighbor(tree().parent(cellId), dir0);
2043 if(nghbrId0 < 0)
return 0;
2045 if(tree().noChildren(nghbrId0) > 0 && tree().level(nghbrId0) <= level) {
2046 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2047 if(!childCode[dir0][child])
continue;
2048 if(dir1 > -1 && !childCode[dir1][child])
continue;
2049 if(dir2 > -1 && !childCode[dir2][child])
continue;
2050 if(tree().child(nghbrId0, child) > -1) {
2051 nghbrs[count] = tree().child(nghbrId0, child);
2056 nghbrs[count] = nghbrId0;
2077 if(!std::is_sorted(m_azimuthalNeighborDomains.begin(), m_azimuthalNeighborDomains.end())) {
2078 TERMM(1,
"Neighbor domains are not sorted in ascending order.");
2083 fill(isNeighborDomain.
begin(), isNeighborDomain.
end(), 0);
2084 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
2085 isNeighborDomain[azimuthalNeighborDomain(d)] = 1;
2090 AT_,
"MPI_IN_PLACE",
"isNeighborDomain[0]");
2093 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
2094 if(!isNeighborDomain[azimuthalNeighborDomain(d)]) {
2095 TERMM(1,
"Domain " + to_string(domainId()) +
" has domain " + to_string(neighborDomain(d))
2096 +
" as a neighbor but not the other way around.");
2119 MIntScratchSpace noWindowCellsRecv(max(1, noAzimuthalNeighborDomains()), AT_,
"noWindowCellsRecv");
2120 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
2121 noWindowCellsRecv[d] = -1;
2123 azimuthalNeighborDomain(d), mpiComm(), &recvRequests[d], AT_,
"noWindowCellsRecv[d]");
2128 MIntScratchSpace noWindowCellsSend(max(1, noAzimuthalNeighborDomains()), AT_,
"noWindowCellsSend");
2129 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
2130 noWindowCellsSend[d] = noAzimuthalWindowCells(d);
2132 &sendRequests[d], AT_,
"noWindowCellsSend[d]");
2136 MPI_Waitall(noAzimuthalNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
2137 MPI_Waitall(noAzimuthalNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
2140 for(
MInt d = 0; d < noAzimuthalNeighborDomains(); d++) {
2141 if(noWindowCellsRecv[d] != noAzimuthalHaloCells(d)) {
2142 TERMM(1,
"Solver " + to_string(m_solverId) +
": Number of azimuthal window cells from domain "
2143 + to_string(azimuthalNeighborDomain(d))
2144 +
" does not match local number of azimuthal halo cells; window: " + to_string(noWindowCellsRecv[d])
2145 +
" ,halo: " + to_string(noAzimuthalHaloCells(d)));
2153 fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
2154 const MInt totalNoWindowCellsRecv = accumulate(noWindowCellsRecv.
begin(), noWindowCellsRecv.
end(), 0);
2155 MIntScratchSpace windowCellsRecv(max(1, totalNoWindowCellsRecv), AT_,
"windowCellsRecv");
2156 fill(windowCellsRecv.
begin(), windowCellsRecv.
end(), -1);
2157 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
2158 if(noAzimuthalHaloCells(d) > 0) {
2160 azimuthalNeighborDomain(d), azimuthalNeighborDomain(d), mpiComm(), &recvRequests[d], AT_,
2161 "windowCellsRecv[offset]");
2163 offset += noAzimuthalHaloCells(d);
2167 fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
2168 const MInt totalNoWindowCellsSend = accumulate(noWindowCellsSend.
begin(), noWindowCellsSend.
end(), 0);
2169 MIntScratchSpace windowCellsSend(max(1, totalNoWindowCellsSend), AT_,
"windowCellsSend");
2170 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
2171 for(
MInt c = 0; c < noWindowCellsSend[d]; c++) {
2172 windowCellsSend[offset + c] = raw().treeb().globalId(m_tree.solver2grid(azimuthalWindowCell(d, c)));
2174 if(noAzimuthalWindowCells(d) > 0) {
2176 azimuthalNeighborDomain(d), domainId(), mpiComm(), &sendRequests[d], AT_,
"windowCellsSend[offset]");
2178 offset += noAzimuthalWindowCells(d);
2182 MPI_Waitall(noAzimuthalNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
2183 MPI_Waitall(noAzimuthalNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
2186 for(
MInt d = 0, offset = 0; d < noAzimuthalNeighborDomains(); d++) {
2187 for(
MInt c = 0; c < noAzimuthalHaloCells(d); c++) {
2188 const MInt cellId = m_tree.solver2grid(azimuthalHaloCell(d, c));
2189 const MInt globalId = raw().treeb().globalId(cellId);
2190 if(windowCellsRecv[offset + c] != globalId) {
2191 TERMM(1,
"Global id of azimuthal window cell " + to_string(c) +
" from domain "
2192 + to_string(azimuthalNeighborDomain(d)) +
" does not match local azimuthal halo cell gobal id ("
2193 + to_string(windowCellsRecv[offset + c]) +
" vs. "
2194 + to_string(raw().treeb().globalId(m_tree.solver2grid(azimuthalHaloCell(d, c)))) +
")");
2197 offset += noAzimuthalHaloCells(d);
2206 if(raw().noAzimuthalNeighborDomains() > 0) {
2209 m_isOutsideWindow.resize(windowCnt);
2210 m_isOutsideHalo.resize(haloCnt);
2213 for(
MInt d = 0; d < raw().noAzimuthalNeighborDomains(); d++) {
2214 for(
MInt c = 0; c < raw().noAzimuthalWindowCells(d); c++) {
2215 const MInt gridWindowId = raw().azimuthalWindowCell(d, c);
2216 MBool outside = checkOutsideGeometry(gridWindowId);
2218 m_isOutsideWindow[cnt] =
true;
2220 m_isOutsideWindow[cnt] =
false;
2225 mpi::exchangeBuffer(raw().azimuthalNeighborDomains(), raw().azimuthalHaloCells(), raw().azimuthalWindowCells(),
2226 raw().mpiComm(), m_isOutsideWindow.data(), m_isOutsideHalo.data());
2229 for(
MInt d = 0; d < raw().noAzimuthalNeighborDomains(); d++) {
2230 for(
MInt c = 0; c < raw().noAzimuthalHaloCells(d); c++) {
2231 const MInt gridHaloId = raw().azimuthalHaloCell(d, c);
2232 ASSERT(raw().treeb().hasProperty(gridHaloId, Cell::IsPeriodic),
"");
2233 MBool outside = checkOutsideGeometry(gridHaloId);
2235 raw().treeb().solver(gridHaloId, solverId()) =
false;
2236 m_isOutsideHalo[cnt] =
true;
2238 if(!raw().treeb().solver(gridHaloId, solverId())) {
2239 if(m_isOutsideHalo[cnt]) {
2240 raw().treeb().solver(gridHaloId, solverId()) =
true;
2241 m_isOutsideHalo[cnt] =
true;
2243 m_isOutsideHalo[cnt] =
true;
2246 m_isOutsideHalo[cnt] =
false;
2252 mpi::exchangeBuffer(raw().azimuthalNeighborDomains(), raw().azimuthalWindowCells(), raw().azimuthalHaloCells(),
2253 raw().mpiComm(), m_isOutsideHalo.data(), m_isOutsideWindow.data());
2256 for(
MInt c = 0; c < raw().noAzimuthalUnmappedHaloCells(); c++) {
2257 const MInt gridHaloId = raw().azimuthalUnmappedHaloCell(c);
2258 ASSERT(raw().treeb().hasProperty(gridHaloId, Cell::IsPeriodic),
"");
2259 ASSERT(raw().a_globalId(gridHaloId) == -1,
"Unmapped grid halo cell " + std::to_string(gridHaloId)
2260 +
" globalId not -1: " + to_string(raw().a_globalId(gridHaloId)));
2261 MBool outside = checkOutsideGeometry(gridHaloId);
2263 raw().treeb().solver(gridHaloId, solverId()) =
false;
2267 for(
MInt c = 0; c < raw().noAzimuthalUnmappedHaloCells(); c++) {
2268 const MInt gridHaloId = raw().azimuthalUnmappedHaloCell(c);
2269 raw().a_isLeafCell(gridHaloId, solverId()) =
false;
2270 if(raw().treeb().solver(gridHaloId, solverId())) {
2271 raw().a_isLeafCell(gridHaloId, solverId()) =
2272 !raw().a_hasChildren(gridHaloId, solverId()) && !raw().a_hasProperty(gridHaloId, Cell::IsPartLvlAncestor);
2283 vector<MInt> levelCellId;
2285 getLocalSameLevelCellIds(levelCellId, level - 1);
2291 for(
auto& cellId : levelCellId) {
2292 const MInt noChilds = tree().noChildren(cellId);
2297 for(
MInt childId = 0; childId < noChilds; childId++) {
2298 const MInt noChilds2 = tree().noChildren(tree().child(cellId, childId));
2299 if(noChilds2 == 0) {
2303 for(
MInt childId2 = 0; childId2 < noChilds2; childId2++) {
2304 for(
MInt dimId = 0; dimId < nDim; dimId++) {
2305 const MInt childCellId2 = tree().child(tree().child(cellId, childId), childId2);
2309 value[tree().child(cellId, childId)][dimId] += value[childCellId2][dimId] * 1.0 / noChilds2;
2313 for(
MInt dimId = 0; dimId < nDim; dimId++) {
2314 value[cellId][dimId] += value[tree().child(cellId, childId)][dimId] * 1.0 / noChilds;
2318 for(
MInt childId = 0; childId < noChilds; childId++) {
2319 const MInt noChilds2 = tree().noChildren(tree().child(cellId, childId));
2320 for(
MInt childId2 = 0; childId2 < noChilds2; childId2++) {
2321 for(
MInt dimId = 0; dimId < nDim; dimId++) {
2322 const MInt childCellId2 = tree().child(tree().child(cellId, childId), childId2);
2324 value[childCellId2][dimId] = 0.4 * value[cellId][dimId] + 0.4 * value[tree().child(cellId, childId)][dimId]
2325 + 0.2 * value[childCellId2][dimId];
2329 for(
MInt dimId = 0; dimId < nDim; dimId++) {
2330 value[tree().child(cellId, childId)][dimId] = 0;
2334 for(
MInt dimId = 0; dimId < nDim; dimId++) {
2335 value[cellId][dimId] = 0;
2350 const MInt noLocalPartitionCells = localPartitionCellOffsets(1) - localPartitionCellOffsets(0);
2353 std::function<void(
MInt)> goDownAndPush = [&](
const MInt cellId) {
2354 const MInt cellLevel = tree().level(cellId);
2355 if(level == cellLevel) {
2356 levelCellId.push_back(cellId);
2358 for(
MInt childId = 0; childId < tree().noChildren(cellId); childId++) {
2359 const MInt childCellId = tree().child(cellId, childId);
2360 goDownAndPush(childCellId);
2366 for(
MInt i = 0; i < noLocalPartitionCells; i++) {
2367 const MInt partionCellId = localPartitionCellLocalIds(i);
2368 const MInt partionLevel = tree().level(partionCellId);
2369 if(partionLevel == level) {
2370 levelCellId.push_back(partionCellId);
2371 }
else if(partionLevel >= level) {
2373 TERMM(-1,
"ERROR: Invalid level!");
2376 if(!tree().hasChildren(partionCellId)) {
2381 for(
MInt childId = 0; childId < tree().noChildren(partionCellId); childId++) {
2382 const MInt partitionChildId = tree().child(partionCellId, childId);
2383 goDownAndPush(partitionChildId);
2393 if(tree().isLeafCell(parentId)) {
2394 levelChilds.push_back(parentId);
2398 for(
MInt child = 0; child < m_maxNoChilds; child++) {
2399 if(!tree().hasChild(parentId, child))
continue;
2400 const MInt childId = tree().child(parentId, child);
2401 getAllLeafChilds(childId, levelChilds);
2413 solverFlag.
fill(-1);
2415 for(
MInt gridId = 0; gridId < raw().noInternalCells(); gridId++) {
2416 if(raw().a_level(gridId) != raw().minLevel()) {
2419 MBool outside = checkOutsideGeometry(gridId);
2420 MInt flag = (!outside ? 1 : -1);
2421 solverFlag[gridId] = flag;
2422 std::vector<MInt> offsprings(raw().maxNoCells());
2423 raw().createLeafCellMapping(solverId(), gridId, offsprings,
true);
2424 for(
auto it = offsprings.begin(); it != offsprings.end(); it++) {
2425 solverFlag[*it] = flag;
2429 for(
MInt gridId = 0; gridId < raw().noInternalCells(); gridId++) {
2430 if(solverFlag[gridId] == 1) {
2431 raw().treeb().solver(gridId, solverId()) =
true;
2433 raw().treeb().solver(gridId, solverId()) =
false;
2440 for(
MInt gridId = raw().noInternalCells(); gridId < raw().maxNoCells(); gridId++) {
2441 if(solverFlag[gridId] == 1) {
2442 raw().treeb().solver(gridId, solverId()) =
true;
2454 if(m_partitionCellGlobalId !=
nullptr) {
2458 MLong localPartitionCellOffsetsGrid[3] = {
static_cast<MLong>(-1),
static_cast<MLong>(-1),
static_cast<MLong>(-1)};
2460 MBool useRestartOffsets = !raw().updatedPartitionCells();
2461 if(raw().m_localPartitionCellOffsetsRestart[2] < 0) useRestartOffsets =
false;
2463 if(useRestartOffsets) {
2464 for(
MInt i = 0; i < 3; i++) {
2465 localPartitionCellOffsetsGrid[i] = raw().m_localPartitionCellOffsetsRestart[i];
2468 for(
MInt i = 0; i < 3; i++) {
2469 localPartitionCellOffsetsGrid[i] = raw().localPartitionCellOffsets(i);
2473 mAlloc(m_partitionCellGlobalId, localPartitionCellOffsetsGrid[2],
"m_partitionCellGlobalId",
static_cast<MLong>(-1),
2476 MInt noLocalPartitionCellsGrid = localPartitionCellOffsetsGrid[1] - localPartitionCellOffsetsGrid[0];
2477 MInt noLocalPartitionCells = 0;
2478 MInt partitionGridCellId;
2479 for(
MInt id = 0;
id < noLocalPartitionCellsGrid;
id++) {
2480 if(useRestartOffsets) {
2481 partitionGridCellId = raw().m_localPartitionCellLocalIdsRestart[
id];
2483 partitionGridCellId = raw().localPartitionCellLocalIds(
id);
2485 if(partitionGridCellId < 0)
continue;
2486 if(m_tree.grid2solver(partitionGridCellId) < 0)
continue;
2487 m_partitionCellGlobalId[noLocalPartitionCells] = m_tree.globalId(m_tree.grid2solver(partitionGridCellId));
2488 noLocalPartitionCells++;
2491 MIntScratchSpace localPartitionCellCounts(noDomains(), AT_,
"localPartitionCellCounts");
2492 MPI_Allgather(&noLocalPartitionCells, 1, MPI_INT, &localPartitionCellCounts[0], 1, MPI_INT, mpiComm(), AT_,
2493 "noLocalPartitionCells",
"localPartitionCellCounts[0]");
2494 MLong noPartitionCellsGlobal = noLocalPartitionCells;
2496 "MPI_IN_PLACE",
"noPartitionCellsGlobal");
2499 for(
MInt dId = 0; dId < domainId(); dId++) {
2500 offset += localPartitionCellCounts[dId];
2503 m_localPartitionCellOffsets[0] = offset;
2504 m_localPartitionCellOffsets[1] = offset + noLocalPartitionCells;
2505 m_localPartitionCellOffsets[2] = noPartitionCellsGlobal;
2520 for(
MInt domainId_ = 0; domainId_ < noDomains(); domainId_++) {
2521 if(globalId >= m_domainOffsets[domainId_] && globalId < m_domainOffsets[domainId_ + 1]) {
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'
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.
This class is a ScratchSpace.
void fill(T val)
fill the scratch with a given value
void getLocalSameLevelCellIds(std::vector< MInt > &levelCellId, const MInt level)
find all cells on the same level used by the smoothFilter!
MInt domainContainingCell(MInt globalId) const
domain id containing a given global cell id
MInt determineAzimuthalBoundarySide(const MFloat *coords)
void checkWindowHaloConsistency() const
MInt solverId() const
Return solver id.
void correctAzimuthalHaloCells()
void updatePartitionCellOffsets()
updates solver-grid partition cell offsets and globalIds!
void setupWindowHaloConnectivityOnLeafLvl(std::map< MInt, MInt > &)
void findEqualLevelNeighborsParDiagonal(MBool idsAreGlobal=true)
MInt getNghbrCells(MInt cellId, MInt level, MInt *nghbrs, MInt dir0, MInt dir1=-1, MInt dir2=-1)
void descendStoreGlobalId(MInt cellId, MInt &localCnt)
void checkNeighborConsistency() const
void exchangeHaloCellsForVisualizationDG(MFloat *data, const MInt *const polyDegs, const MInt *const dataOffsets)
Exchange DG halo/window cell data for visualization with ParaView.
void exchangeHaloCellsForVisualizationSBP(MFloat *data, const MInt *const noNodes1D, const MInt *const dataOffsets)
Exchange DG-SBP halo/window cell data for visualization with ParaView.
MInt getAdjacentGridCells(MInt cellId, MInt noLayers, MIntScratchSpace &adjacentCells, MInt level, MInt diagonalNeighbors=0)
Retrieves all direct and diagonal neighboring cells of the given cell on the child level if available...
void resizeGridMap(const MInt solverSize)
void findCartesianNghbIds()
void setSolverFlagsForAddedSolver()
Set solver flags for newly added solver.
MInt m_maxRefinementLevel
MInt findNeighborDomainId(const MLong globalId)
Find neighbor domain id corresponding to given solver-specific globalId.
Proxy(const MInt solverId, Grid &grid_, Geometry< nDim > &geometry_)
MBool checkOutsideGeometry(MInt gridId)
void smoothFilter(const MInt level, MFloat **value)
smooth the grid-based values over neighboring leaf cell asure conservation of the total value
void checkWindowHaloConsistencyAzimuthal() const
void findNeighborHood(const MInt, const MInt, std::vector< MInt > &)
Obtain list of neighbors for the given extend, using m_storeNghbrIds and m_identNghbrIds.
void checkOffsetConsistency() const
void getAllLeafChilds(const MInt, std::vector< MInt > &)
gathers all leaf child cells for a given parentId
void checkNeighborConsistencyAzimuthal() const
void updateLeafCellExchange()
void findDirectNghbrs(const MInt, std::vector< MInt > &)
Obtain list of direct neighbors of given cell. Requires m_identNghbrIds, as such findCartesianNghbIds...
void updateParallelizationInfo()
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MInt ipow(MInt base, MInt exp)
Integer exponent function for non-negative exponents.
MInt globalNoDomains()
Return global number of domains.
MInt globalDomainId()
Return global domain id.
constexpr MLong IPOW2(MInt x)
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_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_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
MUint getBufferSize(const std::vector< std::vector< MInt > > &exchangeCells)
Generic exchange of data.
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.
Namespace for auxiliary functions/classes.