Loading...
Searching...
No Matches
metisLikeDecomp.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2017-2025 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
29#include "Time.H"
30#include "globalIndex.H"
31#include "globalMeshData.H"
32
33// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
34
36(
37 const labelList& adjncy,
38 const labelList& xadj,
39 const List<scalar>& cWeights,
40 labelList& decomp
41) const
42{
43 if (!UPstream::parRun())
44 {
45 // Treat zero-sized weights as uniform weighting
46 return decomposeSerial
47 (
48 adjncy,
49 xadj,
50 cWeights,
51 decomp
52 );
53 }
54
55 if (debug)
56 {
57 Info<< type() << "Decomp : running in parallel."
58 << " Decomposing all of graph on master processor." << endl;
59 }
60
61 // Protect against zero-sized offset list
62 const label numCells = Foam::max(0, (xadj.size()-1));
63
64 const globalIndex globalAdjncy(adjncy.size());
65 const globalIndex globalCells(numCells);
66
67 List<label> allAdjncy(globalAdjncy.gather(adjncy));
68
69 // Gathering xadj to master is similar to globalIndex gather()
70 // except for the following:
71 //
72 // - gathered list is size+1
73 // - apply local to global renumbering
74
76 const label startOfRequests = UPstream::nRequests();
77
78
79 List<label> allXadj;
80 if (UPstream::master())
81 {
82 allXadj.resize(globalCells.totalSize()+1);
83 allXadj.back() = globalAdjncy.totalSize(); // Final end offset
84
85 // My values - no renumbering required
86 SubList<label>(allXadj, globalCells.localSize(0)) =
87 SubList<label>(xadj, globalCells.localSize(0));
88
89 for (const int proci : globalCells.subProcs())
90 {
91 SubList<label> procSlot(allXadj, globalCells.range(proci));
92
93 if (procSlot.empty())
94 {
95 // Nothing to do
96 }
97 else
98 {
100 (
101 commsType,
102 proci,
103 procSlot,
106 );
107 }
108 }
109 }
110 else
111 {
112 // Send my part of the graph (local numbering)
113
114 if (!numCells)
115 {
116 // Nothing to do
117 }
118 else
119 {
120 SubList<label> procSlot(xadj, numCells);
121
123 (
124 commsType,
126 procSlot,
129 );
130 }
131 }
132
133 // Wait for outstanding requests
134 if (commsType == UPstream::commsTypes::nonBlocking)
135 {
136 UPstream::waitRequests(startOfRequests);
137 }
138
139 // Local to global renumbering
140 if (UPstream::master())
141 {
142 for (const int proci : globalCells.subProcs())
143 {
144 SubList<label> procSlot(allXadj, globalCells.range(proci));
145
146 globalAdjncy.inplaceToGlobal(proci, procSlot);
147 }
148 }
149
150 // Uniform weighting if weights are empty or poorly sized
151
152 List<scalar> allWeights;
153 if (returnReduceAnd(cWeights.size() == globalCells.localSize()))
154 {
155 // ie, hasWeights
156 allWeights = globalCells.gather(cWeights);
157 }
158
159
160 // Global decomposition
161 labelList allDecomp;
162
163 if (UPstream::master())
164 {
166 (
167 allAdjncy,
168 allXadj,
169 allWeights,
170 allDecomp
171 );
172
173 allAdjncy.clear(); // Not needed anymore
174 allXadj.clear(); // ...
175 allWeights.clear(); // ...
176 }
177
178 // The processor-local decomposition (output)
179 decomp.resize_nocopy(globalCells.localSize());
180 globalCells.scatter(allDecomp, decomp);
182 return 0;
183}
184
185
186// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
187
189:
190 decompositionMethod(numDomains),
192{}
193
194
196(
197 const word& derivedType,
198 const dictionary& decompDict,
199 const word& regionName,
200 int select
201)
202:
204 coeffsDict_(findCoeffsDict(derivedType + "Coeffs", select))
205{}
206
207
208// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
209
211(
212 const polyMesh& mesh,
213 const pointField& points,
214 const scalarField& pointWeights
215) const
216{
217 if (!points.empty() && (points.size() != mesh.nCells()))
218 {
220 << "Number of cell centres (" << points.size()
221 << ") != number of cells (" << mesh.nCells() << ")"
222 << exit(FatalError);
223 }
224
225 // Global mesh connectivity
226 CompactListList<label> cellCells;
227 globalMeshData::calcCellCells(mesh, cellCells, true);
228
229 labelList decomp;
230 decomposeGeneral
231 (
232 cellCells.values(),
233 cellCells.offsets(),
234 pointWeights,
235 decomp
236 );
237
238 return decomp;
239}
240
241
243(
244 const polyMesh& mesh,
245 const labelList& agglom,
246 const pointField& agglomPoints,
247 const scalarField& agglomWeights
248) const
249{
250 if (agglom.size() != mesh.nCells())
251 {
253 << "Agglomeration size (" << agglom.size()
254 << ") != number of cells (" << mesh.nCells() << ")"
255 << exit(FatalError);
256 }
257
258 // Make Metis CSR (Compressed Storage Format) storage
259 // adjncy : contains neighbours (= edges in graph)
260 // xadj(celli) : start of information in adjncy for celli
261
262 CompactListList<label> cellCells;
264 (
265 mesh,
266 agglom,
267 agglomPoints.size(),
268 true, // Global mesh connectivity
269 cellCells
270 );
271
272 labelList decomp;
273 decomposeGeneral
274 (
275 cellCells.values(),
276 cellCells.offsets(),
277 agglomWeights,
278 decomp
279 );
280
281 // From coarse back to fine for original mesh
282 return labelList(decomp, agglom);
283}
284
285
287(
288 const CompactListList<label>& globalCellCells,
289 const pointField& cellCentres,
290 const scalarField& cellWeights
291) const
292{
293 if (!cellCentres.empty() && (cellCentres.size() != globalCellCells.size()))
294 {
296 << "Number of cell centres (" << cellCentres.size()
297 << ") != number of cells (" << globalCellCells.size() << ")"
298 << exit(FatalError);
299 }
300
301 // CompactListList is already
302 // Metis CSR (Compressed Storage Format) storage
303 // adjncy : contains neighbours (= edges in graph)
304 // xadj(celli) : start of information in adjncy for celli
305
306 labelList decomp;
307 decomposeGeneral
308 (
309 globalCellCells.values(),
310 globalCellCells.offsets(),
311 cellWeights,
312 decomp
313 );
314
315 return decomp;
316}
317
318
320(
321 const labelListList& globalCellCells,
322 const pointField& cellCentres,
323 const scalarField& cellWeights
324) const
325{
326 if (!cellCentres.empty() && (cellCentres.size() != globalCellCells.size()))
327 {
329 << "Number of cell centres (" << cellCentres.size()
330 << ") != number of cells (" << globalCellCells.size() << ")"
331 << exit(FatalError);
332 }
333
334 // Make Metis CSR (Compressed Storage Format) storage
335 // adjncy : contains neighbours (= edges in graph)
336 // xadj(celli) : start of information in adjncy for celli
337
338
339 auto cellCells(CompactListList<label>::pack(globalCellCells));
340
341 labelList decomp;
342 decomposeGeneral
343 (
344 cellCells.values(),
345 cellCells.offsets(),
346 cellWeights,
347 decomp
348 );
349
350 return decomp;
351}
352
353// ************************************************************************* //
A packed storage of objects of type <T> using an offset table for access.
const labelList & offsets() const noexcept
Return the offset table (= size()+1).
const List< T > & values() const noexcept
Return the packed values.
static CompactListList< T > pack(const UList< SubListType > &lists, const bool checkOverflow=false)
Construct by packing together the list of lists.
label size() const noexcept
The primary size (the number of rows/sublists).
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
static std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr)
Receive buffer contents (contiguous types) from given processor.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
T & back()
Access last element of the list, position [size()-1].
Definition UListI.H:253
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents (contiguous types only) to given processor.
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests).
commsTypes
Communications types.
Definition UPstream.H:81
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition UPstream.H:1691
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
static void waitRequests()
Wait for all requests to finish.
Definition UPstream.H:2497
decompositionMethod(const label numDomains)
Construct with specified number of domains, no coefficients or constraints.
static FOAM_NO_DANGLING_REFERENCE const dictionary & findCoeffsDict(const dictionary &dict, const word &coeffsName, int select=selectionType::DEFAULT)
Locate coeffsName dictionary or the fallback "coeffs" dictionary within an enclosing dictionary.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
label totalSize() const noexcept
The total addressed size, which corresponds to the end offset and also the sum of all localSizes.
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, UList< Type > &allFld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
void inplaceToGlobal(const label proci, labelUList &labels) const
From local to global index on proci (inplace).
labelRange range(label proci) const noexcept
Return start/size range of proci data.
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes).
static void scatter(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &allFld, UList< Type > &fld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Distribute data in processor order.
label localSize(const label proci) const
Size of proci data.
static void calcCellCells(const polyMesh &mesh, const labelUList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
const dictionary & coeffsDict_
Coefficients for all derived methods.
metisLikeDecomp(const metisLikeDecomp &)=delete
No copy construct.
virtual label decomposeSerial(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const =0
Decomposition with metis-like parameters.
virtual labelList decompose(const polyMesh &mesh, const pointField &points=pointField::null(), const scalarField &pointWeights=scalarField::null()) const
Return for every coordinate the wanted processor number.
virtual label decomposeGeneral(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const
Serial and/or collect/distribute for parallel operation.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
A class for handling words, derived from Foam::string.
Definition word.H:66
dynamicFvMesh & mesh
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const pointField & points
Namespace for handling debugging switches.
Definition debug.C:45
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition POSIX.C:801
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125