7#ifndef CARTESIANSOLVER_H_
8#define CARTESIANSOLVER_H_
49template <MInt nDim,
class SolverType>
83 return grid().localPartitionCellGlobalIds(cellId);
97 virtual void sensorDerivative(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
98 std::vector<MFloat>& ,
MInt ,
MInt ) {
99 TERMM(1,
"Not implemented for this solver");
101 virtual void sensorDivergence(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
102 std::vector<MFloat>& ,
MInt ,
MInt ) {
103 TERMM(1,
"Not implemented for this solver");
106 std::vector<std::bitset<64>>& , std::vector<MFloat>& ,
108 TERMM(1,
"Not implemented for this solver");
110 virtual void sensorEntropyGrad(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
111 std::vector<MFloat>& ,
MInt ,
MInt ) {
112 TERMM(1,
"Not implemented for this solver");
114 virtual void sensorEntropyQuot(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
115 std::vector<MFloat>& ,
MInt ,
MInt ) {
116 TERMM(1,
"Not implemented for this solver");
118 virtual void sensorVorticity(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
119 std::vector<MFloat>& ,
MInt ,
MInt ) {
120 TERMM(1,
"Not implemented for this solver");
122 virtual void sensorInterface(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
123 std::vector<MFloat>& ,
MInt ,
MInt ) {
124 TERMM(1,
"Not implemented for this solver");
126 void sensorLimit(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
127 std::vector<MFloat>& ,
MInt ,
MInt ,
129 const MBool ,
const MBool allowCoarsening =
true);
130 void sensorSmooth(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
131 std::vector<MFloat>& ,
MInt ,
MInt );
132 void sensorBand(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
133 std::vector<MFloat>& ,
MInt ,
MInt );
134 virtual void sensorMeanStress(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
135 std::vector<MFloat>& ,
MInt ,
MInt ) {
136 TERMM(1,
"Not implemented for this solver");
138 virtual void sensorParticle(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
139 std::vector<MFloat>& ,
MInt ,
MInt ) {
140 TERMM(1,
"Not implemented for this solver");
142 virtual void sensorSpecies(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
143 std::vector<MFloat>& ,
MInt ,
MInt ) {
144 TERMM(1,
"Not implemented for this solver");
146 virtual void sensorPatch(std::vector<std::vector<MFloat>>& sensor, std::vector<std::bitset<64>>& sensorCellFlag,
147 std::vector<MFloat>& sensorWeight,
MInt sensorOffset,
MInt sen) {
148 patchRefinement(sensor, sensorCellFlag, sensorWeight, sensorOffset, sen);
150 virtual void sensorCutOff(std::vector<std::vector<MFloat>>& , std::vector<std::bitset<64>>& ,
151 std::vector<MFloat>& ,
MInt ,
MInt )
153 TERMM(1,
"Not implemented for this solver");
156 const MInt*
const recalcIds)
override;
171 template <
typename T>
173 template <
typename T>
177 template <
class G,
class S,
class M>
180 template <
typename T>
183 template <
typename T>
185 std::vector<MString>& variablesNameOut,
const MInt noVars,
const MInt noCells,
186 const MBool reverseOrder =
false);
187 template <
typename T>
189 std::vector<MString>& variablesNameOut,
const MInt noVars,
const MInt noCells);
198 template <
typename T>
202 std::vector<MInt>& recalcCellIdsSolver, std::vector<MInt>& reorderedCellIds);
213 const MBool refineDiagonals =
true);
224 MBool allowIncompleteStencil);
226 template <MBool cartesianInterpolation>
238 void patchRefinement(std::vector<std::vector<MFloat>>& sensors, std::vector<std::bitset<64>>& sensorCellFlag,
239 std::vector<MFloat>& sensorWeight,
MInt sensorOffset,
MInt sen);
247 const std::map<MInt, MInt>&,
248 MInt levelThreshold = 999999,
250 MBool levelSetMb =
false)
const;
280 std::vector<std::bitset<64>>&, std::vector<MFloat>&,
MInt,
310template <MInt nDim,
class SolverType>
312 const MBool checkActive)
313 :
Solver(solverId_, comm, checkActive ? gridProxy_.isActive() : true), m_gridProxy(gridProxy_) {
325template <MInt nDim,
class SolverType>
327 const std::vector<MInt>& bndCndIds) {
331 MFloat target[6] = {0, 0, 0, 0, 0, 0};
334 const MInt noCells = solver().grid().tree().size();
336 for(
MInt i = 0; i < noCells; i++) {
337 const MFloat cellHalfLength = solver().grid().cellLengthAtLevel(solver().grid().tree().level(i) + 1);
338 for(
MInt j = 0; j < nDim; j++) {
339 target[j] = solver().a_coordinate(i, j) - cellHalfLength;
340 target[j + nDim] = solver().a_coordinate(i, j) + cellHalfLength;
343 std::vector<MInt> nodeList;
346 if(m_gridCutTest ==
"SAT") {
347 solver().geometry().getIntersectionElements(target, nodeList, cellHalfLength, &solver().a_coordinate(i, 0));
349 solver().geometry().getIntersectionElements(target, nodeList);
352 isInterface[i] =
false;
354 const MInt noNodes = nodeList.size();
355 if(noNodes > 0 && bndCndIds.empty()) {
356 isInterface[i] =
true;
357 }
else if(noNodes > 0) {
358 for(
MInt n = 0; n < noNodes; n++) {
359 for(
const auto& bnd : bndCndIds) {
360 if(bnd == solver().geometry().elements[nodeList[n]].m_bndCndId) {
361 isInterface[i] =
true;
374template <MInt nDim,
class SolverType>
378 const MInt noCells = solver().grid().tree().size();
380 identifyBoundaryCells(&isInterface[0]);
381 for(
MInt i = 0; i < noCells; i++) {
382 solver().a_isInterface(i) = isInterface[i];
398template <MInt nDim,
class SolverType>
402 MFloat target[6] = {0, 0, 0, 0, 0, 0};
403 const MFloat cellHalfLength = solver().grid().cellLengthAtLevel(solver().a_level(cellId) + 1);
404 std::vector<MInt> nodeList;
406 for(
MInt dim = 0; dim < nDim; dim++) {
407 target[dim] = solver().a_coordinate(cellId, dim) - cellHalfLength;
408 target[dim + nDim] = solver().a_coordinate(cellId, dim) + cellHalfLength;
411 if(m_gridCutTest ==
"SAT") {
417 return nodeList.size() > 0;
446template <MInt nDim,
class SolverType>
452 m_log <<
" - exchanging triangles " << std::endl;
453 vector<set<pair<MInt, MInt>>> triangleIdsPerDomain;
455 MPI_Request* mpi_request =
nullptr;
457 mAlloc(mpi_request, solver().grid().noNeighborDomains(),
"mpi_request", AT_);
459 m_log <<
" * collecting window triangles" << std::endl;
461 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
462 set<pair<MInt, MInt>> triangles;
463 for(
MInt w = 0; w < (signed)solver().grid().noWindowCells(n); w++) {
464 MInt currentId = solver().grid().windowCell(n, w);
467 if(solver().grid().tree().parent(currentId) < 0) {
470 MFloat cellHalfLength = solver().grid().cellLengthAtLevel(solver().grid().tree().level(currentId) + 1);
471 cellHalfLength += 0.005 * cellHalfLength;
473 std::vector<MInt> nodeList;
475 for(
MInt j = 0; j < nDim; j++) {
476 target[j] = solver().a_coordinate(currentId, j) - cellHalfLength;
477 target[j + nDim] = solver().a_coordinate(currentId, j) + cellHalfLength;
481 solver().geometry().getIntersectionElements(target, nodeList, cellHalfLength,
482 &solver().a_coordinate(currentId, 0));
484 for(
MInt t = 0; t < (signed)nodeList.size(); t++) {
485 triangles.insert(pair<MInt, MInt>(nodeList[t], solver().geometry().elements[nodeList[t]].m_originalId));
489 triangleIdsPerDomain.push_back(triangles);
493 MIntScratchSpace numUniques(solver().grid().noNeighborDomains(), AT_,
"numUniques");
494 MInt myNumUniques = solver().geometry().m_uniqueOriginalTriId.size();
495 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
496 MPI_Issend(&myNumUniques, 1, MPI_INT, solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &mpi_request[n], AT_,
499 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
500 MPI_Recv(&numUniques[n], 1, MPI_INT, solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &status, AT_,
503 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
504 MPI_Wait(&mpi_request[n], &status, AT_);
508 MIntScratchSpace uniquesDomOff(solver().grid().noNeighborDomains(), AT_,
"uniquesDomOff");
509 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
510 uniquesDomOff[n] = sumuniques;
511 sumuniques += numUniques[n];
517 for(
auto u = solver().geometry().m_uniqueOriginalTriId.begin(); u != solver().geometry().m_uniqueOriginalTriId.end();
523 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
524 if(!myUniques.
empty())
526 MPI_COMM_WORLD, &mpi_request[n], AT_,
"myUniques.getPointer()");
528 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
529 if(numUniques[n] > 0) {
530 MPI_Recv(&alluniques[uniquesDomOff[n]], numUniques[n], MPI_INT, solver().grid().neighborDomain(n), 0,
531 MPI_COMM_WORLD, &status, AT_,
"alluniques[uniquesDomOff[n]]");
534 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
535 if(numUniques[n] > 0) {
536 MPI_Wait(&mpi_request[n], &status, AT_);
540 m_log <<
" * sending and receiving unique originalIds" << std::endl;
541 m_log <<
" + sending " << myUniques.
size() <<
" originalIds to: ";
542 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
543 m_log << solver().grid().neighborDomain(n) <<
" ";
546 m_log <<
" * receiving unique originalIds" << std::endl;
547 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
548 m_log <<
" + receiving from " << solver().grid().neighborDomain(n) <<
": " << numUniques[n] << std::endl;
551 m_log <<
" * removing doubles from sender list" << std::endl;
553 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
556 for(
MInt off = uniquesDomOff[n]; off < uniquesDomOff[n] + numUniques[n]; off++) {
557 un.insert(alluniques[off]);
560 for(
auto it = triangleIdsPerDomain[n].begin(); it != triangleIdsPerDomain[n].end();) {
561 auto iun = un.find(get<1>(*it));
562 if(iun != un.end()) {
563 triangleIdsPerDomain[n].erase(it);
564 it = triangleIdsPerDomain[n].begin();
572 MIntScratchSpace toReceive(solver().grid().noNeighborDomains(), AT_,
"toReceive");
575 m_log <<
" * sending numbers of triangles to send to other domains" << std::endl;
577 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
578 MInt numtris = triangleIdsPerDomain[n].size();
579 MPI_Issend(&numtris, 1, MPI_INT, solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &mpi_request[n], AT_,
584 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
585 MPI_Recv(&toReceive[n], 1, MPI_INT, solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &status, AT_,
588 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
589 MPI_Wait(&mpi_request[n], &status, AT_);
592 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
593 if(toReceive[n] > 0) {
594 m_log <<
" + receive from domain " << solver().grid().neighborDomain(n) <<
" : " << toReceive[n]
597 if(!triangleIdsPerDomain[n].empty()) {
598 m_log <<
" + send to domain " << solver().grid().neighborDomain(n) <<
" : "
599 << triangleIdsPerDomain[n].size() << std::endl;
604 MInt sumofreceive = 0;
606 MIntScratchSpace offsetreceive(solver().grid().noNeighborDomains(), AT_,
"offsetreceive");
607 MIntScratchSpace offsetsend(solver().grid().noNeighborDomains(), AT_,
"offsetsend");
608 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
609 offsetsend[n] = sumofsend;
610 sumofsend += triangleIdsPerDomain[n].
size();
611 offsetreceive[n] = sumofreceive;
612 sumofreceive += toReceive[n];
615 m_log <<
" * receive offsets:" << std::endl;
616 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
617 if(toReceive[n] > 0) {
618 m_log <<
" + from domain " << solver().grid().neighborDomain(n) <<
": " << offsetreceive[n] << std::endl;
622 m_log <<
" * send offsets:" << endl;
623 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
624 if(!triangleIdsPerDomain[n].empty()) {
625 m_log <<
" + from domain " << solver().grid().neighborDomain(n) <<
": " << offsetsend[n] << std::endl;
638 m_log <<
" * sending triangles" << std::endl;
640 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
641 if(triangleIdsPerDomain[n].empty()) {
646 MInt j = offsetsend[n] * trisize;
647 for(
const auto& tri : triangleIdsPerDomain[n]) {
648 sndTris[j++] = (
MFloat)solver().geometry().elements[get<0>(tri)].m_originalId;
649 sndTris[j++] = (
MFloat)solver().geometry().elements[get<0>(tri)].m_segmentId;
650 sndTris[j++] = (
MFloat)solver().geometry().elements[get<0>(tri)].m_bndCndId;
653 for(
MInt d = 0; d < nDim; d++, j++) {
654 sndTris[j] = solver().geometry().elements[get<0>(tri)].m_normal[d];
658 for(
MInt d1 = 0; d1 < nDim; d1++) {
659 for(
MInt d2 = 0; d2 < nDim; d2++, j++) {
660 sndTris[j] = solver().geometry().elements[get<0>(tri)].m_vertices[d1][d2];
664 MPI_Issend(sndTris.
getPointer() + (offsetsend[n] * trisize), trisize * triangleIdsPerDomain[n].size(), MPI_DOUBLE,
665 solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &mpi_request[n], AT_,
666 "sndTris.getPointer()+(offsetsend[n]*trisize)");
669 m_log <<
" * receiving triangles" << endl;
671 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
672 if(toReceive[n] > 0) {
673 MPI_Recv(recTris.getPointer() + (offsetreceive[n] * trisize), toReceive[n] * trisize, MPI_DOUBLE,
674 solver().grid().neighborDomain(n), 0, MPI_COMM_WORLD, &status, AT_,
675 "recTris.getPointer()+(offsetreceive[n]*trisize)");
678 for(
MInt n = 0; n < solver().grid().noNeighborDomains(); n++) {
679 if(toReceive[n] > 0) {
680 MPI_Wait(&mpi_request[n], &status, AT_);
684 m_log <<
" * inserting received triangles" << endl;
687 if(sumofreceive > 0) {
688 solver().geometry().resizeCollector(sumofreceive);
693 for(
MInt tri = 0; tri < sumofreceive * trisize; tri += trisize) {
694 auto originalId = (
MInt)recTris[tri];
697 if(solver().geometry().m_uniqueOriginalTriId.find(originalId) == solver().geometry().m_uniqueOriginalTriId.end()) {
698 solver().geometry().addElement(&recTris[tri]);
703 solver().geometry().calculateBoundingBox();
705 if(solver().geometry().m_debugParGeom && solver().geometry().GetNoElements() > 0) {
706 solver().geometry().writeParallelGeometryVTK(
"allpluswindow");
709 if(solver().geometry().GetNoElements() > 0 && sumofreceive > 0) {
710 solver().geometry().rebuildAdtTree();
722template <MInt nDim,
class SolverType>
728 for(
auto& i : solver().m_freeIndices) {
731 solver().m_freeIndices.clear();
733 if(grid().azimuthalPeriodicity()) {
734 m_gridProxy.correctAzimuthalHaloCells();
737 m_gridProxy.resizeGridMap(solver().m_cells.size());
740 ASSERT(solver().m_cells.size() == m_gridProxy.tree().size(),
741 "m_cells: " + std::to_string(solver().m_cells.size()) +
" tree: " + std::to_string(m_gridProxy.tree().size()));
742 for(
MInt cellId = 0; cellId < solver().m_cells.size(); cellId++) {
743 ASSERT(isToDelete(cellId)
744 || solver().a_isHalo(cellId) == solver().grid().raw().a_isHalo(grid().tree().solver2grid(cellId)),
747 for(
MInt gridCellId = 0; gridCellId < solver().grid().raw().treeb().size(); gridCellId++) {
748 if(solver().grid().raw().treeb().solver(gridCellId, solver().solverId())) {
750 grid().tree().grid2solver(gridCellId) > -1 && grid().tree().grid2solver(gridCellId) < solver().m_cells.size(),
751 std::to_string(gridCellId) +
" " + std::to_string(grid().tree().grid2solver(gridCellId)) +
" "
752 + std::to_string(solver().m_cells.size()) +
" " + std::to_string(solver().grid().raw().treeb().size()));
754 ASSERT(grid().tree().grid2solver(gridCellId) < 0,
755 std::to_string(gridCellId) +
" " + std::to_string(grid().tree().grid2solver(gridCellId)) +
" "
756 + std::to_string(solver().m_cells.size()) +
" "
757 + std::to_string(solver().grid().raw().treeb().size()));
763 MInt noInternalCells = 0;
765 for(
MInt cellId = 0; cellId < solver().m_cells.size(); cellId++) {
766 if(isToDelete(cellId) != 0) {
769 oldCellId(cellId) = cellId;
770 if(!solver().a_isHalo(cellId)) {
776 if(solver().grid().raw().treeb().
noSolvers() == 1) {
777 ASSERT(noCells == solver().grid().raw().treeb().size(),
"");
778 ASSERT(noInternalCells == solver().grid().raw().m_noInternalCells,
"");
782 MInt otherId = solver().m_cells.size() - 1;
783 for(
MInt cellId = 0; cellId < noInternalCells; cellId++) {
784 if(isToDelete(cellId) || solver().a_isHalo(cellId)) {
785 while(isToDelete(otherId) || solver().a_isHalo(otherId)) {
788 ASSERT(cellId < otherId,
"");
790 solver().swapCells(cellId, otherId);
791 grid().swapSolverIds(cellId, otherId);
792 std::swap(oldCellId(cellId), oldCellId(otherId));
793 std::swap(isToDelete(cellId), isToDelete(otherId));
795 ASSERT(grid().tree().solver2grid(cellId) > -1,
"");
796 ASSERT(grid().tree().solver2grid(otherId) < 0 || solver().a_isHalo(otherId),
"");
797 ASSERT(!solver().a_isHalo(cellId),
"");
798 ASSERT(isToDelete(otherId) || solver().a_isHalo(otherId),
"");
800 ASSERT(!solver().a_isHalo(cellId) && !isToDelete(cellId),
"");
804 otherId = solver().m_cells.size() - 1;
805 for(
MInt cellId = noInternalCells; cellId < noCells; cellId++) {
806 if(isToDelete(cellId) != 0) {
807 while(isToDelete(otherId) != 0) {
810 ASSERT(cellId < otherId,
"");
811 ASSERT(otherId >= noCells,
"");
812 ASSERT(solver().a_isHalo(otherId) && !isToDelete(otherId),
"");
813 solver().swapCells(cellId, otherId);
814 grid().swapSolverIds(cellId, otherId);
815 std::swap(oldCellId(cellId), oldCellId(otherId));
816 std::swap(isToDelete(cellId), isToDelete(otherId));
818 ASSERT(grid().tree().solver2grid(cellId) > -1,
"");
819 ASSERT(grid().tree().solver2grid(otherId) < 0,
"");
821 ASSERT(solver().a_isHalo(cellId) && !isToDelete(cellId),
"");
824 for(
MInt cellId = noInternalCells; cellId < noCells; cellId++) {
825 ASSERT(grid().tree().solver2grid(cellId) > -1
826 && grid().tree().solver2grid(cellId) < solver().grid().raw().treeb().size(),
828 ASSERT(solver().a_isHalo(cellId) == solver().grid().raw().a_isHalo(grid().tree().solver2grid(cellId)),
"");
831 solver().m_cells.size(noCells);
832 m_gridProxy.resizeGridMap(solver().m_cells.size());
833 ASSERT(solver().m_cells.size() == m_gridProxy.tree().size(),
"");
836 if(solver().grid().raw().treeb().
noSolvers() == 1) {
837 for(
MInt gridCellId = 0; gridCellId < noCells; gridCellId++) {
838 ASSERT(grid().tree().solver2grid(gridCellId) == gridCellId,
"");
839 ASSERT(grid().tree().grid2solver(gridCellId) == gridCellId,
"");
879template <MInt nDim,
class SolverType>
881 MInt solverCellId = -1;
882 if(solver().m_freeIndices.size() > 0) {
883 auto it = solver().m_freeIndices.begin();
884 solverCellId = *(it);
885 solver().m_freeIndices.erase(it);
886 m_gridProxy.resizeGridMap(solver().m_cells.size());
888 solverCellId = solver().m_cells.size();
889 solver().m_cells.append();
890 m_gridProxy.resizeGridMap(solver().m_cells.size());
892 ASSERT(solverCellId > -1 && solverCellId < solver().m_cells.size(),
"");
894 ASSERT(solverCellId == gridCellId, std::to_string(solverCellId) +
" " + std::to_string(gridCellId));
897 solver().a_resetPropertiesSolver(solverCellId);
898 solver().a_isHalo(solverCellId) = solver().grid().raw().a_isHalo(gridCellId);
900 grid().setSolver2grid(solverCellId, gridCellId);
901 grid().setGrid2solver(gridCellId, solverCellId);
911template <MInt nDim,
class SolverType>
913 const MInt gridCellId = grid().tree().solver2grid(cellId);
914 ASSERT(gridCellId > -1 && gridCellId < solver().grid().raw().treeb().size(),
"");
916 solver().a_resetPropertiesSolver(cellId);
918 grid().setSolver2grid(cellId, std::numeric_limits<MInt>::min());
919 grid().setGrid2solver(gridCellId, std::numeric_limits<MInt>::min());
920 solver().grid().raw().treeb().solver(gridCellId, solver().solverId()) =
false;
922 if(cellId == (solver().m_cells.size() - 1)) {
923 solver().m_cells.size(solver().m_cells.size() - 1);
924 m_gridProxy.resizeGridMap(solver().m_cells.size());
926 solver().m_freeIndices.insert(cellId);
939template <MInt nDim,
class SolverType>
941 const MFloat*
const outerBandWidth,
945 distance.fill(std::numeric_limits<MFloat>::max());
946 std::vector<MInt> currentLayer;
947 MIntScratchSpace onCurrentLayer(solver().a_noCells(), AT_,
"onCurrentLayer");
949 onCurrentLayer.
fill(0);
952 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
953 if(interfaceCell[cellId]) {
954 currentLayer.push_back(cellId);
955 onCurrentLayer(cellId) = 1;
956 accessed(cellId) = 1;
957 distance(cellId) = F0;
961 while(proceed != 0) {
963 solver().exchangeData(distance.data());
964 solver().exchangeData(onCurrentLayer.
data());
965 for(
MInt i = 0; i < solver().noNeighborDomains(); i++) {
966 for(
MInt c = 0; c < solver().noHaloCells(i); c++) {
967 if(onCurrentLayer(solver().haloCellId(i, c))) {
968 currentLayer.push_back(solver().haloCellId(i, c));
969 accessed(solver().haloCellId(i, c)) = 1;
973 onCurrentLayer.
fill(0);
974 std::vector<MInt> currentLayerBak(currentLayer);
975 for(
auto& cellId : currentLayerBak) {
976 for(
MInt dir = 0; dir < solver().m_noDirs; dir++) {
977 if(solver().a_hasNeighbor(cellId, dir)) {
978 MInt nghbrId = solver().c_neighborId(cellId, dir);
979 if(solver().c_isLeafCell(cellId)) {
980 MFloat dx = F1B2 * (solver().c_cellLengthAtCell(cellId) + solver().c_cellLengthAtCell(nghbrId));
981 distance(nghbrId) =
mMin(distance(nghbrId), distance(cellId) + dx);
982 if(accessed(nghbrId) == 0) {
983 currentLayer.push_back(nghbrId);
984 accessed(nghbrId) = 1;
985 onCurrentLayer(nghbrId) = 1;
986 if(distance(nghbrId) < outerBandWidth[
mMax(solver().minLevel(), solver().a_level(nghbrId) - 1)]
987 + F2 * solver().c_cellLengthAtCell(nghbrId)) {
992 for(
MInt c = 0; c < solver().grid().m_maxNoChilds; c++) {
993 if(!childCode[dir][c]) {
996 MInt childId = solver().c_childId(nghbrId, c);
1000 MFloat dx = F1B2 * (solver().c_cellLengthAtCell(cellId) + solver().c_cellLengthAtCell(childId));
1001 distance(childId) =
mMin(distance(childId), distance(cellId) + dx);
1002 if(accessed(childId) == 0) {
1003 currentLayer.push_back(childId);
1004 accessed(childId) = 1;
1005 onCurrentLayer(childId) = 1;
1006 if(distance(childId) < outerBandWidth[
mMax(solver().minLevel(), solver().a_level(childId) - 1)]
1007 + F2 * solver().c_cellLengthAtCell(childId)) {
1014 MInt parentId = solver().c_parentId(cellId);
1015 while(parentId > -1 && !solver().a_hasNeighbor(parentId, dir)) {
1016 parentId = solver().c_parentId(parentId);
1018 if(parentId > -1 && solver().a_hasNeighbor(parentId, dir)) {
1019 MInt nghbrId = solver().c_neighborId(parentId, dir);
1020 if(!solver().c_isLeafCell(nghbrId)) {
1023 MFloat dx = F1B2 * (solver().c_cellLengthAtCell(cellId) + solver().c_cellLengthAtCell(nghbrId));
1024 distance(nghbrId) =
mMin(distance(nghbrId), distance(cellId) + dx);
1025 if(accessed(nghbrId) == 0) {
1026 currentLayer.push_back(nghbrId);
1027 accessed(nghbrId) = 1;
1028 onCurrentLayer(nghbrId) = 1;
1029 if(distance(nghbrId) < outerBandWidth[
mMax(solver().minLevel(), solver().a_level(nghbrId) - 1)]
1030 + F2 * solver().c_cellLengthAtCell(nghbrId)) {
1038 if(currentLayer.empty()) {
1041 MPI_Allreduce(MPI_IN_PLACE, &proceed, 1, MPI_INT, MPI_SUM, solver().mpiComm(), AT_,
"MPI_IN_PLACE",
"proceed");
1056template <MInt nDim,
class SolverType>
1058 const MInt level,
const MBool refineDiagonals) {
1060 static constexpr MInt noDirs = 2 * nDim;
1061 static constexpr std::array<MInt, 4> diagDirs{3, 2, 0, 1};
1065 for(
MInt loopMarker = 1; loopMarker < bandWidth; loopMarker++) {
1066 for(
MInt cellId = 0; cellId < solver().a_noCells(); cellId++) {
1067 if(solver().grid().tree().level(cellId) != level) {
1070 if(inList(cellId) != loopMarker) {
1074 const MInt cellDist = loopMarker + 1;
1077 for(
MInt mainDir = 0; mainDir < noDirs; mainDir++) {
1078 const MInt nghbrId = solver().c_neighborId(cellId, mainDir);
1082 if(inList(nghbrId) == 0) {
1083 inList(nghbrId) = cellDist;
1086 if(refineDiagonals) {
1089 const MInt nghbrId2 = solver().c_neighborId(nghbrId, diagDirs.at(mainDir));
1090 if(nghbrId2 >= 0 && inList(nghbrId2) == 0) {
1091 inList(nghbrId2) = cellDist;
1095 IF_CONSTEXPR(nDim == 3) {
1096 for(
MInt dirZ = 4; dirZ < 6; dirZ++) {
1097 const MInt nghbrIdZ = solver().c_neighborId(cellId, dirZ);
1101 if(nghbrIdZ >= 0 && inList(nghbrIdZ) == 0) {
1102 inList(nghbrIdZ) = cellDist;
1104 for(
MInt dir = 0; dir < 4; dir++) {
1105 const MInt nghbrId2 = solver().c_neighborId(nghbrIdZ, dir);
1109 if(inList(nghbrId2) == 0) {
1110 inList(nghbrId2) = cellDist;
1113 const MInt triDiagNghbrId = solver().c_neighborId(nghbrId2, diagDirs.at(dir));
1114 if(triDiagNghbrId >= 0 && inList(triDiagNghbrId) == 0) {
1115 inList(triDiagNghbrId) = cellDist;
1123 exchangeData(inList.
data());
1124 if(grid().azimuthalPeriodicity()) {
1125 exchangeAzimuthalPer(&inList[0]);
1136template <MInt nDim,
class SolverType>
1150 m_log <<
"check HaloLayer-Count for solver " << solver().solverId() <<
" ... ";
1152 MBool uncorrectLayerCount =
false;
1153 static constexpr MInt cornerIndices[8][3] = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1},
1154 {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};
1288 std::set<MInt> haloCells;
1290 std::multimap<MInt, MInt> firstHaloLayer;
1291 firstHaloLayer.clear();
1295 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
1296 for(
MInt j = 0; j < grid().noHaloCells(i); j++) {
1297 const MInt cellId = grid().haloCell(i, j);
1298 haloCells.insert(cellId);
1302 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
1303 for(
MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
1304 const MInt cellId = grid().azimuthalHaloCell(i, j);
1305 haloCells.insert(cellId);
1308 for(
MInt i = 0; i < grid().noAzimuthalUnmappedHaloCells(); i++) {
1309 const MInt cellId = grid().azimuthalUnmappedHaloCell(i);
1310 haloCells.insert(cellId);
1315 for(
auto it = haloCells.begin(); it != haloCells.end(); ++it) {
1317 if(!grid().tree().isLeafCell(cellId))
continue;
1318 ASSERT(solver().a_isHalo(cellId),
"");
1321 if(grid().tree().hasProperty(cellId, Cell::IsPartLvlAncestor))
continue;
1323 for(
MInt dir = 0; dir < 2 * nDim; dir++) {
1327 if(grid().tree().hasNeighbor(cellId, dir)) {
1329 nghbrId = grid().tree().neighbor(cellId, dir);
1345 }
else if(grid().tree().hasParent(cellId) && grid().tree().parent(cellId) < grid().tree().size()) {
1346 nghbrId = grid().tree().neighbor(grid().tree().parent(cellId), dir);
1348 if(nghbrId < 0)
continue;
1361 if(!grid().tree().hasProperty(nghbrId, Cell::IsHalo)) {
1362 firstHaloLayer.insert(std::make_pair(cellId,
m_revDir[dir]));
1368 for(std::multimap<MInt, MInt>::iterator it = firstHaloLayer.begin(); it != firstHaloLayer.end(); it++) {
1369 MInt cellId = it->first;
1371 const MInt dir = it->second;
1372 ASSERT(dir > -1 && dir < 2 * nDim, std::to_string(dir));
1373 ASSERT(grid().tree().isLeafCell(cellId),
"");
1374 ASSERT(solver().a_isHalo(cellId),
"");
1376 for(
MInt layer = 1; layer < grid().noHaloLayers(); layer++) {
1380 if(grid().tree().hasNeighbor(cellId, dir)) {
1381 nghbrId = grid().tree().neighbor(cellId, dir);
1382 if(!grid().tree().isLeafCell(nghbrId)) {
1384 for(
MInt child = 0; child <
ipow(2, nDim); child++) {
1385 if(!childCode[dir][child])
continue;
1386 if(grid().tree().child(nghbrId, child) < 0) {
1387 if(grid().noHaloLayers() % 2 == 0) {
1389 MBool outside =
true;
1390 const MFloat cellHalfLength = F1B4 * grid().cellLengthAtCell(cellId);
1391 MFloat corner[3] = {0, 0, 0};
1395 for(
MInt k = 0; k < nDim; k++) {
1396 coords[k] = grid().tree().coordinate(nghbrId, k);
1398 for(
MInt k = 0; k < nDim; k++) {
1399 coords[k] += cornerIndices[child][k] * cellHalfLength;
1402 for(
MInt node = 0; node <
ipow(2, nDim); node++) {
1403 for(
MInt dim = 0; dim < nDim; dim++) {
1404 corner[dim] = coords[dim] + cornerIndices[node][dim] * F1B2 * cellHalfLength;
1406 IF_CONSTEXPR(nDim == 2) {
1407 if(!solver().geometry().pointIsInside(corner)) outside =
false;
1410 if(!solver().geometry().pointIsInside2(corner)) outside =
false;
1414 if(outside)
continue;
1416 uncorrectLayerCount =
true;
1417 std::cerr <<
"Incorrect halo-Layer count: 1 " << cellId <<
" " << solver().domainId() <<
" "
1418 << grid().tree().globalId(cellId) <<
" " << solver().solverId() <<
" " << dir << std::endl;
1419 std::cerr << grid().tree().coordinate(cellId, 0) <<
" " << grid().tree().coordinate(cellId, 1) <<
" "
1420 << grid().tree().coordinate(cellId, nDim - 1) << std::endl;
1425 nghbrId1 = grid().tree().child(nghbrId, child);
1434 }
else if(grid().tree().hasParent(cellId) && grid().tree().parent(cellId) < grid().tree().size()) {
1435 nghbrId = grid().tree().neighbor(grid().tree().parent(cellId), dir);
1440 if(nghbrId < 0 || nghbrId > grid().tree().size()) {
1442 MBool outside =
true;
1443 const MFloat cellHalfLength = F1B2 * grid().cellLengthAtCell(cellId);
1444 MFloat corner[3] = {0, 0, 0};
1448 for(
MInt k = 0; k < nDim; k++) {
1449 coords[k] = grid().tree().coordinate(cellId, k);
1451 coords[dir / 2] += ((dir % 2 == 0) ? -F1 : F1) * grid().cellLengthAtCell(cellId);
1453 for(
MInt node = 0; node <
ipow(2, nDim); node++) {
1454 for(
MInt dim = 0; dim < nDim; dim++) {
1455 corner[dim] = coords[dim] + cornerIndices[node][dim] * cellHalfLength;
1457 IF_CONSTEXPR(nDim == 2) {
1458 if(!solver().geometry().pointIsInside(corner)) outside =
false;
1461 if(!solver().geometry().pointIsInside2(corner)) outside =
false;
1469 if(grid().hasCutOff() && grid().tree().cutOff(cellId) > -1) {
1477 uncorrectLayerCount =
true;
1478 std::cerr <<
"Incorrect halo-Layer count: 2 " << solver().domainId() <<
" " << solver().solverId() <<
" "
1479 << layer <<
" " << cellId <<
"/" << grid().tree().globalId(cellId) <<
" " << dir <<
" "
1480 << grid().tree().coordinate(cellId, 0) <<
" " << grid().tree().coordinate(cellId, 1) <<
" "
1481 << grid().tree().coordinate(cellId, nDim - 1) <<
" " << grid().isPeriodic(cellId) << std::endl;
1570 if(uncorrectLayerCount) {
1571 mTerm(1, AT_,
"Incorrect number of halo-layers!");
1575 m_log <<
"done" << std::endl;
1581template <MInt nDim,
class SolverType>
1588 MFloat cellHalfLength = F1B2 * grid().cellLengthAtCell(cellId);
1590 xmin = grid().tree().coordinate(cellId, 0) - (cellHalfLength * fac);
1591 xmax = grid().tree().coordinate(cellId, 0) + (cellHalfLength * fac);
1592 ymin = grid().tree().coordinate(cellId, 1) - (cellHalfLength * fac);
1593 ymax = grid().tree().coordinate(cellId, 1) + (cellHalfLength * fac);
1596 if(point[0] < xmax && point[0] >= xmin && point[1] < ymax && point[1] >= ymin) {
1602 zmin = grid().tree().coordinate(cellId, 2) - (cellHalfLength * fac);
1603 zmax = grid().tree().coordinate(cellId, 2) + (cellHalfLength * fac);
1605 if(point[0] < xmax && point[0] >= xmin && point[1] < ymax && point[1] >= ymin && point[2] < zmax
1606 && point[2] >= zmin) {
1622template <MInt nDim,
class SolverType>
1624 MInt* interpolationCells,
1628 MBool allowIncompleteStencil) {
1632 const MInt maxPosition =
IPOW2(nDim) - 1;
1633 MBool invalidStencil =
false;
1637 if(point[0] > grid().tree().coordinate(cellId, 0)) {
1640 if(point[1] > grid().tree().coordinate(cellId, 1)) {
1644 IF_CONSTEXPR(nDim == 3) {
1645 if(point[2] > grid().tree().coordinate(cellId, 2)) {
1650 position = maxPosition - position;
1654 MInt xNghbrDir = (position + 1) % 2;
1655 MInt posIncrementX = -1 + 2 * xNghbrDir;
1656 MInt yNghbrDir = (position / 2 + 1) % 2;
1657 MInt posIncrementY = -2 + 4 * yNghbrDir;
1659 MInt zNghbrDir = -1;
1660 MInt posIncrementZ = -1;
1663 if(!neighborCheck(cellId, xNghbrDir) || !grid().tree().hasNeighbor(cellId, xNghbrDir)) {
1664 position += posIncrementX;
1666 if(!neighborCheck(cellId, yNghbrDir) || !grid().tree().hasNeighbor(cellId, yNghbrDir)) {
1667 position += posIncrementY;
1670 IF_CONSTEXPR(nDim == 3) {
1671 zNghbrDir = (position / 4 + 1) % 2;
1672 posIncrementZ = -4 + 8 * zNghbrDir;
1675 if(!neighborCheck(cellId, zNghbrDir) || !grid().tree().hasNeighbor(cellId, zNghbrDir)) {
1676 position += posIncrementZ;
1680 interpolationCells[position] = cellId;
1682 IF_CONSTEXPR(nDim == 2) {
1685 if(position % 2 == 0) {
1687 nghbrX = neighborCheck(cellId, xNghbrDir) ? grid().tree().neighbor(cellId, xNghbrDir) : -1;
1691 nghbrX = neighborCheck(cellId, xNghbrDir) ? grid().tree().neighbor(cellId, xNghbrDir) : -1;
1694 if(((
MInt)(position / 2)) % 2 == 0) {
1696 nghbrY = neighborCheck(cellId, yNghbrDir) ? grid().tree().neighbor(cellId, yNghbrDir) : -1;
1700 nghbrY = neighborCheck(cellId, yNghbrDir) ? grid().tree().neighbor(cellId, yNghbrDir) : -1;
1703 interpolationCells[position + posIncrementX] = nghbrX;
1704 interpolationCells[position + posIncrementY] = nghbrY;
1706 interpolationCells[position + posIncrementX + posIncrementY] =
1707 neighborCheck(nghbrX, yNghbrDir) ? grid().tree().neighbor(nghbrX, yNghbrDir) : -1;
1708 else if(nghbrY != -1)
1709 interpolationCells[position + posIncrementX + posIncrementY] =
1710 neighborCheck(nghbrY, xNghbrDir) ? grid().tree().neighbor(nghbrY, xNghbrDir) : -1;
1712 interpolationCells[position + posIncrementX + posIncrementY] = -1;
1718 if(position % 2 == 0) {
1720 nghbrX = neighborCheck(cellId, xNghbrDir) ? grid().tree().neighbor(cellId, xNghbrDir) : -1;
1724 nghbrX = neighborCheck(cellId, xNghbrDir) ? grid().tree().neighbor(cellId, xNghbrDir) : -1;
1727 if(((
MInt)(position / 2)) % 2 == 0) {
1729 nghbrY = neighborCheck(cellId, yNghbrDir) ? grid().tree().neighbor(cellId, yNghbrDir) : -1;
1733 nghbrY = neighborCheck(cellId, yNghbrDir) ? grid().tree().neighbor(cellId, yNghbrDir) : -1;
1736 if((
MInt)(position / 4) == 0) {
1738 nghbrZ = neighborCheck(cellId, zNghbrDir) ? grid().tree().neighbor(cellId, zNghbrDir) : -1;
1742 nghbrZ = neighborCheck(cellId, zNghbrDir) ? grid().tree().neighbor(cellId, zNghbrDir) : -1;
1745 interpolationCells[position + posIncrementX] = nghbrX;
1746 interpolationCells[position + posIncrementY] = nghbrY;
1747 interpolationCells[position + posIncrementZ] = nghbrZ;
1749 interpolationCells[position + posIncrementX + posIncrementZ] =
1750 neighborCheck(nghbrX, zNghbrDir) ? grid().tree().neighbor(nghbrX, zNghbrDir) : -1;
1751 interpolationCells[position + posIncrementX + posIncrementY] =
1752 neighborCheck(nghbrX, yNghbrDir) ? grid().tree().neighbor(nghbrX, yNghbrDir) : -1;
1754 interpolationCells[position + posIncrementX + posIncrementZ] = -1;
1755 interpolationCells[position + posIncrementX + posIncrementY] = -1;
1758 interpolationCells[position + posIncrementY + posIncrementZ] =
1759 neighborCheck(nghbrY, zNghbrDir) ? grid().tree().neighbor(nghbrY, zNghbrDir) : -1;
1761 interpolationCells[position + posIncrementY + posIncrementZ] = -1;
1763 const MInt nghbrXY = interpolationCells[position + posIncrementX + posIncrementY];
1764 if(nghbrX > -1 && nghbrXY > -1)
1765 interpolationCells[position + posIncrementX + posIncrementY + posIncrementZ] =
1766 neighborCheck(nghbrXY, zNghbrDir) ? grid().tree().neighbor(nghbrXY, zNghbrDir) : -1;
1768 interpolationCells[position + posIncrementX + posIncrementY + posIncrementZ] = -1;
1771 for(
MInt p = 0; p <= maxPosition; p++) {
1772 if(interpolationCells[p] == -1) {
1773 invalidStencil =
true;
1777 if(invalidStencil && !allowIncompleteStencil) {
1778 for(
MInt p = 0; p <= maxPosition; p++) {
1779 interpolationCells[p] = cellId;
1797template <MInt nDim,
class SolverType>
1798template <MBool cartesianInterpolation>
1804 IF_CONSTEXPR(cartesianInterpolation) {
1805 const MFloat xMin = coordinate(interpolationCells[0], 0);
1806 const MFloat xMax = coordinate(interpolationCells[1], 0);
1807 const MFloat yMin = coordinate(interpolationCells[0], 1);
1808 const MFloat yMax = coordinate(interpolationCells[2], 1);
1809 const MFloat deltaX_Minus = point[0] - xMin;
1810 const MFloat deltaX_Plus = xMax - point[0];
1811 const MFloat deltaY_Minus = point[1] - yMin;
1812 const MFloat deltaY_Plus = yMax - point[1];
1813 const MFloat Delta = deltaX_Minus + deltaX_Plus;
1815 IF_CONSTEXPR(nDim == 2) {
1816 const MFloat phi = (scalarField(interpolationCells[0], varId) * deltaX_Plus * deltaY_Plus
1817 + scalarField(interpolationCells[1], varId) * deltaX_Minus * deltaY_Plus
1818 + scalarField(interpolationCells[2], varId) * deltaX_Plus * deltaY_Minus
1819 + scalarField(interpolationCells[3], varId) * deltaX_Minus * deltaY_Minus)
1824 const MFloat zMin = coordinate(interpolationCells[0], 2);
1825 const MFloat zMax = coordinate(interpolationCells[4], 2);
1826 const MFloat deltaZ_Minus = point[2] - zMin;
1827 const MFloat deltaZ_Plus = zMax - point[2];
1828 const MFloat phi = (scalarField(interpolationCells[0], varId) * deltaX_Plus * deltaY_Plus * deltaZ_Plus
1829 + scalarField(interpolationCells[1], varId) * deltaX_Minus * deltaY_Plus * deltaZ_Plus
1830 + scalarField(interpolationCells[2], varId) * deltaX_Plus * deltaY_Minus * deltaZ_Plus
1831 + scalarField(interpolationCells[3], varId) * deltaX_Minus * deltaY_Minus * deltaZ_Plus
1832 + scalarField(interpolationCells[4], varId) * deltaX_Plus * deltaY_Plus * deltaZ_Minus
1833 + scalarField(interpolationCells[5], varId) * deltaX_Minus * deltaY_Plus * deltaZ_Minus
1834 + scalarField(interpolationCells[6], varId) * deltaX_Plus * deltaY_Minus * deltaZ_Minus
1835 + scalarField(interpolationCells[7], varId) * deltaX_Minus * deltaY_Minus * deltaZ_Minus)
1836 / (Delta * Delta * Delta);
1845 if(interpolationCells[i] < 0)
continue;
1846 IF_CONSTEXPR(nDim == 2) {
1847 dist = std::sqrt(
POW2(point[0] - coordinate(interpolationCells[i], 0))
1848 +
POW2(point[1] - coordinate(interpolationCells[i], 1)));
1851 dist = std::sqrt(
POW2(point[0] - coordinate(interpolationCells[i], 0))
1852 +
POW2(point[1] - coordinate(interpolationCells[i], 1))
1853 +
POW2(point[2] - coordinate(interpolationCells[i], 2)));
1856 phi += scalarField(interpolationCells[i], varId) *
dist;
1858 return phi / sumDist;
1867template <MInt nDim,
class SolverType>
1871 std::array<MFloat, nDim + 1>
b;
1872 std::array<std::array<
MFloat, (nDim + 1)>, (nDim + 1)> A;
1873 std::array<MFloat, nDim + 1> adjA;
1875 for(
MInt i = 0; i < nDim + 1; i++) {
1876 for(
MInt j = 0; j < nDim + 1; j++) {
1881 const MInt cellId = interpolationCells[n];
1882 b[0] += scalarField(cellId, varId);
1883 MFloat deltax = point[0] - coordinate(cellId, 0);
1884 MFloat deltay = point[1] - coordinate(cellId, 1);
1885 b[1] += scalarField(cellId, varId) * deltax;
1886 b[2] += scalarField(cellId, varId) * deltay;
1889 A[1][1] +=
POW2(deltax);
1890 A[2][2] +=
POW2(deltay);
1893 A[2][1] += deltax * deltay;
1894 IF_CONSTEXPR(nDim == 3) {
1895 MFloat deltaz = point[2] - coordinate(cellId, 2);
1896 b[3] += scalarField(cellId, varId) * deltaz;
1898 A[3][1] += deltaz * deltax;
1899 A[3][2] += deltaz * deltay;
1900 A[3][3] +=
POW2(deltaz);
1907 IF_CONSTEXPR(nDim == 3) {
1914 ASSERT(fabs(det) > MFloatEps,
"Poor least-squares stencil!");
1919 for(
MInt i = 0; i < nDim + 1; i++) {
1920 sum += adjA[i] *
b[i];
1931template <MInt nDim,
class SolverType>
1937 MInt noMinCells = solver().m_localMinCellsOffsets[1] - solver().m_localMinCellsOffsets[0] + 1;
1938 srcGrid.setOffset(noMinCells, solver().m_localMinCellsOffsets[0]);
1941 MIntScratchSpace srcMinCellsGlobalIds(noMinCells, AT_,
"srcMinCellsGlobalIds");
1942 MIntScratchSpace srcMinCellsNoOffsprings(noMinCells, AT_,
"srcMinCellsNoOffsprings");
1944 srcGrid.readArray(srcMinCellsGlobalIds.
getPointer(),
"minCellsId");
1945 srcGrid.readArray(srcMinCellsNoOffsprings.
getPointer(),
"minCellsNoOffsprings");
1948 MInt srcFirstMinCellGlobalId = srcMinCellsGlobalIds(0);
1949 MInt srcNoCells = 0;
1950 for(
MInt i = 0; i < noMinCells; i++) {
1951 srcNoCells += srcMinCellsNoOffsprings(i);
1952 srcMinCellsGlobalIds(i) -= srcFirstMinCellGlobalId;
1955 srcGrid.setOffset(srcNoCells, srcFirstMinCellGlobalId);
1966 std::vector<MString> varNames;
1967 for(
MInt j = 0; j < nDim; ++j) {
1968 std::stringstream ss;
1969 ss <<
"coordinates_" << j;
1970 varNames.push_back(ss.str());
1974 srcGrid.readArray(&srcCoords(0, 0), varNames, nDim);
1977 srcGrid.readArray(srcNoChildIds.
begin(),
"noChildIds");
1979 srcGrid.readArray(srcLevel.
begin(),
"level_0");
1982 std::stringstream ss;
1983 ss <<
"childIds_" << j;
1984 varNames.push_back(ss.str());
1988 srcGrid.readArray(&srcChildIds(0, 0), varNames,
IPOW2(nDim));
1991 for(
MInt i = 0; i < srcNoCells; i++) {
1993 srcChildIds(i, j) -= srcFirstMinCellGlobalId;
1997 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
1998 if(solver().c_noChildren(cellId)) {
2001 auto* coord = (
MFloat*)(&(solver().a_coordinate(cellId, 0)));
2004 for(
MInt srcMinCellId = 0; srcMinCellId < noMinCells; srcMinCellId++) {
2005 MInt srcMinCellGlobalId = srcMinCellsGlobalIds(srcMinCellId);
2006 MFloat* srcCoord = &srcCoords(srcMinCellGlobalId, 0);
2007 MFloat hdc = solver().c_cellLengthAtLevel(srcLevel(srcMinCellGlobalId) + 1);
2009 for(
MInt dim = 0; dim < nDim; dim++) {
2010 if(coord[dim] < srcCoord[dim] + hdc && coord[dim] >= srcCoord[dim] - hdc) {
2015 if(insideCnt == nDim) {
2016 srcId = srcMinCellGlobalId;
2019 if(srcMinCellId == (noMinCells - 1)) {
2020 mTerm(1,
" should not happen, loc cell not in src region");
2024 while(srcNoChildIds(srcId) != 0) {
2025 for(
MInt cc = 0; cc <
IPOW2(nDim); cc++) {
2026 MInt tcid = srcChildIds(srcId, cc);
2028 MFloat* srcCoord = &srcCoords(tcid, 0);
2029 MFloat hdc = solver().c_cellLengthAtLevel(srcLevel(tcid) + 1);
2032 for(
MInt dim = 0; dim < nDim; dim++) {
2033 if(coord[dim] < srcCoord[dim] + hdc && coord[dim] >= srcCoord[dim] - hdc) {
2037 if(insideCnt == nDim) {
2042 if(cc == (
IPOW2(nDim) - 1)) {
2043 mTerm(1,
" should not happen, loc cell not in any child");
2048 cellMap[cellId] = srcId;
2053template <MInt nDim,
class SolverType>
2055 std::vector<std::bitset<64>>& sensorCellFlag,
2056 std::vector<MFloat>& sensorWeight,
MInt sensorOffset,
2058 if(solver().m_testPatch &&
globalTimeStep < solver().m_patchStartTimeStep
2063 m_log <<
" - Sensor preparation for the patch sensor" << std::endl;
2065 MFloat coordinates[nDim]{};
2066 MFloat patchDimensions[nDim * 2]{};
2068 for(
MInt lvl = 0; lvl < solver().m_patchRefinement->noLocalPatchRfnLvls(); lvl++) {
2069 const MInt level = lvl + solver().maxUniformRefinementLevel();
2070 for(
MInt patch = 0; patch < solver().m_patchRefinement->noPatchesPerLevel(lvl); patch++) {
2071 MString patchStr = solver().m_patchRefinement->localRfnLevelMethods[lvl].substr(patch, 1);
2072 const MInt pos = solver().m_patchRefinement->localRfnLevelPropertiesOffset[lvl] + patch;
2073 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2074 if(solver().grid().tree().level(cellId) > level)
continue;
2075 for(
MInt i = 0; i < nDim; i++) {
2076 coordinates[i] = solver().grid().tree().coordinate(cellId, i);
2077 patchDimensions[i] = solver().m_patchRefinement->localRfnPatchProperties[pos][i];
2078 if(patchStr ==
"B") {
2079 patchDimensions[nDim + i] = solver().m_patchRefinement->localRfnPatchProperties[pos][nDim + i];
2082 MBool keepCell =
false;
2084 if(patchStr ==
"B") {
2085 if(maia::geom::isPointInsideBox<MFloat, nDim>(&coordinates[0], &patchDimensions[0])) {
2088 }
else if(patchStr ==
"R") {
2089 if(maia::geom::isPointInsideSphere<nDim>(&coordinates[0], &patchDimensions[0],
2090 solver().m_patchRefinement->localRfnPatchProperties[pos][nDim])) {
2093 }
else if(patchStr ==
"H") {
2096 std::array<MFloat, nDim> center{};
2097 for(
MInt dim = 0; dim < nDim; dim++) {
2098 center[dim] = solver().m_patchRefinement->localRfnPatchProperties[pos][dim];
2101 std::array<MFloat, 2> R{};
2102 R[0] = solver().m_patchRefinement->localRfnPatchProperties[pos][nDim];
2103 R[1] = solver().m_patchRefinement->localRfnPatchProperties[pos][nDim + 1];
2105 std::array<MFloat, 2> phi{};
2106 phi[0] = solver().m_patchRefinement->localRfnPatchProperties[pos][nDim + 2];
2107 phi[1] = solver().m_patchRefinement->localRfnPatchProperties[pos][nDim + 3];
2109 constexpr MInt axis = 2;
2111 if(maia::geom::isPointInsideRingSegment<nDim>(&coordinates[0], ¢er[0], R.data(), phi.data(), axis)) {
2116 MBool refineCell =
false;
2117 if(keepCell && solver().grid().tree().level(cellId) <= level) {
2123 const MInt gridCellId = grid().tree().solver2grid(cellId);
2124 sensors[sensorOffset + sen][gridCellId] = 1.0;
2125 sensorCellFlag[gridCellId][sensorOffset + sen] =
true;
2126 }
else if(keepCell) {
2127 const MInt gridCellId = grid().tree().solver2grid(cellId);
2128 sensors[sensorOffset + sen][gridCellId] = 0.0;
2129 sensorCellFlag[gridCellId][sensorOffset + sen] =
false;
2135 sensorWeight[sensorOffset + sen] = solver().m_sensorWeight[sen];
2140template <MInt nDim,
class SolverType>
2144 ASSERT(solver().m_cells.size() == 0,
"");
2145 ASSERT(!solver().isActive(),
"");
2147 for(
MInt cellId = 0; cellId < solver().grid().tree().size(); cellId++) {
2148 MInt solverCellId = solver().m_cells.size();
2149 solver().m_cells.append();
2150 solver().a_resetPropertiesSolver(solverCellId);
2151 solver().a_isHalo(solverCellId) =
true;
2153 ASSERT(solver().grid().tree().grid2solver(solver().grid().tree().solver2grid(solverCellId)) == solverCellId,
"");
2160template <MInt nDim,
class SolverType>
2162 m_log <<
" + reading patch refinement properties for solver " << solver().solverId() << std::endl;
2164 mAlloc(m_patchRefinement, 1,
"m_patchRefinement", AT_);
2166 MString localRfnLevelMethods = Context::getSolverProperty<MString>(
"localRfnLvlMethods", solver().solverId(), AT_);
2169 if(localRfnLevelMethods.front() ==
'-' || localRfnLevelMethods.back() ==
'-')
2170 mTerm(1, AT_,
"ERROR: localRfnLvlMethods begins or ends with hyphen!");
2172 if(localRfnLevelMethods.find(
" ") != MString::npos)
mTerm(1, AT_,
"ERROR: localRfnLvlMethods contains space!");
2174 MString::size_type prev_pos = MString::npos;
2175 MString::size_type nextMarker = 0;
2178 while(nextMarker != MString::npos) {
2180 nextMarker = localRfnLevelMethods.find(
"-", prev_pos);
2181 MString substring(localRfnLevelMethods.substr(prev_pos, nextMarker - prev_pos));
2182 m_patchRefinement->localRfnLevelMethods.push_back(substring);
2183 prev_pos = nextMarker;
2187 MInt numPatches = 0;
2188 for(
MInt l = 0; l < m_patchRefinement->noLocalPatchRfnLvls(); l++) {
2189 numPatches += m_patchRefinement->noPatchesPerLevel(l);
2192 m_log <<
" - " << numPatches <<
" Total-Patches. Ranging from level " << solver().maxUniformRefinementLevel()
2193 <<
" - " << solver().maxUniformRefinementLevel() + m_patchRefinement->noLocalPatchRfnLvls() << std::endl;
2196 mAlloc(m_patchRefinement->localRfnLevelPropertiesOffset, m_patchRefinement->noLocalPatchRfnLvls() + 1,
2197 "localRfnLevelPropertiesOffset", 0, AT_);
2200 mAlloc(m_patchRefinement->noLocalRfnPatchProperties, numPatches,
"noLocalRfnPatchProperties", 0, AT_);
2203 m_patchRefinement->localRfnLevelPropertiesOffset[0] = 0;
2206 for(
MInt i = 0; i < m_patchRefinement->noLocalPatchRfnLvls(); i++) {
2207 const MString lvlStr = m_patchRefinement->localRfnLevelMethods[i];
2208 for(MString::size_type j = 0; j < lvlStr.size(); j++) {
2209 const MString patchStr = lvlStr.substr(j, 1);
2210 if(patchStr ==
"B") {
2211 m_patchRefinement->noLocalRfnPatchProperties[s] = 2 * nDim;
2212 }
else if(patchStr ==
"R") {
2213 m_patchRefinement->noLocalRfnPatchProperties[s] = nDim + 1;
2214 }
else if(patchStr ==
"H") {
2215 m_patchRefinement->noLocalRfnPatchProperties[s] = nDim + 4;
2217 mTerm(1, AT_,
"Not yet implemented, please do so...");
2219 count_req += m_patchRefinement->noLocalRfnPatchProperties[s];
2222 m_patchRefinement->localRfnLevelPropertiesOffset[i + 1] = s;
2226 mAlloc(m_patchRefinement->localRfnPatchProperties, numPatches, m_patchRefinement->noLocalRfnPatchProperties,
2227 "localRfnPatchProperties", AT_);
2232 if(count_prov < count_req)
2233 mTerm(1, AT_,
"ERROR: number of localRfnLevelProperties does not match the requested value!");
2238 for(
MInt i = 0; i < count_req; i++) {
2239 m_patchRefinement->localRfnPatchProperties[lvl][j] =
2240 Context::getSolverProperty<MFloat>(
"localRfnLevelProperties", solver().solverId(), AT_, i);
2242 if(j == m_patchRefinement->noLocalRfnPatchProperties[lvl]) {
2249 m_testPatch = Context::getSolverProperty<MBool>(
"testPatchRefinement", solver().solverId(), AT_, &m_testPatch);
2252 m_patchStartTimeStep =
2253 Context::getSolverProperty<MInt>(
"patchStart", solver().solverId(), AT_, &m_patchStartTimeStep);
2254 m_patchStopTimeStep = Context::getSolverProperty<MInt>(
"patchStop", solver().solverId(), AT_, &m_patchStopTimeStep);
2258template <MInt nDim,
class SolverType>
2272 m_adaptation =
false;
2273 m_adaptation = Context::getSolverProperty<MBool>(
"adaptation", solver().solverId(), AT_, &m_adaptation);
2276 m_adapts = Context::getSolverProperty<MBool>(
"solverAdapts", solver().solverId(), AT_, &m_adapts);
2278 m_resTriggeredAdapt =
false;
2279 m_resTriggeredAdapt =
2280 Context::getSolverProperty<MBool>(
"resTriggeredAdaptation", solver().solverId(), AT_, &m_resTriggeredAdapt);
2283 m_noInitialSensors = 0;
2284 m_rfnBandWidth =
nullptr;
2285 m_sensorInterface =
false;
2286 m_sensorParticle =
false;
2288 if(!m_adaptation)
return;
2290 const MInt maxLevel = Context::getSolverProperty<MInt>(
"maxRfnmntLvl", solver().solverId(), AT_);
2292 m_log <<
"##################################################################" << std::endl;
2293 m_log <<
"##################### Adaptation is active #######################" << std::endl;
2294 m_log <<
"##################################################################" << std::endl << std::endl;
2296 solver().m_singleAdaptation =
false;
2297 solver().m_singleAdaptation =
2298 Context::getSolverProperty<MBool>(
"singleAdaptationLoop", solver().solverId(), AT_, &solver().m_singleAdaptation);
2301 "Lenght of sensorType and sensorWeight not equal.");
2308 TERMM(-1,
"sensorWeight property not set!");
2312 "Length of sensorType " + std::to_string(m_noSensors) +
" and sensorWeight "
2315 m_saveSensorData =
false;
2317 m_saveSensorData = Context::getSolverProperty<MBool>(
"saveSensorData", solver().solverId(), AT_);
2320 m_log <<
" * Sensors for adaptive mesh refinement for solver " << solver().solverId() <<
" are active:" << std::endl;
2323 for(
MInt s = 0; s < m_noSensors; s++) {
2324 const MString sensor = Context::getSolverProperty<MString>(
"sensorType", solver().solverId(), AT_, s);
2325 const MFloat weight = Context::getSolverProperty<MFloat>(
"sensorWeight", solver().solverId(), AT_, s);
2326 const MInt level = Context::getSolverProperty<MInt>(
"maxSensorLevel", solver().solverId(), AT_, &maxLevel, s);
2328 m_sensorType.push_back(sensor);
2329 m_sensorWeight.push_back(weight);
2330 m_maxSensorRefinementLevel.push_back(level);
2332 m_log <<
" - sensor: " << sensor << std::endl;
2333 m_log <<
" - Weight: " << weight << std::endl;
2334 m_log <<
" - maxLevel: " << level << std::endl;
2339 "sensorDerivativeVariables not stated for this sensor");
2341 MInt derivative = Context::getSolverProperty<MInt>(
"sensorDerivativeVariables", solver().solverId(), AT_, der);
2342 m_sensorDerivativeVariables.push_back(derivative);
2365 ASSERT(s == 0,
"Interface sensor has to be the first sensor");
2366 m_sensorInterface =
true;
2368 ASSERT((
MInt)m_sensorWeight[s] == -1,
"Must be discrete sensor!");
2369 m_noInitialSensors++;
2373 m_sensorParticle =
true;
2374 ASSERT((
MInt)m_sensorWeight[s] == -1,
"Must be discrete sensor!");
2375 m_noInitialSensors++;
2382 readPatchProperties();
2384 ASSERT(s == 0 || (m_sensorInterface && s == 1),
"");
2385 ASSERT((
MInt)m_sensorWeight[s] == -1,
"Must be discrete sensor!");
2386 m_noInitialSensors++;
2390 m_noInitialSensors++;
2394 m_noInitialSensors++;
2395 m_noSmoothingLayers = Context::getSolverProperty<MInt>(
"smoothingLayers", solver().solverId(), AT_);
2399 m_sensorBandAdditionalLayers = 10;
2400 m_sensorBandAdditionalLayers = Context::getSolverProperty<MInt>(
"sensorBandAdditionalLayers", m_solverId, AT_,
2401 &m_sensorBandAdditionalLayers);
2402 ASSERT(s == (m_noSensors - 1),
"Please ensure this is the last sensor to be called.");
2405 m_sensorDerivativeVariables.push_back(-1);
2406 mTerm(1, AT_,
"Sensor not found! Check property sensorType!");
2422template <MInt nDim,
class SolverType>
2424 std::vector<std::bitset<64>>& sensorCellFlag,
2425 std::vector<MFloat>& sensorWeight,
2430 if(this->m_adaptationStep < (maxRefinementLevel() - minLevel()))
return;
2433 MIntScratchSpace bandWidth(this->m_maxSensorRefinementLevel[sen], AT_,
"bandWidth");
2434 markedCells.
fill(0);
2437 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2438 if(c_level(cellId) != m_maxSensorRefinementLevel[sen])
continue;
2439 markedCells[cellId] = 1;
2440 MInt parentId = c_parentId(cellId);
2441 while(parentId > -1 && parentId < solver().c_noCells()) {
2442 markedCells[parentId] = 1;
2443 parentId = c_parentId(parentId);
2447 bandWidth[this->m_maxSensorRefinementLevel[sen] - 1] =
2448 m_bandWidth[this->m_maxSensorRefinementLevel[sen] - 1] + this->m_sensorBandAdditionalLayers;
2450 for(
MInt i = this->m_maxSensorRefinementLevel[sen] - 2; i >= 0; i--) {
2451 bandWidth[i] = (bandWidth[i + 1] / 2) + this->m_sensorBandAdditionalLayers;
2454 for(
MInt level = minLevel(); level < this->m_maxSensorRefinementLevel[sen]; level++) {
2455 this->markSurrndCells(markedCells, bandWidth[level], level,
true);
2458 MInt refinedCells = 0;
2459 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2460 if(markedCells(cellId) > 0) {
2461 const MInt gridCellId = grid().tree().solver2grid(cellId);
2463 sensors[sensorOffset + sen][gridCellId] = 1;
2464 sensorCellFlag[gridCellId][sensorOffset + sen] =
true;
2465 MInt parent = c_parentId(cellId);
2466 if(parent > -1 && parent < solver().a_noCells()) {
2467 MInt parentGridCellId = grid().tree().solver2grid(parent);
2468 if(parentGridCellId > -1 && parentGridCellId < grid().raw().m_noInternalCells) {
2469 sensors[sensorOffset + sen][parentGridCellId] = 1;
2470 sensorCellFlag[parentGridCellId][sensorOffset + sen] =
true;
2475 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
2491template <MInt nDim,
class SolverType>
2493 std::vector<std::bitset<64>>& sensorCellFlag,
2494 std::vector<MFloat>& sensorWeight,
MInt sensorOffset,
MInt sen,
2496 const MInt* bandWidth,
const MBool refineDiagonals,
2497 const MBool allowCoarsening) {
2500 std::ignore = sensorWeight[sensorOffset];
2503 markedCells.
fill(0);
2505 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2506 if(value(cellId) >= limit) {
2507 markedCells[cellId] = 1;
2508 MInt parentId = c_parentId(cellId);
2509 while(parentId > -1 && parentId < solver().a_noCells()) {
2510 markedCells[parentId] = 1;
2511 parentId = c_parentId(parentId);
2516 exchangeData(&markedCells[0], 1);
2518 for(
MInt level = minLevel(); level < m_maxSensorRefinementLevel[sen]; level++) {
2519 this->markSurrndCells(markedCells, bandWidth[level], level, refineDiagonals);
2522 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2523 if(markedCells(cellId) == 0) {
2524 if(solver().grid().tree().level(cellId) == minLevel())
continue;
2525 if(!solver().c_isLeafCell(cellId))
continue;
2526 if(markedCells[solver().c_parentId(cellId)])
continue;
2527 if(!allowCoarsening)
continue;
2529 const MInt gridCellId = grid().tree().solver2grid(cellId);
2530 sensors[sensorOffset + sen][gridCellId] = -1.0;
2531 sensorCellFlag[gridCellId][sensorOffset + sen] =
true;
2534 if(solver().c_level(cellId) < m_maxSensorRefinementLevel[sen]) {
2537 const MInt gridCellId = grid().tree().solver2grid(cellId);
2538 sensors[sensorOffset + sen][gridCellId] = 1.0;
2539 sensorCellFlag[gridCellId][sensorOffset + sen] =
true;
2541 MInt parent = solver().c_parentId(cellId);
2542 if(parent > -1 && parent < solver().c_noCells()) {
2543 MInt parentGridCellId = grid().tree().solver2grid(parent);
2544 if(parentGridCellId > -1 && parentGridCellId < solver().grid().raw().m_noInternalCells) {
2545 sensors[sensorOffset + sen][parentGridCellId] = 1.0;
2546 sensorCellFlag[parentGridCellId][sensorOffset + sen] =
true;
2565template <MInt nDim,
class SolverType>
2568 const MInt*
const recalcIdsTree) {
2570 ASSERT(nDim == 2 || nDim == 3,
"wrong number of dimensions!");
2573 std::vector<MInt> recalcCellIdsSolver(0);
2575 MInt noInternalCellIds;
2576 std::vector<MInt> reorderedCellIds(0);
2577 this->calcRecalcCellIdsSolver(recalcIdsTree, noCells, noInternalCellIds, recalcCellIdsSolver, reorderedCellIds);
2579 MLong totalNoInternalCells = -1;
2580 const MLong longNoInternalCells = noInternalCellIds;
2581 MPI_Allreduce(&longNoInternalCells, &totalNoInternalCells, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_,
2582 "longNoInternalCells",
"totalNoInternalCells");
2585 std::stringstream fileName;
2586 fileName << outputDir() <<
"sensorData_" << solverId() <<
"_" << std::to_string(level) <<
"_" <<
globalTimeStep
2587 << ParallelIo::fileExt();
2588 ParallelIo parallelIo(fileName.str(), PIO_REPLACE, mpiComm());
2590 parallelIo.defineScalar(PIO_INT,
"noCells");
2591 parallelIo.setAttribute(solverId(),
"solverId");
2592 for(
MUint counter = 0; counter < sensors.size(); counter++) {
2593 const MString arrayName =
"variables" + std::to_string(counter);
2594 parallelIo.defineArray(PIO_FLOAT, arrayName, totalNoInternalCells);
2595 const MString varName =
"sensor_" + m_sensorType[counter];
2596 parallelIo.setAttribute(varName,
"name", arrayName);
2599 parallelIo.setAttribute(gridFileName,
"gridFile",
"");
2600 parallelIo.setAttribute(solver().time(),
"time");
2603 parallelIo.writeScalar(totalNoInternalCells,
"noCells");
2605 ParallelIo::size_type offset = 0;
2606 MPI_Exscan(&longNoInternalCells, &offset, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_,
"longNoInternalCells",
"offset");
2607 const ParallelIo::size_type noInternalCells = longNoInternalCells;
2608 parallelIo.setOffset(noInternalCells, offset);
2610 const MString name =
"variables";
2612 for(
auto&& sensor : sensors) {
2614 for(
MInt cellId = 0; cellId < noInternalCells; cellId++) {
2615 const MInt cellIdRecalc = (recalcIdsTree ==
nullptr) ? cellId : recalcCellIdsSolver[cellId];
2616 const MInt cellIdGrid = grid().tree().solver2grid(cellIdRecalc);
2617 buffer[cellId] = sensor[cellIdGrid];
2619 parallelIo.writeArray(buffer.
data(), name + std::to_string(suffix));
2631template <MInt nDim,
class SolverType>
2633 std::vector<std::bitset<64>>& sensorCellFlag,
2634 std::vector<MFloat>& sensorWeight,
2639 static constexpr MInt noDirs = 2 * nDim;
2640 ASSERT(m_noSmoothingLayers > 0,
"No-smoothing layers not specified!");
2641 static constexpr std::array<MInt, 4> diagDirs{3, 2, 0, 1};
2648 for(
MInt lvl = m_maxSensorRefinementLevel[sen]; lvl > maxUniformRefinementLevel(); lvl--) {
2649 markedCells.
fill(-1.0);
2651 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
2652 markedLevel[cellId] = c_level(cellId);
2657 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2658 if(solver().c_level(cellId) != lvl)
continue;
2659 MBool atLvlJump =
false;
2660 for(
MInt dir = 0; dir < noDirs; dir++) {
2661 if(solver().a_hasNeighbor(cellId, dir))
continue;
2663 if(solver().a_hasNeighbor(c_parentId(cellId), dir)) {
2668 markedCells(c_parentId(cellId)) = 1.0;
2673 exchangeData(&markedCells[0], 1);
2679 for(
MInt loopMarker = 1; loopMarker <= m_noSmoothingLayers + 1; loopMarker++) {
2680 for(
MInt cellId = 0; cellId < solver().c_noCells(); cellId++) {
2681 if((
MInt)floor(markedCells(cellId)) != loopMarker)
continue;
2682 const MInt orgLvl = markedLevel[cellId];
2685 if(solver().c_level(cellId) == orgLvl) {
2686 cellDist = loopMarker + 1;
2689 ASSERT(solver().c_level(cellId) < orgLvl,
"");
2690 cellDist = loopMarker + 2 * (orgLvl - solver().c_level(cellId));
2694 for(
MInt mainDir = 0; mainDir < noDirs; mainDir++) {
2695 MInt nghbrId = solver().c_neighborId(cellId, mainDir);
2697 if(c_parentId(cellId) > -1 && solver().a_hasNeighbor(c_parentId(cellId), mainDir)) {
2698 nghbrId = solver().c_neighborId(c_parentId(cellId), mainDir);
2703 const MFloat nghbDist = markedCells(nghbrId);
2704 if(nghbDist < cellDist) {
2705 markedCells(nghbrId) = cellDist;
2706 markedLevel(nghbrId) = orgLvl;
2708 if(mainDir < 4 && loopMarker < m_noSmoothingLayers) {
2710 MInt nghbrId2 = solver().c_neighborId(nghbrId, diagDirs.at(mainDir));
2712 if(c_parentId(nghbrId) > -1 && solver().a_hasNeighbor(c_parentId(nghbrId), diagDirs.at(mainDir))) {
2713 nghbrId2 = solver().c_neighborId(c_parentId(nghbrId), diagDirs.at(mainDir));
2717 const MFloat nghbDist2 = markedCells(nghbrId2);
2718 if(nghbDist2 < cellDist) {
2719 markedCells(nghbrId2) = cellDist;
2720 markedLevel(nghbrId2) = orgLvl;
2723 IF_CONSTEXPR(nDim == 3) {
2725 for(
MInt dirZ = 4; dirZ < 6; dirZ++) {
2726 MInt nghbrIdZ = solver().c_neighborId(nghbrId, dirZ);
2728 if(c_parentId(nghbrId) > -1 && solver().a_hasNeighbor(c_parentId(nghbrId), dirZ)) {
2729 nghbrIdZ = solver().c_neighborId(c_parentId(nghbrId), dirZ);
2733 const MFloat nghbDistZ = markedCells(nghbrIdZ);
2734 if(nghbDistZ < cellDist) {
2735 markedCells(nghbrIdZ) = cellDist;
2736 markedLevel(nghbrIdZ) = orgLvl;
2744 exchangeData(&markedCells[0], 1);
2748 for(
MInt cellId = 0; cellId < solver().noInternalCells(); cellId++) {
2749 if(markedCells(cellId) < 0)
continue;
2750 if(solver().c_level(cellId) < m_maxSensorRefinementLevel[sen]) {
2751 const MInt gridCellId = grid().tree().solver2grid(cellId);
2754 if(markedLevel[cellId] > solver().c_level(cellId)) {
2755 sensors[sensorOffset + sen][gridCellId] = 1.0;
2756 sensorCellFlag[gridCellId][sensorOffset + sen] =
true;
2758 MInt parent = solver().c_parentId(cellId);
2759 if(parent > -1 && parent < solver().c_noCells()) {
2760 MInt parentGridCellId = grid().tree().solver2grid(parent);
2761 if(parentGridCellId > -1 && parentGridCellId < solver().grid().raw().m_noInternalCells) {
2762 sensors[sensorOffset + sen][parentGridCellId] = 1.0;
2763 sensorCellFlag[parentGridCellId][sensorOffset + sen] =
true;
2770 sensorWeight[sensorOffset + sen] = m_sensorWeight[sen];
2778template <MInt nDim,
class SolverType>
2782 if(grid().newMinLevel() < 0) {
2787 std::map<MLong, MInt> minLevelCells;
2789 for(
MInt cellId = 0; cellId < solver().a_noCells(); cellId++) {
2791 if(grid().tree().hasProperty(cellId, Cell::IsHalo)
2792 && !grid().raw().a_hasProperty(grid().tree().solver2grid(cellId), Cell::IsPartLvlAncestor)) {
2795 if(c_level(cellId) == grid().newMinLevel()) {
2796 const MLong hilbertId = grid().generateHilbertIndex(cellId, grid().newMinLevel());
2797 if(minLevelCells.count(hilbertId) > 0) {
2798 mTerm(1, AT_,
"duplicate hilbertId.");
2800 minLevelCells.insert(std::make_pair(hilbertId, cellId));
2804 const MInt size = minLevelCells.size();
2805 std::vector<MInt> newMinCellOrder;
2806 newMinCellOrder.reserve(size);
2807 for(
auto& minLevelCell : minLevelCells) {
2808 newMinCellOrder.push_back(minLevelCell.second);
2812 reOrderedCells.reserve(size);
2813 for(
auto it = newMinCellOrder.begin(); it != newMinCellOrder.end(); it++) {
2814 reOrderedCells.push_back(*it);
2815 addChildren(reOrderedCells, *it);
2825template <MInt nDim,
class SolverType>
2827 for(
MInt child = 0; child < grid().m_maxNoChilds; child++) {
2828 const MInt childId = grid().tree().child(parentId, child);
2830 if(childId < 0)
continue;
2832 reOrderedIds.push_back(childId);
2834 if(grid().tree().noChildren(childId) > 0) {
2835 addChildren(reOrderedIds, childId);
2844template <MInt nDim,
class SolverType>
2846 std::vector<MLong>& newGlobalIds) {
2847 std::vector<MLong> domainOffsets;
2849 MInt countInternal = 0;
2850 for(
MUint i = 0; i < reOrderedCells.size(); i++) {
2851 if(solver().a_isHalo(reOrderedCells[i]))
continue;
2855 MIntScratchSpace newInternalCells(solver().grid().noDomains(), AT_,
"newInternalCells");
2856 newInternalCells[solver().domainId()] = countInternal;
2858 solver().mpiComm(), AT_,
"MPI_IN_PLACE",
"newInternalCells");
2860 domainOffsets.assign(solver().grid().noDomains() + 1, -1);
2861 domainOffsets[0] = solver().grid().bitOffset();
2862 for(
MInt d = 1; d < solver().grid().noDomains() + 1; d++) {
2863 domainOffsets[d] = domainOffsets[d - 1] + (
MLong)newInternalCells[d - 1];
2866 newGlobalIds.clear();
2867 for(
MUint i = 0; i < reOrderedCells.size(); i++) {
2868 if(solver().a_isHalo(reOrderedCells[i]))
continue;
2869 newGlobalIds.push_back(domainOffsets[solver().domainId()] + i);
2877template <MInt nDim,
class SolverType>
2878template <
typename T>
2880 const std::vector<MString>& variablesNameIn,
2881 std::vector<MString>& variablesNameOut,
const MInt noVars,
2882 const MInt noCells,
const MBool reverseOrder) {
2885 const MInt variablesOffset = variablesNameOut.size();
2886 const MInt noTotalVars = noVars + variablesOffset;
2887 for(
MInt j = variablesOffset; j < noTotalVars; j++) {
2888 const MInt k = j - variablesOffset;
2889 for(
MInt i = 0; i < noCells; i++) {
2891 variablesOut.
p[j * noCells + i] = variablesIn[k * noCells + i];
2893 variablesOut.
p[j * noCells + i] = variablesIn[i * noVars + k];
2896 variablesNameOut.push_back(variablesNameIn[k]);
2905template <MInt nDim,
class SolverType>
2906template <
typename T>
2908 const std::vector<MString>& variablesNameIn,
2909 std::vector<MString>& variablesNameOut,
const MInt noVars,
2910 const MInt noCells) {
2913 const MInt variablesOffset = variablesNameOut.size();
2914 const MInt noTotalVars = noVars + variablesOffset;
2915 for(
MInt j = variablesOffset; j < noTotalVars; j++) {
2916 const MInt k = j - variablesOffset;
2917 for(
MInt i = 0; i < noCells; i++) {
2918 variablesOut.
p[j * noCells + i] = variablesIn[i][k];
2920 variablesNameOut.push_back(variablesNameIn[k]);
2928template <MInt nDim,
class SolverType>
2929template <
typename T>
2931 const MChar* parametersNameIn,
2932 std::vector<MString>& parametersNameOut) {
2935 const MInt parsOffset = parametersNameOut.size();
2936 parametersOut.
p[parsOffset] = parametersIn;
2937 parametersNameOut.push_back(parametersNameIn);
2948template <MInt nDim,
class SolverType>
2950 MInt& noInternalCellIds,
2951 std::vector<MInt>& recalcCellIdsSolver,
2952 std::vector<MInt>& reorderedCellIds) {
2953 MBool needRecalcCellIdsSolver = (recalcIdsTree !=
nullptr);
2954 noCells = noInternalCells();
2955 noInternalCellIds = noInternalCells();
2957 if(grid().newMinLevel() > 0) {
2958 if(domainId() == 0) {
2959 std::cerr <<
"Increasing minLevel for solver " << m_solverId << std::endl;
2961 this->reOrderCellIds(reorderedCellIds);
2962 MInt countInternal = 0;
2963 for(
MUint i = 0; i < reorderedCellIds.size(); i++) {
2964 if(grid().tree().hasProperty(reorderedCellIds[i], Cell::IsHalo)) {
2969 needRecalcCellIdsSolver =
false;
2970 noCells = reorderedCellIds.size();
2971 noInternalCellIds = countInternal;
2974 if(needRecalcCellIdsSolver) {
2975 recalcCellIdsSolver.resize(grid().tree().size());
2977 MInt recalcCounter = 0;
2978 for(
MInt cellIdGrid = 0; cellIdGrid < grid().raw().noInternalCells(); cellIdGrid++) {
2979 if(grid().raw().a_hasProperty(cellIdGrid, Cell::IsHalo)) {
2982 const MInt cellIdSolver = grid().tree().grid2solver(recalcIdsTree[cellIdGrid]);
2983 if(cellIdSolver > -1) {
2984 recalcCellIdsSolver[recalcCounter] = cellIdSolver;
2986 ASSERT(grid().solverFlag(recalcIdsTree[cellIdGrid], m_solverId),
"");
2989 ASSERT(recalcCounter == grid().noInternalCells(),
"recalc ids size is wrong");
2993 MInt internalGCells = 0;
2994 for(
MInt k = 0; k < a_noCells(); ++k) {
2995 if(grid().tree().hasProperty(k, Cell::IsHalo))
continue;
2998 ASSERT(internalGCells == noInternalCells(),
"");
3007template <MInt nDim,
class SolverType>
3009 const MChar* fileName,
const MChar* gridFileName,
const MInt noTotalCells,
const MInt noInternal,
3013 std::vector<MString>& idParametersName,
MInt* recalcIds,
MFloat time) {
3016 MString tmpNcVariablesName =
"";
3017 noDbVars = dbVariablesName.size();
3018 noIdVars = idVariablesName.size();
3019 MInt noIdPars = idParametersName.size();
3020 MInt noDbPars = dbParametersName.size();
3021 std::vector<MString> ncVariablesName;
3023 MInt* tmpIdVariables;
3026 ParallelIo parallelIo(fileName, PIO_REPLACE, solver().mpiComm());
3029 MLong longNoInternalCells = (
MLong)noInternal;
3030 MPI_Allreduce(&longNoInternalCells, &num, 1, MPI_LONG, MPI_SUM, solver().mpiComm(), AT_,
"noInternalCells",
"num");
3032 for(
MInt j = 0; j < noDbVars; j++) {
3033 tmpNcVariablesName =
"variables" + std::to_string(j);
3034 ncVariablesName.push_back(tmpNcVariablesName);
3035 parallelIo.defineArray(PIO_FLOAT, ncVariablesName[j], num);
3036 m_log << dbVariablesName[j].c_str() << std::endl;
3037 parallelIo.setAttribute(dbVariablesName[j],
"name", ncVariablesName[j]);
3040 for(
MInt j = 0; j < noIdVars; j++) {
3042 tmpNcVariablesName =
"variables" + std::to_string(k);
3043 ncVariablesName.push_back(tmpNcVariablesName);
3044 parallelIo.defineArray(PIO_INT, ncVariablesName[k], num);
3045 parallelIo.setAttribute(idVariablesName[j],
"name", ncVariablesName[k]);
3048 for(
MInt j = 0; j < noIdPars; j++) {
3049 parallelIo.defineScalar(PIO_INT, idParametersName[j]);
3052 for(
MInt j = 0; j < noDbPars; j++) {
3053 parallelIo.defineScalar(PIO_FLOAT, dbParametersName[j]);
3056 parallelIo.setAttribute(gridFileName,
"gridFile");
3058 parallelIo.setAttribute(solver().solverId(),
"solverId");
3060 parallelIo.setAttribute(num,
"noCells");
3063 parallelIo.setAttribute(time,
"levelSetTime");
3066 ParallelIo::size_type start = 0;
3067 ParallelIo::size_type count = 1;
3069 MInt noInternalCellIds = noInternal;
3070 MPI_Exscan(&noInternalCellIds, &start, 1, MPI_INT, MPI_SUM, solver().mpiComm(), AT_,
"noInternalCellIds",
"start");
3071 count = noInternalCellIds;
3073 parallelIo.setOffset(count, start);
3075 for(
MInt j = 0; j < noDbVars; j++) {
3076 tmpDbVariables = &(dbVariables.
p[j * noTotalCells]);
3078 if(recalcIds !=
nullptr) {
3079 for(
MInt l = 0; l < count; ++l) {
3080 tmpDouble[l] = tmpDbVariables[recalcIds[l]];
3083 for(
MInt l = 0; l < count; ++l) {
3084 tmpDouble[l] = tmpDbVariables[l];
3087 parallelIo.writeArray(tmpDouble.
begin(), ncVariablesName[j]);
3090 for(
MInt j = 0; j < noIdVars; j++) {
3091 tmpIdVariables = &(idVariables.
p[j * noTotalCells]);
3093 if(recalcIds !=
nullptr) {
3094 for(
MInt l = 0; l < count; ++l) {
3095 tmpInt[l] = tmpIdVariables[recalcIds[l]];
3098 for(
MInt l = 0; l < count; ++l) {
3099 tmpInt[l] = tmpIdVariables[l];
3102 parallelIo.writeArray(tmpInt.
begin(), ncVariablesName[j + noDbVars]);
3105 for(
MInt j = 0; j < noIdPars; j++) {
3106 parallelIo.writeScalar(idParameters.
p[j], idParametersName[j]);
3109 for(
MInt j = 0; j < noDbPars; j++) {
3110 parallelIo.writeScalar(dbParameters.
p[j], dbParametersName[j]);
3125template <MInt nDim,
class SolverType>
3126template <
typename T>
3129 if(noNeighborDomains() == 0) {
3133 maia::mpi::exchangeData(solver().grid().neighborDomains(), solver().grid().haloCells(), solver().grid().windowCells(),
3134 solver().mpiComm(), data, dataBlockSize);
3146template <MInt nDim,
class SolverType>
3147template <
typename T>
3151 if(grid().noDomains() < 2) {
3155 const MInt tag = 613;
3157 ScratchSpace<T> receiveBuffer(noDat * grid().leafRecSize(), AT_,
"windowBuffer");
3158 ScratchSpace<T> sendBuffer(noDat * grid().leafSendSize(), AT_,
"windowBuffer");
3164 MInt receiveCount = 0;
3165 for(
MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
3166 const MInt d = grid().leafRecvNeighborDomain(n);
3167 MPI_Irecv(&(receiveBuffer[receiveCount]), noDat * grid().noLeafHaloCells(d), DTYPE, grid().neighborDomain(d), tag,
3168 grid().mpiComm(), &recvRequests[n], AT_,
"receiveBuffer");
3169 receiveCount += noDat * grid().noLeafHaloCells(d);
3174 for(
MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
3175 const MInt d = grid().leafSendNeighborDomain(n);
3176 for(
MInt j = 0; j < grid().noLeafWindowCells(d); j++) {
3177 const MInt cellId = grid().leafWindowCell(d, j);
3178 for(
MInt k = 0; k < noDat; k++) {
3179 sendBuffer[sendCount] = data(cellId, k);
3187 for(
MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
3188 const MInt d = grid().leafSendNeighborDomain(n);
3189 MPI_Isend(&sendBuffer[sendCount], noDat * grid().noLeafWindowCells(d), DTYPE, grid().neighborDomain(d), tag,
3190 grid().mpiComm(), &sendRequests[n], AT_,
"&sendBuffer[sendCount]");
3191 sendCount += noDat * grid().noLeafWindowCells(d);
3195 MPI_Waitall(grid().noLeafRecvNeighborDomains(), &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
3199 for(
MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
3200 const MInt d = grid().leafRecvNeighborDomain(n);
3201 for(
MInt j = 0; j < grid().noLeafHaloCells(d); j++) {
3202 const MInt cellId = grid().leafHaloCell(d, j);
3203 for(
MInt k = 0; k < noDat; k++) {
3204 data(cellId, k) = receiveBuffer(recvCount);
3210 MPI_Waitall(grid().noLeafSendNeighborDomains(), &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
3227template <MInt nDim,
class SolverType>
3228template <
class G,
class S,
class M>
3233 auto* mpi_send_req =
new MPI_Request[grid().noNeighborDomains()];
3234 auto* mpi_recv_req =
new MPI_Request[grid().noNeighborDomains()];
3236 MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_,
"sendBufferSize");
3237 MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_,
"receiveBufferSize");
3239 MIntScratchSpace sendBuffersInt(grid().noNeighborDomains(), AT_,
"sendBuffersInt");
3240 MIntScratchSpace receiveBuffersInt(grid().noNeighborDomains(), AT_,
"receiveBuffersInt");
3242 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3243 mpi_send_req[i] = MPI_REQUEST_NULL;
3244 mpi_recv_req[i] = MPI_REQUEST_NULL;
3248 MInt sendBufferCounter;
3249 MInt sendBufferCounterOverall = 0;
3250 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3251 sendBufferCounter = 0;
3252 sendBufferCounter++;
3253 for(
MInt j = 0; j < grid().noLeafWindowCells(i); j++) {
3254 const MInt cellId = grid().leafWindowCell(i, j);
3255 const MInt index = cellMapping(cellId, 0);
3256 if(index < 0)
continue;
3257 for(
MInt d = 0; d < dataSize; d++) {
3258 ASSERT(!std::isnan(getData(index, d)), grid().tree().globalId(cellId));
3262 sendBufferCounter++;
3265 sendBufferCounter += dataSize;
3267 sendBufferSize[i] = sendBufferCounter;
3268 sendBuffersInt[i] = sendBufferCounter;
3269 sendBufferCounterOverall += sendBufferCounter;
3273 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3274 MPI_Irecv(&receiveBuffersInt[i], 1, MPI_INT, grid().neighborDomain(i), 2, grid().mpiComm(), &mpi_recv_req[i], AT_,
3275 "receiveBuffers[i]");
3277 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3278 MPI_Isend(&sendBuffersInt[i], 1, MPI_INT, grid().neighborDomain(i), 2, grid().mpiComm(), &mpi_send_req[i], AT_,
3279 "sendBuffersInt[i]");
3281 MPI_Waitall(grid().noNeighborDomains(), mpi_recv_req, MPI_STATUSES_IGNORE, AT_);
3282 MPI_Waitall(grid().noNeighborDomains(), mpi_send_req, MPI_STATUSES_IGNORE, AT_);
3285 MInt receiveBufferCounterOverall = 0;
3286 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3287 receiveBufferCounterOverall += receiveBuffersInt[i];
3288 receiveBufferSize[i] = receiveBuffersInt[i];
3291 MFloatScratchSpace sendBuffersOverall(sendBufferCounterOverall, AT_,
"sendBuffersOverall");
3292 MFloatScratchSpace receiveBuffersOverall(receiveBufferCounterOverall, AT_,
"receiveBuffersOverall");
3295 MInt counterSend = 0;
3296 MInt counterReceive = 0;
3297 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3298 sendBuffers.
p[i] = &sendBuffersOverall.
p[counterSend];
3299 counterSend += sendBufferSize[i];
3300 receiveBuffers.
p[i] = &receiveBuffersOverall.
p[counterReceive];
3301 counterReceive += receiveBufferSize[i];
3305 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3306 mpi_send_req[i] = MPI_REQUEST_NULL;
3307 mpi_recv_req[i] = MPI_REQUEST_NULL;
3311 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3312 sendBufferCounter = 0;
3313 sendBuffers[i][0] = (
MFloat)(-1);
3314 sendBufferCounter++;
3315 for(
MInt j = 0; j < grid().noLeafWindowCells(i); j++) {
3316 const MInt cellId = grid().leafWindowCell(i, j);
3317 const MInt index = cellMapping(cellId, 0);
3318 if(index < 0)
continue;
3320 sendBuffers[i][sendBufferCounter] = (
MFloat)j;
3321 sendBufferCounter++;
3323 for(
MInt d = 0; d < dataSize; d++) {
3324 ASSERT(!std::isnan(getData(index, d)),
"");
3325 sendBuffers[i][sendBufferCounter] = getData(index, d);
3326 sendBufferCounter++;
3329 sendBufferSize[i] = sendBufferCounter;
3330 sendBuffers[i][0] = (
MFloat)(sendBufferCounter);
3335 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3336 MInt bufSize = receiveBufferSize[i];
3337 MPI_Irecv(receiveBuffers[i], bufSize, MPI_DOUBLE, grid().neighborDomain(i), 2, grid().mpiComm(), &mpi_recv_req[i],
3338 AT_,
"receiveBuffers[i]");
3342 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3343 MInt bufSize = sendBufferSize[i];
3344 MPI_Isend(sendBuffers[i], bufSize, MPI_DOUBLE, grid().neighborDomain(i), 2, grid().mpiComm(), &mpi_send_req[i], AT_,
3347 MPI_Waitall(grid().noNeighborDomains(), mpi_recv_req, MPI_STATUSES_IGNORE, AT_);
3348 MPI_Waitall(grid().noNeighborDomains(), mpi_send_req, MPI_STATUSES_IGNORE, AT_);
3351 MInt receiveBufferCounter = 0;
3353 for(
MInt i = 0; i < grid().noNeighborDomains(); i++) {
3354 receiveBufferCounter = 0;
3355 if(receiveBufferSize[i] != receiveBuffersInt[i]) {
3356 mTerm(1, AT_,
" receiveBufferSize doesn't match expected size from previous communication! ");
3358 if(receiveBufferSize[i] == 0) {
3359 m_log <<
"Warning: empty message from rank " << grid().neighborDomain(i) << std::endl;
3361 receiveBufferCounter++;
3362 while(receiveBufferCounter < receiveBufferSize[i]) {
3363 j = (
MInt)receiveBuffers[i][receiveBufferCounter];
3364 receiveBufferCounter++;
3365 const MInt cellId = grid().leafHaloCell(i, j);
3368 if(cellId > grid().tree().size()) skip =
true;
3375 const MInt index = cellMapping(cellId, 0);
3377 ASSERT(index > -1,
"No corresponding halo cell found!");
3380 for(
MInt d = 0; d < dataSize; d++) {
3381 setData(index, d) = receiveBuffers[i][receiveBufferCounter];
3382 receiveBufferCounter++;
3386 receiveBufferCounter += dataSize;
3391 delete[] mpi_send_req;
3392 delete[] mpi_recv_req;
3406template <MInt nDim,
class SolverType>
3407template <
typename T>
3411 if(grid().noAzimuthalNeighborDomains() == 0) {
3416 ScratchSpace<T> windowData(sndSize * dataBlockSize, AT_,
"windowData");
3423 if(std::is_same<T, MInt>::value || std::is_same<T, MBool>::value || std::is_same<T, MLong>::value) {
3424 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
3425 for(
MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
3426 MInt windowId = grid().azimuthalWindowCell(i, j);
3427 for(
MInt b = firstBlock;
b < firstBlock + dataBlockSize;
b++) {
3428 windowData[sndCnt] = data[windowId * dataBlockSize +
b];
3433 }
else if(std::is_same<T, MFloat>::value) {
3435 return static_cast<MBool>(grid().tree().hasNeighbor(cell,
id));
3438 return static_cast<MFloat>(grid().tree().coordinate(cell,
id));
3441 return data[cell * dataBlockSize +
id];
3444 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
3445 for(
MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
3446 MInt windowId = grid().azimuthalWindowCell(i, j);
3447 std::array<MFloat, nDim> recCoord;
3448 std::copy_n(&(solver().m_azimuthalCartRecCoord[cellCnt * nDim]), nDim, &recCoord[0]);
3451 const MInt magic_number = 8;
3452 std::array<MInt, magic_number> interpolationCells = {0, 0, 0, 0, 0, 0, 0, 0};
3454 setUpInterpolationStencil(windowId, interpolationCells.data(), recCoord.data(), neighborCheck,
false);
3455 for(
MInt b = firstBlock;
b < firstBlock + dataBlockSize;
b++) {
3457 windowData[sndCnt] =
3458 interpolateFieldData<true>(&interpolationCells[0], &recCoord[0],
b, scalarField, coordinate);
3460 windowData[sndCnt] = scalarField(windowId,
b);
3468 mTerm(1, AT_,
"Non implemented data type.");
3478 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
3479 for(
MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
3480 MInt haloId = grid().azimuthalHaloCell(i, j);
3482 for(
MInt b = firstBlock;
b < firstBlock + dataBlockSize;
b++) {
3483 data[haloId * dataBlockSize +
b] = haloData[rcvCnt * dataBlockSize +
b];
3491 const MInt magic_number = 126;
3493 for(
MInt i = 0; i < grid().noAzimuthalUnmappedHaloCells(); i++) {
3494 MInt haloId = grid().azimuthalUnmappedHaloCell(i);
3496 MInt counter = grid().getAdjacentGridCells(haloId, 2, nghbrList, grid().tree().level(haloId), 0);
3497 for(
MInt n = 0; n < counter; n++) {
3498 MInt nghbrId = nghbrList[n];
3502 for(
MInt b = firstBlock;
b < firstBlock + dataBlockSize;
b++) {
3503 data[haloId * dataBlockSize +
b] = data[nghbrId * dataBlockSize +
b];
3509 std::cerr <<
"Unmapped not set:" << domainId() <<
" " << haloId <<
" " << grid().tree().coordinate(haloId, 0)
3510 <<
" " << grid().tree().coordinate(haloId, 1) <<
" " << grid().tree().coordinate(haloId, 2)
3513 ASSERT(valueSet,
"No value set!");
3523template <MInt nDim,
class Solver>
3526 const MBool extractHaloCells,
3527 const std::map<MInt, MInt>& splitChildToSplitCell,
3536 for(
MInt cellId = 0; cellId < solver().c_noCells(); cellId++) {
3537 ASSERT(solver().a_hasProperty(cellId, FvCell::IsSplitChild)
3538 ? splitChildToSplitCell.count(cellId) == 1
3539 && splitChildToSplitCell.find(cellId)->second < solver().c_noCells()
3540 && splitChildToSplitCell.find(cellId)->second > -1
3542 "associated BndryCell for splitChild is missing.");
3548 const MInt noCells = solver().c_noCells();
3549 const MInt maxNoGridPoints = noCells + (noCells / 2);
3551 const MInt sign[8][3] = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1},
3552 {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};
3553 const MFloat DX = solver().c_cellLengthAtLevel(maxRefinementLevel());
3554 const MFloat EPS = 0.1 * DX;
3557 for(
MInt l = 0; l <= maxRefinementLevel(); l++) {
3558 cellLength.
p[l] = solver().c_cellLengthAtLevel(l);
3561 if(bBox ==
nullptr) {
3562 bBox = &bbox_mem[0];
3563 solver().geometry().getBoundingBox(bBox);
3564 for(
MInt i = 0; i < nDim; i++) {
3565 bBox[i] = bBox[i] - F1B2 * cellLength(maxUniformRefinementLevel());
3566 bBox[nDim + i] = bBox[nDim + i] + F1B2 * cellLength(maxUniformRefinementLevel());
3570 for(
MInt i = 0; i < nDim; i++) {
3572 bBox[nDim + i] += EPS;
3575 bbox2[i] = bBox[i] - cellLength(maxUniformRefinementLevel());
3576 bbox2[nDim + i] = bBox[nDim + i] + cellLength(maxUniformRefinementLevel());
3580 if(levelThreshold < minLevel()) {
3582 std::cerr <<
"level threshold reset to minimum refinement level, since it was below." << std::endl;
3583 levelThreshold = minLevel();
3586 cellIsActive.
fill(
false);
3587 for(
MInt cellId = 0; cellId < noCells; cellId++) {
3588 if(solver().a_isBndryGhostCell(cellId))
continue;
3589 if(!solver().a_hasProperty(cellId, FvCell::IsOnCurrentMGLevel))
continue;
3590 if(!solver().a_hasProperty(cellId, FvCell::IsSplitChild) && solver().c_noChildren(cellId) > 0)
continue;
3591 cellIsActive(cellId) =
true;
3592 MInt parentId = solver().a_hasProperty(cellId, FvCell::IsSplitChild) ? splitChildToSplitCell.find(cellId)->second
3593 : c_parentId(cellId);
3594 while(parentId > -1) {
3595 cellIsActive(parentId) =
true;
3596 parentId = c_parentId(parentId);
3601 for(
MInt i = 0; i < nDim; i++)
3602 N[i] = 1 + (
size_t)((bbox2[nDim + i] - bbox2[i]) / DX);
3603 if(N[0] * N[1] * N[2] > std::numeric_limits<MUlong>::max()) {
3604 std::cerr <<
"Warning: MUlong exceeded by hash function!" << std::endl;
3606 std::unordered_map<size_t, MInt> table;
3610 if(extractedCells) {
3611 std::cerr <<
"Warning: extractedCells is not a nullptr pointer as expected." << std::endl;
3612 delete extractedCells;
3613 extractedCells =
nullptr;
3616 std::cerr <<
"Warning: gridPoints is not a nullptr pointer as expected." << std::endl;
3618 gridPoints =
nullptr;
3622 if(!extractedCells) {
3623 mTerm(1, AT_,
"Allocation of extractedCells failed.");
3626 mTerm(1, AT_,
"Allocation of gridPoints failed.");
3631 MInt noExtractedCells = 0;
3632 extractedCells->resetSize(0);
3633 for(
MInt cellId = 0; cellId < noCells; cellId++) {
3634 if(a_isBndryGhostCell(cellId))
continue;
3636 if((solver().a_hasProperty(cellId, FvCell::IsSplitChild) || solver().c_noChildren(cellId) == 0)
3637 && !solver().a_hasProperty(cellId, FvCell::IsOnCurrentMGLevel))
3639 if(!solver().a_hasProperty(cellId, FvCell::IsSplitChild) && solver().c_noChildren(cellId) > 0
3640 && solver().a_level(cellId) < levelThreshold)
3642 if(solver().a_level(
3643 solver().a_hasProperty(cellId, FvCell::IsSplitChild) ? splitChildToSplitCell.find(cellId)->second : cellId)
3646 if(levelSetMb && !cellIsActive(cellId))
continue;
3647 if(!( extractHaloCells)
3648 && solver().a_isHalo(cellId)) {
3651 if(solver().a_level(
3652 solver().a_hasProperty(cellId, FvCell::IsSplitChild) ? splitChildToSplitCell.find(cellId)->second : cellId)
3653 <
mMin(maxUniformRefinementLevel(), levelThreshold))
3656 if(solver().a_hasProperty(cellId, FvCell::IsSplitCell))
continue;
3659 MBool outside =
false;
3660 for(
MInt i = 0; i < nDim; i++) {
3661 if(solver().a_coordinate(cellId, i) < bBox[i] || solver().a_coordinate(cellId, i) > bBox[nDim + i])
3665 if(grid().azimuthalPeriodicity() && solver().a_isPeriodic(cellId)) {
3669 if(outside)
continue;
3670 extractedCells->append();
3671 extractedCells->a[noExtractedCells].m_cellId = cellId;
3672 for(
MInt p = 0; p < noPoints; p++) {
3673 extractedCells->a[noExtractedCells].m_pointIds[p] = -1;
3681 for(
MInt c = 0; c < noExtractedCells; c++) {
3682 const MInt cellId = extractedCells->a[c].m_cellId;
3683 for(
MInt p = 0; p < noPoints; p++) {
3684 MInt gridPointId = -1;
3685 MFloat coords[3] = {std::numeric_limits<MFloat>::max(), std::numeric_limits<MFloat>::max(),
3686 std::numeric_limits<MFloat>::max()};
3687 size_t index[3] = {0, 0, 0};
3689 for(
MInt i = 0; i < nDim; i++) {
3690 coords[i] = solver().a_coordinate(cellId, i)
3692 * cellLength.
p[solver().a_level(solver().a_hasProperty(cellId, FvCell::IsSplitChild)
3693 ? splitChildToSplitCell.find(cellId)->second
3695 ASSERT(coords[i] + EPS > bbox2[i] && coords[i] - EPS < bbox2[nDim + i],
3696 std::to_string(cellId) <<
" "
3698 solver().a_level(solver().a_hasProperty(cellId, FvCell::IsSplitChild)
3699 ? splitChildToSplitCell.find(cellId)->second
3701 <<
" " << std::to_string(i) <<
" " << std::to_string(EPS) <<
" "
3702 << std::to_string(coords[i]) <<
" " << std::to_string(bbox2[i]) <<
" "
3703 << std::to_string(bbox2[nDim + i]));
3704 index[i] = (size_t)((coords[i] - bbox2[i] + EPS) / DX);
3707 for(
MInt i = 0; i < nDim; i++) {
3708 coords[i] = solver().a_coordinate(cellId, i) + sign[p][i] * F1B2 * cellLength.
p[solver().a_level(cellId)];
3709 ASSERT(coords[i] + EPS > bbox2[i] && coords[i] - EPS < bbox2[nDim + i],
3710 std::to_string(cellId) <<
" " << std::to_string(solver().a_level(cellId)) <<
" " << std::to_string(i)
3711 <<
" " << std::to_string(EPS) <<
" " << std::to_string(coords[i]) <<
" "
3712 << std::to_string(bbox2[i]) <<
" " << std::to_string(bbox2[nDim + i]));
3713 index[i] = (size_t)((coords[i] - bbox2[i] + EPS) / DX);
3716 size_t key = index[0] + N[0] * index[1] + N[0] * N[1] * index[2];
3717 std::pair<typename std::unordered_map<size_t, MInt>::iterator,
MBool> ret = table.insert(std::make_pair(key, -1));
3719 gridPointId = gridPoints->
size();
3720 ASSERT(gridPointId < maxNoGridPoints,
"");
3722 gridPoints->
a[gridPointId].m_noAdjacentCells = 0;
3723 for(
MInt i = 0; i < noPoints; i++)
3724 gridPoints->
a[gridPointId].m_cellIds[i] = -1;
3725 for(
MInt i = 0; i < nDim; i++)
3726 gridPoints->
a[gridPointId].m_coordinates[i] = coords[i];
3727 ret.first->second = gridPointId;
3729 ASSERT(gridPointId < maxNoGridPoints,
"");
3730 gridPointId = ret.first->second;
3732 ASSERT(gridPointId > -1 && gridPointId < maxNoGridPoints,
"");
3733 extractedCells->a[c].m_pointIds[p] = gridPointId;
3735 (solver().a_hasProperty(cellId, FvCell::IsSplitChild)) ? splitChildToSplitCell.find(cellId)->second : cellId;
3736 MBool found =
false;
3737 for(
MInt n = 0; n < gridPoints->
a[gridPointId].m_noAdjacentCells; n++) {
3738 if(gridPoints->
a[gridPointId].m_cellIds[n] == rootId) found =
true;
3743 if(gridPoints->
a[gridPointId].m_noAdjacentCells <
IPOW2(nDim)) {
3744 gridPoints->
a[gridPointId].m_cellIds[gridPoints->
a[gridPointId].m_noAdjacentCells] = rootId;
3745 gridPoints->
a[gridPointId].m_noAdjacentCells++;
3747 std::cerr <<
"Warning: grid point with more than " <<
IPOW2(nDim)
3748 <<
" neighbor cells: " << gridPoints->
a[gridPointId].m_noAdjacentCells << std::endl;
3751 for(
MInt p = 0; p < noPoints; p++) {
3752 if(extractedCells->a[c].m_pointIds[p] < 0) {
3753 std::cerr <<
"Warning: no point for cell " << cellId <<
" " << p << std::endl;
3760 if(!extractHaloCells) {
3761 for(
MInt d = 0; d < noNeighborDomains(); d++) {
3762 for(
MInt c = 0; c < noHaloCells(d); c++) {
3763 MInt cellId = haloCellId(d, c);
3765 if((solver().a_hasProperty(cellId, FvCell::IsSplitChild) || solver().c_noChildren(cellId) == 0)
3766 && !solver().a_hasProperty(cellId, FvCell::IsOnCurrentMGLevel))
3768 if((!solver().a_hasProperty(cellId, FvCell::IsSplitChild) || solver().c_noChildren(cellId) > 0)
3769 && solver().a_level(cellId) < levelThreshold)
3771 if(levelSetMb && !cellIsActive(cellId))
continue;
3772 if(solver().a_hasProperty(cellId, FvCell::IsNotGradient))
continue;
3774 if(solver().a_hasProperty(cellId, FvCell::IsSplitCell))
continue;
3775 if(solver().a_level(solver().a_hasProperty(cellId, FvCell::IsSplitChild)
3776 ? splitChildToSplitCell.find(cellId)->second
3781 MBool outside =
false;
3782 for(
MInt i = 0; i < nDim; i++)
3783 if(solver().a_coordinate(cellId, i) < bBox[i] || solver().a_coordinate(cellId, i) > bBox[nDim + i])
3785 if(outside)
continue;
3786 for(
MInt p = 0; p < noPoints; p++) {
3787 MInt gridPointId = -1;
3789 size_t index[3] = {0, 0, 0};
3791 for(
MInt i = 0; i < nDim; i++) {
3792 coords[i] = solver().a_coordinate(cellId, i)
3794 * cellLength.
p[solver().a_level(solver().a_hasProperty(cellId, FvCell::IsSplitChild)
3795 ? splitChildToSplitCell.find(cellId)->second
3797 ASSERT(coords[i] + EPS > bbox2[i] && coords[i] - EPS < bbox2[nDim + i],
"");
3798 index[i] = (size_t)((coords[i] - bbox2[i] + EPS) / DX);
3801 for(
MInt i = 0; i < nDim; i++) {
3802 coords[i] = solver().a_coordinate(cellId, i) + sign[p][i] * F1B2 * cellLength.
p[solver().a_level(cellId)];
3803 ASSERT(coords[i] + EPS > bbox2[i] && coords[i] - EPS < bbox2[nDim + i],
"");
3804 index[i] = (size_t)((coords[i] - bbox2[i] + EPS) / DX);
3807 size_t key = index[0] + N[0] * index[1] + N[0] * N[1] * index[2];
3808 std::pair<typename std::unordered_map<size_t, MInt>::iterator,
MBool> ret =
3809 table.insert(std::make_pair(key, -1));
3813 ASSERT(gridPointId < maxNoGridPoints,
"");
3814 gridPointId = ret.first->second;
3816 if(gridPointId < 0)
continue;
3817 ASSERT(gridPointId > -1 && gridPointId < maxNoGridPoints, std::to_string(gridPointId));
3818 ASSERT(gridPoints->
a[gridPointId].m_noAdjacentCells > -1
3819 && gridPoints->
a[gridPointId].m_noAdjacentCells <
IPOW2(nDim),
3820 std::to_string(gridPoints->
a[gridPointId].m_noAdjacentCells));
3821 gridPoints->
a[gridPointId].m_cellIds[gridPoints->
a[gridPointId].m_noAdjacentCells] = cellId;
3822 gridPoints->
a[gridPointId].m_noAdjacentCells++;
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
GridCell
Grid cell Property Labels.
This class defines a grid point, grid cells consist of.
MInt resetSize(MInt inputSize)
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.
virtual MInt getIntersectionElements(MFloat *, std::vector< MInt > &)
This class defines a grid cell which is a internal data structure for cartesian cells needed for an e...
static MString printSelfReport()
Returns a shortened string summing up the scratch space state information.
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
void fill(T val)
fill the scratch with a given value
pointer p
Deprecated: use [] instead!
Parent class of all solvers This class is the base for all solvers. I.e. all solver class (e....
virtual MFloat time() const =0
Return the time.
virtual MInt domainId() const
Return the domainId (rank)
MInt solverId() const
Return the solverId.
void exchangeLeafData(std::function< T &(MInt, MInt)> data, const MInt noDat=1)
Blocking exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell NOTE: exchange ...
virtual void sensorCutOff(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
void sensorBand(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
This sensor generates a max refinement band around the cells with max refinement level....
virtual void sensorDerivative(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
virtual void sensorVorticity(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
MLong c_parentId(const MInt cellId) const
Returns the grid parent id of the cell cellId.
MInt setUpInterpolationStencil(const MInt cellId, MInt *, const MFloat *, std::function< MBool(MInt, MInt)>, MBool allowIncompleteStencil)
MString gridInputFileName() const
void removeCellId(const MInt cellId)
MInt noWindowCells(const MInt domainId) const
constexpr const SolverType & solver() const
MInt minLevel() const
Read-only accessors for grid data.
constexpr GridProxy & grid() const
std::vector< MFloat > m_azimuthalCartRecCoord
MLong domainOffset(const MInt id) const
typename maia::grid::Proxy< nDim > GridProxy
void saveGridFlowVars(const MChar *fileName, const MChar *gridFileName, const MInt noTotalCells, const MInt noInternal, MFloatScratchSpace &dbVariables, std::vector< MString > &dbVariablesName, MInt noDbVars, MIntScratchSpace &idVariables, std::vector< MString > &idVariablesName, MInt noIdVars, MFloatScratchSpace &dbParameters, std::vector< MString > &dbParametersName, MIntScratchSpace &idParameters, std::vector< MString > &idParametersName, MInt *recalcIds, MFloat time)
This function writes the parallel Netcdf cartesian grid cell based solution/restart file currently us...
void assertValidGridCellId(const MInt) const
void collectVariables(T *variablesIn, ScratchSpace< T > &variablesOut, const std::vector< MString > &variablesNameIn, std::vector< MString > &variablesNameOut, const MInt noVars, const MInt noCells, const MBool reverseOrder=false)
generalised helper function for writing restart files! This is necessary for example if the minLevel ...
MBool m_resTriggeredAdapt
MInt maxRefinementLevel() const
void extractPointIdsFromGrid(Collector< PointBasedCell< nDim > > *&, Collector< CartesianGridPoint< nDim > > *&, const MBool, const std::map< MInt, MInt > &, MInt levelThreshold=999999, MFloat *bBox=nullptr, MBool levelSetMb=false) const
Creates a list of unique corner points for all cells using a hash map levelThreshold optionally speci...
MInt m_patchStartTimeStep
void receiveWindowTriangles()
Receives triangles from neighbors contained in their window cells and inserts them locally.
void collectParameters(T, ScratchSpace< T > &, const MChar *, std::vector< MString > &)
This function collects a single parameters for the massivley parallel IO functions.
MInt noHaloCells(const MInt domainId) const
MFloat leastSquaresInterpolation(MInt *, MFloat *, MInt varId, std::function< MFloat(MInt, MInt)> scalarField, std::function< MFloat(MInt, MInt)> coordinate)
void setBoundaryDistance(const MBool *const interfaceCell, const MFloat *const outerBandWidth, MFloatScratchSpace &distance)
transverses over all neighboring cells for a specified length
std::vector< MFloat > m_sensorWeight
MFloat interpolateFieldData(MInt *, MFloat *, MInt varId, std::function< MFloat(MInt, MInt)> scalarField, std::function< MFloat(MInt, MInt)> coordinate)
MLong c_neighborId(const MInt cellId, const MInt dir) const
Returns the grid neighbor id of the grid cell cellId dir.
void exchangeAzimuthalPer(T *data, MInt dataBlockSize=1, MInt firstBlock=0)
Exchange of sparse data structures on max Level.
void collectVariables(T **variablesIn, ScratchSpace< T > &variablesOut, const std::vector< MString > &variablesNameIn, std::vector< MString > &variablesNameOut, const MInt noVars, const MInt noCells)
generalised helper function for writing restart files! This is necessary for example if the minLevel ...
MBool cellIsOnGeometry(MInt cellId, Geometry< nDim > *geom)
checks whether a cell lies on a certain geometry copied the essential part from identifyBoundaryCells
void compactCells()
Removes all holes in the cell collector and moves halo cells to the back of the collector.
void saveSensorData(const std::vector< std::vector< MFloat > > &sensors, const MInt &level, const MString &gridFileName, const MInt *const recalcIds) override
Saves all sensor values for debug/tunig purposes.
const MInt & windowCell(const MInt domainId, const MInt cellId) const
std::vector< fun > m_sensorFnPtr
void mapInterpolationCells(std::map< MInt, MInt > &cellMap)
MBool isActive() const override
MInt windowCellId(const MInt domainId, const MInt cellId) const
virtual void sensorSpecies(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
virtual void sensorDivergence(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
std::vector< MString > m_sensorType
MInt neighborList(const MInt cellId, const MInt dir) const
void identifyBoundaryCells()
void reOrderCellIds(std::vector< MInt > &reOrderedCells)
reOrder cellIds before writing the restart file! This is necessary for example if the minLevel shall ...
MFloat centerOfGravity(const MInt dir) const
const MInt & haloCell(const MInt domainId, const MInt cellId) const
MInt noNeighborDomains() const
virtual void sensorInterface(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
void checkNoHaloLayers()
check that each solver has the required number of haloLayers for leaf cells!!! TODO labels:toenhance ...
MInt createCellId(const MInt gridCellId)
void sensorLimit(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt, std::function< MFloat(MInt)>, const MFloat, const MInt *, const MBool, const MBool allowCoarsening=true)
simple sensor to apply a limit for a value
virtual void sensorMeanStress(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
MFloat reductionFactor() const
MInt haloCellId(const MInt domainId, const MInt cellId) const
MLong localPartitionCellOffsets(const MInt index) const
void readPatchProperties()
MInt maxUniformRefinementLevel() const
virtual void sensorEntropyQuot(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
std::vector< MFloat > m_sensorDerivativeVariables
MInt neighborDomain(const MInt id) const
void calcRecalcCellIdsSolver(const MInt *const recalcIdsTree, MInt &noCells, MInt &noInternalCellIds, std::vector< MInt > &recalcCellIdsSolver, std::vector< MInt > &reorderedCellIds)
Derive recalc cell ids of the solver and reordered cell ids.
std::vector< MInt > m_maxSensorRefinementLevel
void(CartesianSolver< nDim, SolverType >::*)(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt) fun
virtual void sensorTotalPressure(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
void markSurrndCells(MIntScratchSpace &inList, const MInt bandWidth, const MInt level, const MBool refineDiagonals=true)
virtual void sensorEntropyGrad(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
void identifyBoundaryCells(MBool *const isInterface, const std::vector< MInt > &bndCndIds=std::vector< MInt >())
void patchRefinement(std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen)
MInt m_sensorBandAdditionalLayers
void recomputeGlobalIds(std::vector< MInt > &, std::vector< MLong > &)
reOrder cellIds before writing the restart file! This is necessary for example if the minLevel shall ...
MInt maxNoGridCells() const
CartesianSolver(const MInt solverId, GridProxy &gridProxy_, const MPI_Comm comm, const MBool checkActive=false)
const MLong & localPartitionCellGlobalIds(const MInt cellId) const
MInt c_level(const MInt cellId) const
void exchangeData(T *data, const MInt dataBlockSize=1)
Exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell.
virtual void sensorPatch(std::vector< std::vector< MFloat > > &sensor, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen)
MInt noHaloLayers() const
MInt inCell(const MInt cellId, MFloat *point, MFloat fac=F1)
MInt minCell(const MInt id) const
void exchangeSparseLeafValues(G getData, S setData, const MInt dataSize, M cellMapping)
Exchange of sparse data structures on max Level.
void setHaloCellsOnInactiveRanks()
virtual void sensorParticle(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
void addChildren(std::vector< MInt > &reOrderedIds, const MInt parentId)
add childs to reOrdered cellIds This is necessary for example if the minLevel shall be raised at the ...
MInt m_adaptationInterval
MLong c_globalGridId(const MInt cellId)
PatchRefinement * m_patchRefinement
void sensorSmooth(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
sensor to smooth level jumps NOTE: only refines additional cells to ensure a smooth level transition ...
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr Real POW2(const Real x)
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)
constexpr MLong IPOW2(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_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_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_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Exscan(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_Exscan
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_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
GridCell Cell
Underlying enum type for property access.
void adjoint1stRow(std::array< std::array< T, N >, N > &m, std::array< T, N > &A)
MFloat determinant(std::array< T, N > &m)
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.
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
MInt noPatchesPerLevel(MInt addLevel)
MFloat ** localRfnPatchProperties
MInt noLocalPatchRfnLvls()
MInt * localRfnLevelPropertiesOffset
MInt * noLocalRfnPatchProperties
std::vector< MString > localRfnLevelMethods