14 DNDS::log() <<
"UnstructuredMeshSerialRW === Doing MeshPartitionCell2Cell" << std::endl;
17 idx_t nPart =
mesh->getMPI().size;
29 std::vector<idx_t> vtxdist(
mesh->getMPI().size + 1);
31# pragma omp parallel for
37# pragma omp parallel for
39 for (
DNDS::index iCell = 0; iCell < xadj.size(); iCell++)
41 std::vector<idx_t> adjncy(xadj.back());
42 std::vector<idx_t> adjncyWeights;
45# pragma omp parallel for
47 for (
DNDS::index iAdj = 0; iAdj < xadj.back(); iAdj++)
51 adjncyWeights.reserve(xadj.back());
52 std::vector<real> adjncyWeightsR;
53 adjncyWeightsR.reserve(xadj.back());
61 std::sort(cell2nodeCV.begin(), cell2nodeCV.end());
64 std::vector<index> cell2nodeCVOther =
cell2nodeSerial->operator[](iCellOther);
65 std::sort(cell2nodeCVOther.begin(), cell2nodeCVOther.end());
66 std::vector<index> faceFound;
68 std::set_intersection(cell2nodeCV.begin(), cell2nodeCV.end(), cell2nodeCVOther.begin(), cell2nodeCVOther.end(), std::back_inserter(faceFound));
70 std::vector<int> faceFoundC2F;
71 faceFoundC2F.reserve(faceFound.size());
72 for (
auto iN : faceFound)
75 faceFoundC2F.push_back(
i);
76 DNDS_assert(faceFoundC2F.size() == faceFound.size());
79 for (
int i = 0;
i < coordsF.cols();
i++)
80 for (
int j = 0;
j < coordsF.cols();
j++)
82 maxDist = std::max(maxDist, (coordsF(EigenAll,
i) - coordsF(EigenAll,
j)).norm());
83 adjncyWeightsR.push_back(maxDist);
84 maxDistMax = std::max(maxDist, maxDistMax);
88 {
return std::pow(
x, 1); };
89 for (
auto d : adjncyWeightsR)
90 adjncyWeights.push_back(weightMapping(d / maxDistMax) * (INT_MAX - 1) + 1.);
97 std::array<idx_t, METIS_NOPTIONS> options{};
98 METIS_SetDefaultOptions(options.data());
100 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
101 options[METIS_OPTION_CTYPE] = METIS_CTYPE_SHEM;
102 options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_GROW;
103 options[METIS_OPTION_RTYPE] = METIS_RTYPE_FM;
105 options[METIS_OPTION_NCUTS] = std::max(c_options.
metisNcuts, 1);
106 options[METIS_OPTION_NITER] = 10;
109 options[METIS_OPTION_MINCONN] = 1;
110 options[METIS_OPTION_CONTIG] = 1;
111 options[METIS_OPTION_SEED] = c_options.
metisSeed;
112 options[METIS_OPTION_NUMBERING] = 0;
114 options[METIS_OPTION_DBGLVL] = METIS_DBG_TIME;
116 std::vector<idx_t> partOut(
nCell);
118 partOut.resize(1, -1);
121 if (
mesh->getMPI().size == 1 || (isSerial &&
mesh->getMPI().rank ==
mRank))
125 int ret = c_options.
metisType == std::string(
"KWAY")
126 ? METIS_PartGraphKway(
127 &
nCell, &nCon, xadj.data(), adjncy.data(),
nullptr,
nullptr, c_options.
edgeWeightMethod ? adjncyWeights.data() :
nullptr,
128 &nPart,
nullptr,
nullptr, options.data(), &objval, partOut.data())
129 : METIS_PartGraphRecursive(
130 &
nCell, &nCon, xadj.data(), adjncy.data(),
nullptr,
nullptr, c_options.
edgeWeightMethod ? adjncyWeights.data() :
nullptr,
131 &nPart,
nullptr,
nullptr, options.data(), &objval, partOut.data());
134 DNDS::log() <<
"METIS returned not OK: [" << ret <<
"]" << std::endl;
138 else if (
mesh->getMPI().size != 1 && (!isSerial))
141 for (
int i = 0;
i < vtxdist.size() - 1;
i++)
142 DNDS_assert_info(vtxdist[
i + 1] - vtxdist[
i] > 0,
"need more than zero cells on each proc!");
143 std::vector<real_t> tpWeights(
static_cast<index>(nPart) * nCon, 1.0 / nPart);
144 std::array<real_t, 1> ubVec{1.05};
146 std::array<idx_t, 3> optsC{};
147 idx_t wgtflag{0}, numflag{0};
152 int ret = ParMETIS_V3_PartKway(
153 vtxdist.data(), xadj.data(), adjncy.data(),
nullptr,
nullptr, &wgtflag, &numflag,
154 &nCon, &nPart, tpWeights.data(), ubVec.data(), optsC.data(), &objval, partOut.data(),
155 &
mesh->getMPI().comm);
158 DNDS::log() <<
"METIS returned not OK: [" << ret <<
"]" << std::endl;
165 partOut.assign(partOut.size(), 0);
172 std::vector<index> partCellCnt(nPart, 0);
175 auto [min, max] = std::minmax_element(partCellCnt.begin(), partCellCnt.end());
176 log() <<
"UnstructuredMeshSerialRW === Done MeshPartitionCell2Cell "
177 << fmt::format(
"ave [{}], min [{}], max [{}], ",
real(
cellPartition.size()) / nPart, *min, *max)
178 << fmt::format(
"ratio [{:.4f}] ",
real(*min) / *max) << std::endl;
329 localFillOrderingNew2Old.reserve(this->
NumCell());
332 localFillOrderingNew2Old.push_back(
i);
335 localFillOrderingNew2Old.push_back(
i);
336 localFillOrderingOld2New.resize(this->
NumCell());
338 localFillOrderingOld2New.at(localFillOrderingNew2Old.at(
i)) =
i;
340 else if (
control.getOrderingCode() == 0)
344 else if (
control.getOrderingCode() == 1)
348 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling metis" << std::endl;
351 localFillOrderingNew2Old = std::move(
New2Old);
352 localFillOrderingOld2New = std::move(
Old2New);
355 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): metis done" << std::endl;
357 else if (
control.getOrderingCode() == 2)
360 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling boost::minimum_degree_ordering" << std::endl;
363 localFillOrderingNew2Old = std::move(
New2Old);
364 localFillOrderingOld2New = std::move(
Old2New);
367 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): boost done" << std::endl;
369 else if (
control.getOrderingCode() == 3)
373 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling boost::cuthill_mckee_ordering" << std::endl;
376 localFillOrderingNew2Old = std::move(
New2Old);
377 localFillOrderingOld2New = std::move(
Old2New);
382 log() << fmt::format(
"UnstructuredMesh::ObtainLocalFactFillOrdering(): boost done, old BW [{}] new BW [{}] ",
bandWidthOld,
bandWidthNew) << std::endl;
387 else if (
control.getOrderingCode() == 4)
391 log() <<
"UnstructuredMesh::ObtainLocalFactFillOrdering(): start calling CorrectRCM::CuthillMcKeeOrdering" << std::endl;
396 localFillOrderingNew2Old = std::move(
New2Old);
397 localFillOrderingOld2New = std::move(
Old2New);
402 log() << fmt::format(
"UnstructuredMesh::ObtainLocalFactFillOrdering(): CorrectRCM done, old BW [{}] new BW [{}] ",
bandWidthOld,
bandWidthNew) << std::endl;
413 localFillOrderingNew2Old = put_perm_back_to_local_parts(localFillOrderingNew2Old, this->
localPartitionStarts);
414 for (
index i = 0;
i < localFillOrderingNew2Old.size();
i++)
415 localFillOrderingOld2New[localFillOrderingNew2Old[
i]] =
i;
417 check_permutations(localFillOrderingNew2Old, localFillOrderingOld2New, this->
localPartitionStarts);