28#include "bitpit_common.hpp"
31#include "voloctree.hpp"
59#if BITPIT_ENABLE_MPI==1
87#if BITPIT_ENABLE_MPI==1
94#if BITPIT_ENABLE_MPI==1
95 initializeTree(
nullptr, haloSize);
97 initializeTree(
nullptr);
111#if BITPIT_ENABLE_MPI==1
132VolOctree::VolOctree(
int dimension,
const std::array<double, 3> &origin,
double length,
double dh, MPI_Comm communicator, std::size_t haloSize)
143VolOctree::
VolOctree(int dimension, const std::array<double, 3> &origin, double length, double dh)
149#if BITPIT_ENABLE_MPI==1
171VolOctree::VolOctree(
int id,
int dimension,
const std::array<double, 3> &origin,
double length,
double dh, MPI_Comm communicator, std::size_t haloSize)
183VolOctree::
VolOctree(int id, int dimension, const std::array<double, 3> &origin, double length, double dh)
188#if BITPIT_ENABLE_MPI==1
189 m_tree = std::unique_ptr<PabloUniform>(
190 new PabloUniform(origin[0], origin[1], origin[2], length, dimension,
193 m_tree = std::unique_ptr<PabloUniform>(
194 new PabloUniform(origin[0], origin[1], origin[2], length, dimension,
199#if BITPIT_ENABLE_MPI==1
200 initializeTree(
nullptr, haloSize);
202 initializeTree(
nullptr);
220 __setDimension(dimension);
226 if (m_tree->getNumOctants() > 0) {
227 int initialLevel =
static_cast<int>(std::ceil(log2(std::max(1., length / dh))));
228 m_tree->setMarker((uint32_t) 0, initialLevel);
232#if BITPIT_ENABLE_MPI==1
258#if BITPIT_ENABLE_MPI==1
259 initializeTree(
nullptr, haloSize);
261 initializeTree(
nullptr);
274#if BITPIT_ENABLE_MPI==1
295#if BITPIT_ENABLE_MPI==1
307#if BITPIT_ENABLE_MPI==1
318#if BITPIT_ENABLE_MPI==1
319 initializeTree(adopter, m_tree->getNofGhostLayers());
321 initializeTree(adopter);
339 __setDimension(m_tree->getDim());
350 m_octantLocalFacesOnVertex = other.m_octantLocalFacesOnVertex;
351 m_octantLocalFacesOnEdge = other.m_octantLocalFacesOnEdge;
352 m_octantLocalEdgesOnVertex = other.m_octantLocalEdgesOnVertex;
354 m_cellTypeInfo = other.m_cellTypeInfo;
355 m_interfaceTypeInfo = other.m_interfaceTypeInfo;
357 m_cellToOctant = other.m_cellToOctant;
358 m_cellToGhost = other.m_cellToGhost;
359 m_octantToCell = other.m_octantToCell;
360 m_ghostToCell = other.m_ghostToCell;
363 m_tree = std::unique_ptr<PabloUniform>(new PabloUniform(*(other.m_tree)));
366 m_treeAdopter = other.m_treeAdopter;
377 std::swap(temporary, *
this);
388 m_treeAdopter->swap(m_tree);
399 return std::unique_ptr<VolOctree>(
new VolOctree(*
this));
417void VolOctree::__reset(
bool resetTree)
422 m_tree->setOrigin(std::array<double, 3>{{0., 0., 0.}});
427 m_cellToOctant.clear();
428 m_octantToCell.clear();
430 m_cellToGhost.clear();
431 m_ghostToCell.clear();
439#if BITPIT_ENABLE_MPI==1
444void VolOctree::initializeTree(std::unique_ptr<PabloUniform> *adopter, std::size_t haloSize)
446void VolOctree::initializeTree(std::unique_ptr<PabloUniform> *adopter)
451 m_tree->getLog().setVerbosities(log::LEVEL_WARNING);
454#if BITPIT_ENABLE_MPI==1
456 if (isCommunicatorSet()) {
457 if (!m_tree->getParallel()) {
459 if (haloSize != m_tree->getNofGhostLayers()) {
460 initializeTreeHaloSize(haloSize);
464 initializeTreePartitioning();
467 if (haloSize != m_tree->getNofGhostLayers()) {
468 throw std::runtime_error (
"Unable to set the requested halo size.");
475 setTreeAdopter(adopter);
481void VolOctree::initialize()
483 log::cout() <<
">> Initializing Octree mesh" << std::endl;
492 m_cellTypeInfo =
nullptr;
493 m_interfaceTypeInfo =
nullptr;
514 __setDimension(dimension);
522void VolOctree::__setDimension(
int dimension)
524 if (m_tree->getDim() > 0 && dimension != m_tree->getDim()) {
525 throw std::runtime_error (
"The dimension does not match the dimension of the octree.");
529 std::vector<std::vector<int>>().swap(m_octantLocalFacesOnVertex);
530 std::vector<std::vector<int>>().swap(m_octantLocalEdgesOnVertex);
531 std::vector<std::vector<int>>().swap(m_octantLocalFacesOnEdge);
533 if (dimension == 3) {
534 m_octantLocalFacesOnVertex.reserve(8);
535 m_octantLocalFacesOnVertex.push_back({{0, 2, 4}});
536 m_octantLocalFacesOnVertex.push_back({{1, 2, 4}});
537 m_octantLocalFacesOnVertex.push_back({{0, 3, 4}});
538 m_octantLocalFacesOnVertex.push_back({{1, 3, 4}});
539 m_octantLocalFacesOnVertex.push_back({{0, 2, 5}});
540 m_octantLocalFacesOnVertex.push_back({{1, 2, 5}});
541 m_octantLocalFacesOnVertex.push_back({{0, 3, 5}});
542 m_octantLocalFacesOnVertex.push_back({{1, 3, 5}});
544 m_octantLocalEdgesOnVertex.reserve(8);
545 m_octantLocalEdgesOnVertex.push_back({{0, 2, 4}});
546 m_octantLocalEdgesOnVertex.push_back({{1, 2, 5}});
547 m_octantLocalEdgesOnVertex.push_back({{0, 3, 6}});
548 m_octantLocalEdgesOnVertex.push_back({{1, 3, 7}});
549 m_octantLocalEdgesOnVertex.push_back({{4, 8, 10}});
550 m_octantLocalEdgesOnVertex.push_back({{5, 9, 10}});
551 m_octantLocalEdgesOnVertex.push_back({{6, 8, 11}});
552 m_octantLocalEdgesOnVertex.push_back({{7, 9, 11}});
554 m_octantLocalFacesOnEdge.reserve(12);
555 m_octantLocalFacesOnEdge.push_back({{0, 4}});
556 m_octantLocalFacesOnEdge.push_back({{1, 4}});
557 m_octantLocalFacesOnEdge.push_back({{2, 4}});
558 m_octantLocalFacesOnEdge.push_back({{3, 4}});
559 m_octantLocalFacesOnEdge.push_back({{0, 2}});
560 m_octantLocalFacesOnEdge.push_back({{1, 2}});
561 m_octantLocalFacesOnEdge.push_back({{0, 3}});
562 m_octantLocalFacesOnEdge.push_back({{1, 3}});
563 m_octantLocalFacesOnEdge.push_back({{0, 5}});
564 m_octantLocalFacesOnEdge.push_back({{1, 5}});
565 m_octantLocalFacesOnEdge.push_back({{2, 5}});
566 m_octantLocalFacesOnEdge.push_back({{3, 5}});
568 m_octantLocalFacesOnVertex.reserve(4);
569 m_octantLocalFacesOnVertex.push_back({{0, 2}});
570 m_octantLocalFacesOnVertex.push_back({{1, 2}});
571 m_octantLocalFacesOnVertex.push_back({{0, 3}});
572 m_octantLocalFacesOnVertex.push_back({{1, 3}});
577 if (dimension == 3) {
578 cellType = ElementType::VOXEL;
580 cellType = ElementType::PIXEL;
587 if (dimension == 3) {
588 interfaceType = ElementType::PIXEL;
590 interfaceType = ElementType::LINE;
599void VolOctree::setBoundingBox()
601 std::array<double, 3> minPoint;
602 std::array<double, 3> maxPoint;
605 m_tree->getBoundingBox(minPoint, maxPoint);
607#if BITPIT_ENABLE_MPI==1
611 for (CellConstIterator ghostCellItr =
ghostCellConstBegin(); ghostCellItr != endItr; ++ghostCellItr) {
612 ConstProxyVector<long> ghostVertexIds = ghostCellItr->getVertexIds();
613 int nGhostCellVertices = ghostVertexIds.size();
614 for (
int i = 0; i < nGhostCellVertices; ++i) {
615 const std::array<double, 3> coords = m_vertices[ghostVertexIds[i]].getCoords();
616 for (
int d = 0; d < 3; ++d) {
617 minPoint[d] = std::min(coords[d], minPoint[d]);
618 maxPoint[d] = std::max(coords[d], maxPoint[d]);
625 setBoundingBox(minPoint, maxPoint);
647 case adaption::MARKER_COARSEN:
651 case adaption::MARKER_REFINE:
660 int nMaxVirtualOctants;
662 nMaxVirtualOctants = 8;
664 nMaxVirtualOctants = 4;
667 std::vector<Octant> virtualOctants;
668 virtualOctants.reserve(nMaxVirtualOctants);
669 m_tree->expectedOctantAdapt(octant, markerValue, &virtualOctants);
670 std::size_t nVirtualOctants = virtualOctants.size();
673 int nCellVertices = m_cellTypeInfo->nVertices;
675 virtualVertices->
clear();
676 virtualVertices->
reserve(nCellVertices * nVirtualOctants);
678 virtualCells->clear();
679 virtualCells->resize(nVirtualOctants);
681 for (std::size_t k = 0; k < nVirtualOctants; ++k) {
682 const Octant *virtualOctant = &(virtualOctants[k]);
684 std::unique_ptr<long[]> connectStorage = std::unique_ptr<long[]>(
new long[nCellVertices]);
685 for (
int i = 0; i < nCellVertices; ++i) {
686 long vertexId = k * nCellVertices + i;
687 connectStorage[i] = vertexId;
688 virtualVertices->
emplaceBack(vertexId, vertexId, m_tree->getNode(virtualOctant, i));
691 virtualCells->emplace_back(
id, m_cellTypeInfo->type, std::move(connectStorage),
true,
false,
false);
706 return m_tree->getVolume(octant);
720 return m_tree->getCenter(octant);
734 return m_tree->getSize(octant);
745 const Interface &
interface = getInterface(id);
751 return m_tree->getArea(octant);
762 const Interface &
interface = getInterface(id);
764 long owner = interface.getOwner();
769 return m_tree->getNormal(octant, (uint8_t) ownerFace);
781 auto octantItr = m_cellToOctant.find(
id);
782 if (octantItr != m_cellToOctant.end()) {
787 return OctantInfo(m_cellToGhost.at(
id),
false);
818 m_treeAdopter = adopter;
829 std::unordered_map<uint32_t, long>::const_iterator octantItr;
830 if (octantInfo.internal) {
831 octantItr = m_octantToCell.find(octantInfo.id);
832 if (octantItr == m_octantToCell.end()) {
833 return Element::NULL_ID;
836 octantItr = m_ghostToCell.find(octantInfo.id);
837 if (octantItr == m_ghostToCell.end()) {
838 return Element::NULL_ID;
842 return octantItr->second;
854 if (octantInfo.internal) {
855 octant = m_tree->getOctant(octantInfo.id);
857 octant = m_tree->getGhostOctant(octantInfo.id);
872 if (octantInfo.internal) {
873 octant = m_tree->getOctant(octantInfo.id);
875 octant = m_tree->getGhostOctant(octantInfo.id);
887VolOctree::OctantHash VolOctree::evaluateOctantHash(
const OctantInfo &octantInfo)
889 uint8_t level = m_tree->getLevel(octantInfo.id);
890 uint64_t morton = m_tree->getMorton(octantInfo.id);
892 OctantHash octantHash;
893 octantHash |= morton;
925 return m_tree->getFamilySplittingNode(octant);
950 int currentRank = -1;
951#if BITPIT_ENABLE_MPI==1
956 std::vector<uint32_t> treeIds;
957 std::vector<int8_t> treeMarkers;
958 std::vector<bool> treeGhosts;
959 m_tree->getPreMapping(treeIds, treeMarkers, treeGhosts);
960 std::size_t nUpdatedOctants = treeIds.size();
963 uint64_t previousFatherMorton = PABLO::INVALID_MORTON;
964 for (std::size_t n = 0; n < nUpdatedOctants; ++n) {
965 OctantInfo octantInfo(treeIds[n], !treeGhosts[n]);
968 adaption::Type adaptionType;
969 if (treeMarkers[n] > 0) {
970 adaptionType = adaption::TYPE_REFINEMENT;
972 adaptionType = adaption::TYPE_COARSENING;
975 bool createAdaption =
true;
976 if (adaptionType == adaption::TYPE_COARSENING) {
978 if (fatherMorton == previousFatherMorton) {
979 createAdaption =
false;
981 previousFatherMorton = fatherMorton;
985 if (createAdaption) {
986 std::size_t adaptionInfoId = adaptionData.
insert(adaptionType, adaption::ENTITY_CELL, currentRank);
987 adaptionInfo = &(adaptionData[adaptionInfoId]);
990 assert(adaptionInfo);
991 adaptionInfo->previous.emplace_back(
getOctantId(octantInfo));
994#if BITPIT_ENABLE_MPI==1
1000 std::size_t adaptionInfoId = adaptionData.
insert(adaption::TYPE_DELETION, adaption::ENTITY_CELL, currentRank);
1003 for (CellConstIterator itr = beginItr; itr != endItr; ++itr) {
1004 adaptionInfo.previous.emplace_back();
1005 long &deletedGhostCellId = adaptionInfo.previous.back();
1006 deletedGhostCellId = itr.getId();
1012 return adaptionData.
dump();
1029 bool emptyPatch =
empty();
1030 bool buildMapping = !emptyPatch;
1031 bool updated = m_tree->adapt(buildMapping);
1033 if (!updated && !emptyPatch) {
1034 log::cout() <<
" Already updated" << std::endl;
1035 return std::vector<adaption::Info>();
1040 return sync(trackAdaption);
1061 m_tree->settleMarkers();
1071std::vector<adaption::Info> VolOctree::sync(
bool trackChanges)
1073 log::cout() <<
">> Syncing patch..." << std::endl;
1080 bool importFromScratch =
empty();
1083 ParaTree::Operation lastTreeOperation = m_tree->getLastOperation();
1084 if (lastTreeOperation == ParaTree::OP_ADAPT_UNMAPPED && !importFromScratch) {
1085 throw std::runtime_error (
"Unable to sync the patch after an unmapped adaption");
1089 uint32_t nOctants =
static_cast<uint32_t
>(m_tree->getNumOctants());
1090 uint32_t nPreviousOctants =
static_cast<uint32_t
>(m_octantToCell.size());
1092 log::cout() <<
">> Number of octants : " << nOctants << std::endl;
1095 uint32_t nGhostsOctants =
static_cast<uint32_t
>(m_tree->getNumGhosts());
1096 uint32_t nPreviousGhosts =
static_cast<uint32_t
>(m_ghostToCell.size());
1099 adaption::InfoCollection adaptionData;
1102 int currentRank = -1;
1103#if BITPIT_ENABLE_MPI==1
1111 log::cout() <<
">> Extract information for transforming the patch...";
1113 std::vector<bool> unmappedOctants(nPreviousOctants,
true);
1114 std::vector<OctantInfo> addedOctants;
1115 std::vector<RenumberInfo> renumberedOctants;
1116 std::vector<DeleteInfo> deletedOctants;
1118 addedOctants.reserve(nOctants + nGhostsOctants);
1119 if (!importFromScratch) {
1120 renumberedOctants.reserve(nPreviousOctants + nPreviousGhosts);
1121 deletedOctants.reserve(nPreviousOctants + nPreviousGhosts);
1124 uint32_t treeId = 0;
1125 std::vector<uint32_t> mapper_octantMap;
1126 std::vector<bool> mapper_ghostFlag;
1127 std::vector<int> mapper_octantRank;
1128 while (treeId < (uint32_t) nOctants) {
1130 mapper_octantMap.clear();
1131 mapper_ghostFlag.clear();
1132 mapper_octantRank.clear();
1133 if (!importFromScratch) {
1134 m_tree->getMapping(treeId, mapper_octantMap, mapper_ghostFlag, mapper_octantRank);
1138 adaption::Type adaptionType = adaption::TYPE_NONE;
1139 if (importFromScratch) {
1140 adaptionType = adaption::TYPE_CREATION;
1141 }
else if (lastTreeOperation == ParaTree::OP_ADAPT_MAPPED) {
1142 bool isNewR = m_tree->getIsNewR(treeId);
1144 adaptionType = adaption::TYPE_REFINEMENT;
1146 bool isNewC = m_tree->getIsNewC(treeId);
1148 adaptionType = adaption::TYPE_COARSENING;
1149 }
else if (treeId != mapper_octantMap.front()) {
1150 adaptionType = adaption::TYPE_RENUMBERING;
1153#if BITPIT_ENABLE_MPI==1
1154 }
else if (lastTreeOperation == ParaTree::OP_LOADBALANCE || lastTreeOperation == ParaTree::OP_LOADBALANCE_FIRST) {
1155 if (currentRank != mapper_octantRank.front()) {
1156 adaptionType = adaption::TYPE_PARTITION_RECV;
1157 }
else if (treeId != mapper_octantMap.front()) {
1158 adaptionType = adaption::TYPE_RENUMBERING;
1165 if (adaptionType == adaption::TYPE_NONE) {
1166 unmappedOctants[treeId] =
false;
1175 if (adaptionType == adaption::TYPE_RENUMBERING) {
1176 uint32_t previousTreeId = mapper_octantMap.front();
1177 OctantInfo previousOctantInfo(previousTreeId, !mapper_ghostFlag.front());
1179 renumberedOctants.emplace_back(cellId, treeId);
1180 unmappedOctants[previousTreeId] =
false;
1197 long nCurrentTreeIds;
1198 if (importFromScratch) {
1199 nCurrentTreeIds = nOctants - treeId;
1200 }
else if (adaptionType == adaption::TYPE_REFINEMENT) {
1203 nCurrentTreeIds = 1;
1206 const long lastCurrentTreeId = treeId + nCurrentTreeIds;
1207 for (
int currentTreeId = treeId; currentTreeId < lastCurrentTreeId; ++currentTreeId) {
1208 addedOctants.emplace_back(currentTreeId,
true);
1214 if (!importFromScratch) {
1215 int nPreviousTreeIds = mapper_octantMap.size();
1216 for (
int k = 0; k < nPreviousTreeIds; ++k) {
1217#if BITPIT_ENABLE_MPI==1
1219 if (mapper_octantRank[k] != currentRank) {
1225 if (mapper_ghostFlag[k]) {
1230 uint32_t previousTreeId = mapper_octantMap[k];
1231 OctantInfo previousOctantInfo(previousTreeId, !mapper_ghostFlag[k]);
1233 deletedOctants.emplace_back(cellId, adaptionType);
1235 unmappedOctants[previousTreeId] =
false;
1251 int rank = currentRank;
1252#if BITPIT_ENABLE_MPI==1
1253 if (adaptionType == adaption::TYPE_PARTITION_RECV) {
1254 rank = mapper_octantRank[0];
1259 std::size_t infoId = adaptionData.insert(adaptionType, adaption::ENTITY_CELL, rank);
1260 adaption::Info &adaptionInfo = adaptionData[infoId];
1270 adaptionInfo.current.reserve(nCurrentTreeIds);
1271 auto addedOctantsIter = addedOctants.cend() - nCurrentTreeIds;
1272 while (addedOctantsIter != addedOctants.cend()) {
1273 adaptionInfo.current.emplace_back();
1274 long &adaptionId = adaptionInfo.current.back();
1275 adaptionId = (*addedOctantsIter).id;
1286 int nPreviousCellIds = mapper_octantMap.size();
1287 adaptionInfo.previous.reserve(nPreviousCellIds);
1288 for (
int k = 0; k < nPreviousCellIds; ++k) {
1289 long previousCellId;
1290#if BITPIT_ENABLE_MPI==1
1291 if (mapper_octantRank[k] != currentRank) {
1292 previousCellId = Cell::NULL_ID;
1296 OctantInfo previousOctantInfo(mapper_octantMap[k], !mapper_ghostFlag[k]);
1300 adaptionInfo.previous.emplace_back();
1301 long &adaptionId = adaptionInfo.previous.back();
1302 adaptionId = previousCellId;
1307 treeId += nCurrentTreeIds;
1312#if BITPIT_ENABLE_MPI==1
1314 for (uint32_t treeId = 0; treeId < (uint32_t) nGhostsOctants; ++treeId) {
1315 addedOctants.emplace_back(treeId,
false);
1320 if (!importFromScratch) {
1321#if BITPIT_ENABLE_MPI==1
1323 PabloUniform::LoadBalanceRanges loadBalanceRanges = m_tree->getLoadBalanceRanges();
1324 for (
const auto &rankEntry : loadBalanceRanges.sendRanges) {
1325 int rank = rankEntry.first;
1326 if (rank == currentRank) {
1330 adaption::Type deletionType;
1331 if (loadBalanceRanges.sendAction == PabloUniform::LoadBalanceRanges::ACTION_DELETE) {
1332 deletionType = adaption::TYPE_DELETION;
1334 deletionType = adaption::TYPE_PARTITION_SEND;
1337 uint32_t beginTreeId = rankEntry.second[0];
1338 uint32_t endTreeId = rankEntry.second[1];
1339 for (uint32_t treeId = beginTreeId; treeId < endTreeId; ++treeId) {
1342 deletedOctants.emplace_back(cellId, deletionType, rank);
1343 unmappedOctants[treeId] =
false;
1348 if (nPreviousGhosts > 0) {
1349 for (uint32_t ghostTreeId = 0; ghostTreeId < nPreviousGhosts; ++ghostTreeId) {
1350 OctantInfo ghostOctantInfo(ghostTreeId,
false);
1352 deletedOctants.emplace_back(ghostCellId, adaption::TYPE_DELETION);
1362 for (uint32_t previousTreeId = 0; previousTreeId < nPreviousOctants; ++previousTreeId) {
1363 if (unmappedOctants[previousTreeId]) {
1366 deletedOctants.emplace_back(cellId, adaption::TYPE_DELETION);
1376 renumberCells(renumberedOctants);
1379 StitchInfo stitchInfo;
1380 if (deletedOctants.size() > 0) {
1381 log::cout() <<
">> Removing non-existing cells...";
1395 std::unordered_set<long> sendAdaptionInfo;
1396 std::unordered_set<long> removedInterfaces;
1397 for (
const DeleteInfo &deleteInfo : deletedOctants) {
1399 long cellId = deleteInfo.cellId;
1406 adaption::Type adaptionType = deleteInfo.trigger;
1407 bool adaptionIsDeletion = (adaptionType == adaption::TYPE_DELETION);
1408 bool adaptionIsSend = (adaptionType == adaption::TYPE_PARTITION_SEND);
1410 if (adaptionIsDeletion || adaptionIsSend) {
1411 int rank = deleteInfo.rank;
1412 std::size_t adaptionInfoId = adaptionData.insert(adaptionType, adaption::ENTITY_CELL, rank);
1413 adaption::Info &adaptionInfo = adaptionData[adaptionInfoId];
1414 adaptionInfo.previous.emplace_back();
1415 long &deletedId = adaptionInfo.previous.back();
1419 if (adaptionIsSend) {
1420 sendAdaptionInfo.insert(adaptionInfoId);
1425 const Cell &cell = m_cells.at(cellId);
1426 long nCellInterfaces = cell.getInterfaceCount();
1427 const long *interfaces = cell.getInterfaces();
1428 for (
int k = 0; k < nCellInterfaces; ++k) {
1429 long interfaceId = interfaces[k];
1430 if (interfaceId >= 0) {
1431 removedInterfaces.insert(interfaceId);
1436#if BITPIT_ENABLE_MPI==1
1443 for (
int adaptionInfoId : sendAdaptionInfo) {
1444 adaption::Info &adaptionInfo = adaptionData[adaptionInfoId];
1445 std::sort(adaptionInfo.previous.begin(), adaptionInfo.previous.end(),
CellPositionLess(*
this,
false));
1450 std::size_t adaptionInfoId = adaptionData.insert(adaption::TYPE_DELETION, adaption::ENTITY_INTERFACE, currentRank);
1451 adaption::Info &adaptionInfo = adaptionData[adaptionInfoId];
1452 adaptionInfo.previous.reserve(removedInterfaces.size());
1453 for (
long interfaceId : removedInterfaces) {
1454 adaptionInfo.previous.emplace_back();
1455 long &deletedInterfaceId = adaptionInfo.previous.back();
1456 deletedInterfaceId = interfaceId;
1461 stitchInfo = deleteCells(deletedOctants);
1464 log::cout() <<
">> Cells removed: " << deletedOctants.size() << std::endl;
1467 std::vector<DeleteInfo>().swap(deletedOctants);
1470 std::vector<long> createdCells;
1471 if (addedOctants.size() > 0) {
1472 log::cout() <<
">> Importing new octants...";
1474 createdCells = importCells(addedOctants, stitchInfo);
1477 log::cout() <<
">> Octants imported: " << addedOctants.size() << std::endl;
1480 StitchInfo().swap(stitchInfo);
1488 for (
auto &adaptionInfo : adaptionData.data()) {
1489 if (adaptionInfo.entity != adaption::ENTITY_CELL) {
1494 int nCurrentIds = adaptionInfo.current.size();
1495 for (
int k = 0; k < nCurrentIds; ++k) {
1496 long cellId = m_octantToCell.at(adaptionInfo.current[k]);
1497 adaptionInfo.current[k] = cellId;
1500#if BITPIT_ENABLE_MPI==1
1506 adaption::Type adaptionType = adaptionInfo.type;
1507 if (adaptionType == adaption::TYPE_PARTITION_RECV) {
1508 std::sort(adaptionInfo.current.begin(), adaptionInfo.current.end(),
CellPositionLess(*
this,
false));
1513#if BITPIT_ENABLE_MPI==1
1515 if (nGhostsOctants > 0) {
1516 std::size_t adaptionInfoId = adaptionData.insert(adaption::TYPE_CREATION, adaption::ENTITY_CELL, currentRank);
1517 adaption::Info &adaptionInfo = adaptionData[adaptionInfoId];
1519 adaptionInfo.current.reserve(nGhostsOctants);
1520 auto cellIterator = m_cellToGhost.cbegin();
1521 while (cellIterator != m_cellToGhost.cend()) {
1522 adaptionInfo.current.emplace_back();
1523 long &adaptionId = adaptionInfo.current.back();
1524 adaptionId = cellIterator->first;
1532 if (createdCells.size() > 0) {
1534 std::unordered_set<long> createdInterfaces;
1535 for (
const auto &cellId : createdCells) {
1536 const Cell &cell = m_cells.at(cellId);
1537 long nCellInterfaces = cell.getInterfaceCount();
1538 const long *interfaces = cell.getInterfaces();
1539 for (
int k = 0; k < nCellInterfaces; ++k) {
1540 long interfaceId = interfaces[k];
1541 if (interfaceId >= 0) {
1542 createdInterfaces.insert(interfaceId);
1548 std::size_t infoId = adaptionData.insert(adaption::TYPE_CREATION, adaption::ENTITY_INTERFACE, currentRank);
1549 adaption::Info &adaptionInfo = adaptionData[infoId];
1550 adaptionInfo.current.reserve(createdInterfaces.size());
1551 for (
long interfaceId : createdInterfaces) {
1552 adaptionInfo.current.emplace_back();
1553 long &createdInterfaceId = adaptionInfo.current.back();
1554 createdInterfaceId = interfaceId;
1560 return adaptionData.dump();
1572VolOctree::StitchInfo VolOctree::deleteCells(
const std::vector<DeleteInfo> &deletedOctants)
1575 int nCellVertices = m_cellTypeInfo->nVertices;
1576 int nCellFaces = m_cellTypeInfo->nFaces;
1579 std::unordered_set<long> deadVertices;
1581 std::vector<long> deadCells;
1582 deadCells.reserve(deletedOctants.size());
1583 for (
const DeleteInfo &deleteInfo : deletedOctants) {
1584 long cellId = deleteInfo.cellId;
1585 const Cell &cell = m_cells[cellId];
1591 ConstProxyVector<long> cellVertexIds = cell.getVertexIds();
1592 deadVertices.insert(cellVertexIds.cbegin(), cellVertexIds.cend());
1596 uint32_t treeId = octantInfo.id;
1598 if (cell.isInterior()) {
1599 m_cellToOctant.erase(cellId);
1601 auto octantToCellItr = m_octantToCell.find(treeId);
1602 assert(octantToCellItr != m_octantToCell.end());
1603 if (octantToCellItr->second == cellId) {
1604 m_octantToCell.erase(octantToCellItr);
1607 m_cellToGhost.erase(cellId);
1609 auto ghostToCellItr = m_ghostToCell.find(treeId);
1610 assert(ghostToCellItr != m_ghostToCell.end());
1611 if (ghostToCellItr->second == cellId) {
1612 m_ghostToCell.erase(ghostToCellItr);
1617 deadCells.push_back(cellId);
1653 StitchInfo stitchVertices;
1654 for (
const auto &entry: m_alteredCells) {
1661 long cellId = entry.first;
1662 const Cell &cell = m_cells[cellId];
1663 ConstProxyVector<long> cellVertexIds = cell.getVertexIds();
1668 for (
int k = 0; k < nCellVertices; ++k) {
1669 long vertexId = cellVertexIds[k];
1670 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1671 stitchVertices.insert({vertexTreeKey, vertexId});
1672 deadVertices.erase(vertexId);
1679 int cellLevel = octant->getLevel();
1681 for (
int face = 0; face < nCellFaces; ++face) {
1682 int nFaceAdjacencies = cell.getAdjacencyCount(face);
1683 const long *faceAdjacencies = cell.getAdjacencies(face);
1684 for (
int i = 0; i < nFaceAdjacencies; ++i) {
1685 int neighId = faceAdjacencies[i];
1688 int neighLevel = neighOctant->getLevel();
1689 if (neighLevel <= cellLevel) {
1693 const Cell &neigh = m_cells[neighId];
1695 const int *localNeighFaceConnect = m_cellTypeInfo->faceConnectStorage[neighFace].data();
1696 ConstProxyVector<long> faceVertexIds = neigh.getFaceVertexIds(neighFace);
1697 std::size_t nFaceVertexIds = faceVertexIds.size();
1698 for (std::size_t k = 0; k < nFaceVertexIds; ++k) {
1699 long vertexId = faceVertexIds[k];
1700 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(neighOctant, localNeighFaceConnect[k]);
1701 stitchVertices.insert({vertexTreeKey, vertexId});
1702 deadVertices.erase(vertexId);
1712 return stitchVertices;
1721void VolOctree::renumberCells(
const std::vector<RenumberInfo> &renumberedOctants)
1724 for (
const RenumberInfo &renumberInfo : renumberedOctants) {
1725 long cellId = renumberInfo.cellId;
1726 if (!m_cells[cellId].isInterior()) {
1731 uint32_t previousTreeId = previousOctantInfo.id;
1733 m_octantToCell.erase(previousTreeId);
1737 for (
const RenumberInfo &renumberInfo : renumberedOctants) {
1738 long cellId = renumberInfo.cellId;
1739 if (!m_cells[cellId].isInterior()) {
1743 uint32_t treeId = renumberInfo.newTreeId;
1745 m_cellToOctant[cellId] = treeId;
1746 m_octantToCell[treeId] = cellId;
1760std::vector<long> VolOctree::importCells(
const std::vector<OctantInfo> &octantInfoList,
1761 StitchInfo &stitchInfo, std::istream *restoreStream)
1764 int nCellVertices = m_cellTypeInfo->nVertices;
1765 for (
const OctantInfo &octantInfo : octantInfoList) {
1767 for (
int k = 0; k < nCellVertices; ++k) {
1768 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1769 if (stitchInfo.count(vertexTreeKey) == 0) {
1771 std::array<double, 3> nodeCoords = m_tree->getNode(octant, k);
1775 if (!restoreStream) {
1776#if BITPIT_ENABLE_MPI==1
1777 VertexIterator vertexIterator =
addVertex(std::move(nodeCoords));
1779 VertexIterator vertexIterator =
addVertex(std::move(nodeCoords));
1781 vertexId = vertexIterator.getId();
1785#if BITPIT_ENABLE_MPI==1
1799 stitchInfo[vertexTreeKey] = vertexId;
1805 long nOctants = m_tree->getNumOctants();
1806 m_cellToOctant.reserve(nOctants);
1807 m_octantToCell.reserve(nOctants);
1809 long nGhostsOctants = m_tree->getNumGhosts();
1810 m_cellToGhost.reserve(nGhostsOctants);
1811 m_ghostToCell.reserve(nGhostsOctants);
1814 size_t octantInfoListSize = octantInfoList.size();
1815 m_cells.reserve(m_cells.size() + octantInfoListSize);
1817 std::vector<long> createdCells(octantInfoListSize);
1818 for (
size_t i = 0; i < octantInfoListSize; ++i) {
1819 const OctantInfo &octantInfo = octantInfoList[i];
1825 std::unique_ptr<long[]> cellConnect = std::unique_ptr<long[]>(
new long[nCellVertices]);
1826 for (
int k = 0; k < nCellVertices; ++k) {
1827 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1828 cellConnect[k] = stitchInfo.at(vertexTreeKey);
1831#if BITPIT_ENABLE_MPI==1
1834 if (octantInfo.internal) {
1837 uint64_t globalTreeId = m_tree->getGhostGlobalIdx(octantInfo.id);
1838 owner = m_tree->getOwnerRank(globalTreeId);
1842 int haloLayer = m_tree->getGhostLayer(octant);
1847 if (!restoreStream) {
1848#if BITPIT_ENABLE_MPI==1
1849 CellIterator cellIterator =
addCell(m_cellTypeInfo->type, std::move(cellConnect), owner, haloLayer);
1851 CellIterator cellIterator =
addCell(m_cellTypeInfo->type, std::move(cellConnect));
1853 cellId = cellIterator.getId();
1857#if BITPIT_ENABLE_MPI==1
1858 restoreCell(m_cellTypeInfo->type, std::move(cellConnect), owner, haloLayer, cellId);
1860 restoreCell(m_cellTypeInfo->type, std::move(cellConnect), cellId);
1865 if (octantInfo.internal) {
1866 m_cellToOctant.insert({{cellId, octantInfo.id}});
1867 m_octantToCell.insert({{octantInfo.id, cellId}});
1869 m_cellToGhost.insert({{cellId, octantInfo.id}});
1870 m_ghostToCell.insert({{octantInfo.id, cellId}});
1874 createdCells[i] = cellId;
1878 if (restoreStream) {
1880#if BITPIT_ENABLE_MPI==1
1886 if (restoreStream) {
1898 if (!restoreStream) {
1903 return createdCells;
1915 int maxLevel = m_tree->getMaxDepth();
1918 int nCellFaces = m_cellTypeInfo->nFaces;
1919 const uint8_t *oppositeFace = m_tree->getOppface();
1922 std::vector<std::size_t> nDirtyAdjacenciesCellsByLevel(maxLevel + 1, 0);
1923 for (
const auto &entry : m_alteredCells) {
1924 AlterationFlags cellAlterationFlags = entry.second;
1929 long cellId = entry.first;
1932 ++nDirtyAdjacenciesCellsByLevel[cellLevel];
1936 std::vector<std::vector<long>> hierarchicalCellIds(maxLevel + 1);
1937 for (
int level = 0; level <= maxLevel; ++level) {
1938 hierarchicalCellIds[level].reserve(nDirtyAdjacenciesCellsByLevel[level]);
1941 for (
const auto &entry : m_alteredCells) {
1942 AlterationFlags cellAlterationFlags = entry.second;
1947 long cellId = entry.first;
1949 hierarchicalCellIds[cellLevel].push_back(cellId);
1953 std::vector<uint32_t> neighTreeIds;
1954 std::vector<bool> neighGhostFlags;
1955 for (
int level = 0; level <= maxLevel; ++level) {
1956 for (
long cellId : hierarchicalCellIds[level]) {
1957 Cell &cell = m_cells[cellId];
1960 for (
int face = 0; face < nCellFaces; ++face) {
1992 if (nFaceAdjacencies > 0) {
1993 if (nFaceAdjacencies == 1) {
1994 long cellLevel = octant->
getLevel();
1997 if (neighLevel <= cellLevel) {
2001 uint64_t neighsArea = 0;
2003 for (
int k = 0; k < nFaceAdjacencies; ++k) {
2004 long neighId = faceAdjacencies[k];
2011 if (faceArea == neighsArea) {
2018 neighTreeIds.clear();
2019 neighGhostFlags.clear();
2020 m_tree->findNeighbours(octant, face, 1, neighTreeIds, neighGhostFlags);
2027 int nNeighs = neighTreeIds.size();
2028 for (
int k = 0; k < nNeighs; ++k) {
2029 OctantInfo neighOctantInfo(neighTreeIds[k], !neighGhostFlags[k]);
2036 int neighFace = oppositeFace[face];
2037 Cell &neigh = m_cells[neighId];
2052 return setMarker(
id, 1);
2062 return setMarker(
id, -1);
2073 return setMarker(
id, 0);
2085 if (!octantInfo.internal) {
2086 return adaption::MARKER_UNDEFINED;
2089 int8_t treeMarker = m_tree->getMarker(octantInfo.id);
2090 if (treeMarker > 0) {
2091 return adaption::MARKER_REFINE;
2092 }
else if (treeMarker < 0) {
2093 return adaption::MARKER_COARSEN;
2095 return adaption::MARKER_NONE;
2105bool VolOctree::setMarker(
long id, int8_t value)
2108 if (!octantInfo.internal) {
2112 m_tree->setMarker(octantInfo.id, value);
2127 if (!octantInfo.internal) {
2131 m_tree->setBalance(octantInfo.id, enabled);
2146 return (m_tree->getPointOwner(point, isGhost) !=
nullptr);
2158 const Cell &cell = m_cells[id];
2159 ConstProxyVector<long> cellVertexIds = cell.
getVertexIds();
2161 int lowerLeftVertex = 0;
2164 const std::array<double, 3> &lowerLeft =
getVertexCoords(cellVertexIds[lowerLeftVertex]);
2165 const std::array<double, 3> &upperRight =
getVertexCoords(cellVertexIds[upperRightVertex]);
2167 const double EPS =
getTol();
2168 for (
int d = 0; d < 3; ++d){
2169 if (point[d] < lowerLeft[d] - EPS || point[d] > upperRight[d] + EPS) {
2190 uint32_t treeId = m_tree->getPointOwnerIdx(point, isGhost);
2191 if (treeId == std::numeric_limits<uint32_t>::max()) {
2192 return Element::NULL_ID;
2207 m_tree->setTol(tolerance);
2219 double tolerance = m_tree->getTol();
2230 const int DUMP_VERSION = 4;
2232 return DUMP_VERSION;
2243 std::size_t nOctants = m_tree->getNumOctants();
2244 std::size_t nGhostsOctants = m_tree->getNumGhosts();
2246 std::vector<OctantInfo> octantInfoList;
2247 octantInfoList.reserve(nOctants + nGhostsOctants);
2249 for (std::size_t n = 0; n < nOctants; ++n) {
2250 octantInfoList.emplace_back(n,
true);
2253 for (std::size_t n = 0; n < nGhostsOctants; ++n) {
2254 octantInfoList.emplace_back(n,
false);
2258 m_tree->dump(stream);
2263 m_vertices.dumpKernel(stream);
2268 m_cells.dumpKernel(stream);
2274 std::unordered_set<long> dumpedVertices;
2276 for (
const OctantInfo &octantInfo : octantInfoList) {
2278 ConstProxyVector<long> cellVertexIds = cell.
getVertexIds();
2279 for (
int k = 0; k < m_cellTypeInfo->nVertices; ++k) {
2280 long vertexId = cellVertexIds[k];
2281 if (dumpedVertices.count(vertexId) == 0) {
2283#if BITPIT_ENABLE_MPI==1
2289 dumpedVertices.insert(vertexId);
2298 for (
const OctantInfo &octantInfo : octantInfoList) {
2318 m_tree->restore(stream);
2321 m_vertices.restoreKernel(stream);
2324 m_cells.restoreKernel(stream);
2331 size_t nOctants = m_tree->getNumOctants();
2332 size_t nGhostsOctants = m_tree->getNumGhosts();
2334 StitchInfo stitchInfo;
2336 std::vector<OctantInfo> octantInfoList;
2337 octantInfoList.reserve(nOctants + nGhostsOctants);
2338 for (std::size_t n = 0; n < nOctants; ++n) {
2339 octantInfoList.emplace_back(n,
true);
2341 for (std::size_t n = 0; n < nGhostsOctants; ++n) {
2342 octantInfoList.emplace_back(n,
false);
2345 importCells(octantInfoList, stitchInfo, &stream);
2369 return octantInfo.id;
2382 return m_tree->getOrigin();
2394 std::array<double, 3> translation = origin -
getOrigin();
2405 m_tree->setOrigin(m_tree->getOrigin() + translation);
2420 return m_tree->getL();
2431 m_tree->setL(length);
2437 if (m_vertices.size() > 0) {
2439 m_tree->computeConnectivity();
2442 std::unordered_set<long> alreadyEvaluated;
2443 for (
const Cell &cell : m_cells) {
2446 ConstProxyVector<long> cellVertexIds = cell.getVertexIds();
2447 for (
int k = 0; k < m_cellTypeInfo->nVertices; ++k) {
2448 long vertexId = cellVertexIds[k];
2449 if (alreadyEvaluated.count(vertexId) == 0) {
2450 Vertex &vertex = m_vertices.at(vertexId);
2451 vertex.
setCoords(m_tree->getNode(octant, k));
2452 alreadyEvaluated.insert(vertexId);
2458 m_tree->clearConnectivity();
2468void VolOctree::scale(
const std::array<double, 3> &scaling,
const std::array<double, 3> ¢er)
2470 bool uniformScaling =
true;
2471 uniformScaling &= (std::abs(scaling[0] - scaling[1]) > 1e-14);
2472 uniformScaling &= (std::abs(scaling[0] - scaling[2]) > 1e-14);
2473 assert(uniformScaling);
2474 if (!uniformScaling) {
2475 log::cout() <<
"VolOctree patch only allows uniform scaling." << std::endl;
2479 std::array<double, 3> origin = m_tree->getOrigin();
2480 for (
int n = 0; n < 3; ++n) {
2481 origin[n] = center[n] + scaling[n] * (origin[n] - center[n]);
2483 m_tree->setOrigin(origin);
2485 m_tree->setL(m_tree->getL() * scaling[0]);
2512 std::vector<uint32_t> neighTreeIds;
2513 std::vector<bool> neighGhostFlags;
2514 m_tree->findAllCodimensionNeighbours(octant, neighTreeIds, neighGhostFlags);
2516 int nNeighs = neighTreeIds.size();
2517 for (
int i = 0; i < nNeighs; ++i) {
2518 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2521 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2522 utils::addToOrderedVector<long>(neighId, *neighs);
2554 findOctantCodimensionNeighs(octantInfo, edge, codimension, blackList, neighs);
2567 std::vector<long> faceNeighs;
2569 int octantLevel = octant->
getLevel();
2570 for (
int face : m_octantLocalFacesOnEdge[edge]) {
2573 for (
long neighId : faceNeighs) {
2576 int neighOctantLevel = neighOctant->
getLevel();
2577 if (neighOctantLevel <= octantLevel) {
2578 utils::addToOrderedVector<long>(neighId, *neighs);
2579 }
else if (m_tree->isEdgeOnOctant(octant, edge, neighOctant)) {
2580 utils::addToOrderedVector<long>(neighId, *neighs);
2606 std::vector<uint32_t> neighTreeIds;
2607 std::vector<bool> neighGhostFlags;
2608 m_tree->findAllNodeNeighbours(octant, vertex, neighTreeIds, neighGhostFlags);
2610 int nNeighs = neighTreeIds.size();
2611 for (
int i = 0; i < nNeighs; ++i) {
2612 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2615 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2616 utils::addToOrderedVector<long>(neighId, *neighs);
2637void VolOctree::findOctantCodimensionNeighs(
const OctantInfo &octantInfo,
int index,
int codimension,
2638 const std::vector<long> *blackList, std::vector<long> *neighs)
const
2641 if (codimension > dimension || codimension <= 0) {
2647 std::vector<uint32_t> neighTreeIds;
2648 std::vector<bool> neighGhostFlags;
2649 m_tree->findNeighbours(octant, index, codimension, neighTreeIds, neighGhostFlags);
2651 int nNeighs = neighTreeIds.size();
2652 for (
int i = 0; i < nNeighs; ++i) {
2653 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2656 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2657 utils::addToOrderedVector<long>(neighId, *neighs);
2673 long cellId = cell.
getId();
2676 int neighFace = m_tree->getOppface()[cellFace];
2680 const long *neighFaceAdjacencies = neigh.
getAdjacencies(neighFace);
2681 for (
int k = 0; k < nNeighFaceAdjacencies; ++k) {
2682 if (neighFaceAdjacencies[k] == cellId) {
2703 if (m_tree->getOppface()[face_A] != face_B) {
2708 long cellId_A = cell_A.
getId();
2711 const long *neighFaceAdjacencies_B = cell_B.
getAdjacencies(face_B);
2712 for (
int k = 0; k < nNeighFaceAdjacencies_B; ++k) {
2713 if (neighFaceAdjacencies_B[k] == cellId_A) {
The Cell class defines the cells.
bool pushAdjacency(int face, long adjacency)
long getAdjacency(int face, int index=0) const
const long * getAdjacencies() const
int getAdjacencyCount() const
static ConstProxyVector< long > getVertexIds(ElementType type, const long *connectivity)
The Interface class defines the interfaces among cells.
uint64_t getLogicalArea() const
uint64_t computeFatherMorton() const
static BITPIT_PUBLIC_API const std::string DEFAULT_LOG_FILE
void dumpInterfaces(std::ostream &stream) const
int getVertexOwner(long id) const
PiercedVector< Cell > & getCells()
@ ADAPTION_AUTOMATIC
No adaption can be performed.
bool testAlterationFlags(AlterationFlags availableFlags, AlterationFlags requestedFlags) const
void pruneStaleAdjacencies()
void updateFirstGhostCellId()
VertexIterator restoreVertex(const std::array< double, 3 > &coords, int owner, long id)
AdaptionMode getAdaptionMode() const
CellIterator restoreCell(ElementType type, std::unique_ptr< long[]> &&connectStorage, int owner, int haloLayer, long id)
virtual long getVertexCount() const
virtual void _findCellFaceNeighs(long id, int face, const std::vector< long > *blackList, std::vector< long > *neighs) const
VertexIterator addVertex(const Vertex &source, long id=Vertex::NULL_ID)
bool empty(bool global=true) const
void setBoundingBoxFrozen(bool frozen)
virtual void _setTol(double tolerance)
bool deleteVertices(const IdStorage &ids)
CellIterator addCell(const Cell &source, long id=Element::NULL_ID)
void updateInterfaces(bool forcedUpdated=false)
void scale(const std::array< double, 3 > &scaling)
virtual void setDimension(int dimension)
virtual void translate(const std::array< double, 3 > &translation)
@ PARTITIONING_ENABLED
No partitioning can be performed.
void setAdaptionStatus(AdaptionStatus status)
CellConstIterator ghostCellConstEnd() const
void restore(std::istream &stream, bool reregister=false)
bool isPartitioned() const
void restoreInterfaces(std::istream &stream)
void setAdaptionMode(AdaptionMode mode)
const std::array< double, 3 > & getVertexCoords(long id) const
void updateAdjacencies(bool forcedUpdated=false)
CellConstIterator ghostCellConstBegin() const
bool deleteCells(const IdStorage &ids)
void updateLastInternalCellId()
long getGhostCellCount() const
void pruneStaleInterfaces()
bool isThreeDimensional() const
The PatchManager oversee the handling of the patches.
Metafunction for generating a pierced vector.
void clear(bool release=true)
void emplaceBack(id_t id, Args &&... args)
void reserve(std::size_t n)
static BITPIT_PUBLIC_API const ReferenceElementInfo & getInfo(ElementType type)
The Vertex class defines the vertexs.
void setCoords(const std::array< double, 3 > &coords)
void _updateAdjacencies() override
void setDimension(int dimension) override
int getCellLevel(long id) const
long locatePoint(const std::array< double, 3 > &point) const override
std::vector< adaption::Info > _adaptionPrepare(bool trackAdaption) override
std::array< double, 3 > evalInterfaceNormal(long id) const override
double evalCellSize(long id) const override
void _setTol(double tolerance) override
void _findCellEdgeNeighs(long id, int edge, const std::vector< long > *blackList, std::vector< long > *neighs) const override
void scale(const std::array< double, 3 > &scaling, const std::array< double, 3 > ¢er) override
long _getCellNativeIndex(long id) const override
void _restore(std::istream &stream) override
std::array< double, 3 > getOrigin() const
void translate(const std::array< double, 3 > &translation) override
std::vector< adaption::Info > _adaptionAlter(bool trackAdaption) override
adaption::Marker _getCellAdaptionMarker(long id) override
double evalCellVolume(long id) const override
bool isPointInside(const std::array< double, 3 > &point) const override
void settleAdaptionMarkers() override
OctantInfo getCellOctant(long id) const
Octant * getOctantPointer(const OctantInfo &octantInfo)
void simulateCellUpdate(long id, adaption::Marker marker, std::vector< Cell > *virtualCells, PiercedVector< Vertex, long > *virtualVertices) const override
VolOctree(MPI_Comm communicator, std::size_t haloSize=1)
double evalInterfaceArea(long id) const override
bool _enableCellBalancing(long id, bool enabled) override
int getCellFamilySplitLocalVertex(long id) const
int _getDumpVersion() const override
void _findCellVertexNeighs(long id, int vertex, const std::vector< long > *blackList, std::vector< long > *neighs) const override
void setTreeAdopter(std::unique_ptr< PabloUniform > *entruster)
void _resetTol() override
bool _resetCellAdaptionMarker(long id) override
PabloUniform & getTree()
Gets a reference to the octree associated with the patch.
VolOctree & operator=(const VolOctree &other)
void setOrigin(const std::array< double, 3 > &origin)
std::array< double, 3 > evalCellCentroid(long id) const override
std::unique_ptr< PatchKernel > clone() const override
bool isSameFace(const Cell &cell_A, int face_A, const Cell &cell_B, int face_B) const override
void _adaptionCleanup() override
void _dump(std::ostream &stream) const override
bool _markCellForRefinement(long id) override
void setLength(double length)
void _findCellNeighs(long id, const std::vector< long > *blackList, std::vector< long > *neighs) const override
long getOctantId(const OctantInfo &octantInfo) const
int findAdjoinNeighFace(const Cell &cell, int cellFace, const Cell &neigh) const override
bool _markCellForCoarsening(long id) override
VolumeKernel(MPI_Comm communicator, std::size_t haloSize, AdaptionMode adaptionMode, PartitioningMode partitioningMode)
The InfoCollection class is a container that holds one or more adaption info items.
std::vector< Info > dump()
T uipow(const T &, unsigned int)
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNUSED(variable)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
The Info struct defines the infomation associated to an adaption.