28#include "bitpit_common.hpp"
31#include "voloctree.hpp"
59#if BITPIT_ENABLE_MPI==1
77 :
VolumeKernel(communicator, haloSize, ADAPTION_AUTOMATIC, PARTITIONING_ENABLED)
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)
172 :
VolumeKernel(id, dimension, communicator, haloSize, ADAPTION_AUTOMATIC, PARTITIONING_ENABLED)
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
246 :
VolumeKernel(communicator, haloSize, ADAPTION_AUTOMATIC, PARTITIONING_ENABLED)
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
308 :
VolumeKernel(
id, tree->getDim(), tree->getComm(), tree->getNofGhostLayers(), ADAPTION_AUTOMATIC, PARTITIONING_ENABLED)
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);
749 const Octant *octant = getOctantPointer(octantInfo);
751 return m_tree->getArea(octant);
762 const Interface &
interface = getInterface(id);
764 long owner = interface.getOwner();
767 const Octant *octant = getOctantPointer(octantInfo);
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.
create(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.
create(adaption::TYPE_DELETION, adaption::ENTITY_CELL, currentRank);
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.create(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) {
1340 OctantInfo octantInfo(treeId,
true);
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]) {
1364 OctantInfo octantInfo = OctantInfo(previousTreeId,
true);
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.create(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.create(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.create(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.create(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 if (octantToCellItr->second == cellId) {
1603 m_octantToCell.erase(octantToCellItr);
1606 m_cellToGhost.erase(cellId);
1608 auto ghostToCellItr = m_ghostToCell.find(treeId);
1609 if (ghostToCellItr->second == cellId) {
1610 m_ghostToCell.erase(ghostToCellItr);
1615 deadCells.push_back(cellId);
1651 StitchInfo stitchVertices;
1652 for (
const auto &entry: m_alteredCells) {
1659 long cellId = entry.first;
1660 const Cell &cell = m_cells[cellId];
1661 ConstProxyVector<long> cellVertexIds = cell.getVertexIds();
1666 for (
int k = 0; k < nCellVertices; ++k) {
1667 long vertexId = cellVertexIds[k];
1668 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1669 stitchVertices.insert({vertexTreeKey, vertexId});
1670 deadVertices.erase(vertexId);
1677 int cellLevel = octant->getLevel();
1679 for (
int face = 0; face < nCellFaces; ++face) {
1680 int nFaceAdjacencies = cell.getAdjacencyCount(face);
1681 const long *faceAdjacencies = cell.getAdjacencies(face);
1682 for (
int i = 0; i < nFaceAdjacencies; ++i) {
1683 int neighId = faceAdjacencies[i];
1686 int neighLevel = neighOctant->getLevel();
1687 if (neighLevel <= cellLevel) {
1691 const Cell &neigh = m_cells[neighId];
1693 const int *localNeighFaceConnect = m_cellTypeInfo->faceConnectStorage[neighFace].data();
1694 ConstProxyVector<long> faceVertexIds = neigh.getFaceVertexIds(neighFace);
1695 std::size_t nFaceVertexIds = faceVertexIds.size();
1696 for (std::size_t k = 0; k < nFaceVertexIds; ++k) {
1697 long vertexId = faceVertexIds[k];
1698 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(neighOctant, localNeighFaceConnect[k]);
1699 stitchVertices.insert({vertexTreeKey, vertexId});
1700 deadVertices.erase(vertexId);
1710 return stitchVertices;
1719void VolOctree::renumberCells(
const std::vector<RenumberInfo> &renumberedOctants)
1722 for (
const RenumberInfo &renumberInfo : renumberedOctants) {
1723 long cellId = renumberInfo.cellId;
1724 if (!m_cells[cellId].isInterior()) {
1728 const OctantInfo &previousOctantInfo =
getCellOctant(cellId);
1729 uint32_t previousTreeId = previousOctantInfo.id;
1731 m_octantToCell.erase(previousTreeId);
1735 for (
const RenumberInfo &renumberInfo : renumberedOctants) {
1736 long cellId = renumberInfo.cellId;
1737 if (!m_cells[cellId].isInterior()) {
1741 uint32_t treeId = renumberInfo.newTreeId;
1743 m_cellToOctant[cellId] = treeId;
1744 m_octantToCell[treeId] = cellId;
1758std::vector<long> VolOctree::importCells(
const std::vector<OctantInfo> &octantInfoList,
1759 StitchInfo &stitchInfo, std::istream *restoreStream)
1762 int nCellVertices = m_cellTypeInfo->nVertices;
1763 for (
const OctantInfo &octantInfo : octantInfoList) {
1765 for (
int k = 0; k < nCellVertices; ++k) {
1766 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1767 if (stitchInfo.count(vertexTreeKey) == 0) {
1769 std::array<double, 3> nodeCoords = m_tree->getNode(octant, k);
1773 if (!restoreStream) {
1774#if BITPIT_ENABLE_MPI==1
1775 VertexIterator vertexIterator =
addVertex(std::move(nodeCoords));
1777 VertexIterator vertexIterator =
addVertex(std::move(nodeCoords));
1779 vertexId = vertexIterator.getId();
1783#if BITPIT_ENABLE_MPI==1
1797 stitchInfo[vertexTreeKey] = vertexId;
1803 long nOctants = m_tree->getNumOctants();
1804 m_cellToOctant.reserve(nOctants);
1805 m_octantToCell.reserve(nOctants);
1807 long nGhostsOctants = m_tree->getNumGhosts();
1808 m_cellToGhost.reserve(nGhostsOctants);
1809 m_ghostToCell.reserve(nGhostsOctants);
1812 size_t octantInfoListSize = octantInfoList.size();
1813 m_cells.reserve(m_cells.size() + octantInfoListSize);
1815 std::vector<long> createdCells(octantInfoListSize);
1816 for (
size_t i = 0; i < octantInfoListSize; ++i) {
1817 const OctantInfo &octantInfo = octantInfoList[i];
1823 std::unique_ptr<long[]> cellConnect = std::unique_ptr<long[]>(
new long[nCellVertices]);
1824 for (
int k = 0; k < nCellVertices; ++k) {
1825 uint64_t vertexTreeKey = m_tree->computeNodePersistentKey(octant, k);
1826 cellConnect[k] = stitchInfo.at(vertexTreeKey);
1829#if BITPIT_ENABLE_MPI==1
1832 if (octantInfo.internal) {
1835 uint64_t globalTreeId = m_tree->getGhostGlobalIdx(octantInfo.id);
1836 owner = m_tree->getOwnerRank(globalTreeId);
1840 int haloLayer = m_tree->getGhostLayer(octant);
1845 if (!restoreStream) {
1846#if BITPIT_ENABLE_MPI==1
1847 CellIterator cellIterator =
addCell(m_cellTypeInfo->type, std::move(cellConnect), owner, haloLayer);
1849 CellIterator cellIterator =
addCell(m_cellTypeInfo->type, std::move(cellConnect));
1851 cellId = cellIterator.getId();
1855#if BITPIT_ENABLE_MPI==1
1856 restoreCell(m_cellTypeInfo->type, std::move(cellConnect), owner, haloLayer, cellId);
1858 restoreCell(m_cellTypeInfo->type, std::move(cellConnect), cellId);
1863 if (octantInfo.internal) {
1864 m_cellToOctant.insert({{cellId, octantInfo.id}});
1865 m_octantToCell.insert({{octantInfo.id, cellId}});
1867 m_cellToGhost.insert({{cellId, octantInfo.id}});
1868 m_ghostToCell.insert({{octantInfo.id, cellId}});
1872 createdCells[i] = cellId;
1876 if (restoreStream) {
1878#if BITPIT_ENABLE_MPI==1
1884 if (restoreStream) {
1896 if (!restoreStream) {
1901 return createdCells;
1913 int maxLevel = m_tree->getMaxDepth();
1916 int nCellFaces = m_cellTypeInfo->nFaces;
1917 const uint8_t *oppositeFace = m_tree->getOppface();
1920 std::vector<std::size_t> nDirtyAdjacenciesCellsByLevel(maxLevel + 1, 0);
1921 for (
const auto &entry : m_alteredCells) {
1922 AlterationFlags cellAlterationFlags = entry.second;
1927 long cellId = entry.first;
1930 ++nDirtyAdjacenciesCellsByLevel[cellLevel];
1934 std::vector<std::vector<long>> hierarchicalCellIds(maxLevel + 1);
1935 for (
int level = 0; level <= maxLevel; ++level) {
1936 hierarchicalCellIds[level].reserve(nDirtyAdjacenciesCellsByLevel[level]);
1939 for (
const auto &entry : m_alteredCells) {
1940 AlterationFlags cellAlterationFlags = entry.second;
1945 long cellId = entry.first;
1947 hierarchicalCellIds[cellLevel].push_back(cellId);
1951 std::vector<uint32_t> neighTreeIds;
1952 std::vector<bool> neighGhostFlags;
1953 for (
int level = 0; level <= maxLevel; ++level) {
1954 for (
long cellId : hierarchicalCellIds[level]) {
1955 Cell &cell = m_cells[cellId];
1958 for (
int face = 0; face < nCellFaces; ++face) {
1990 if (nFaceAdjacencies > 0) {
1991 if (nFaceAdjacencies == 1) {
1992 long cellLevel = octant->
getLevel();
1995 if (neighLevel <= cellLevel) {
1999 uint64_t neighsArea = 0;
2001 for (
int k = 0; k < nFaceAdjacencies; ++k) {
2002 long neighId = faceAdjacencies[k];
2009 if (faceArea == neighsArea) {
2016 neighTreeIds.clear();
2017 neighGhostFlags.clear();
2018 m_tree->findNeighbours(octant, face, 1, neighTreeIds, neighGhostFlags);
2025 int nNeighs = neighTreeIds.size();
2026 for (
int k = 0; k < nNeighs; ++k) {
2027 OctantInfo neighOctantInfo(neighTreeIds[k], !neighGhostFlags[k]);
2034 int neighFace = oppositeFace[face];
2035 Cell &neigh = m_cells[neighId];
2050 return setMarker(
id, 1);
2060 return setMarker(
id, -1);
2071 return setMarker(
id, 0);
2083 if (!octantInfo.internal) {
2084 return adaption::MARKER_UNDEFINED;
2087 int8_t treeMarker = m_tree->getMarker(octantInfo.id);
2088 if (treeMarker > 0) {
2089 return adaption::MARKER_REFINE;
2090 }
else if (treeMarker < 0) {
2091 return adaption::MARKER_COARSEN;
2093 return adaption::MARKER_NONE;
2103bool VolOctree::setMarker(
long id, int8_t value)
2106 if (!octantInfo.internal) {
2110 m_tree->setMarker(octantInfo.id, value);
2125 if (!octantInfo.internal) {
2129 m_tree->setBalance(octantInfo.id, enabled);
2144 return (m_tree->getPointOwner(point, isGhost) !=
nullptr);
2156 const Cell &cell = m_cells[id];
2159 int lowerLeftVertex = 0;
2162 const std::array<double, 3> &lowerLeft =
getVertexCoords(cellVertexIds[lowerLeftVertex]);
2163 const std::array<double, 3> &upperRight =
getVertexCoords(cellVertexIds[upperRightVertex]);
2165 const double EPS =
getTol();
2166 for (
int d = 0; d < 3; ++d){
2167 if (point[d] < lowerLeft[d] - EPS || point[d] > upperRight[d] + EPS) {
2188 uint32_t treeId = m_tree->getPointOwnerIdx(point, isGhost);
2189 if (treeId == std::numeric_limits<uint32_t>::max()) {
2190 return Element::NULL_ID;
2205 m_tree->setTol(tolerance);
2217 double tolerance = m_tree->getTol();
2228 const int DUMP_VERSION = 4;
2230 return DUMP_VERSION;
2241 std::size_t nOctants = m_tree->getNumOctants();
2242 std::size_t nGhostsOctants = m_tree->getNumGhosts();
2244 std::vector<OctantInfo> octantInfoList;
2245 octantInfoList.reserve(nOctants + nGhostsOctants);
2247 for (std::size_t n = 0; n < nOctants; ++n) {
2248 octantInfoList.emplace_back(n,
true);
2251 for (std::size_t n = 0; n < nGhostsOctants; ++n) {
2252 octantInfoList.emplace_back(n,
false);
2256 m_tree->dump(stream);
2261 m_vertices.dumpKernel(stream);
2266 m_cells.dumpKernel(stream);
2272 std::unordered_set<long> dumpedVertices;
2274 for (
const OctantInfo &octantInfo : octantInfoList) {
2277 for (
int k = 0; k < m_cellTypeInfo->nVertices; ++k) {
2278 long vertexId = cellVertexIds[k];
2279 if (dumpedVertices.count(vertexId) == 0) {
2281#if BITPIT_ENABLE_MPI==1
2287 dumpedVertices.insert(vertexId);
2296 for (
const OctantInfo &octantInfo : octantInfoList) {
2316 m_tree->restore(stream);
2319 m_vertices.restoreKernel(stream);
2322 m_cells.restoreKernel(stream);
2329 size_t nOctants = m_tree->getNumOctants();
2330 size_t nGhostsOctants = m_tree->getNumGhosts();
2332 StitchInfo stitchInfo;
2334 std::vector<OctantInfo> octantInfoList;
2335 octantInfoList.reserve(nOctants + nGhostsOctants);
2336 for (std::size_t n = 0; n < nOctants; ++n) {
2337 octantInfoList.emplace_back(n,
true);
2339 for (std::size_t n = 0; n < nGhostsOctants; ++n) {
2340 octantInfoList.emplace_back(n,
false);
2343 importCells(octantInfoList, stitchInfo, &stream);
2367 return octantInfo.id;
2380 return m_tree->getOrigin();
2392 std::array<double, 3> translation = origin -
getOrigin();
2403 m_tree->setOrigin(m_tree->getOrigin() + translation);
2418 return m_tree->getL();
2429 m_tree->setL(length);
2435 if (m_vertices.size() > 0) {
2437 m_tree->computeConnectivity();
2440 std::unordered_set<long> alreadyEvaluated;
2441 for (
const Cell &cell : m_cells) {
2445 for (
int k = 0; k < m_cellTypeInfo->nVertices; ++k) {
2446 long vertexId = cellVertexIds[k];
2447 if (alreadyEvaluated.count(vertexId) == 0) {
2448 Vertex &vertex = m_vertices.at(vertexId);
2449 vertex.
setCoords(m_tree->getNode(octant, k));
2450 alreadyEvaluated.insert(vertexId);
2456 m_tree->clearConnectivity();
2466void VolOctree::scale(
const std::array<double, 3> &scaling,
const std::array<double, 3> ¢er)
2468 bool uniformScaling =
true;
2469 uniformScaling &= (std::abs(scaling[0] - scaling[1]) > 1e-14);
2470 uniformScaling &= (std::abs(scaling[0] - scaling[2]) > 1e-14);
2471 assert(uniformScaling);
2472 if (!uniformScaling) {
2473 log::cout() <<
"VolOctree patch only allows uniform scaling." << std::endl;
2477 std::array<double, 3> origin = m_tree->getOrigin();
2478 for (
int n = 0; n < 3; ++n) {
2479 origin[n] = center[n] + scaling[n] * (origin[n] - center[n]);
2481 m_tree->setOrigin(origin);
2483 m_tree->setL(m_tree->getL() * scaling[0]);
2510 std::vector<uint32_t> neighTreeIds;
2511 std::vector<bool> neighGhostFlags;
2512 m_tree->findAllCodimensionNeighbours(octant, neighTreeIds, neighGhostFlags);
2514 int nNeighs = neighTreeIds.size();
2515 for (
int i = 0; i < nNeighs; ++i) {
2516 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2519 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2520 utils::addToOrderedVector<long>(neighId, *neighs);
2552 findOctantCodimensionNeighs(octantInfo, edge, codimension, blackList, neighs);
2565 std::vector<long> faceNeighs;
2567 int octantLevel = octant->
getLevel();
2568 for (
int face : m_octantLocalFacesOnEdge[edge]) {
2571 for (
long neighId : faceNeighs) {
2574 int neighOctantLevel = neighOctant->
getLevel();
2575 if (neighOctantLevel <= octantLevel) {
2576 utils::addToOrderedVector<long>(neighId, *neighs);
2577 }
else if (m_tree->isEdgeOnOctant(octant, edge, neighOctant)) {
2578 utils::addToOrderedVector<long>(neighId, *neighs);
2604 std::vector<uint32_t> neighTreeIds;
2605 std::vector<bool> neighGhostFlags;
2606 m_tree->findAllNodeNeighbours(octant, vertex, neighTreeIds, neighGhostFlags);
2608 int nNeighs = neighTreeIds.size();
2609 for (
int i = 0; i < nNeighs; ++i) {
2610 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2613 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2614 utils::addToOrderedVector<long>(neighId, *neighs);
2635void VolOctree::findOctantCodimensionNeighs(
const OctantInfo &octantInfo,
int index,
int codimension,
2636 const std::vector<long> *blackList, std::vector<long> *neighs)
const
2639 if (codimension > dimension || codimension <= 0) {
2645 std::vector<uint32_t> neighTreeIds;
2646 std::vector<bool> neighGhostFlags;
2647 m_tree->findNeighbours(octant, index, codimension, neighTreeIds, neighGhostFlags);
2649 int nNeighs = neighTreeIds.size();
2650 for (
int i = 0; i < nNeighs; ++i) {
2651 OctantInfo neighOctantInfo(neighTreeIds[i], !neighGhostFlags[i]);
2654 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
2655 utils::addToOrderedVector<long>(neighId, *neighs);
2671 long cellId = cell.
getId();
2674 int neighFace = m_tree->getOppface()[cellFace];
2678 const long *neighFaceAdjacencies = neigh.
getAdjacencies(neighFace);
2679 for (
int k = 0; k < nNeighFaceAdjacencies; ++k) {
2680 if (neighFaceAdjacencies[k] == cellId) {
2701 if (m_tree->getOppface()[face_A] != face_B) {
2706 long cellId_A = cell_A.
getId();
2709 const long *neighFaceAdjacencies_B = cell_B.
getAdjacencies(face_B);
2710 for (
int k = 0; k < nNeighFaceAdjacencies_B; ++k) {
2711 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()
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)
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.
Iterator for the class PiercedStorage.
Metafunction for generating a pierced vector.
void clear(bool release=true)
void emplaceBack(id_t id, Args &&... args)
void reserve(std::size_t n)
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
static BITPIT_PUBLIC_API const ReferenceElementInfo & getInfo(ElementType type)
The Vertex class defines the vertexs.
void setCoords(const std::array< double, 3 > &coords)
The VolOctree defines a Octree patch.
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
The VolumeKernel class provides an interface for defining volume patches.
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 information associated to an adaption.