25#include "levelSetObject.hpp"
26#include "levelSetCommon.hpp"
86 m_defaultSignedLevelSet(false),
87 m_narrowBandSize(levelSetDefaults::NARROW_BAND_SIZE),
103 : m_kernel(other.m_kernel),
104 m_defaultSignedLevelSet(other.m_defaultSignedLevelSet),
105 m_enabledOutputFields(other.m_enabledOutputFields),
106 m_narrowBandSize(other.m_narrowBandSize),
107 m_cellLocationCacheId(other.m_cellLocationCacheId),
108 m_cellPropagatedSignCacheId(other.m_cellPropagatedSignCacheId),
110 m_nReferences(other.m_nReferences),
111 m_cellBulkEvaluationMode(other.m_cellBulkEvaluationMode),
113 m_cellFieldCacheModes(other.m_cellFieldCacheModes),
114 m_cellFieldCacheIds(other.m_cellFieldCacheIds)
117 for (
const auto &fieldEntry : m_enabledOutputFields ) {
127 : m_kernel(std::move(other.m_kernel)),
128 m_defaultSignedLevelSet(std::move(other.m_defaultSignedLevelSet)),
129 m_narrowBandSize(std::move(other.m_narrowBandSize)),
130 m_cellLocationCacheId(std::move(other.m_cellLocationCacheId)),
131 m_cellPropagatedSignCacheId(std::move(other.m_cellPropagatedSignCacheId)),
132 m_id(std::move(other.m_id)),
133 m_nReferences(std::move(other.m_nReferences)),
134 m_cellBulkEvaluationMode(std::move(other.m_cellBulkEvaluationMode)),
135 m_cellCacheCollection(std::move(other.m_cellCacheCollection)),
136 m_cellFieldCacheModes(std::move(other.m_cellFieldCacheModes)),
137 m_cellFieldCacheIds(std::move(other.m_cellFieldCacheIds))
139 for (
const auto &fieldEntry : other.m_enabledOutputFields ) {
143 for (
const auto &fieldEntry : other.m_enabledOutputFields ) {
144 other.enableVTKOutput(fieldEntry.first,
false);
156 LevelSetFieldset enabledOutputFieldset;
157 enabledOutputFieldset.reserve(m_enabledOutputFields.size());
158 for (
const auto &fieldEntry : m_enabledOutputFields ) {
159 enabledOutputFieldset.push_back(fieldEntry.first);
163 }
catch (
const std::exception &exception) {
177 LevelSetFieldset supportedFields;
182 return supportedFields;
190void LevelSetObject::setId(
int id) {
197std::size_t LevelSetObject::incrementReferenceCount() {
201 return m_nReferences;
208std::size_t LevelSetObject::decrementReferenceCount() {
210 assert(m_nReferences > 0);
213 return m_nReferences;
223 return m_nReferences ;
235 m_defaultSignedLevelSet = signedLevelSet;
247 for (
const auto &fieldEntry : m_enabledOutputFields ) {
253 m_cellCacheCollection = std::unique_ptr<CellCacheCollection>(
new CellCacheCollection(cacheKernel));
298 std::vector<LevelSetField> fillableFields;
299 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
312 fillableFields.push_back(field);
337void LevelSetObject::update(
const std::vector<adaption::Info> &adaptionData )
340 std::vector<LevelSetField> fillableFields;
341 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
354 fillableFields.push_back(field);
415 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
419 bool destroyFieldCache =
true;
421 destroyFieldCache =
false;
423 destroyFieldCache =
false;
426 if (destroyFieldCache) {
504 if (locationCacheEntry.isValid()) {
520 switch (cellLocation) {
532 throw std::runtime_error(
"Cell location identification has not been performed!");
535 throw std::runtime_error(
"Unable to identify cell zone!");
556 std::vector<long> internalCellIds;
559 internalCellIds.resize(nCells);
560 std::iota(internalCellIds.begin(), internalCellIds.end(), 0);
566 internalCellIds.reserve(nCells);
568 long cellId = cellItr.
getId();
569 internalCellIds.push_back(cellId);
580 for (
long cellId : internalCellIds) {
591 std::vector<long> intersectedCellIds;
593 for (
long cellId : internalCellIds) {
599 intersectedCellIds.push_back(cellId);
605 for (
long cellId : intersectedCellIds) {
606 auto neighProcessor = [
this, &locationCache](
long neighId,
int layer) {
625 for (
long cellId : internalCellIds) {
627 assert(locationCacheEntry.isValid());
633#if BITPIT_ENABLE_MPI==1
664 std::unordered_set<long> unknownZoneCellIds;
666 if (adaptionInfo.entity != adaption::Entity::ENTITY_CELL) {
674 if (adaptionInfo.type == adaption::Type::TYPE_PARTITION_RECV && !locationCache->isVolatile()) {
679 for (
long cellId : adaptionInfo.current) {
685 bool isCellProcessable =
true;
686#if BITPIT_ENABLE_MPI==1
689 isCellProcessable = cellItr->isInterior();
693 if (isCellProcessable) {
694 unknownZoneCellIds.insert(cellId);
706 std::unordered_set<long> intersectedCellIds;
708 auto cellIdItr = unknownZoneCellIds.begin();
709 while (cellIdItr != unknownZoneCellIds.end()) {
710 long cellId = *cellIdItr;
717 intersectedCellIds.insert(cellId);
722 cellIdItr = unknownZoneCellIds.erase(cellIdItr);
729#if BITPIT_ENABLE_MPI==1
743 for (
long cellId : unknownZoneCellIds) {
748 auto neighProcessor = [
this, &intersectedCellIds](
long neighId,
int layer) {
752 if (intersectedCellIds.count(neighId) > 0) {
763 intersectedCellIds.insert(neighId);
776 for (
long cellId : intersectedCellIds) {
778 auto neighProcessor = [
this, &locationCache, &unknownZoneCellIds](
long neighId,
int layer) {
788 unknownZoneCellIds.erase(neighId);
798 for (
long cellId : unknownZoneCellIds) {
802#if BITPIT_ENABLE_MPI==1
830 double cellUnsignedValue = std::abs(cellCacheValue);
845 locationCache->insertEntry(
id,
static_cast<char>(cellLocation));
947 return m_cellBulkEvaluationMode;
969 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
973 bool destroyFieldCache =
false;
975 destroyFieldCache =
true;
977 destroyFieldCache =
true;
980 if (destroyFieldCache) {
987 m_cellBulkEvaluationMode = evaluationMode;
1035#if BITPIT_ENABLE_MPI==1
1040 std::unique_ptr<DataCommunicator> ghostCommunicator;
1041 if (ghostExchangeNeeded) {
1045 const int rank = entry.first;
1046 const std::vector<long> &sources = entry.second;
1047 ghostCommunicator->setSend(rank, sources.size() * (
sizeof(
unsigned char) +
sizeof(
char)));
1051 const int rank = entry.first;
1052 const std::vector<long> &targets = entry.second;
1053 ghostCommunicator->setRecv(rank, targets.size() * (
sizeof(
unsigned char) +
sizeof(
char)));
1059 std::vector<long> internalCellIds;
1061 long nCells = cartesianMesh->getCellCount();
1062 internalCellIds.resize(nCells);
1063 std::iota(internalCellIds.begin(), internalCellIds.end(), 0);
1069 internalCellIds.reserve(nCells);
1071 long cellId = cellItr.
getId();
1072 internalCellIds.push_back(cellId);
1086 std::unordered_set<long> seedIds;
1087 for (
long cellId : internalCellIds) {
1089 char cellSign =
static_cast<char>(
evalCellSign(cellId));
1090 propagatedSignCache->insertEntry(cellId, cellSign);
1091 if (cellSign != 0) {
1092 seedIds.insert(cellId);
1098 std::vector<long> processList;
1100 bool signMismatch =
false;
1101 while (!seedIds.empty()) {
1103 long seedId = *(seedIds.begin());
1104 seedIds.erase(seedIds.begin());
1108 char seedSign = *(seedSignEntry);
1115 processList.assign(1, seedId);
1116 while (!processList.empty()) {
1118 long cellId = processList.back();
1119 processList.pop_back();
1129 if (cellId != seedId) {
1131 if (cellSignEntry.isValid()) {
1132 char cellSign = *(cellSignEntry);
1133 if (cellSign != seedSign) {
1134 signMismatch =
true;
1135 log::error() <<
"Sign mismatch on cell " << cellId <<
"!" << std::endl;
1141 propagatedSignCache->insertEntry(cellId, seedSign);
1142 seedIds.erase(cellId);
1147 auto neighProcessor = [&mesh, &propagatedSignCache, &processList](
long neighId,
int layer) {
1149#if BITPIT_ENABLE_MPI==0
1154 if (propagatedSignCache->contains(neighId)) {
1158#if BITPIT_ENABLE_MPI==1
1162 const Cell &neigh = *neighItr;
1170 processList.push_back(neighId);
1186#if BITPIT_ENABLE_MPI==1
1187 if (ghostExchangeNeeded) {
1188 MPI_Allreduce(MPI_IN_PLACE, &signMismatch, 1, MPI_C_BOOL, MPI_LOR, mesh.
getCommunicator());
1193 throw std::runtime_error(
"Sign mismatch in sign propagation!");
1196#if BITPIT_ENABLE_MPI==1
1201 if (ghostExchangeNeeded) {
1203 ghostCommunicator->startAllRecvs();
1206 int rank = entry.first;
1207 SendBuffer &buffer = ghostCommunicator->getSendBuffer(rank);
1208 for (
long cellId : entry.second) {
1211 char cellHasSign = cellSignEntry.isValid() ? 1 : 0;
1212 buffer << cellHasSign;
1215 char cellSign = *(cellSignEntry);
1219 ghostCommunicator->startSend(rank);
1222 bool ghostSignMismatch =
false;
1223 int nPendingRecvs = ghostCommunicator->getRecvCount();
1224 while (nPendingRecvs != 0) {
1225 int rank = ghostCommunicator->waitAnyRecv();
1226 RecvBuffer buffer = ghostCommunicator->getRecvBuffer(rank);
1230 buffer >> sourceHasSign;
1232 if (sourceHasSign == 1) {
1234 buffer >> sourceSign;
1236 if (!propagatedSignCache->contains(cellId)) {
1237 seedIds.insert(cellId);
1238 propagatedSignCache->insertEntry(cellId, sourceSign);
1240 char cellCachedSign = *(propagatedSignCache->findEntry(cellId));
1241 if (cellCachedSign != sourceSign) {
1242 ghostSignMismatch =
true;
1243 log::error() <<
"Sign mismatch on ghost cell " << cellId <<
"!" <<
getId() << std::endl;
1253 if (ghostSignMismatch) {
1258 ghostCommunicator->waitAllSends();
1261 if (ghostExchangeNeeded) {
1262 MPI_Allreduce(MPI_IN_PLACE, &ghostSignMismatch, 1, MPI_C_BOOL, MPI_LOR, mesh.
getCommunicator());
1265 if (ghostSignMismatch) {
1266 throw std::runtime_error(
"Sign mismatch in sign propagation!");
1272 bool completed = seedIds.empty();
1273#if BITPIT_ENABLE_MPI==1
1274 if (ghostExchangeNeeded) {
1275 MPI_Allreduce(MPI_IN_PLACE, &completed, 1, MPI_C_BOOL, MPI_LAND, mesh.
getCommunicator());
1409 double tangentSphere =
m_kernel->computeCellTangentRadius(
id) ;
1421 double boundingSphere =
m_kernel->computeCellBoundingRadius(
id) ;
1433 double boundingSphere =
m_kernel->computeCellBoundingRadius(
id) ;
1438 double tangentSphere =
m_kernel->computeCellTangentRadius(
id) ;
1450 double boundingSphere =
m_kernel->computeCellBoundingRadius(
id) ;
1455 double tangentSphere =
m_kernel->computeCellTangentRadius(
id) ;
1484 auto evaluator = [
this] (
long id)
1488 if (propagatedSignCache) {
1490 if (propagatedSignCacheEntry.isValid()) {
1491 return static_cast<short>(*propagatedSignCacheEntry);
1503 if (valueCacheEntry.isValid()) {
1511 return _evalCellSign(
id);
1514 auto fallback = [
this] (
long id)
1518 if (propagatedSignCache) {
1521 if (propagatedSignCacheEntry.isValid()) {
1522 return static_cast<short>(*propagatedSignCacheEntry);
1531 short sign = evalCellFieldCached<short>(field,
id, evaluator, fallback);
1547 auto evaluator = [
this] (
long id)
1549 return _evalCellValue(
id,
false);
1552 auto fallback = [] (
long id)
1560 double value = evalCellFieldCached<double>(field,
id, evaluator, fallback);
1563 if (signedLevelSet) {
1580 auto evaluator = [
this] (
long id)
1582 return _evalCellGradient(
id,
false);
1585 auto fallback = [] (
long id)
1593 std::array<double, 3> gradient = evalCellFieldCached<std::array<double, 3>>(field, id, evaluator, fallback);
1596 if (signedLevelSet) {
1598 if (cellSign <= 0) {
1599 gradient *=
static_cast<double>(cellSign);
1632 return _evalValue(point, signedLevelSet);
1642 return _evalGradient(point, signedLevelSet);
1670 return static_cast<short>(
sign(value));
1691 std::size_t nCaches = m_cellCacheCollection->size();
1693 for (std::size_t cacheId = 0; cacheId < nCaches; ++cacheId) {
1694 CellCacheCollection::Item &cacheItem = (*m_cellCacheCollection)[cacheId];
1697 bool hasFactory = cacheItem.hasFactory();
1705 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
1710 field = LevelSetField::UNDEFINED;
1715 if (field != LevelSetField::UNDEFINED) {
1720 bool hasCache = cacheItem.hasCache();
1724 cache->dump(stream);
1729 std::size_t nEnabledOutputFields = m_enabledOutputFields.size() ;
1731 for (
const auto &fieldEntry : m_enabledOutputFields) {
1743 LevelSetFieldset enabledOutputFieldset;
1744 enabledOutputFieldset.reserve(m_enabledOutputFields.size());
1745 for (
const auto &fieldEntry : m_enabledOutputFields ) {
1746 enabledOutputFieldset.push_back(fieldEntry.first);
1752 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
1760 m_cellCacheCollection->clear();
1772 std::size_t expectedCellLocationCacheId;
1775 std::size_t expectedCellPropagatedSignCacheId;
1778 std::size_t nCaches;
1780 for (std::size_t cacheId = 0; cacheId < nCaches; ++cacheId) {
1791 if (field != LevelSetField::UNDEFINED) {
1792 std::size_t fieldIndex =
static_cast<std::size_t
>(field);
1801 if (cacheId == expectedCellLocationCacheId) {
1803 }
else if (cacheId == expectedCellPropagatedSignCacheId) {
1805 }
else if (field != LevelSetField::UNDEFINED) {
1808 throw std::runtime_error(
"Unable to restore levelset object " + std::to_string(
getId()) +
"!");
1813 cache->restore(stream);
1819 std::size_t nEnabledVTKOutputs ;
1821 for (std::size_t i = 0; i < nEnabledVTKOutputs; ++i) {
1823 std::string fieldName;
1838 std::stringstream objectNameStream;
1839 objectNameStream <<
getId();
1867 std::stringstream objectNameStream;
1868 objectNameStream <<
getId();
1885 if (std::find(supportedFields.begin(), supportedFields.end(), field) == supportedFields.end()) {
1897 m_enabledOutputFields.erase(field) ;
1912 std::stringstream objectNameStream;
1913 objectNameStream <<
getId();
1928 LevelSetFieldset fieldset;
1940 if (std::find(supportedFields.begin(), supportedFields.end(), field) == supportedFields.end()) {
1941 log::warning() <<
"The specified field is not supported by the levelset object" << std::endl;
1945 fieldset.push_back(field);
1965 return vtkWriter.
hasData(name);
1998 vtkWriter.
addData<
double>( name, VTKFieldType::SCALAR, VTKLocation::CELL,
this);
2002 vtkWriter.
addData<
short>( name, VTKFieldType::SCALAR, VTKLocation::CELL,
this);
2006 vtkWriter.
addData<
double>( name, VTKFieldType::VECTOR, VTKLocation::CELL,
this);
2010 throw std::runtime_error(
"Unsupported value of field in LevelSetObject::addDataToVTK() ");
2026 std::stringstream nameStream;
2028 std::string name = nameStream.str();
2054 throw std::runtime_error(
"Unsupported value of field in LevelSetObject::addDataToVTK() ");
2073 for (
const auto &fieldEntry : m_enabledOutputFields ) {
2074 const std::string &fieldName = fieldEntry.second;
2101 auto evaluator = [
this] (
long id) {
return evalCellValue(
id,
true); };
2103 flushVTKOutputData<double>(stream, format, field, evaluator, fallback);
2109 auto evaluator = [
this] (
long id) {
return (
short)
evalCellSign(
id); };
2111 flushVTKOutputData<short>(stream, format, field, evaluator, fallback);
2119 flushVTKOutputData<std::array<double, 3>>(stream, format, field, evaluator, fallback);
2125 throw std::runtime_error(
"Unable to write the field.");
2131#if BITPIT_ENABLE_MPI
2153 const std::vector<std::size_t> &cacheIds,
2158 for (
const auto &entry : sendCellIds) {
2160 int rank = entry.first;
2161 dataCommunicator->
setSend(rank, 0);
2164 const std::vector<long> &rankSendCellIds = entry.second;
2166 for (std::size_t cacheId : cacheIds) {
2167 getCellCache(cacheId)->writeBuffer(rankSendCellIds, buffer);
2204 const std::vector<std::size_t> &cacheIds,
2208 int nCompletedRecvs = 0;
2209 while (nCompletedRecvs < dataCommunicator->getRecvCount()) {
2212 const std::vector<long> &rankRecvCellIds = recvCellIds.at(rank);
2214 for (std::size_t cacheId : cacheIds) {
2215 getCellCache(cacheId)->readBuffer(rankRecvCellIds, buffer);
2235 std::size_t fieldIndex =
static_cast<std::size_t
>(field);
2237 return m_cellFieldCacheModes[fieldIndex];
2268 std::size_t fieldIndex =
static_cast<std::size_t
>(field);
2269 m_cellFieldCacheModes[fieldIndex] = cacheMode;
2300 std::size_t fieldIndex =
static_cast<std::size_t
>(field);
2314#if BITPIT_ENABLE_MPI==1
2320 bool allCachesEmpty =
true;
2321 for (std::size_t cacheId = 0; cacheId < m_cellCacheCollection->size(); ++cacheId) {
2322 CellCacheCollection::Item &cacheItem = (*m_cellCacheCollection)[cacheId];
2323 if (cacheItem.hasCache()) {
2324 allCachesEmpty =
false;
2329#if BITPIT_ENABLE_MPI==1
2335 if (allCachesEmpty) {
2339#if BITPIT_ENABLE_MPI
2341 std::vector<std::size_t> nonVolatileCellCacheIds;
2344 if (locationCache && !locationCache->isVolatile()) {
2348 for (std::size_t fieldIndex = 0; fieldIndex < static_cast<std::size_t>(LevelSetField::COUNT); ++fieldIndex) {
2351 if (fieldCache && !fieldCache->isVolatile()) {
2353 nonVolatileCellCacheIds.push_back(fieldCacheId);
2360 std::unordered_map<int, std::vector<long>> exchangeSendList ;
2361 std::unordered_map<int, std::vector<long>> exchangeRecvList ;
2362 if (!nonVolatileCellCacheIds.empty()) {
2365 if( adaptionInfo.entity != adaption::Entity::ENTITY_CELL){
2369 switch (adaptionInfo.type) {
2371 case adaption::Type::TYPE_PARTITION_SEND:
2372 exchangeSendList.insert({{adaptionInfo.rank,adaptionInfo.previous}}) ;
2375 case adaption::Type::TYPE_PARTITION_RECV:
2376 exchangeRecvList.insert({{adaptionInfo.rank,adaptionInfo.current}}) ;
2387 bool exchangeCacheData = (!exchangeSendList.empty() || !exchangeRecvList.empty());
2393 std::unique_ptr<DataCommunicator> dataCommunicator;
2394 if (exchangeCacheData) {
2399#if BITPIT_ENABLE_MPI
2401 if (exchangeCacheData) {
2409 for (std::size_t cacheId = 0; cacheId < m_cellCacheCollection->size(); ++cacheId) {
2410 CellCacheCollection::Item &cacheItem = (*m_cellCacheCollection)[cacheId];
2411 if (!cacheItem.hasCache()) {
2418#if BITPIT_ENABLE_MPI
2420 if (exchangeCacheData) {
2435 CellCacheCollection::Item &cacheItem = (*m_cellCacheCollection)[cacheId];
2438 cacheItem.destroyCache();
2439 }
else if (cacheItem.hasCache()) {
2454 CellCacheCollection::Item &cacheItem = (*m_cellCacheCollection)[cacheId];
2455 if (!cacheItem.hasCache()) {
2462 cache->
erase(cellIds);
2466 cache->shrink_to_fit();
2479 switch (cacheMode) {
2491 throw std::runtime_error(
"Unsupported cache mode!");
2507 const std::vector<adaption::Info> &adaptionData)
const
2509 switch (cacheMode) {
2521 throw std::runtime_error(
"Unsupported cache mode!");
2538 return std::vector<long>();
2557 return std::vector<long>();
2572 return std::vector<long>();
2577 return std::vector<long>();
2590 std::vector<long> cellFillIds(nCells);
2591 std::iota(cellFillIds.begin(), cellFillIds.end(), 0);
2595 return mesh.
getCells().getIds(
false);
2598 std::vector<long> cellFillIds;
2600 long nCells = cartesianMesh->getCellCount();
2601 for (
long cellId = 0; cellId < nCells; ++cellId) {
2603 cellFillIds.push_back(cellId);
2608 long cellId = cell.getId();
2610 cellFillIds.push_back(cellId);
2634 return std::vector<long>();
2639 return std::vector<long>();
2646 std::vector<long> cellFillIds;
2648 if (adaptionInfo.entity != adaption::Entity::ENTITY_CELL) {
2653 cellFillIds.insert(cellFillIds.end(), adaptionInfo.current.begin(), adaptionInfo.current.end());
2655 for (
long cellId : adaptionInfo.current) {
2657 cellFillIds.push_back(cellId);
2678 return std::vector<long>();
2693 return std::vector<long>();
2699 std::vector<long> cellFillIds;
2702 for (
long cellId = 0; cellId < nCells; ++cellId) {
2704 cellFillIds.push_back(cellId);
2709 long cellId = cell.getId();
2711 cellFillIds.push_back(cellId);
2736 return std::vector<long>();
2751 return std::vector<long>();
2754 std::vector<long> cellFillIds;
2756 if (adaptionInfo.entity != adaption::Entity::ENTITY_CELL) {
2760 for (
long cellId : adaptionInfo.current) {
2762 cellFillIds.push_back(cellId);
2787 std::vector<long> cellPruneIds;
2789 if (adaptionInfo.entity != adaption::Entity::ENTITY_CELL) {
2793 cellPruneIds.insert(cellPruneIds.end(), adaptionInfo.previous.begin(), adaptionInfo.previous.end());
2794 cellPruneIds.insert(cellPruneIds.end(), adaptionInfo.current.begin(), adaptionInfo.current.end());
2797 return cellPruneIds;
2829 std::size_t fieldIndex =
static_cast<std::size_t
>(field);
2831 return m_cellFieldCacheIds[fieldIndex];
2847 return createFieldCellCache<double>(field, cacheId);
2850 return createFieldCellCache<short>(field, cacheId);
2853 return createFieldCellCache<std::array<double, 3>>(field, cacheId);
2856 throw std::runtime_error(
"The requested field is not supported!");
2869 std::size_t fieldIndex =
static_cast<std::size_t
>(field);;
2886 if (fields.empty()) {
2891 for (std::size_t cacheModeIndex = 0; cacheModeIndex < static_cast<std::size_t>(LevelSetCacheMode::COUNT); ++cacheModeIndex) {
2895 std::vector<LevelSetField> cacheModeFields;
2901 cacheModeFields.push_back(field);
2904 if (cacheModeFields.empty()) {
2926 const std::vector<adaption::Info> &adaptionData)
2929 if (fields.empty()) {
2933#if BITPIT_ENABLE_MPI==1
2938 bool areNonVolatileCacheProcessed =
false;
2941 if (fieldCache && !fieldCache->isVolatile()) {
2942 areNonVolatileCacheProcessed =
true;
2948 std::unordered_set<long> recievedCellIds;
2949 if (areNonVolatileCacheProcessed) {
2952 if( adaptionInfo.entity != adaption::Entity::ENTITY_CELL){
2956 switch (adaptionInfo.type) {
2958 case adaption::Type::TYPE_PARTITION_RECV:
2959 recievedCellIds.insert(adaptionInfo.current.begin(), adaptionInfo.current.end());
2972 for (std::size_t cacheModeIndex = 0; cacheModeIndex < static_cast<std::size_t>(LevelSetCacheMode::COUNT); ++cacheModeIndex) {
2976 std::vector<LevelSetField> cacheModeFields;
2982 cacheModeFields.push_back(field);
2985 if (cacheModeFields.empty()) {
2990 std::vector<long> cellVolatileCacheFillIds =
evalCellCacheFillIds(zone, cacheMode, adaptionData);
2992 bool emptyCellVolatileCacheFillIds = cellVolatileCacheFillIds.empty();
2993#if BITPIT_ENABLE_MPI==1
2995 MPI_Allreduce(MPI_IN_PLACE, &emptyCellVolatileCacheFillIds, 1, MPI_C_BOOL, MPI_LAND,
m_kernel->
getCommunicator()) ;
2999 if (emptyCellVolatileCacheFillIds) {
3007 std::vector<long> cellNonVolatileCacheFillIds;
3008#if BITPIT_ENABLE_MPI
3009 if (areNonVolatileCacheProcessed && !recievedCellIds.empty()) {
3010 cellNonVolatileCacheFillIds.reserve(cellVolatileCacheFillIds.size());
3011 for (
long cellId : cellVolatileCacheFillIds) {
3012 if (recievedCellIds.count(cellId)) {
3016 cellNonVolatileCacheFillIds.push_back(cellId);
3019 cellNonVolatileCacheFillIds = cellVolatileCacheFillIds;
3022 cellNonVolatileCacheFillIds = cellVolatileCacheFillIds;
3028 if (cache->isVolatile()) {
3050#if BITPIT_ENABLE_MPI==1
3059 bool emptyCellIds = cellIds.
empty();
3060#if BITPIT_ENABLE_MPI==1
3071 std::unordered_set<long> ghostExchangeSources;
3072 std::unordered_set<long> ghostExchangeTargets;
3073#if BITPIT_ENABLE_MPI
3075 const std::vector<long> &rankSourceList = entry.second;
3076 ghostExchangeSources.insert(rankSourceList.begin(), rankSourceList.end());
3080 const std::vector<long> &rankTargetList = entry.second;
3081 ghostExchangeTargets.insert(rankTargetList.begin(), rankTargetList.end());
3085#if BITPIT_ENABLE_MPI
3090 std::unique_ptr<DataCommunicator> dataCommunicator;
3096 for (
long cellId : cellIds) {
3097 if (ghostExchangeSources.count(cellId) == 0) {
3105 if (dataCommunicator) {
3114 for (
long cellId : cellIds) {
3115 if (ghostExchangeSources.count(cellId) > 0) {
3117 }
else if (ghostExchangeTargets.count(cellId) > 0) {
3124#if BITPIT_ENABLE_MPI
3126 if (dataCommunicator) {
3161 throw std::runtime_error(
"Unsupported field!");
3181 return (*m_cellCacheCollection)[cacheId].getCache();
3191 m_cellCacheCollection->erase(cacheId);
3229short LevelSetObject::getSign(
long cellId)
const {
3240double LevelSetObject::getValue(
long cellId)
const {
3251std::array<double,3> LevelSetObject::getGradient(
long cellId)
const {
The Cell class defines the cells.
The DataCommunicator class provides the infrastructure needed to exchange data among processes.
void clearAllSends(bool synchronous=false)
SendBuffer & getSendBuffer(int rank)
int waitAnyRecv(const std::vector< int > &blackList=std::vector< int >())
void setSend(int rank, long length=0)
RecvBuffer & getRecvBuffer(int rank)
The class ElementCacheCollection allows to store a collection of caches for the elements of a mesh.
static const std::size_t NULL_CACHE_ID
The class LevelSetCache is the base class for defining caches.
std::size_t erase(const Keys &keys)
Mesh specific implementation to calculate the levelset function.
virtual VolumeKernel * getMesh() const
LevelSetFillIn getExpectedFillIn() const
double getDistanceTolerance() const
virtual bool intersectCellPlane(long, const std::array< double, 3 > &, const std::array< double, 3 > &, double)
MPI_Comm getCommunicator() const
std::unique_ptr< DataCommunicator > createDataCommunicator() const
Interface class for all objects with respect to whom the levelset function may be computed.
double getLS(long cellId) const
std::vector< long > evalCellCacheStaleIds(const std::vector< adaption::Info > &adaptionData) const
void clearCellCache(std::size_t cacheId, bool release)
void flushData(std::fstream &, const std::string &, VTKFormat) override
LevelSetInfo getLevelSetInfo(long cellId) const
virtual void destroyFieldCellCache(LevelSetField field)
CellCacheCollection::ValueCache< value_t > * getCellCache(std::size_t cacheId) const
static const LevelSetIntersectionMode CELL_LOCATION_INTERSECTION_MODE
void destroyCellCache(std::size_t cacheId)
LevelSetBulkEvaluationMode getCellBulkEvaluationMode() const
void pruneCellCache(std::size_t cacheId, const std::vector< long > &cellIds)
void updateCellNarrowBandData(const std::vector< adaption::Info > &adaptionData)
void completeCellCachesExchange(const std::unordered_map< int, std::vector< long > > &sendCellIds, const std::vector< std::size_t > &cacheIds, DataCommunicator *)
void startCellCachesExchange(const std::unordered_map< int, std::vector< long > > &recvCellIds, const std::vector< std::size_t > &cacheIds, DataCommunicator *) const
void setSizeNarrowBand(double)
void destroyCellBulkData()
std::vector< long > evalCellCacheFillIds(LevelSetZone zone, LevelSetCacheMode cacheMode) const
void fillFieldCellCache(LevelSetField field, const std::vector< long > &cellIds)
void setDefaultLevelSetSigndness(bool signedLevelSet)
short evalValueSign(double value) const
virtual double evalValue(const std::array< double, 3 > &point, bool signedLevelSet) const
LevelSetKernel * m_kernel
virtual std::array< double, 3 > evalCellProjectionPoint(long id) const
void removeVTKOutputData(LevelSetField field, const std::string &objectName)
void completeCellCacheExchange(const std::unordered_map< int, std::vector< long > > &sendCellIds, std::size_t cacheIds, DataCommunicator *)
void enableFieldCellCache(LevelSetField field, LevelSetCacheMode cacheMode)
std::array< double BITPIT_COMMA 3 > computeVertexProjectionPoint(long vertexId) const
virtual const LevelSetKernel * getKernel() const
std::size_t getFieldCellCacheId(LevelSetField field) const
CellCacheCollection::ValueCache< value_t > * getFieldCellCache(LevelSetField field) const
virtual std::size_t createCellLocationCache(std::size_t cacheId=CellCacheCollection::NULL_CACHE_ID)
void updateCellBulkData(const std::vector< adaption::Info > &adaptionData)
void setCellBulkEvaluationMode(LevelSetBulkEvaluationMode evaluationMode)
virtual void addVTKOutputData(LevelSetField field, const std::string &objectName)
void destroyCellLocationCache()
static const bool CELL_CACHE_IS_SIGNED
double m_narrowBandSize
Size of narrow band.
virtual std::string getVTKOutputFieldName(LevelSetField field) const
LevelSetIntersectionStatus intersectSurface(long, LevelSetIntersectionMode=LevelSetIntersectionMode::FAST_FUZZY) const
virtual bool isPrimary() const
virtual ~LevelSetObject()
virtual std::size_t createCellPropagatedSignCache(std::size_t cacheId=CellCacheCollection::NULL_CACHE_ID)
virtual void fillCellPropagatedSignCache()
virtual short evalSign(const std::array< double, 3 > &point) const
virtual std::array< double, 3 > evalProjectionPoint(const std::array< double, 3 > &point) const
LevelSetCacheMode getFieldCellCacheMode(LevelSetField field) const
virtual short _evalSign(const std::array< double, 3 > &point) const
std::vector< long > evalCellNarrowBandCacheFillIds(LevelSetZone zone) const
virtual LevelSetIntersectionStatus _intersectSurface(long, double distance, LevelSetIntersectionMode=LevelSetIntersectionMode::FAST_FUZZY) const
virtual std::array< double, 3 > evalCellGradient(long id, bool signedLevelSet) const
void disableFieldCellCache(LevelSetField field)
void destroyCellPropagatedSignCache()
virtual double evalCellValue(long id, bool signedLevelSet) const
virtual std::array< double, 3 > evalGradient(const std::array< double, 3 > &point, bool signedLevelSet) const
virtual LevelSetFieldset getSupportedFields() const
virtual void dump(std::ostream &)
bool hasVTKOutputData(LevelSetField field, const std::string &objectName) const
virtual void fillCellLocationCache()
virtual short evalCellSign(long id) const
LevelSetCellLocation getCellLocation(long id) const
LevelSetZone getCellZone(long id) const
void evaluateCellNarrowBandData()
void adaptCellCaches(const std::vector< adaption::Info > &adaptionData)
virtual bool isCellInNarrowBand(long id) const
std::vector< long > evalCellOnDemandCacheFillIds(LevelSetZone zone) const
void setNarrowBandSize(double size)
std::size_t m_cellLocationCacheId
Id of the cache that will keep track if cell zones.
double getNarrowBandSize() const
void destroyCellNarrowBandData()
double getSizeNarrowBand() const
std::array< double BITPIT_COMMA 3 > computeProjectionPoint(long cellId) const
virtual LevelSetCellLocation fillCellGeometricNarrowBandLocationCache(long id)
void enableVTKOutput(const LevelSetFieldset &fieldset, bool enable=true)
std::size_t m_cellPropagatedSignCacheId
Id of the cache that will keep track if cell propagated sign.
void fillFieldCellCaches(LevelSetZone zone, const std::vector< LevelSetField > &fields)
virtual void flushVTKOutputData(std::fstream &stream, VTKFormat format, LevelSetField field) const
virtual void setKernel(LevelSetKernel *)
void evaluateCellBulkData()
virtual void restore(std::istream &)
std::size_t getReferenceCount() const
std::vector< long > evalCellFullCacheFillIds(LevelSetZone zone) const
virtual std::size_t createFieldCellCache(LevelSetField field, std::size_t cacheId=CellCacheCollection::NULL_CACHE_ID)
std::string getVTKOutputDataName(LevelSetField field, const std::string &objectName) const
virtual bool isInNarrowBand(const std::array< double, 3 > &point) const
void startCellCacheExchange(const std::unordered_map< int, std::vector< long > > &recvCellIds, std::size_t cacheIds, DataCommunicator *) const
The class LevelSetCache is the base class for defining caches that store values.
CellConstIterator internalCellConstEnd() const
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeSources() const
PiercedVector< Cell > & getCells()
CellConstIterator internalCellConstBegin() const
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeTargets() const
bool empty(bool global=true) const
VTKUnstructuredGrid & getVTK()
const MPI_Comm & getCommunicator() const
void processCellFaceNeighbours(long seedId, int nLayers, Function function) const
bool isPartitioned() const
virtual long getCellCount() const
const std::array< double, 3 > & getVertexCoords(long id) const
CellConstIterator getCellConstIterator(long id) const
id_t getId(const id_t &fallback=-1) const noexcept
Iterator for the class PiercedStorage.
Metafunction for generating a pierced vector.
Buffer to be used for receive communications.
Buffer to be used for send communications.
A base class for VTK input output.
VTKField & addData(VTKField &&field)
void removeData(const std::string &)
bool hasData(const std::string &) const
The VolCartesian defines a Cartesian patch.
The VolumeKernel class provides an interface for defining volume patches.
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNREACHABLE(str)
#define BITPIT_UNUSED(variable)
bool keywordInString(const std::string &line, const std::string &key)
LevelSetIntersectionStatus
LevelSetBulkEvaluationMode
@ NARROW_BAND
Narrow band zone.
@ NARROW_BAND
Data are cached only inside the narrow band.
@ NONE
No caching will be performed.
@ FULL
Data are cached in the whole domain.
@ ON_DEMAND
Data are cached only where explicitly evaluated.
@ UNKNOWN
Unknown location.
@ NARROW_BAND_INTERSECTED
Narrow band zone, the cell intersects the surface.
@ SIGN_PROPAGATION
Sign is propagated from the narrow band, no other data will be evaluated.
@ EXACT
Exact data is evaluated.
const std::array< double, 3 > GRADIENT
Logger & error(log::Visibility defaultVisibility)
Logger & warning(log::Visibility defaultVisibility)
A public container which includes all information provided by LevelSet.
The Info struct defines the information associated to an adaption.