9#include <unordered_map>
10#include <unordered_set>
73 const std::vector<DNDS::index> &pushIndex,
74 const std::vector<DNDS::index> &pushIndexStart,
78 Serial2Global.
InitPair(
"Serial2Global", mpi);
79 Serial2Global.
father->Resize(localSize);
81 Serial2Global.
trans.createFatherGlobalMapping();
82 Serial2Global.
trans.createGhostMapping(pushIndex, pushIndexStart);
83 Serial2Global.
trans.createMPITypes();
84 Serial2Global.
son->createGlobalMapping();
86 for (
DNDS::index iSon = 0; iSon < Serial2Global.
son->Size(); iSon++)
87 (*Serial2Global.
son)[iSon] = Serial2Global.
son->pLGlobalMapping->operator()(mpi.rank, iSon);
88 Serial2Global.
trans.pushOnce();
89 serial2Global.resize(localSize);
91 serial2Global[iFat] = Serial2Global.
father->operator[](iFat);
108 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing PartitionReorderToMeshCell2Cell" << std::endl;
113 for (
DNDS::rowsize ic2n = 0; ic2n < (*cell2nodeSerial).RowSize(iCell); ic2n++)
120 std::vector<DNDS::index> cell_push, cell_pushStart, node_push, node_pushStart, bnd_push, bnd_pushStart;
124 std::vector<DNDS::index> cell_Serial2Global, node_Serial2Global, bnd_Serial2Global;
132 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing PartitionReorderToMeshCell2Cell ConvertAdjSerial2Global" << std::endl;
139 mesh->coords.InitPair(
"coords",
mesh->getMPI());
142 mesh->cell2node.InitPair(
"cell2node",
mesh->getMPI());
143 mesh->cell2cellOrig.InitPair(
"cell2cellOrig",
mesh->getMPI());
144 mesh->node2nodeOrig.InitPair(
"node2nodeOrig",
mesh->getMPI());
145 mesh->bnd2bndOrig.InitPair(
"bnd2bndOrig",
mesh->getMPI());
146 if (
mesh->isPeriodic)
147 mesh->cell2nodePbi.InitPair(
"cell2nodePbi",
mesh->getMPI());
149 mesh->bnd2node.InitPair(
"bnd2node",
mesh->getMPI());
150 mesh->bnd2cell.InitPair(
"bnd2cell",
mesh->getMPI());
151 if (
mesh->isPeriodic)
152 mesh->bnd2nodePbi.InitPair(
"bnd2nodePbi",
mesh->getMPI());
156 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing PartitionReorderToMeshCell2Cell Trasfer Data Coord" << std::endl;
161 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing PartitionReorderToMeshCell2Cell Trasfer Data Cell" << std::endl;
167 if (
mesh->isPeriodic)
171 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing PartitionReorderToMeshCell2Cell Trasfer Data Bnd" << std::endl;
177 if (
mesh->isPeriodic)
182 { log() <<
"[" << mesh->getMPI().rank <<
": nCell " << mesh->cell2node.father->Size() <<
"] " << (((mesh->getMPI().rank + 1) % 10) ?
"" :
"\n") << std::flush; });
184 if (
mesh->getMPI().rank == 0)
187 { log() <<
"[" << mesh->getMPI().rank <<
": nNode " << mesh->coords.father->Size() <<
"] " << (((mesh->getMPI().rank + 1) % 10) ?
"" :
"\n") << std::flush; });
189 if (
mesh->getMPI().rank == 0)
192 { log() <<
"[" << mesh->getMPI().rank <<
": nBnd " << mesh->bnd2node.father->Size() <<
"] " << (((mesh->getMPI().rank + 1) % 10) ?
"" :
"\n") << std::flush; });
194 if (
mesh->getMPI().rank == 0)
199 DNDS::log() <<
"UnstructuredMeshSerialRW === Done PartitionReorderToMeshCell2Cell" << std::endl;
210 std::vector<DNDS::index> serialPullCell;
211 std::vector<DNDS::index> serialPullNode;
220 serialPullCell.resize(numCellGlobal);
221 serialPullNode.resize(numNodeGlobal);
224 serialPullCell[i] = i;
226 serialPullNode[i] = i;
231 if (
mesh->isPeriodic)
238 if (
mesh->isPeriodic)
247 if (
mesh->isPeriodic)
255 if (
mesh->isPeriodic)
263 if (
mesh->isPeriodic)
271 if (
mesh->isPeriodic)
278 DNDS::log() <<
"UnstructuredMeshSerialRW === BuildSerialOut Done " << std::endl;
289 using namespace Elem;
294 if (
eType == ElemType::Line2 ||
295 eType == ElemType::Tri3 ||
296 eType == ElemType::Quad4 ||
297 eType == ElemType::Tet4 ||
298 eType == ElemType::Hex8 ||
299 eType == ElemType::Prism6 ||
300 eType == ElemType::Pyramid5)
317 using namespace Elem;
322 if (
eType == ElemType::Line3 ||
323 eType == ElemType::Tri6 ||
324 eType == ElemType::Quad9 ||
325 eType == ElemType::Tet10 ||
326 eType == ElemType::Hex27 ||
327 eType == ElemType::Prism18 ||
328 eType == ElemType::Pyramid14)
345 static void GeneralCell2NodeToNode2Cell(
350 const auto &mpi = coords.father->getMPI();
351 std::unordered_set<index> ghostNodesCompactSet;
352 std::vector<index> ghostNodesCompact;
353 std::unordered_map<index, std::unordered_set<index>> node2CellLocalRecord;
355 for (
index iCell = 0; iCell < cell2node.
father->Size(); iCell++)
356 for (
auto iNode : cell2node[iCell])
358 auto [ret, rank, val] = coords.father->pLGlobalMapping->search(iNode);
360 if (rank != mpi.rank)
361 ghostNodesCompact.push_back(iNode), ghostNodesCompactSet.insert(iNode);
362 node2CellLocalRecord[iNode].insert(CellIndexLocal2Global_NoSon(iCell));
369 node2cell.
InitPair(
"node2cell", mpi);
370 node2cellPast = make_ssp<tAdj::element_type>(
ObjName{
"node2cellPast"}, mpi);
372 node2cell.
father->Resize(coords.father->Size());
373 for (
index iNode = 0; iNode < coords.father->Size(); iNode++)
375 index iNodeG = NodeIndexLocal2Global_NoSon(iNode);
376 if (node2CellLocalRecord.count(iNodeG))
378 node2cell.
ResizeRow(iNode, node2CellLocalRecord[iNodeG].size());
380 for (
auto v : node2CellLocalRecord[iNodeG])
381 node2cell(iNode, in2c++) =
v;
385 node2cell.
trans.createFatherGlobalMapping();
386 node2cell.
trans.createGhostMapping(ghostNodesCompact);
388 node2cell.
son->Resize(node2cell.
trans.pLGhostMapping->ghostIndex.size());
390 for (
auto &[k, s] : node2CellLocalRecord)
394 if (!node2cell.
trans.pLGhostMapping->search(k, rank, val))
398 node2cell.
son->ResizeRow(val, s.size());
401 node2cell.
son->operator()(val, in2c++) =
v;
411 std::vector<index> pushSonSeries(node2cell.
son->Size());
412 for (
index i = 0; i < node2cell.
son->Size(); i++)
413 pushSonSeries[i] = i;
422 for (
index i = 0; i < node2cellPast->Size(); i++)
424 index iNodeG = node2cell.
trans.pLGhostMapping->pushingIndexGlobal[i];
425 for (
auto iCell : (*node2cellPast)[i])
426 node2CellLocalRecord[iNodeG].insert(iCell);
441 node2cell.
InitPair(
"node2cell", mpi);
443 node2cell.
father->Resize(coords.father->Size());
444 for (
index iNode = 0; iNode < coords.father->Size(); iNode++)
446 index iNodeG = NodeIndexLocal2Global_NoSon(iNode);
447 if (node2CellLocalRecord.count(iNodeG))
449 node2cell.
ResizeRow(iNode, node2CellLocalRecord[iNodeG].size());
451 for (
auto v : node2CellLocalRecord[iNodeG])
452 node2cell(iNode, in2c++) =
v;
458 const tPoint &translation1,
461 const tPoint &translation2,
464 const tPoint &translation3,
504 GeneralCell2NodeToNode2Cell(
513 GeneralCell2NodeToNode2Cell(
684 DNDS_assert_info(
ret, fmt::format(
"periodic bnd {} candidate cell {} not found in ghost mapping", i,
ic));
709 fmt::format(
"periodic bnd {} has {} cells after pbi filter", i,
cellRecFiltered.size()));
727 std::vector<Geom::NodePeriodicBits>
pbi0,
pbi1;
755 if (
bndElemInfo(i, 0).zone == Geom::BC_ID_PERIODIC_1_DONOR)
757 else if (
bndElemInfo(i, 0).zone == Geom::BC_ID_PERIODIC_2_DONOR)
759 else if (
bndElemInfo(i, 0).zone == Geom::BC_ID_PERIODIC_3_DONOR)
789 ?
"this periodic bnd matches both sides"
790 :
"this periodic bnd matches no sides");
959 [&](
index v) { return CellIndexGlobal2Local(v); });
967 [&](
index v) { auto r = NodeIndexGlobal2Local(v); DNDS_assert(r >= 0); return r; });
970 [&](
index v) { auto r = NodeIndexGlobal2Local(v); DNDS_assert(r >= 0); return r; });
985 [&](
index v) { return CellIndexLocal2Global(v); });
993 [&](
index v) { auto r = NodeIndexLocal2Global(v); DNDS_assert(r >= 0); return r; });
996 [&](
index v) { auto r = NodeIndexLocal2Global(v); DNDS_assert(r >= 0); return r; });
1009 [&](
index v) { auto r = NodeIndexGlobal2Local(v); DNDS_assert(r >= 0); return r; });
1021 [&](
index v) { auto r = NodeIndexLocal2Global(v); DNDS_assert(r >= 0); return r; });
1033# pragma omp parallel for
1070# pragma omp parallel for
1112# pragma omp parallel for
1152# pragma omp parallel for
1195# pragma omp parallel for
1202# pragma omp parallel for
1222# pragma omp parallel for
1229# pragma omp parallel for
1320 [&](
index v) { return CellIndexLocal2Global(v); });
1334 [&](
index v) { return CellIndexGlobal2Local(v); });
1348 struct FaceEnumerationResult
1372 FaceEnumerationResult EnumerateFacesFromCells(
1381 FaceEnumerationResult
result;
1388 std::vector<std::vector<DNDS::index>> node2face(coordsSize);
1390 using idx_pbi_pair = std::pair<index, NodePeriodicBits>;
1391 auto idx_pbi_pair_less = [](idx_pbi_pair &L, idx_pbi_pair &R)
1392 {
return L.first == R.first ? uint8_t(L.second) < uint8_t(R.second) : L.first < R.first; };
1393 auto idx_pbi_pair_eq = [](idx_pbi_pair &L, idx_pbi_pair &R)
1394 {
return L.first == R.first && uint8_t(L.second) == uint8_t(R.second); };
1396 for (
DNDS::index iCell = 0; iCell < cell2cellSize; iCell++)
1398 auto eCell = Elem::Element{cellElemInfo[iCell]->getElemType()};
1399 cell2face.ResizeRow(iCell, eCell.GetNumFaces());
1400 for (
int ic2f = 0; ic2f < eCell.GetNumFaces(); ic2f++)
1402 auto eFace = eCell.ObtainFace(ic2f);
1403 std::vector<DNDS::index> faceNodes(eFace.GetNumNodes());
1404 eCell.ExtractFaceNodes(ic2f, cell2node[iCell], faceNodes);
1406 std::vector<DNDS::index> faceVerts(faceNodes.begin(), faceNodes.begin() + eFace.GetNumVertices());
1407 std::sort(faceVerts.begin(), faceVerts.end());
1409 std::vector<NodePeriodicBits> faceNodePeriodicBits;
1410 std::vector<idx_pbi_pair> faceNodeNodePeriodicBits;
1413 faceNodePeriodicBits.resize(eFace.GetNumNodes());
1414 faceNodeNodePeriodicBits.resize(eFace.GetNumNodes());
1415 eCell.ExtractFaceNodes(ic2f, cell2nodePbi[iCell], faceNodePeriodicBits);
1416 for (
size_t i = 0; i < faceNodeNodePeriodicBits.size(); i++)
1417 faceNodeNodePeriodicBits[i].first = faceNodes[i], faceNodeNodePeriodicBits[i].second = faceNodePeriodicBits[i];
1418 std::sort(faceNodeNodePeriodicBits.begin(), faceNodeNodePeriodicBits.end(),
1420 for (
size_t i = 1; i < faceNodeNodePeriodicBits.size(); i++)
1422 DNDS_assert_info(!idx_pbi_pair_eq(faceNodeNodePeriodicBits[i - 1], faceNodeNodePeriodicBits[i]),
1423 "the face has identical (periodic) nodes");
1427 for (
auto iV : faceVerts)
1429 for (
auto iFOther : node2face[iV])
1431 auto eFaceOther = Elem::Element{
faceElemInfoV[iFOther].getElemType()};
1432 if (eFaceOther.type != eFace.type)
1434 std::vector<DNDS::index> faceVertsOther(
1436 face2nodeV[iFOther].begin() + eFace.GetNumVertices());
1437 std::sort(faceVertsOther.begin(), faceVertsOther.end());
1438 if (std::equal(faceVerts.begin(), faceVerts.end(), faceVertsOther.begin(), faceVertsOther.end()))
1442 std::vector<std::pair<index, NodePeriodicBits>> faceNodeNodePeriodicBitsOther(eFaceOther.GetNumNodes());
1443 for (
size_t i = 0; i < faceNodeNodePeriodicBitsOther.size(); i++)
1444 faceNodeNodePeriodicBitsOther[i].first =
face2nodeV[iFOther][i],
1445 faceNodeNodePeriodicBitsOther[i].second =
face2nodePbiV[iFOther][i];
1446 std::sort(faceNodeNodePeriodicBitsOther.begin(), faceNodeNodePeriodicBitsOther.end(),
1448 auto v0 = faceNodeNodePeriodicBits.at(0).second ^ faceNodeNodePeriodicBitsOther.at(0).second;
1449 DNDS_assert(faceNodeNodePeriodicBitsOther.size() == faceNodeNodePeriodicBits.size());
1450 bool collaborating =
true;
1451 for (
size_t i = 1; i < faceNodeNodePeriodicBitsOther.size(); i++)
1452 if ((faceNodeNodePeriodicBits[i].second ^ faceNodeNodePeriodicBitsOther[i].second) != v0)
1453 collaborating =
false;
1470 for (
auto iV : faceVerts)
1471 node2face[iV].push_back(
nFaces);
1472 cell2face(iCell, ic2f) =
nFaces;
1479 cell2face(iCell, ic2f) = iFound;
1489 struct FaceCollectionResult
1509 FaceCollectionResult CollectFaces(
1511 const std::vector<std::pair<DNDS::index, DNDS::index>> &
face2cellV,
1519 FaceCollectionResult
result;
1521 result.faceSendLocals.resize(nMPIRanks);
1530 else if (
face2cellV[iFace].first >= nLocalCells &&
1533 else if (
face2cellV[iFace].first >= nLocalCells ||
1542 auto retL = globalMapping.
search(cellGlobL, rankL, valL);
1543 auto retR = globalMapping.
search(cellGlobR, rankR, valR);
1547 result.iFaceAllToCollected[iFace] = -1;
1552 result.faceSendLocals[rankR].push_back(
result.nFacesNew);
1553 result.iFaceAllToCollected[iFace] =
result.nFacesNew++;
1558 result.iFaceAllToCollected[iFace] =
result.nFacesNew++;
1563 result.iFaceAllToCollected[iFace] =
result.nFacesNew++;
1583 void CompactFacesAndRemapCell2Face(
1584 const FaceEnumerationResult &faceEnum,
1585 const FaceCollectionResult &faceCollect,
1594 const auto &
face2nodeV = faceEnum.face2nodeV;
1596 const auto &
face2cellV = faceEnum.face2cellV;
1631# pragma omp parallel for
1633 for (
DNDS::index iCell = 0; iCell < cell2face.Size(); iCell++)
1635 for (
rowsize ic2f = 0; ic2f < cell2face.RowSize(iCell); ic2f++)
1649 void MatchBoundariesToFaces(
1657 std::vector<index> &bnd2faceV,
1658 std::unordered_map<index, index> &face2bndM,
1662 bnd2faceV.resize(bndElemInfo.father->Size(), -1);
1663 face2bndM.reserve(bndElemInfo.father->Size());
1664 std::unordered_map<index, index> iFace2iBnd;
1665 for (
DNDS::index iBnd = 0; iBnd < bndElemInfo.father->Size(); iBnd++)
1668 std::vector<DNDS::index> b2nRow = bnd2node[iBnd];
1669 std::sort(b2nRow.begin(), b2nRow.end());
1671 auto faceID = bndElemInfo[iBnd]->zone;
1672 for (
int ic2f = 0; ic2f < cell2face.RowSize(pCell); ic2f++)
1674 auto iFace = cell2face(pCell, ic2f);
1677 std::vector<DNDS::index> f2nRow = face2node[iFace];
1678 std::sort(f2nRow.begin(), f2nRow.end());
1679 if (std::equal(b2nRow.begin(), b2nRow.end(), f2nRow.begin(), f2nRow.end()))
1681 if (iFace2iBnd.count(iFace))
1684 index iBndOther = iFace2iBnd[iFace];
1685 index iCellA = bnd2cell[iBnd][0];
1686 index iCellB = bnd2cell[iBndOther][0];
1690 if (iCellA > iCellB)
1693 iFace2iBnd[iFace] = iBnd;
1697 faceElemInfo(iFace, 0) = bndElemInfo(iBnd, 0);
1698 bnd2faceV[iBnd] = iFace;
1699 face2bndM[iFace] = iBnd;
1702 "bnd elem should have a BC id not interior");
1708 face2bnd.father->Resize(face2node.father->Size());
1709 for (
index iFace = 0; iFace < face2bnd.father->Size(); iFace++)
1710 face2bnd.father->operator()(iFace) = face2bndM.count(iFace) ? face2bndM[iFace] :
UnInitIndex;
1711 bnd2face.father->Resize(bnd2node.father->Size());
1712 for (
index iBnd = 0; iBnd < bnd2node.father->Size(); iBnd++)
1713 bnd2face.father->operator()(iBnd) = bnd2faceV.at(iBnd);
1723 void AssignGhostFacesToCells(
1724 const tAdj2 &face2cellSon,
1725 const tAdj &face2nodeSon,
1733# pragma omp parallel for
1735 for (
DNDS::index iFace = 0; iFace < face2cellSon->Size(); iFace++)
1738 DNDS_assert((*face2cellSon)(iFace, 0) >= cell2node.father->Size());
1739 auto eFace = Elem::Element{(*faceElemInfoSon)(iFace, 0).getElemType()};
1740 auto faceVerts = std::vector<index>((*face2nodeSon)[iFace].begin(), (*face2nodeSon)[iFace].begin() + eFace.GetNumVertices());
1741 std::sort(faceVerts.begin(), faceVerts.end());
1742 for (
rowsize if2c = 0; if2c < 2; if2c++)
1744 index iCell = (*face2cellSon)(iFace, if2c);
1745 auto cell2faceRow = cell2face[iCell];
1746 auto cellNodes = cell2node[iCell];
1747 auto eCell = Elem::Element{cellElemInfo(iCell, 0).getElemType()};
1749 for (
rowsize ic2f = 0; ic2f < cell2face.RowSize(iCell); ic2f++)
1751 auto eFace = eCell.ObtainFace(ic2f);
1752 std::vector<index> faceNodesC(eFace.GetNumNodes());
1753 eCell.ExtractFaceNodes(ic2f, cellNodes, faceNodesC);
1754 std::sort(faceNodesC.begin(), faceNodesC.end());
1755 if (std::includes(faceNodesC.begin(), faceNodesC.end(), faceVerts.begin(), faceVerts.end()))
1758 cell2face(iCell, ic2f) = iFace + nFatherFaces;
1853 cell2face.TransAttach();
1880 log() <<
"UnstructuredMesh === InterpolateFace: total faces " <<
gSize << std::endl;
1902 "Face {} is internal, but f2c[1] is null, at {},{},{} - {},{},{}",
iFace,
1942 serializerP->WriteString(
"mesh",
"UnstructuredMesh");
2046 log() <<
"UnstructuredMesh === ReadSerialize "
2047 <<
"Global NumCell [ " << nCellG <<
" ]" << std::endl;
2048 log() <<
"UnstructuredMesh === ReadSerialize "
2049 <<
"Global NumNode [ " <<
nNodeG <<
" ]" << std::endl;
2050 log() <<
"UnstructuredMesh === ReadSerialize "
2051 <<
"Global NumBnd [ " <<
nNodeB <<
" ]" << std::endl;
2064 bMesh.cell2node.InitPair(
"bMesh.cell2node",
mpi);
2065 bMesh.coords.InitPair(
"bMesh.coords",
mpi);
2068 bMesh.isPeriodic =
true;
2072 bMesh.cellElemInfo.InitPair(
"bMesh.cellElemInfo",
mpi);
2073 bMesh.cell2cellOrig.InitPair(
"bMesh.cell2cellOrig",
mpi);
2074 bMesh.node2nodeOrig.InitPair(
"bMesh.node2nodeOrig",
mpi);
2076 bMesh.bnd2cell.InitPair(
"bMesh.bnd2cell",
mpi);
2077 bMesh.bnd2node.InitPair(
"bMesh.bnd2node",
mpi);
2078 bMesh.bndElemInfo.InitPair(
"bMesh.bndElemInfo",
mpi);
2079 bMesh.bnd2bndOrig.InitPair(
"bMesh.bnd2bndOrig",
mpi);
2081 bMesh.bnd2nodePbi.InitPair(
"bMesh.bnd2nodePbi",
mpi);
2135 bMesh.coords.TransAttach();
2136 bMesh.coords.trans.createFatherGlobalMapping();
2149 bMesh.coords.trans.createMPITypes();
2151 bMesh.node2nodeOrig.TransAttach();
2152 bMesh.node2nodeOrig.trans.BorrowGGIndexing(
bMesh.coords.trans);
2153 bMesh.node2nodeOrig.trans.createMPITypes();
2168 bMesh.coords.trans.pullOnce();
2215 bMesh.cell2node.father->createGlobalMapping();
2216 bMesh.cell2node.TransAttach();
2217 bMesh.cell2node.trans.createGhostMapping(std::vector<int>{});
2223 bMesh.cellElemInfo.father->createGlobalMapping();
2224 bMesh.cell2cellOrig.father->createGlobalMapping();
2228 log() <<
"UnstructuredMesh === ConstructBndMesh Done" << std::endl;
2248 struct CellPermutationResult
2274 CellPermutationResult ComputeCellPermutation(
2281 CellPermutationResult
result;
2282 result.cellOld2New.resize(nCell, -1);
2283 result.cellNew2Old.resize(nCell);
2284 for (
index i = 0; i < nCell; i++)
2285 result.cellNew2Old[i] = i;
2288 cell2cellFaceV.begin(),
2289 cell2cellFaceV.end(),
2290 result.cellNew2Old.begin(),
2293 if (nPartsInner > 1)
2296 auto dbgCheckSubGraphRanges = [&](
const char *tag)
2298 for (
int p = 0; p < static_cast<int>(
result.localPartitionStarts.size()) - 1; p++)
2302 for (
index iC = pStart; iC < pEnd; iC++)
2303 for (
auto jC : cell2cellFaceV[iC])
2305 jC >= 0 && jC < nCell,
2306 "%s: partition %d [%lld,%lld): cell %lld has neighbor %lld outside [0,%lld)",
2307 tag, p, (
long long)pStart, (
long long)pEnd,
2308 (
long long)iC, (
long long)jC, (
long long)nCell);
2311 auto dbgCheckBidir = [&](
const char *tag)
2313 for (
index iC = 0; iC < nCell; iC++)
2314 for (
auto jC : cell2cellFaceV[iC])
2317 for (
auto kC : cell2cellFaceV[jC])
2324 "%s: edge %lld->%lld exists but reverse %lld->%lld missing",
2325 tag, (
long long)iC, (
long long)jC, (
long long)jC, (
long long)iC);
2329 dbgCheckSubGraphRanges(
"before inner partitioning");
2330 dbgCheckBidir(
"before inner partitioning");
2334 for (
int iPart = 0; iPart < static_cast<int>(
result.localPartitionStarts.size()) - 1; iPart++)
2336 index bwOldC{0}, bwNewC{0};
2337 index offset =
result.localPartitionStarts[iPart];
2338 index offsetN =
result.localPartitionStarts[iPart + 1];
2340 cell2cellFaceV.begin() + offset,
2341 cell2cellFaceV.begin() + offsetN,
2342 result.cellNew2Old.begin() + offset,
2343 result.cellNew2Old.begin() + offsetN, nPartsInner, offset,
true, bwOldC, bwNewC,
2344 cell2cellFaceV.begin(), nCell);
2348 dbgCheckSubGraphRanges(fmt::format(
"after inner part {}", iPart).c_str());
2351 dbgCheckBidir(
"after all inner partitioning");
2357 auto cellIsNotPrivate = [&](
index iCell)
2359 for (
auto iCellOther : cell2cell[iCell])
2361 if (iCellOther >= nCell)
2366 int nLocalParts =
result.localPartitionStarts.size() ?
static_cast<int>(
result.localPartitionStarts.size()) - 1 : 1;
2367 auto localPartStart = [&](
int iPart) ->
index
2368 {
return result.localPartitionStarts.size() ?
result.localPartitionStarts.at(iPart) : 0; };
2369 auto localPartEnd = [&](
int iPart) ->
index
2370 {
return result.localPartitionStarts.size() ?
result.localPartitionStarts.at(iPart + 1) : nCell; };
2372 std::vector<index> cellNew2Old_new;
2373 cellNew2Old_new.reserve(nCell);
2374 for (
index i = 0; i < nCell; i++)
2375 result.cellOld2New[i] = cellIsNotPrivate(
result.cellNew2Old[i]);
2376 for (
int iPart = 0; iPart < nLocalParts; iPart++)
2378 for (
index i = localPartStart(iPart); i < localPartEnd(iPart); i++)
2379 if (!
result.cellOld2New[i])
2380 cellNew2Old_new.push_back(
result.cellNew2Old[i]);
2381 for (
index i = localPartStart(iPart); i < localPartEnd(iPart); i++)
2382 if (
result.cellOld2New[i])
2383 cellNew2Old_new.push_back(
result.cellNew2Old[i]);
2386 result.cellNew2Old = std::move(cellNew2Old_new);
2393 std::unordered_set<index>
set;
2395 for (
index i = 0; i < nCell; i++)
2422 << fmt::format(
"UnstructuredMesh === ReorderLocalCells, nPart0 [{}], got reordering, bw [{}] to [{}]",
nParts,
perm.bwOld,
perm.bwNew) << std::endl;
2513 face2cell.trans.pullOnce();
2516 cell2cell.trans.pullOnce();
2528 if (this->isPeriodic)
2557 if (this->isPeriodic)
2584 log() << fmt::format(
"UnstructuredMesh === ReorderLocalCells finished") << std::endl;
Reserved for template implementations of #DeviceStorage primitives.
Pre-compiled-header style shim that includes the heavy Eigen headers under DNDSR's warning suppressio...
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
#define DNDS_assert_infof(expr, info,...)
Debug-only assertion with a printf-style format message.
#define DNDS_check_throw(expr)
Runtime check active in both debug and release builds. Throws std::runtime_error if expr evaluates to...
std::vector< index > cellNew2Old
std::vector< std::vector< DNDS::index > > face2nodeV
std::vector< index > cellOld2New
std::vector< std::pair< DNDS::index, DNDS::index > > face2cellV
std::vector< index > iFaceAllToCollected
mapping: old face idx -> collected idx (or UnInitIndex/-1)
std::vector< std::vector< index > > faceSendLocals
per-rank lists of local face indices to send as ghost
std::vector< index > localPartitionStarts
std::vector< std::vector< NodePeriodicBits > > face2nodePbiV
std::vector< ElemInfo > faceElemInfoV
Internal helpers for mesh partition redistribution.
Table mapping rank-local row indices to the global index space.
bool search(index globalQuery, MPI_int &rank, index &val) const
Convert a global index to (rank, local). Returns false if out of range.
Mapping between a rank's main data and its ghost copies.
void PushInfo2Serial2Global(std::vector< DNDS::index > &serial2Global, DNDS::index localSize, const std::vector< DNDS::index > &pushIndex, const std::vector< DNDS::index > &pushIndexStart, const DNDS::MPIInfo &mpi)
Reserved skeleton for parallel topology interpolation.
ArrayPair< ArrayNodePeriodicBits< DNDS::NonUniformSize > > tPbiPair
void Partition2LocalIdx(const std::vector< TPartitionIdx > &partition, std::vector< DNDS::index > &localPush, std::vector< DNDS::index > &localPushStart, const DNDS::MPIInfo &mpi)
void Partition2Serial2Global(const std::vector< TPartitionIdx > &partition, std::vector< DNDS::index > &serial2Global, const DNDS::MPIInfo &mpi, DNDS::MPI_int nPart)
decltype(tAdj2Pair::father) tAdj2
DNDS_DEVICE_CALLABLE bool FaceIDIsInternal(t_index id)
std::function< index(index)> tIndexMapFunc
decltype(tAdjPair::father) tAdj
DNDS::ArrayAdjacencyPair< 2 > tAdj2Pair
DNDS::ArrayPair< DNDS::ParArray< ElemInfo > > tElemInfoArrayPair
DNDS::ssp< DNDS::ParArray< ElemInfo > > tElemInfoArray
DNDS::ArrayAdjacencyPair< 1 > tAdj1Pair
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodic(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodicDonor(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodicMain(t_index id)
void TransferDataSerial2Global(TArr &arraySerial, TArr &arrayDist, const std::vector< DNDS::index > &pushIndex, const std::vector< DNDS::index > &pushIndexStart, const DNDS::MPIInfo &mpi)
std::vector< index > ReorderSerialAdj_PartitionMetisC(tLocalMatStruct::iterator mat_begin, tLocalMatStruct::iterator mat_end, std::vector< index >::iterator i_new2old_begin, std::vector< index >::iterator i_new2old_end, int nParts, index ind_offset, bool do_rcm, index &bwOldM, index &bwNewM, tLocalMatStruct::iterator full_mat_begin, index full_n_elem)
Partition a sub-graph into nParts and optionally apply RCM reordering within each part.
void ConvertAdjSerial2Global(TAdj &arraySerialAdj, const std::vector< DNDS::index > &partitionJSerial2Global, const DNDS::MPIInfo &mpi)
DNDS::ArrayAdjacencyPair< DNDS::NonUniformSize > tAdjPair
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodic3(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodic2(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsExternalBC(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodic1(t_index id)
std::vector< std::vector< index > > tLocalMatStruct
MPI_int Scan(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Scan (inclusive prefix reduction).
MPI_int Allreduce(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Allreduce.
MPI_int Barrier(MPI_Comm comm)
Wrapper over MPI_Barrier.
void AllreduceOneIndex(index &v, MPI_Op op, const MPIInfo &mpi)
Single-scalar Allreduce helper for indices (in-place, count = 1).
ssp< SerializerBase > SerializerBaseSSP
the host side operators are provided as implemented
const MPI_Datatype DNDS_MPI_INDEX
MPI datatype matching index (= MPI_INT64_T).
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
void MPISerialDo(const MPIInfo &mpi, F f)
Execute f on each rank serially, in rank order.
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
index size_to_index(size_t v)
Range-checked conversion from size_t to DNDS::index.
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
ssp< T > make_ssp(Args &&...args)
Type-safe replacement for DNDS_MAKE_SSP. Creates ssp<T> with forwarded args.
std::ostream & log()
Return the current DNDSR log stream (either std::cout or the installed file).
int MPI_int
MPI counterpart type for MPI_int (= C int). Used for counts and ranks in MPI calls.
set(LIBNAME cfv) set(LINKS) set(LINKS_SHARED geom_shared dnds_shared $
DNDS_DEVICE_CALLABLE index Size() const
Combined father + son row count.
Convenience bundle of a father, son, and attached ArrayTransformer.
void TransAttach()
Bind the transformer to the current father / son pointers.
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
void WriteSerialize(Serializer::SerializerBaseSSP serializerP, const std::string &name, bool includePIG=true, bool includeSon=true)
Writes the ArrayPair (father, optional son, optional ghost mapping).
index Size() const
Combined row count (father->Size() + son->Size()).
void InitPair(const std::string &name, Args &&...args)
Allocate both father and son arrays, forwarding all args to TArray constructor.
ssp< TArray > son
Ghost-side array (sized automatically by createMPITypes / BorrowAndPull).
void BorrowAndPull(TPrimaryPair &primary)
Attach, borrow ghost indexing from a primary pair, create MPI types, and pull once.
auto RowSize() const
Uniform row width (delegates to father).
void ResizeRow(index i, rowsize rs)
Resize a single row in the combined address space.
void ReadSerialize(Serializer::SerializerBaseSSP serializerP, const std::string &name, bool includePIG=true, bool includeSon=true)
Reads an ArrayPair written by WriteSerialize (same partition count).
TTrans trans
Ghost-communication engine bound to father and son.
void ObtainSymmetricSymbolicFactorization(const TAdj &cell2cellFaceV, const std::vector< index > localPartStarts_in, int iluCode)
get symmetric symbolic matrix factorization over cell2cellFaceV
static MPI_Datatype CommType()
static MPI_Datatype CommType()
DNDS_HOST void WriteSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name)
std::array< tPointPortable, 4 > rotationCenter
std::array< tPointPortable, 4 > translation
std::array< tGPointPortable, 4 > rotation
DNDS_HOST void ReadSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name)
tAdjPair::t_deviceView< B > cell2node
tCoordPair::t_deviceView< B > coords
reader
DNDS::ArrayTransformerType< tCoord::element_type >::Type coordSerialOutTrans
DNDS::ArrayTransformerType< tElemInfoArray::element_type >::Type cellElemInfoSerialOutTrans
void BuildSerialOut()
should be called to build data for serial out
DNDS::ArrayTransformerType< tAdj::element_type >::Type cell2nodeSerialOutTrans
tElemInfoArray bndElemInfoSerial
DNDS::ssp< UnstructuredMesh > mesh
void PartitionReorderToMeshCell2Cell()
DNDS::ArrayTransformerType< tPbi::element_type >::Type cell2nodePbiSerialOutTrans
std::vector< DNDS::MPI_int > cellPartition
std::vector< DNDS::MPI_int > bndPartition
tAdj1 node2nodeOrigSerial
tAdj1 cell2cellOrigSerial
tElemInfoArray cellElemInfoSerial
std::vector< DNDS::MPI_int > nodePartition
void AdjLocal2GlobalN2CB()
UnstructuredMeshDeviceView< B > t_deviceView
index NodeIndexGlobal2Local_NoSon(index i)
tPbiPair cell2nodePbi
periodic only, after reader
std::unordered_map< index, index > face2bndM
index NumNodeProc() const
index CellIndexLocal2Global_NoSon(index i)
tPbiPair face2nodePbi
periodic only, after interpolated
std::vector< index > node2bndNode
void BuildGhostPrimary()
building ghost (son) from primary (currently only cell2cell)
index NumNodeGhost() const
void AdjGlobal2LocalN2CB()
void AdjLocal2GlobalC2F()
void AdjGlobal2LocalPrimaryForBnd()
MeshAdjState adjC2CFaceState
std::vector< index > node2parentNode
parent built
index NumCellProc() const
index NodeIndexLocal2Global_NoSon(index i)
void AdjLocal2GlobalFacial()
void AdjGlobal2LocalPrimary()
tLocalMatStruct cell2cellFaceVLocalParts
for cell local factorization
index BndIndexLocal2Global_NoSon(index i)
index CellIndexGlobal2Local(DNDS::index i)
tLocalMatStruct GetCell2CellFaceVLocal(bool onLocalPartition=false)
void RecoverNode2CellAndNode2Bnd()
only requires father part of cell2node, bnd2node and coords generates node2cell and node2bnd (father ...
MeshAdjState adjN2CBState
void ReorderLocalCells(int nParts=1, int nPartsInner=1)
void AdjGlobal2LocalC2F()
void ReadSerialize(Serializer::SerializerBaseSSP serializerP, const std::string &name)
tAdjPair cell2cellFace
constructed on demand
index CellIndexGlobal2Local_NoSon(index i)
index BndIndexLocal2Global(DNDS::index i)
tAdjPair node2cell
inverse relations
std::vector< index > bnd2faceV
index CellIndexLocal2Global(DNDS::index i)
void AdjLocal2GlobalPrimary()
MeshAdjState adjPrimaryState
void ObtainSymmetricSymbolicFactorization(Direct::SerialSymLUStructure &symLU, Direct::DirectPrecControl control) const
index CellFaceOther(index iCell, index iFace) const
tElemInfoArrayPair faceElemInfo
void SetPeriodicGeometry(const tPoint &translation1, const tPoint &rotationCenter1, const tPoint &eulerAngles1, const tPoint &translation2, const tPoint &rotationCenter2, const tPoint &eulerAngles2, const tPoint &translation3, const tPoint &rotationCenter3, const tPoint &eulerAngles3)
void BuildCell2CellFace()
void AdjGlobal2LocalC2CFace()
std::vector< index > localPartitionStarts
MeshAdjState adjFacialState
index BndIndexGlobal2Local(DNDS::index i)
void RecoverCell2CellAndBnd2Cell()
needs to use RecoverNode2CellAndNode2Bnd before doing this. Requires node2cell.father and builds a ve...
void WriteSerialize(Serializer::SerializerBaseSSP serializerP, const std::string &name)
tElemInfoArrayPair cellElemInfo
static void ConvertAdjEntries(TAdj &adj, index nRows, TFn &&fn)
Apply a conversion function to every entry of an adjacency array's first nRows rows.
index NumCellGhost() const
void AdjLocal2GlobalC2CFace()
static void PermuteRows(TPair &pair, index nRows, TFn &&old2new)
Permute the father rows of an ArrayPair according to a mapping function.
void AdjGlobal2LocalFacial()
void ConstructBndMesh(UnstructuredMesh &bMesh)
tElemInfoArrayPair bndElemInfo
void AdjLocal2GlobalPrimaryForBnd()
tAdjPair cell2face
interpolated
Lightweight bundle of an MPI communicator and the calling rank's coordinates.
int size
Number of ranks in comm (-1 until initialised).
int rank
This rank's 0-based index within comm (-1 until initialised).
MPI_Comm comm
The underlying MPI communicator handle.
Tag type for naming objects created via make_ssp.
Eigen::Matrix< real, 5, 1 > v
if(g_mpi.rank==0) std auto[rhsDensity, rhsEnergy, incL2]
for(int i=0;i< 10;i++) theta(i