7#include <unordered_map>
21 struct FaceEnumerationResult
25 std::vector<std::pair<DNDS::index, DNDS::index>>
face2cellV;
45 [[maybe_unused]] FaceEnumerationResult EnumerateFacesFromCells(
54 FaceEnumerationResult
result;
61 std::vector<std::vector<DNDS::index>> node2face(coordsSize);
63 using idx_pbi_pair = std::pair<index, NodePeriodicBits>;
64 auto idx_pbi_pair_less = [](idx_pbi_pair &L, idx_pbi_pair &R)
65 {
return L.first == R.first ? uint8_t(L.second) < uint8_t(R.second) : L.first < R.first; };
66 auto idx_pbi_pair_eq = [](idx_pbi_pair &L, idx_pbi_pair &R)
67 {
return L.first == R.first && uint8_t(L.second) == uint8_t(R.second); };
69 for (
DNDS::index iCell = 0; iCell < cell2cellSize; iCell++)
71 auto eCell = Elem::Element{
cellElemInfo[iCell]->getElemType()};
72 cell2face.
ResizeRow(iCell, eCell.GetNumFaces());
73 for (
int ic2f = 0; ic2f < eCell.GetNumFaces(); ic2f++)
75 auto eFace = eCell.ObtainFace(ic2f);
76 std::vector<DNDS::index> faceNodes(eFace.GetNumNodes());
77 eCell.ExtractFaceNodes(ic2f,
cell2node[iCell], faceNodes);
79 std::vector<DNDS::index> faceVerts(faceNodes.begin(), faceNodes.begin() + eFace.GetNumVertices());
80 std::sort(faceVerts.begin(), faceVerts.end());
82 std::vector<NodePeriodicBits> faceNodePeriodicBits;
83 std::vector<idx_pbi_pair> faceNodeNodePeriodicBits;
86 faceNodePeriodicBits.resize(eFace.GetNumNodes());
87 faceNodeNodePeriodicBits.resize(eFace.GetNumNodes());
88 eCell.ExtractFaceNodes(ic2f,
cell2nodePbi[iCell], faceNodePeriodicBits);
89 for (
size_t i = 0;
i < faceNodeNodePeriodicBits.size();
i++)
90 faceNodeNodePeriodicBits[
i].first = faceNodes[
i], faceNodeNodePeriodicBits[
i].second = faceNodePeriodicBits[
i];
91 std::sort(faceNodeNodePeriodicBits.begin(), faceNodeNodePeriodicBits.end(),
93 for (
size_t i = 1;
i < faceNodeNodePeriodicBits.size();
i++)
95 DNDS_assert_info(!idx_pbi_pair_eq(faceNodeNodePeriodicBits[
i - 1], faceNodeNodePeriodicBits[
i]),
96 "the face has identical (periodic) nodes");
100 for (
auto iV : faceVerts)
102 for (
auto iFOther : node2face[iV])
104 auto eFaceOther = Elem::Element{
faceElemInfoV[iFOther].getElemType()};
105 if (eFaceOther.type != eFace.type)
107 std::vector<DNDS::index> faceVertsOther(
109 face2nodeV[iFOther].begin() + eFace.GetNumVertices());
110 std::sort(faceVertsOther.begin(), faceVertsOther.end());
111 if (std::equal(faceVerts.begin(), faceVerts.end(), faceVertsOther.begin(), faceVertsOther.end()))
115 std::vector<std::pair<index, NodePeriodicBits>> faceNodeNodePeriodicBitsOther(eFaceOther.GetNumNodes());
116 for (
size_t i = 0;
i < faceNodeNodePeriodicBitsOther.size();
i++)
117 faceNodeNodePeriodicBitsOther[
i].first =
face2nodeV[iFOther][
i],
119 std::sort(faceNodeNodePeriodicBitsOther.begin(), faceNodeNodePeriodicBitsOther.end(),
121 auto v0 = faceNodeNodePeriodicBits.at(0).second ^ faceNodeNodePeriodicBitsOther.at(0).second;
122 DNDS_assert(faceNodeNodePeriodicBitsOther.size() == faceNodeNodePeriodicBits.size());
123 bool collaborating =
true;
124 for (
size_t i = 1;
i < faceNodeNodePeriodicBitsOther.size();
i++)
125 if ((faceNodeNodePeriodicBits[
i].second ^ faceNodeNodePeriodicBitsOther[
i].second) != v0)
126 collaborating =
false;
143 for (
auto iV : faceVerts)
145 cell2face(iCell, ic2f) =
nFaces;
152 cell2face(iCell, ic2f) = iFound;
162 struct FaceCollectionResult
182 [[maybe_unused]] FaceCollectionResult CollectFaces(
184 const std::vector<std::pair<DNDS::index, DNDS::index>> &
face2cellV,
192 FaceCollectionResult
result;
194 result.faceSendLocals.resize(nMPIRanks);
217 auto retL = globalMapping.
search(cellGlobL, rankL, valL);
218 auto retR = globalMapping.
search(cellGlobR, rankR, valR);
222 result.iFaceAllToCollected[iFace] = -1;
227 result.faceSendLocals[rankR].push_back(
result.nFacesNew);
258 [[maybe_unused]]
void CompactFacesAndRemapCell2Face(
259 const FaceEnumerationResult &faceEnum,
260 const FaceCollectionResult &faceCollect,
306# pragma omp parallel for
308 for (
DNDS::index iCell = 0; iCell < cell2face.Size(); iCell++)
310 for (
rowsize ic2f = 0; ic2f < cell2face.RowSize(iCell); ic2f++)
324 void MatchBoundariesToFaces(
332 std::vector<index> &bnd2faceV,
333 std::unordered_map<index, index> &face2bndM,
337 bnd2faceV.resize(bndElemInfo.father->Size(), -1);
338 face2bndM.reserve(bndElemInfo.father->Size());
339 std::unordered_map<index, index> iFace2iBnd;
340 for (
DNDS::index iBnd = 0; iBnd < bndElemInfo.father->Size(); iBnd++)
343 std::vector<DNDS::index> b2nRow = bnd2node[iBnd];
344 std::sort(b2nRow.begin(), b2nRow.end());
346 auto faceID = bndElemInfo[iBnd]->zone;
347 for (
int ic2f = 0; ic2f < cell2face.RowSize(pCell); ic2f++)
349 auto iFace = cell2face(pCell, ic2f);
352 std::vector<DNDS::index> f2nRow = face2node[iFace];
353 std::sort(f2nRow.begin(), f2nRow.end());
354 if (std::equal(b2nRow.begin(), b2nRow.end(), f2nRow.begin(), f2nRow.end()))
356 if (iFace2iBnd.count(iFace))
359 index iBndOther = iFace2iBnd[iFace];
360 index iCellA = bnd2cell[iBnd][0];
361 index iCellB = bnd2cell[iBndOther][0];
368 iFace2iBnd[iFace] = iBnd;
372 faceElemInfo(iFace, 0) = bndElemInfo(iBnd, 0);
373 bnd2faceV[iBnd] = iFace;
374 face2bndM[iFace] = iBnd;
377 "bnd elem should have a BC id not interior");
383 face2bnd.father->Resize(face2node.father->Size());
384 for (
index iFace = 0; iFace < face2bnd.father->Size(); iFace++)
385 face2bnd.father->operator()(iFace) = face2bndM.count(iFace) ? face2bndM[iFace] :
UnInitIndex;
386 bnd2face.father->Resize(bnd2node.father->Size());
387 for (
index iBnd = 0; iBnd < bnd2node.father->Size(); iBnd++)
388 bnd2face.father->operator()(iBnd) = bnd2faceV.at(iBnd);
398 [[maybe_unused]]
void AssignGhostFacesToCells(
399 const tAdj2 &face2cellSon,
400 const tAdj &face2nodeSon,
408# pragma omp parallel for
410 for (
DNDS::index iFace = 0; iFace < face2cellSon->Size(); iFace++)
414 auto eFace = Elem::Element{(*faceElemInfoSon)(iFace, 0).getElemType()};
415 auto faceVerts = std::vector<index>((*face2nodeSon)[iFace].begin(), (*face2nodeSon)[iFace].begin() + eFace.GetNumVertices());
416 std::sort(faceVerts.begin(), faceVerts.end());
417 for (
rowsize if2c = 0; if2c < 2; if2c++)
419 index iCell = (*face2cellSon)(iFace, if2c);
420 auto cell2faceRow = cell2face[iCell];
422 auto eCell = Elem::Element{
cellElemInfo(iCell, 0).getElemType()};
424 for (
rowsize ic2f = 0; ic2f < cell2face.RowSize(iCell); ic2f++)
426 auto eFace = eCell.ObtainFace(ic2f);
427 std::vector<index> faceNodesC(eFace.GetNumNodes());
428 eCell.ExtractFaceNodes(ic2f, cellNodes, faceNodesC);
429 std::sort(faceNodesC.begin(), faceNodesC.end());
430 if (std::includes(faceNodesC.begin(), faceNodesC.end(), faceVerts.begin(), faceVerts.end()))
433 cell2face(iCell, ic2f) = iFace + nFatherFaces;
#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 + ...
std::vector< std::vector< DNDS::index > > face2nodeV
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< std::vector< NodePeriodicBits > > face2nodePbiV
std::vector< ElemInfo > faceElemInfoV
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.
ArrayPair< ArrayNodePeriodicBits< DNDS::NonUniformSize > > tPbiPair
decltype(tAdj2Pair::father) tAdj2
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::ArrayAdjacencyPair< DNDS::NonUniformSize > tAdjPair
DNDS_DEVICE_CALLABLE bool FaceIDIsExternalBC(t_index id)
MPI_int Barrier(MPI_Comm comm)
Wrapper over MPI_Barrier.
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
constexpr MPI_int UnInitMPIInt
Sentinel "not initialised" MPI_int value (= -1, invalid rank).
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
int MPI_int
MPI counterpart type for MPI_int (= C int). Used for counts and ranks in MPI calls.
DNDS_DEVICE_CALLABLE index Size() const
Combined father + son row count.
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
void ResizeRow(index i, rowsize rs)
Resize a single row in the combined address space.
if(DEFINED ENV{DNDS_TEST_NP_LIST}) set(DNDS_TEST_NP_LIST "$ENV
if(g_mpi.rank==0) std auto[rhsDensity, rhsEnergy, incL2]
for(int i=0;i< 10;i++) theta(i
tElemInfoArrayPair cellElemInfo
input explicitMaps push_back(EntityReorderMap{EntityKind::Cell, cellPartition})