25 result.parent2entity.father->Resize(nParent);
27 auto &entityElemInfoV =
result.entityElemInfo;
32 std::vector<std::vector<index>> ent2nodeVec;
33 std::vector<std::vector<index>> ent2parentVec;
41 std::vector<EntityOrigin> ent2origin;
45 std::vector<std::vector<index>> node2entity(
nNode);
48 constexpr int maxSubEntityNodes = 10;
49 std::array<index, maxSubEntityNodes> subNodesBuf{};
51 const bool hasMatchExtra = bool(
query.matchExtra);
53 for (
index iParent = 0; iParent < nParent; iParent++)
55 int nSubs =
query.numSubEntities(iParent);
56 result.parent2entity.father->ResizeRow(iParent, nSubs);
59 auto parentNodeAccessor = [&](
int j) ->
index
61 return parent2node[iParent][
j];
64 for (
int iSub = 0; iSub < nSubs; iSub++)
68 fmt::format(
"Interpolate: sub-entity has {} nodes, max is {}",
69 desc.
nNodes, maxSubEntityNodes));
72 query.extractNodes(iParent, iSub, parentNodeAccessor, subNodesBuf.data());
75 std::vector<index> subVerts(subNodesBuf.begin(),
77 std::sort(subVerts.begin(), subVerts.end());
81 for (
auto iV : subVerts)
86 fmt::format(
"Interpolate: node index {} out of range [0, {})",
88 for (
auto iEnt : node2entity[iV])
91 if (entityElemInfoV[iEnt].type != desc.
typeTag)
95 auto &entNodes = ent2nodeVec[iEnt];
98 std::vector<index> entVerts(entNodes.begin(),
99 entNodes.begin() + nEntVerts);
100 std::sort(entVerts.begin(), entVerts.end());
102 if (!std::equal(subVerts.begin(), subVerts.end(),
103 entVerts.begin(), entVerts.end()))
109 auto &orig = ent2origin[iEnt];
110 if (!
query.matchExtra(iParent, iSub,
112 orig.parentIdx, orig.subIdx))
124 std::vector<index> subNodesVec(subNodesBuf.begin(),
125 subNodesBuf.begin() + desc.
nNodes);
126 ent2nodeVec.emplace_back(std::move(subNodesVec));
127 ent2parentVec.push_back({iParent});
129 ent2origin.push_back({iParent, iSub});
132 for (
auto iV : subVerts)
135 result.parent2entity.father->operator()(iParent, iSub) = nEntities;
141 ent2parentVec[iFound].push_back(iParent);
143 result.parent2entity.father->operator()(iParent, iSub) = iFound;
151 result.entity2node.InitPair(
"Interpolate_e2n", mpi);
152 result.entity2node.father->Resize(nEntities);
153 for (
index iEnt = 0; iEnt < nEntities; iEnt++)
155 auto &nodes = ent2nodeVec[iEnt];
156 result.entity2node.father->ResizeRow(iEnt, nodes.size());
157 for (
rowsize j = 0; j < static_cast<rowsize>(nodes.size());
j++)
158 result.entity2node.father->operator()(iEnt,
j) = nodes[
j];
162 result.entity2parent.InitPair(
"Interpolate_e2p", mpi);
163 result.entity2parent.father->Resize(nEntities);
164 for (
index iEnt = 0; iEnt < nEntities; iEnt++)
166 auto &parents = ent2parentVec[iEnt];
167 result.entity2parent.father->ResizeRow(iEnt, parents.size());
168 for (
rowsize j = 0; j < static_cast<rowsize>(parents.size());
j++)
169 result.entity2parent.father->operator()(iEnt,
j) = parents[
j];
195 index nAllEntities = localResult.nEntities;
196 std::vector<index> oldToOwned(nAllEntities,
UnInitIndex);
197 std::vector<std::vector<index>> pushPerRank(mpi.size);
200 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
202 index parentL = localResult.entity2parent.father->operator()(iEnt, 0);
203 index parentR = (localResult.entity2parent.father->RowSize(iEnt) >= 2)
204 ? localResult.entity2parent.father->operator()(iEnt, 1)
207 auto decision =
resolver(parentL, parentR, nLocalParents);
210 oldToOwned[iEnt] = nOwned;
211 for (
auto pr : decision.peerRanks)
212 if (pr >= 0 && pr != mpi.rank)
213 pushPerRank[pr].push_back(nOwned);
226 result.entity2node.InitPair(
"InterpDist_e2n", mpi);
227 result.entity2node.father->Resize(nOwned);
230 result.entity2parent.InitPair(
"InterpDist_e2p", mpi);
231 result.entity2parent.father->Resize(nOwned);
234 result.entityElemInfo.InitPair(
"InterpDist_eInfo", mpi);
235 result.entityElemInfo.father->Resize(nOwned);
237 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
239 index iNew = oldToOwned[iEnt];
244 auto row = localResult.entity2node.father->operator[](iEnt);
245 result.entity2node.father->ResizeRow(iNew, row.size());
246 for (
rowsize j = 0; j < static_cast<rowsize>(row.size());
j++)
247 result.entity2node.father->operator()(iNew,
j) =
254 auto parentRow = localResult.entity2parent.father->operator[](iEnt);
255 index pL = parentRow[0];
257 result.entity2parent.father->operator()(iNew, 0) =
258 parentGhostMapping(-1, pL);
259 result.entity2parent.father->operator()(iNew, 1) =
264 result.entityElemInfo.father->operator()(iNew, 0) =
265 localResult.entityElemInfo[iEnt];
267 result.entity2node.father->Compress();
272 std::vector<index> pushIdx;
273 std::vector<index> pushStarts(mpi.size + 1, 0);
275 pushStarts[
r + 1] = pushStarts[
r] +
static_cast<index>(pushPerRank[
r].size());
276 pushIdx.resize(pushStarts.back());
278 std::copy(pushPerRank[
r].begin(), pushPerRank[
r].end(),
279 pushIdx.begin() + pushStarts[
r]);
281 result.entity2parent.TransAttach();
282 result.entity2parent.trans.createFatherGlobalMapping();
283 result.entity2parent.trans.createGhostMapping(pushIdx, pushStarts);
284 result.entity2parent.trans.createMPITypes();
285 result.entity2parent.trans.pullOnce();
288 result.entity2node.TransAttach();
289 result.entity2node.trans.BorrowGGIndexing(
result.entity2parent.trans);
290 result.entity2node.trans.createMPITypes();
291 result.entity2node.trans.pullOnce();
293 result.entityElemInfo.TransAttach();
294 result.entityElemInfo.trans.BorrowGGIndexing(
result.entity2parent.trans);
295 result.entityElemInfo.trans.createMPITypes();
296 result.entityElemInfo.trans.pullOnce();
303 ?
result.entity2parent.son->Size()
305 for (
index iGhost = 0; iGhost < nGhostEntities; iGhost++)
307 for (
rowsize side = 0; side < 2; side++)
309 index &pGlobal = (*
result.entity2parent.son)(iGhost, side);
312 auto [found, rank, localAppend] =
315 fmt::format(
"InterpolateDistributed: ghost entity parent "
316 "global {} not found locally",
318 pGlobal = localAppend;
322 for (
index iOwned = 0; iOwned < nOwned; iOwned++)
324 for (
rowsize side = 0; side < 2; side++)
326 index &pGlobal =
result.entity2parent.father->operator()(iOwned, side);
329 auto [found, rank, localAppend] =
332 fmt::format(
"InterpolateDistributed: owned entity parent "
333 "global {} not found locally",
335 pGlobal = localAppend;
341 for (
index iFace = 0; iFace < nOwned + nGhostEntities; iFace++)
346 auto [found, rank, localAppend] =
349 fmt::format(
"InterpolateDistributed: entity node "
350 "global {} not found locally",
352 nGlobal = localAppend;
364 result.parent2entity.InitPair(
"InterpDist_p2e", mpi);
365 result.parent2entity.father->Resize(nLocalParents);
366 result.parent2entity.son = std::make_shared<tAdj::element_type>(
367 ObjName{
"InterpDist_p2e.son"}, mpi);
368 result.parent2entity.son->Resize(nTotalParents - nLocalParents);
370 for (
index iParent = 0; iParent < nTotalParents; iParent++)
372 rowsize nSubs = localResult.parent2entity.father->RowSize(iParent);
373 result.parent2entity.ResizeRow(iParent, nSubs);
377 index oldEntIdx = localResult.parent2entity.father->operator()(iParent,
j);
378 index newEntIdx = oldToOwned[oldEntIdx];
389 for (
index iGhost = 0; iGhost < nGhostEntities; iGhost++)
391 index entityLocalAppended = nOwned + iGhost;
394 auto ghostRow =
result.entity2node[entityLocalAppended];
399 std::vector<index>
ghostNodes(ghostRow.begin(), ghostRow.end());
402 for (
rowsize side = 0; side < 2; side++)
404 index parentLocalAppended =
result.entity2parent(entityLocalAppended, side);
407 rowsize nSubs =
result.parent2entity.RowSize(parentLocalAppended);
411 if (
result.parent2entity(parentLocalAppended,
j) != -1)
415 index oldEntIdx = localResult.parent2entity.father->operator()(parentLocalAppended,
j);
416 auto oldRow = localResult.entity2node.father->operator[](oldEntIdx);
417 std::vector<index> oldNodes(oldRow.begin(), oldRow.end());
418 std::sort(oldNodes.begin(), oldNodes.end());
422 result.parent2entity(parentLocalAppended,
j) = entityLocalAppended;
428 fmt::format(
"InterpolateDistributed: ghost entity {} "
429 "could not be matched to parent {}",
430 iGhost, parentLocalAppended));
455 const bool hasPbi = bool(parent2nodePbi.
father);
461 index nAllEntities = localResult.nEntities;
468 constexpr int maxSubEntityNodes = 10;
469 std::vector<std::vector<NodePeriodicBits>> localEntityPbi(nAllEntities);
470 if (hasPbi &&
query.extractPbi)
473 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
475 index firstParent = localResult.entity2parent.father->operator()(iEnt, 0);
478 for (
rowsize j = 0;
j < localResult.parent2entity.father->RowSize(firstParent);
j++)
480 if (localResult.parent2entity.father->operator()(firstParent,
j) == iEnt)
488 auto desc =
query.describe(firstParent, iSub);
489 localEntityPbi[iEnt].resize(desc.nNodes);
492 return parent2nodePbi[firstParent][k];
494 query.extractPbi(firstParent, iSub, pbiAccessor,
495 localEntityPbi[iEnt].data());
509 std::vector<std::vector<NodePeriodicBits>> localParent2EntityPbi;
510 if (hasPbi &&
query.extractPbi)
512 localParent2EntityPbi.resize(nTotalParents);
513 std::array<NodePeriodicBits, maxSubEntityNodes> thisPbiBuf{};
514 std::array<index, maxSubEntityNodes> thisNodeBuf{};
515 for (
index iParent = 0; iParent < nTotalParents; iParent++)
517 rowsize nSubs = localResult.parent2entity.
father->RowSize(iParent);
518 localParent2EntityPbi[iParent].resize(nSubs);
521 index iEnt = localResult.parent2entity.father->operator()(iParent,
j);
522 auto desc =
query.describe(iParent,
j);
527 return parent2nodePbi[iParent][k];
529 query.extractPbi(iParent,
j, pbiAccessor, thisPbiBuf.data());
531 auto nodeAccessor = [&](
int k) ->
index
533 return parent2node[iParent][k];
535 query.extractNodes(iParent,
j, nodeAccessor, thisNodeBuf.data());
538 auto &entPbi = localEntityPbi[iEnt];
539 auto entNodeRow = localResult.entity2node.
father->operator[](iEnt);
540 DNDS_assert(desc.nNodes ==
static_cast<int>(entPbi.size()));
545 using NP = std::pair<index, uint8_t>;
546 std::vector<NP> thisNP(desc.nNodes), entNP(desc.nNodes);
547 for (
int k = 0; k < desc.nNodes; k++)
549 thisNP[k] = {thisNodeBuf[k], uint8_t(thisPbiBuf[k])};
550 entNP[k] = {entNodeRow[k], uint8_t(entPbi[k])};
552 auto cmp = [](
const NP &a,
const NP &
b)
553 {
return a.first ==
b.first ? a.second <
b.second : a.first <
b.first; };
554 std::sort(thisNP.begin(), thisNP.end(), cmp);
555 std::sort(entNP.begin(), entNP.end(), cmp);
558 uint8_t xorVal = thisNP[0].second ^ entNP[0].second;
559 for (
int k = 1; k < desc.nNodes; k++)
562 fmt::format(
"parent2entityPbi: node mismatch at parent {} sub {} node {}: "
564 iParent,
j, k, thisNP[k].first, entNP[k].first));
565 uint8_t xk = thisNP[k].second ^ entNP[k].second;
567 fmt::format(
"parent2entityPbi: non-uniform XOR at parent {} sub {} node {}: "
568 "expected 0x{:02x}, got 0x{:02x}",
569 iParent,
j, k, xorVal, xk));
590 index parentGlobal = parentGhostMapping(-1, parentLocal);
593 auto ret = parentGlobalMapping.
search(parentGlobal, rank, val);
598 struct EntityClassification
602 std::vector<MPI_int> peerRanks;
604 std::vector<EntityClassification> classifications(nAllEntities);
607 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
609 auto parentRow = localResult.entity2parent.father->operator[](iEnt);
610 bool anyLocal =
false, anyGhost =
false;
611 std::vector<index> parents;
612 std::vector<MPI_int> parentRanks;
613 parents.reserve(parentRow.size());
614 parentRanks.reserve(parentRow.size());
616 for (
auto p : parentRow)
618 parents.push_back(
p);
620 parentRanks.push_back(
r);
621 if (
p < nLocalParents)
630 classifications[iEnt].discard =
true;
637 classifications[iEnt].owned =
true;
642 auto decision =
resolver(parents, parentRanks, nLocalParents);
643 classifications[iEnt].owned = decision.owned;
644 classifications[iEnt].discard = !decision.owned;
646 classifications[iEnt].peerRanks = std::move(decision.peerRanks);
652 std::vector<index> oldToOwned(nAllEntities,
UnInitIndex);
654 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
656 if (classifications[iEnt].owned)
658 oldToOwned[iEnt] = nOwned;
667 result.entity2node.InitPair(
"InterpGlobal_e2n", mpi);
668 result.entity2node.father->Resize(nOwned);
671 result.entity2parent.InitPair(
"InterpGlobal_e2p", mpi);
672 result.entity2parent.father->Resize(nOwned);
676 result.entity2nodePbi.InitPair(
"InterpGlobal_e2nPbi", mpi);
678 result.entity2nodePbi.father->Resize(nOwned);
681 result.entityElemInfo.InitPair(
"InterpGlobal_eInfo", mpi);
682 result.entityElemInfo.father->Resize(nOwned);
684 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
686 index iNew = oldToOwned[iEnt];
691 auto nodeRow = localResult.entity2node.father->operator[](iEnt);
692 result.entity2node.father->ResizeRow(iNew, nodeRow.size());
693 for (
rowsize j = 0; j < static_cast<rowsize>(nodeRow.size());
j++)
694 result.entity2node.father->operator()(iNew,
j) =
698 auto parentRow = localResult.entity2parent.father->operator[](iEnt);
701 result.entity2parent.father->ResizeRow(iNew, parentRow.size());
702 for (
rowsize j = 0; j < static_cast<rowsize>(parentRow.size());
j++)
703 result.entity2parent.father->operator()(iNew,
j) =
704 parentGhostMapping(-1, parentRow[
j]);
710 result.entity2parent.father->operator()(iNew,
j) =
711 (
j <
static_cast<rowsize>(parentRow.size()))
712 ? parentGhostMapping(-1, parentRow[
j])
719 auto &pbi = localEntityPbi[iEnt];
720 result.entity2nodePbi.father->ResizeRow(iNew, pbi.size());
721 for (
rowsize j = 0; j < static_cast<rowsize>(pbi.size());
j++)
722 result.entity2nodePbi.father->operator()(iNew,
j) = pbi[
j];
726 result.entityElemInfo.father->operator()(iNew, 0) =
727 localResult.entityElemInfo[iEnt];
729 result.entity2node.father->Compress();
731 result.entity2nodePbi.father->Compress();
736 result.entity2node.TransAttach();
737 result.entity2node.trans.createFatherGlobalMapping();
738 auto faceGlobalMapping =
result.entity2node.trans.pLGlobalMapping;
739 index myFaceOffset = (*faceGlobalMapping)(mpi.rank, 0);
755 std::vector<std::vector<std::array<index, 3>>> pushMessages(mpi.size);
756 for (
index iEnt = 0; iEnt < nAllEntities; iEnt++)
758 if (!classifications[iEnt].owned)
760 index iNew = oldToOwned[iEnt];
761 index globalB = myFaceOffset + iNew;
763 auto parentRow = localResult.entity2parent.father->operator[](iEnt);
764 for (
auto pLocal : parentRow)
766 if (pLocal >= nLocalParents)
768 MPI_int pRank = getParentRank(pLocal);
769 index pGlobal = parentGhostMapping(-1, pLocal);
771 for (
rowsize s = 0; s < localResult.parent2entity.father->RowSize(pLocal); s++)
773 if (localResult.parent2entity.father->operator()(pLocal, s) == iEnt)
780 pushMessages[pRank].push_back({pGlobal, globalB,
static_cast<index>(subIdx)});
786 std::vector<int> sendCounts(mpi.size), recvCounts(mpi.size);
788 sendCounts[
r] =
static_cast<int>(pushMessages[
r].size() * 3);
790 recvCounts.data(), 1, MPI_INT, mpi.comm);
792 std::vector<int> sendDisp(mpi.size + 1, 0), recvDisp(mpi.size + 1, 0);
795 sendDisp[
r + 1] = sendDisp[
r] + sendCounts[
r];
796 recvDisp[
r + 1] = recvDisp[
r] + recvCounts[
r];
799 std::vector<index> sendBuf(sendDisp.back());
802 index offset = sendDisp[
r];
803 for (
auto &msg : pushMessages[
r])
805 sendBuf[offset++] = msg[0];
806 sendBuf[offset++] = msg[1];
807 sendBuf[offset++] = msg[2];
810 std::vector<index> recvBuf(recvDisp.back());
812 recvBuf.data(), recvCounts.data(), recvDisp.data(),
DNDS_MPI_INDEX,
816 std::unordered_map<index, std::unordered_map<int, index>> receivedA2SubB;
817 for (
index i = 0; i < static_cast<index>(recvBuf.size());
i += 3)
820 index gB = recvBuf[
i + 1];
821 int subIdx =
static_cast<int>(recvBuf[
i + 2]);
822 receivedA2SubB[gA][subIdx] = gB;
826 result.parent2entity.InitPair(
"InterpGlobal_p2e", mpi);
827 result.parent2entity.father->Resize(nLocalParents);
828 result.parent2entity.son = std::make_shared<tAdj::element_type>(
829 ObjName{
"InterpGlobal_p2e.son"}, mpi);
830 result.parent2entity.son->Resize(nTotalParents - nLocalParents);
834 result.parent2entityPbi.InitPair(
"InterpGlobal_p2ePbi", mpi);
835 result.parent2entityPbi.father->Resize(nLocalParents);
836 result.parent2entityPbi.son = std::make_shared<
typename decltype(
result.parent2entityPbi.son)::element_type>(
838 result.parent2entityPbi.son->Resize(nTotalParents - nLocalParents);
841 for (
index iParent = 0; iParent < nTotalParents; iParent++)
843 rowsize nSubs = localResult.parent2entity.father->RowSize(iParent);
844 result.parent2entity.ResizeRow(iParent, nSubs);
846 result.parent2entityPbi.ResizeRow(iParent, nSubs);
853 result.parent2entityPbi(iParent,
j) =
854 localParent2EntityPbi[iParent][
j];
856 index oldEntIdx = localResult.parent2entity.father->operator()(iParent,
j);
857 index newOwnedIdx = oldToOwned[oldEntIdx];
861 result.parent2entity(iParent,
j) = myFaceOffset + newOwnedIdx;
866 index parentGlobal = parentGhostMapping(-1, iParent);
867 auto it = receivedA2SubB.find(parentGlobal);
868 if (it != receivedA2SubB.end())
870 auto jt = it->second.find(
static_cast<int>(
j));
871 if (jt != it->second.end())
873 result.parent2entity(iParent,
j) = jt->second;