12 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing MeshPartitionCell2Cell" << std::endl;
15 idx_t nPart =
mesh->getMPI().size;
27 std::vector<idx_t> vtxdist(
mesh->getMPI().size + 1);
29# pragma omp parallel for
35# pragma omp parallel for
37 for (
DNDS::index iCell = 0; iCell < xadj.size(); iCell++)
39 std::vector<idx_t> adjncy(xadj.back());
40 std::vector<idx_t> adjncyWeights;
43# pragma omp parallel for
45 for (
DNDS::index iAdj = 0; iAdj < xadj.back(); iAdj++)
49 adjncyWeights.reserve(xadj.back());
50 std::vector<real> adjncyWeightsR;
51 adjncyWeightsR.reserve(xadj.back());
59 std::sort(cell2nodeCV.begin(), cell2nodeCV.end());
62 std::vector<index> cell2nodeCVOther =
cell2nodeSerial->operator[](iCellOther);
63 std::sort(cell2nodeCVOther.begin(), cell2nodeCVOther.end());
64 std::vector<index> faceFound;
66 std::set_intersection(cell2nodeCV.begin(), cell2nodeCV.end(), cell2nodeCVOther.begin(), cell2nodeCVOther.end(), std::back_inserter(faceFound));
68 std::vector<int> faceFoundC2F;
69 faceFoundC2F.reserve(faceFound.size());
70 for (
auto iN : faceFound)
73 faceFoundC2F.push_back(i);
74 DNDS_assert(faceFoundC2F.size() == faceFound.size());
77 for (
int i = 0; i < coordsF.cols(); i++)
78 for (
int j = 0; j < coordsF.cols(); j++)
80 maxDist = std::max(maxDist, (coordsF(EigenAll, i) - coordsF(EigenAll, j)).norm());
81 adjncyWeightsR.push_back(maxDist);
82 maxDistMax = std::max(maxDist, maxDistMax);
86 {
return std::pow(
x, 1); };
87 for (
auto d : adjncyWeightsR)
88 adjncyWeights.push_back(weightMapping(d / maxDistMax) * (INT_MAX - 1) + 1.);
94 idx_t nCon{1}, options[METIS_NOPTIONS];
95 METIS_SetDefaultOptions(options);
97 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
98 options[METIS_OPTION_CTYPE] = METIS_CTYPE_SHEM;
99 options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_GROW;
100 options[METIS_OPTION_RTYPE] = METIS_RTYPE_FM;
102 options[METIS_OPTION_NCUTS] = std::max(c_options.
metisNcuts, 1);
103 options[METIS_OPTION_NITER] = 10;
106 options[METIS_OPTION_MINCONN] = 1;
107 options[METIS_OPTION_CONTIG] = 1;
108 options[METIS_OPTION_SEED] = c_options.
metisSeed;
109 options[METIS_OPTION_NUMBERING] = 0;
111 options[METIS_OPTION_DBGLVL] = METIS_DBG_TIME;
113 std::vector<idx_t> partOut(nCell);
115 partOut.resize(1, -1);
118 if (
mesh->getMPI().size == 1 || (isSerial &&
mesh->getMPI().rank ==
mRank))
122 int ret = c_options.
metisType == std::string(
"KWAY")
123 ? METIS_PartGraphKway(
124 &nCell, &nCon, xadj.data(), adjncy.data(), NULL, NULL, c_options.
edgeWeightMethod ? adjncyWeights.data() : NULL,
125 &nPart, NULL, NULL, options, &objval, partOut.data())
126 : METIS_PartGraphRecursive(
127 &nCell, &nCon, xadj.data(), adjncy.data(), NULL, NULL, c_options.
edgeWeightMethod ? adjncyWeights.data() : NULL,
128 &nPart, NULL, NULL, options, &objval, partOut.data());
131 DNDS::log() <<
"METIS returned not OK: [" << ret <<
"]" << std::endl;
135 else if (
mesh->getMPI().size != 1 && (!isSerial))
138 for (
int i = 0; i < vtxdist.size() - 1; i++)
139 DNDS_assert_info(vtxdist[i + 1] - vtxdist[i] > 0,
"need more than zero cells on each proc!");
140 std::vector<real_t> tpWeights(nPart * nCon, 1.0 / nPart);
141 real_t ubVec[1]{1.05};
144 idx_t wgtflag{0}, numflag{0};
149 int ret = ParMETIS_V3_PartKway(
150 vtxdist.data(), xadj.data(), adjncy.data(), NULL, NULL, &wgtflag, &numflag,
151 &nCon, &nPart, tpWeights.data(), ubVec, optsC, &objval, partOut.data(),
152 &
mesh->getMPI().comm);
155 DNDS::log() <<
"METIS returned not OK: [" << ret <<
"]" << std::endl;
162 partOut.assign(partOut.size(), 0);
169 std::vector<index> partCellCnt(nPart, 0);
172 auto [min, max] = std::minmax_element(partCellCnt.begin(), partCellCnt.end());
173 log() <<
"UnstructuredMeshSerialRW === Done MeshPartitionCell2Cell "
174 << fmt::format(
"ave [{}], min [{}], max [{}], ",
real(
cellPartition.size()) / nPart, *min, *max)
175 << fmt::format(
"ratio [{:.4f}] ",
real(*min) / *max) << std::endl;
325 localFillOrderingNew2Old.reserve(this->
NumCell());
328 localFillOrderingNew2Old.push_back(i);
331 localFillOrderingNew2Old.push_back(i);
332 localFillOrderingOld2New.resize(this->
NumCell());
334 localFillOrderingOld2New.at(localFillOrderingNew2Old.at(i)) = i;
336 else if (
control.getOrderingCode() == 0)
340 else if (
control.getOrderingCode() == 1)
344 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling metis" << std::endl;
347 localFillOrderingNew2Old = std::move(
New2Old);
348 localFillOrderingOld2New = std::move(
Old2New);
351 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): metis done" << std::endl;
353 else if (
control.getOrderingCode() == 2)
356 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling boost::minimum_degree_ordering" << std::endl;
359 localFillOrderingNew2Old = std::move(
New2Old);
360 localFillOrderingOld2New = std::move(
Old2New);
363 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): boost done" << std::endl;
365 else if (
control.getOrderingCode() == 3)
369 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling boost::cuthill_mckee_ordering" << std::endl;
372 localFillOrderingNew2Old = std::move(
New2Old);
373 localFillOrderingOld2New = std::move(
Old2New);
378 log() << fmt::format(
"UnstructuredMesh::ObtainLocalFactFillOrdering(): boost done, old BW [{}] new BW [{}] ",
bandWidthOld,
bandWidthNew) << std::endl;
383 else if (
control.getOrderingCode() == 4)
387 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling CorrectRCM::CuthillMcKeeOrdering" << std::endl;
392 localFillOrderingNew2Old = std::move(
New2Old);
393 localFillOrderingOld2New = std::move(
Old2New);
398 log() << fmt::format(
"UnstructuredMesh::ObtainLocalFactFillOrdering(): CorrectRCM done, old BW [{}] new BW [{}] ",
bandWidthOld,
bandWidthNew) << std::endl;
409 localFillOrderingNew2Old = put_perm_back_to_local_parts(localFillOrderingNew2Old, this->
localPartitionStarts);
410 for (
index i = 0; i < localFillOrderingNew2Old.size(); i++)
411 localFillOrderingOld2New[localFillOrderingNew2Old[i]] = i;
413 check_permutations(localFillOrderingNew2Old, localFillOrderingOld2New, this->
localPartitionStarts);