DNDSR 0.2.1
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
Mesh_CellPermutation.hpp
Go to the documentation of this file.
1#pragma once
2/// @file Mesh_CellPermutation.hpp
3/// @brief Helper for computing cell reordering permutations via Metis.
4///
5/// Extracted from Mesh.cpp for use by both the legacy ReorderLocalCellsLegacy
6/// and the new ReorderLocalCells (in Mesh_Reorder.cpp).
7
8#include "DNDS/Defines.hpp"
9#include "DNDS/ArrayPair.hpp"
11
12#include <vector>
13
14#include <fmt/core.h>
15
17{
18 /// Result of local cell permutation computation.
20 {
21 std::vector<index> cellOld2New;
22 std::vector<index> cellNew2Old;
23 std::vector<index> localPartitionStarts;
26 };
27
28 /// Compute a cell reordering permutation using Metis partitioning
29 /// with optional inner partitioning and contiguous sorting.
30 ///
31 /// 1. Partition via Metis + RCM.
32 /// 2. Optionally sub-partition each first-level partition.
33 /// 3. Within each partition, sort cells so interior (private) cells come
34 /// before cells that touch ghost neighbors.
35 /// 4. Build inverse permutation.
36 ///
37 /// @param cell2cellFaceV Local face-adjacency graph (no ghost edges).
38 /// @param cell2cell Full cell-to-cell adjacency (with ghost).
39 /// @param nCell Number of local (father) cells.
40 /// @param nParts Number of first-level partitions.
41 /// @param nPartsInner Number of inner partitions per first-level part.
43 tLocalMatStruct &cell2cellFaceV,
44 const tAdjPair &cell2cell,
46 int nParts,
47 int nPartsInner)
48 {
50 result.cellOld2New.resize(nCell, -1);
51 result.cellNew2Old.resize(nCell);
52 for (index i = 0; i < nCell; i++)
53 result.cellNew2Old[i] = i;
54
55 result.localPartitionStarts = ReorderSerialAdj_PartitionMetisC(
56 cell2cellFaceV.begin(),
57 cell2cellFaceV.end(),
58 result.cellNew2Old.begin(),
59 result.cellNew2Old.end(), nParts, 0, nPartsInner <= 1, result.bwOld, result.bwNew);
60
61 if (nPartsInner > 1)
62 {
63 auto dbgCheckSubGraphRanges = [&]([[maybe_unused]] const char *tag)
64 {
65 for (int p = 0; p < static_cast<int>(result.localPartitionStarts.size()) - 1; p++)
66 {
67 index pStart = result.localPartitionStarts[p];
68 index pEnd = result.localPartitionStarts[p + 1];
69 for (index iC = pStart; iC < pEnd; iC++)
70 for (auto jC : cell2cellFaceV[iC])
72 jC >= 0 && jC < nCell,
73 "%s: partition %d [%lld,%lld): cell %lld has neighbor %lld outside [0,%lld)",
74 tag, p, (long long)pStart, (long long)pEnd,
75 (long long)iC, (long long)jC, (long long)nCell);
76 }
77 };
78 auto dbgCheckBidir = [&]([[maybe_unused]] const char *tag)
79 {
80 for (index iC = 0; iC < nCell; iC++)
81 for (auto jC : cell2cellFaceV[iC])
82 {
83 bool found = false;
84 for (auto kC : cell2cellFaceV[jC])
85 if (kC == iC)
86 {
87 found = true;
88 break;
89 }
91 "%s: edge %lld->%lld exists but reverse %lld->%lld missing",
92 tag, (long long)iC, (long long)jC, (long long)jC, (long long)iC);
93 }
94 };
95
96#ifndef DNDS_NDEBUG
97 dbgCheckSubGraphRanges("before inner partitioning");
98 dbgCheckBidir("before inner partitioning");
99#endif
100
101 for (int iPart = 0; iPart < static_cast<int>(result.localPartitionStarts.size()) - 1; iPart++)
102 {
103 index bwOldC{0}, bwNewC{0};
104 index offset = result.localPartitionStarts[iPart];
105 index offsetN = result.localPartitionStarts[iPart + 1];
106 auto inner_parts_start = ReorderSerialAdj_PartitionMetisC(
107 cell2cellFaceV.begin() + offset,
108 cell2cellFaceV.begin() + offsetN,
109 result.cellNew2Old.begin() + offset,
110 result.cellNew2Old.begin() + offsetN, nPartsInner, offset, true, bwOldC, bwNewC,
111 cell2cellFaceV.begin(), nCell);
112 result.bwOld = std::max(result.bwOld, bwOldC);
113 result.bwNew = std::max(result.bwNew, bwNewC);
114
115#ifndef DNDS_NDEBUG
116 dbgCheckSubGraphRanges(fmt::format("after inner part {}", iPart).c_str());
117#endif
118 }
119
120#ifndef DNDS_NDEBUG
121 dbgCheckBidir("after all inner partitioning");
122#endif
123 }
124
125 // Contiguous sorting: within each partition, put interior cells before
126 // cells that touch ghost neighbors.
127 {
128 auto cellIsNotPrivate = [&](index iCell)
129 {
130 for (auto iCellOther : cell2cell[iCell])
131 {
132 if (iCellOther >= nCell)
133 return 1;
134 }
135 return 0;
136 };
137 int nLocalParts = !result.localPartitionStarts.empty()
138 ? static_cast<int>(result.localPartitionStarts.size()) - 1
139 : 1;
140 auto localPartStart = [&](int iPart) -> index
141 { return !result.localPartitionStarts.empty() ? result.localPartitionStarts.at(iPart) : 0; };
142 auto localPartEnd = [&](int iPart) -> index
143 { return !result.localPartitionStarts.empty() ? result.localPartitionStarts.at(iPart + 1) : nCell; };
144
145 std::vector<index> cellNew2Old_new;
146 cellNew2Old_new.reserve(nCell);
147 for (index i = 0; i < nCell; i++)
148 result.cellOld2New[i] = cellIsNotPrivate(result.cellNew2Old[i]);
149 for (int iPart = 0; iPart < nLocalParts; iPart++)
150 {
151 for (index i = localPartStart(iPart); i < localPartEnd(iPart); i++)
152 if (!result.cellOld2New[i])
153 cellNew2Old_new.push_back(result.cellNew2Old[i]);
154 for (index i = localPartStart(iPart); i < localPartEnd(iPart); i++)
155 if (result.cellOld2New[i])
156 cellNew2Old_new.push_back(result.cellNew2Old[i]);
157 }
158
159 result.cellNew2Old = std::move(cellNew2Old_new);
160 DNDS_assert(static_cast<index>(result.cellNew2Old.size()) == nCell);
161 for (auto v : result.cellNew2Old)
162 DNDS_assert(v < nCell && v >= 0);
163 }
164
165 // Build inverse permutation
166 {
167 std::vector<bool> seen(nCell, false);
168 for (index i = 0; i < nCell; i++)
169 {
170 DNDS_assert(result.cellNew2Old[i] >= 0 && result.cellNew2Old[i] < nCell);
171 DNDS_assert(!seen[result.cellNew2Old[i]]);
172 seen[result.cellNew2Old[i]] = true;
173 result.cellOld2New.at(result.cellNew2Old[i]) = i;
174 }
175 }
176 return result;
177 }
178
179} // namespace DNDS::Geom::detail
Father-son array pairs with device views and ghost communication.
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:112
#define DNDS_assert_infof(expr, info,...)
Debug-only assertion with a printf-style format message.
Definition Errors.hpp:122
CellPermutationResult ComputeCellPermutation(tLocalMatStruct &cell2cellFaceV, const tAdjPair &cell2cell, index nCell, int nParts, int nPartsInner)
std::vector< index > ReorderSerialAdj_PartitionMetisC(tLocalMatStruct::iterator mat_begin, tLocalMatStruct::iterator mat_end, std::vector< index >::iterator i_new2old_begin, std::vector< index >::iterator i_new2old_end, int nParts, index ind_offset, bool do_rcm, index &bwOldM, index &bwNewM, tLocalMatStruct::iterator full_mat_begin, index full_n_elem)
Partition a sub-graph into nParts and optionally apply RCM reordering within each part.
std::vector< std::vector< index > > tLocalMatStruct
Definition Geometric.hpp:66
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:112
Convenience bundle of a father, son, and attached ArrayTransformer.
Result of local cell permutation computation.
Eigen::Matrix< real, 5, 1 > v
auto result
const DNDS::index nCell
const tPoint const tPoint const tPoint & p