24 std::vector<index> periodicDonorIBnd1;
25 std::vector<index> periodicDonorIBnd2;
26 std::vector<index> periodicDonorIBnd3;
31 Eigen::Matrix<real, 3, Eigen::Dynamic> coordBnd;
35 coordBnd(EigenAll, ib2n) =
coordSerial->operator[]((*bnd2nodeSerial)(iBnd, ib2n));
37 tPoint faceCent = coordBnd.rowwise().mean();
44 if (faceID == BC_ID_PERIODIC_1_DONOR)
45 periodicDonorCenter1.
pts.push_back(faceCent), periodicDonorIBnd1.push_back(iBnd);
46 if (faceID == BC_ID_PERIODIC_2_DONOR)
47 periodicDonorCenter2.
pts.push_back(faceCent), periodicDonorIBnd2.push_back(iBnd);
48 if (faceID == BC_ID_PERIODIC_3_DONOR)
49 periodicDonorCenter3.
pts.push_back(faceCent), periodicDonorIBnd3.push_back(iBnd);
52 index nDonor = periodicDonorCenter1.
pts.size() +
53 periodicDonorCenter2.
pts.size() +
54 periodicDonorCenter3.
pts.size();
58 mesh->isPeriodic =
true;
61 mesh->isPeriodic =
false;
65 using kdtree_t = nanoflann::KDTreeSingleIndexAdaptor<
66 nanoflann::L2_Simple_Adaptor<real, PointCloudKDTree>,
70 kdtree_t periodicDonorTree1(3, periodicDonorCenter1);
71 kdtree_t periodicDonorTree2(3, periodicDonorCenter2);
72 kdtree_t periodicDonorTree3(3, periodicDonorCenter3);
74 std::unordered_map<index, index> periodicMainToDonor1;
75 std::unordered_map<index, index> periodicMainToDonor2;
76 std::unordered_map<index, index> periodicMainToDonor3;
78 std::unordered_map<index, index> iNodeDonorToMain1;
79 std::unordered_map<index, index> iNodeDonorToMain2;
80 std::unordered_map<index, index> iNodeDonorToMain3;
85 Eigen::Matrix<real, 3, Eigen::Dynamic> coordBnd;
89 coordBnd(EigenAll, ib2n) =
coordSerial->operator[]((*bnd2nodeSerial)(iBnd, ib2n));
91 tPoint faceCent = coordBnd.rowwise().mean();
95 tPoint faceCentTrans =
mesh->periodicInfo.TransCoord(faceCent, faceID);
96 std::vector<index> outIndices(2);
97 Eigen::Vector<real, Eigen::Dynamic> outDistancesSqr;
98 outDistancesSqr.resize(2);
100 if (faceID == BC_ID_PERIODIC_1)
101 nResults = periodicDonorTree1.knnSearch(faceCentTrans.data(), 2, outIndices.data(), outDistancesSqr.data());
102 if (faceID == BC_ID_PERIODIC_2)
103 nResults = periodicDonorTree2.knnSearch(faceCentTrans.data(), 2, outIndices.data(), outDistancesSqr.data());
104 if (faceID == BC_ID_PERIODIC_3)
105 nResults = periodicDonorTree3.knnSearch(faceCentTrans.data(), 2, outIndices.data(), outDistancesSqr.data());
106 DNDS_assert_info(nResults >= 1,
"Tree Search of periodic result number not enough");
110 fmt::format(
"nearest neighbour dist{} not matching under the threshold",
111 outDistancesSqr[0]));
117 if (!(outDistancesSqr[1] >
sqr(search_eps)))
119 << fmt::format(
"Warning: second nearest neighbour dist{} not matching over the threshold",
127 if (faceID == BC_ID_PERIODIC_1)
128 donorIBnd = periodicDonorIBnd1.at(outIndices[0]), periodicMainToDonor1[iBnd] = donorIBnd;
129 if (faceID == BC_ID_PERIODIC_2)
130 donorIBnd = periodicDonorIBnd2.at(outIndices[0]), periodicMainToDonor2[iBnd] = donorIBnd;
131 if (faceID == BC_ID_PERIODIC_3)
132 donorIBnd = periodicDonorIBnd3.at(outIndices[0]), periodicMainToDonor3[iBnd] = donorIBnd;
133 Eigen::Matrix<real, 3, Eigen::Dynamic> coordBndOther;
137 coordBndOther(EigenAll, ib2n) =
138 coordSerial->operator[]((*bnd2nodeSerial)(donorIBnd, ib2n));
140 DNDS_assert(coordBndOther.cols() == coordBnd.cols());
141 for (
rowsize ib2n = 0; ib2n < coordBnd.cols(); ib2n++)
146 for (
rowsize jb2n = 0; jb2n < coordBnd.cols(); jb2n++)
148 real dist = (coordBndOther(EigenAll, jb2n) -
149 mesh->periodicInfo.TransCoord(coordBnd(EigenAll, ib2n), faceID))
156 if (dist <
sqr(search_eps))
159 if (faceID == BC_ID_PERIODIC_1)
160 iNodeDonorToMain1[(*bnd2nodeSerial)(donorIBnd, jb2nMin)] = (*
bnd2nodeSerial)(iBnd, ib2n);
161 if (faceID == BC_ID_PERIODIC_2)
162 iNodeDonorToMain2[(*bnd2nodeSerial)(donorIBnd, jb2nMin)] = (*
bnd2nodeSerial)(iBnd, ib2n);
163 if (faceID == BC_ID_PERIODIC_3)
164 iNodeDonorToMain3[(*bnd2nodeSerial)(donorIBnd, jb2nMin)] = (*
bnd2nodeSerial)(iBnd, ib2n);
168 std::cerr <<
TermColor::Red << fmt::format(
"face-face node search min dist was: [{}]", minDist) <<
"\n"
183 std::unordered_map<index, std::vector<index>> donorNode2Cell;
187 auto iNode = (*cell2nodeSerial)(iCell, iN);
188 if (iNodeDonorToMain1.count(iNode) || iNodeDonorToMain2.count(iNode) || iNodeDonorToMain3.count(iNode))
190 donorNode2Cell[iNode].push_back(iCell);
193 std::unordered_map<index, std::vector<index>> donorNode2Bnd;
197 auto iNode = (*bnd2nodeSerial)(iBnd, iN);
198 if (iNodeDonorToMain1.count(iNode) || iNodeDonorToMain2.count(iNode) || iNodeDonorToMain3.count(iNode))
200 donorNode2Bnd[iNode].push_back(iBnd);
205 cell2nodePbiSerial = make_ssp<decltype(cell2nodePbiSerial)::element_type>(
ObjName{
"Deduplicate1to1Periodic::cell2nodePbiSerial"},
mesh->getMPI());
215 for (
auto iNodeFace : (*bnd2nodeSerial)[iBnd])
218 for (
auto iCell : donorNode2Cell[iNodeFace])
219 for (
auto iNode : (*bnd2nodeSerial)[iBnd])
220 for (
rowsize ic2n = 0; ic2n < (*cell2nodeSerial).RowSize(iCell); ic2n++)
224 if (faceID == BC_ID_PERIODIC_1_DONOR)
225 (*cell2nodePbiSerial)(iCell, ic2n).setP1True();
226 if (faceID == BC_ID_PERIODIC_2_DONOR)
227 (*cell2nodePbiSerial)(iCell, ic2n).setP2True();
228 if (faceID == BC_ID_PERIODIC_3_DONOR)
229 (*cell2nodePbiSerial)(iCell, ic2n).setP3True();
235 bnd2nodePbiSerial = make_ssp<decltype(bnd2nodePbiSerial)::element_type>(
ObjName{
"Deduplicate1to1Periodic::bnd2nodePbiSerial"},
mesh->getMPI());
245 for (
auto iNodeFace : (*bnd2nodeSerial)[iBnd])
248 for (
auto iBndAdj : donorNode2Bnd[iNodeFace])
249 for (
auto iNode : (*bnd2nodeSerial)[iBnd])
250 for (
rowsize ic2n = 0; ic2n < (*bnd2nodeSerial).RowSize(iBndAdj); ic2n++)
254 if (faceID == BC_ID_PERIODIC_1_DONOR)
255 (*bnd2nodePbiSerial)(iBndAdj, ic2n).setP1True();
256 if (faceID == BC_ID_PERIODIC_2_DONOR)
257 (*bnd2nodePbiSerial)(iBndAdj, ic2n).setP2True();
258 if (faceID == BC_ID_PERIODIC_3_DONOR)
259 (*bnd2nodePbiSerial)(iBndAdj, ic2n).setP3True();
267 std::vector<index> iNodeOld2New(
coordSerial->Size(), 0);
270 auto getNewNodeMap = [&](
const decltype(iNodeDonorToMain1) &iNodeDonorToMainI) ->
void
275 if (iNodeOld2New[iNode] < 0)
277 bool isDonor = iNodeDonorToMainI.count(iNode);
279 iNodeOld2New[iNode] = nNodeNew++;
281 for (
const auto &p : iNodeDonorToMainI)
283 index iMain = p.second;
284 iNodeOld2New.at(p.first) = -1 - iMain;
287 getNewNodeMap(iNodeDonorToMain1);
288 getNewNodeMap(iNodeDonorToMain2);
289 getNewNodeMap(iNodeDonorToMain3);
293 while (iNodeOld2New.at(iNode) < 0)
294 iNode = -1 - iNodeOld2New[iNode];
295 return iNodeOld2New.at(iNode);
299 for (
auto &ii : (*cell2nodeSerial)[i])
302 for (
auto &ii : (*bnd2nodeSerial)[i])
319 coordSerial = make_ssp<decltype(coordSerial)::element_type>(
ObjName{
"Deduplicate1to1Periodic::coordSerial"},
mesh->getMPI());
321 for (
index i = 0; i < coordSerialOld->Size(); i++)
322 if (iNodeOld2New[i] >= 0)
323 (*coordSerial)[iNodeOld2New[i]] = (*coordSerialOld)[i];
324 coordSerialOld.reset();
331 real t0 = MPI_Wtime();
333 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing BuildCell2Cell "
335 << fmt::format(
"Using OMP [{}]", omp_get_max_threads())
338 cell2cellSerial = make_ssp<decltype(cell2cellSerial)::element_type>(
ObjName{
"BuildCell2Cell::cell2cellSerial"},
mesh->getMPI());
344 std::vector<std::vector<DNDS::index>> node2cell(
coordSerial->Size());
361 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing BuildCell2Cell Part 1" << std::endl;
365 index nCellsDone = 0;
367# pragma omp parallel for
371 auto CellElem =
Elem::Element{(*cellElemInfoSerial)[iCell]->getElemType()};
372 std::vector<DNDS::index> cell2nodeRow{
373 (*cell2nodeSerial)[iCell].begin(),
375 std::sort(cell2nodeRow.begin(), cell2nodeRow.end());
377 std::unordered_set<DNDS::index> c_neighbors_hash;
378 c_neighbors_hash.reserve(64);
379 std::vector<DNDS::index>
381 c_neighbors.reserve(64);
391 if (nCellsDone % (nCells / 1000 + 1) == 0)
400 if (nCellsDone == nCells - 1)
407 for (
auto iNode : cell2nodeRow)
408 for (
auto iCellOther : node2cell[iNode])
410 if (iCellOther == iCell || c_neighbors_hash.count(iCellOther) == 1)
413 c_neighbors.push_back(iCellOther);
414 c_neighbors_hash.insert(iCellOther);
418 auto CellElemO =
Elem::Element{(*cellElemInfoSerial)[iCellOther]->getElemType()};
419 std::vector<DNDS::index> cell2nodeRowO{
420 (*cell2nodeSerial)[iCellOther].begin(),
421 (*cell2nodeSerial)[iCellOther].begin() + CellElemO.
GetNumVertices()};
422 std::sort(cell2nodeRowO.begin(), cell2nodeRowO.end());
423 std::vector<DNDS::index> interSect;
424 interSect.reserve(32);
425 std::set_intersection(cell2nodeRowO.begin(), cell2nodeRowO.end(), cell2nodeRow.begin(), cell2nodeRow.end(),
426 std::back_inserter(interSect));
427 if ((iCellOther != iCell) && interSect.size() > (
mesh->dim - 1))
436 c_neighbors_hash.insert(iCellOther);
437 c_neighbors.push_back(iCellOther);
446 std::sort(c_neighbors.begin(), c_neighbors.end());
449 for (
auto iCellOther : c_neighbors)
456 (*cell2cellSerial).Compress();
463 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing BuildCell2Cell Part 2" << std::endl;
467# pragma omp parallel for
475 if (nCellsDone % (nCells / 1000 + 1) == 0)
484 if (nCellsDone == nCells - 1)
489 std::vector<index> facialNeighbors;
490 facialNeighbors.reserve(6);
494 std::sort(c2ni.begin(), c2ni.end());
495 for (
auto iCellOther : (*cell2cellSerial)[iCell])
500 std::sort(c2nj.begin(), c2nj.end());
501 std::vector<index> intersect;
502 intersect.reserve(9);
503 std::set_intersection(c2ni.begin(), c2ni.end(), c2nj.begin(), c2nj.end(), std::back_inserter(intersect));
504 if (intersect.size() >=
mesh->dim)
505 facialNeighbors.push_back(iCellOther);
507 (*cell2cellSerialFacial).ResizeRow(iCell, facialNeighbors.size());
508 (*cell2cellSerialFacial)[iCell] = facialNeighbors;
519 DNDS::log() <<
"UnstructuredMeshSerialRW === Done BuildCell2Cell"
520 << fmt::format(
" time [{:.4g}]", MPI_Wtime() - t0) << std::endl;