DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
Mesh_PartitionHelpers.hpp
Go to the documentation of this file.
1#pragma once
2/// @file Mesh_PartitionHelpers.hpp
3/// @brief Internal helpers for mesh partition redistribution.
4///
5/// These template functions support converting mesh data from one partition
6/// to another using ArrayTransformer push-based transfer. Originally defined
7/// as file-local in Mesh.cpp, they are now shared between Mesh.cpp and
8/// Mesh_ReadSerializeDistributed.cpp.
9
10#include "Mesh_DeviceView.hpp"
12
13namespace DNDS::Geom
14{
15
16 /**
17 * Builds CSR-style push indices from a partition vector.
18 * partition[i] = rank that element i should go to.
19 * Output: localPush[localPushStart[r]..localPushStart[r+1]) = local indices going to rank r.
20 */
21 template <class TPartitionIdx>
23 const std::vector<TPartitionIdx> &partition,
24 std::vector<DNDS::index> &localPush,
25 std::vector<DNDS::index> &localPushStart, const DNDS::MPIInfo &mpi)
26 {
27 std::vector<DNDS::index> localPushSizes(mpi.size, 0);
28 for (auto r : partition)
29 {
30 DNDS_assert(r < mpi.size);
31 localPushSizes[r]++;
32 }
33 DNDS::AccumulateRowSize(localPushSizes, localPushStart);
34 localPush.resize(localPushStart[mpi.size]);
35 localPushSizes.assign(mpi.size, 0);
36 DNDS_assert(partition.size() == localPush.size());
37 for (size_t i = 0; i < partition.size(); i++)
38 localPush[localPushStart[partition[i]] + (localPushSizes[partition[i]]++)] = DNDS::size_to_index(i);
39 }
40
41 /**
42 * Computes the serial-to-global index mapping after repartitioning.
43 * Elements assigned to the same rank are grouped contiguously in the new global
44 * numbering. Uses MPI_Allreduce + MPI_Scan for prefix sums.
45 */
46 template <class TPartitionIdx>
48 const std::vector<TPartitionIdx> &partition,
49 std::vector<DNDS::index> &serial2Global, const DNDS::MPIInfo &mpi, DNDS::MPI_int nPart)
50 {
51 serial2Global.resize(partition.size());
52 std::vector<DNDS::index> numberAtLocal(nPart, 0);
53 for (auto r : partition)
54 numberAtLocal[r]++;
55 std::vector<DNDS::index> numberTotal(nPart), numberPrev(nPart);
56 MPI::Allreduce(numberAtLocal.data(), numberTotal.data(), nPart, DNDS::DNDS_MPI_INDEX, MPI_SUM, mpi.comm);
57 MPI::Scan(numberAtLocal.data(), numberPrev.data(), nPart, DNDS::DNDS_MPI_INDEX, MPI_SUM, mpi.comm);
58 std::vector<DNDS::index> numberTotalPlc(nPart + 1);
59 numberTotalPlc[0] = 0;
60 for (DNDS::MPI_int r = 0; r < nPart; r++)
61 numberTotalPlc[r + 1] = numberTotalPlc[r] + numberTotal[r], numberPrev[r] -= numberAtLocal[r];
62 numberAtLocal.assign(numberAtLocal.size(), 0);
63 DNDS::index iFill = 0;
64 for (auto r : partition)
65 serial2Global[iFill++] = (numberAtLocal[r]++) + numberTotalPlc[r] + numberPrev[r];
66 }
67
68 /**
69 * Converts adjacency entries from old (serial/evenly-split) indices to new
70 * global indices using a lookup table communicated via ArrayTransformer.
71 */
72 template <class TAdj = tAdj1>
73 void ConvertAdjSerial2Global(TAdj &arraySerialAdj,
74 const std::vector<DNDS::index> &partitionJSerial2Global,
75 const DNDS::MPIInfo &mpi)
76 {
77 tAdj1 JSG, JSGGhost;
78 JSG = make_ssp<tAdj1::element_type>(ObjName{"ConvertAdjSerial2Global::JSG"}, mpi);
79 JSGGhost = make_ssp<tAdj1::element_type>(ObjName{"ConvertAdjSerial2Global::JSGGhost"}, mpi);
80 JSG->Resize(partitionJSerial2Global.size());
81 for (DNDS::index i = 0; i < JSG->Size(); i++)
82 (*JSG)(i, 0) = partitionJSerial2Global[i];
83 JSG->createGlobalMapping();
84 std::vector<DNDS::index> ghostJSerialQuery;
85
86 DNDS::index nGhost = 0;
87 for (DNDS::index i = 0; i < arraySerialAdj->Size(); i++)
88 {
89 for (DNDS::rowsize j = 0; j < arraySerialAdj->RowSize(i); j++)
90 {
91 DNDS::index v = (*arraySerialAdj)(i, j);
92 if (v == DNDS::UnInitIndex)
93 break;
94 DNDS::MPI_int rank = -1;
95 DNDS::index val = -1;
96 if (!JSG->pLGlobalMapping->search(v, rank, val))
97 DNDS_assert_info(false, "search failed");
98 if (rank != mpi.rank)
99 nGhost++;
100 }
101 }
102 ghostJSerialQuery.reserve(nGhost);
103 for (DNDS::index i = 0; i < arraySerialAdj->Size(); i++)
104 {
105 for (DNDS::rowsize j = 0; j < arraySerialAdj->RowSize(i); j++)
106 {
107 DNDS::index v = (*arraySerialAdj)(i, j);
108 if (v == DNDS::UnInitIndex)
109 break;
110 DNDS::MPI_int rank = -1;
111 DNDS::index val = -1;
112 bool ret = JSG->pLGlobalMapping->search(v, rank, val);
113 DNDS_assert_info(ret, "search failed");
114 if (rank != mpi.rank)
115 ghostJSerialQuery.push_back(v);
116 }
117 }
119 JSGTrans.setFatherSon(JSG, JSGGhost);
120 JSGTrans.createGhostMapping(ghostJSerialQuery);
121 JSGTrans.createMPITypes();
122 JSGTrans.pullOnce();
123
124 for (DNDS::index i = 0; i < arraySerialAdj->Size(); i++)
125 {
126 for (DNDS::rowsize j = 0; j < arraySerialAdj->RowSize(i); j++)
127 {
128 DNDS::index &v = (*arraySerialAdj)(i, j);
129 if (v == DNDS::UnInitIndex)
130 break;
131 DNDS::MPI_int rank = -1;
132 DNDS::index val = -1;
133 if (!JSGTrans.pLGhostMapping->search(v, rank, val))
134 DNDS_assert_info(false, "search failed");
135 if (rank == -1)
136 v = (*JSG)(val, 0);
137 else
138 v = (*JSGGhost)(val, 0);
139 }
140 }
141 }
142
143 /**
144 * Transfers array data from current (serial/evenly-split) layout to the new
145 * distributed layout using ArrayTransformer push-based ghost mapping.
146 */
147 template <class TArr = tAdj1>
148 void TransferDataSerial2Global(TArr &arraySerial,
149 TArr &arrayDist,
150 const std::vector<DNDS::index> &pushIndex,
151 const std::vector<DNDS::index> &pushIndexStart,
152 const DNDS::MPIInfo &mpi)
153 {
155 trans.setFatherSon(arraySerial, arrayDist);
156 trans.createFatherGlobalMapping();
157 trans.createGhostMapping(pushIndex, pushIndexStart);
158 trans.createMPITypes();
159 trans.pullOnce();
160 }
161
162} // namespace DNDS::Geom
ParArray (MPI-aware array) and ArrayTransformer (ghost/halo communication).
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
Ghost-communication engine for a father / son ParArray pair.
t_pLGhostMapping pLGhostMapping
Ghost index mapping (rank-local layout). Populated by createGhostMapping.
void createMPITypes()
Collective: build the MPI derived datatypes (or in-situ buffers) that describe the ghost send/recv la...
void pullOnce()
Convenience: init + start + wait + clear a single pull.
void setFatherSon(const t_pArray &n_father, const t_pArray &n_son)
Attach father and son arrays. First setup step.
void createGhostMapping(TPullSet &&pullingIndexGlobal)
create ghost by pulling data
decltype(tAdj1Pair::father) tAdj1
void Partition2LocalIdx(const std::vector< TPartitionIdx > &partition, std::vector< DNDS::index > &localPush, std::vector< DNDS::index > &localPushStart, const DNDS::MPIInfo &mpi)
void Partition2Serial2Global(const std::vector< TPartitionIdx > &partition, std::vector< DNDS::index > &serial2Global, const DNDS::MPIInfo &mpi, DNDS::MPI_int nPart)
void TransferDataSerial2Global(TArr &arraySerial, TArr &arrayDist, const std::vector< DNDS::index > &pushIndex, const std::vector< DNDS::index > &pushIndexStart, const DNDS::MPIInfo &mpi)
void ConvertAdjSerial2Global(TAdj &arraySerialAdj, const std::vector< DNDS::index > &partitionJSerial2Global, const DNDS::MPIInfo &mpi)
MPI_int Scan(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Scan (inclusive prefix reduction).
Definition MPI.cpp:220
MPI_int Allreduce(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Allreduce.
Definition MPI.cpp:203
const MPI_Datatype DNDS_MPI_INDEX
MPI datatype matching index (= MPI_INT64_T).
Definition MPI.hpp:90
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
Definition Defines.hpp:176
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
Definition Defines.hpp:109
void AccumulateRowSize(const TtRowsizeVec &rowsizes, TtIndexVec &rowstarts)
Build a prefix-sum table from a row-size vector.
Definition Defines.hpp:452
index size_to_index(size_t v)
Range-checked conversion from size_t to DNDS::index.
Definition Defines.hpp:426
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
int MPI_int
MPI counterpart type for MPI_int (= C int). Used for counts and ranks in MPI calls.
Definition MPI.hpp:43
Lightweight bundle of an MPI communicator and the calling rank's coordinates.
Definition MPI.hpp:215
Tag type for naming objects created via make_ssp.
Definition Defines.hpp:249
Eigen::Matrix< real, 5, 1 > v
ArrayTransformer< DNDS::real, DynamicSize > trans
tVec r(NCells)