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-2023 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
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 
28 #include "metisLikeDecomp.H"
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 = 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.data_bytes(),
104  procSlot.size_bytes(),
107  );
108  }
109  }
110  }
111  else
112  {
113  // Send my part of the graph (local numbering)
114 
115  if (!numCells)
116  {
117  // Nothing to do
118  }
119  else
120  {
121  SubList<label> procSlot(xadj, numCells);
122 
124  (
125  commsType,
127  procSlot.cdata_bytes(),
128  procSlot.size_bytes(),
131  );
132  }
133  }
134 
135  // Wait for outstanding requests
136  if (commsType == UPstream::commsTypes::nonBlocking)
137  {
138  UPstream::waitRequests(startOfRequests);
139  }
140 
141  // Local to global renumbering
142  if (UPstream::master())
143  {
144  for (const int proci : globalCells.subProcs())
145  {
146  SubList<label> procSlot(allXadj, globalCells.range(proci));
147 
148  globalAdjncy.inplaceToGlobal(proci, procSlot);
149  }
150  }
151 
152  // Uniform weighting if weights are empty or poorly sized
153 
154  List<scalar> allWeights;
155  if (returnReduceAnd(cWeights.size() == globalCells.localSize()))
156  {
157  // ie, hasWeights
158  allWeights = globalCells.gather(cWeights);
159  }
160 
161 
162  // Global decomposition
163  labelList allDecomp;
164 
165  if (UPstream::master())
166  {
168  (
169  allAdjncy,
170  allXadj,
171  allWeights,
172  allDecomp
173  );
174 
175  allAdjncy.clear(); // Not needed anymore
176  allXadj.clear(); // ...
177  allWeights.clear(); // ...
178  }
179 
180  // The processor-local decomposition (output)
181  decomp.resize_nocopy(globalCells.localSize());
182  globalCells.scatter(allDecomp, decomp);
184  return 0;
185 }
186 
187 
188 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
189 
190 Foam::metisLikeDecomp::metisLikeDecomp(const label numDomains)
191 :
192  decompositionMethod(numDomains),
193  coeffsDict_(dictionary::null)
194 {}
195 
196 
198 (
199  const word& derivedType,
200  const dictionary& decompDict,
201  const word& regionName,
202  int select
203 )
204 :
205  decompositionMethod(decompDict, regionName),
206  coeffsDict_(findCoeffsDict(derivedType + "Coeffs", select))
207 {}
208 
209 
210 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
211 
213 (
214  const polyMesh& mesh,
215  const pointField& points,
216  const scalarField& pointWeights
217 ) const
218 {
219  if (!points.empty() && (points.size() != mesh.nCells()))
220  {
222  << "Number of cell centres (" << points.size()
223  << ") != number of cells (" << mesh.nCells() << ")"
224  << exit(FatalError);
225  }
226 
227  CompactListList<label> cellCells;
229  (
230  mesh,
231  identity(mesh.nCells()),
232  mesh.nCells(),
233  true,
234  cellCells
235  );
236 
237  // Decompose using default weights
238  labelList decomp;
239  decomposeGeneral
240  (
241  cellCells.values(),
242  cellCells.offsets(),
243  pointWeights,
244  decomp
245  );
246 
247  return decomp;
248 }
249 
250 
252 (
253  const polyMesh& mesh,
254  const labelList& agglom,
255  const pointField& agglomPoints,
256  const scalarField& agglomWeights
257 ) const
258 {
259  if (agglom.size() != mesh.nCells())
260  {
262  << "Agglomeration size (" << agglom.size()
263  << ") != number of cells (" << mesh.nCells() << ")"
264  << exit(FatalError);
265  }
266 
267  // Make Metis CSR (Compressed Storage Format) storage
268  // adjncy : contains neighbours (= edges in graph)
269  // xadj(celli) : start of information in adjncy for celli
270 
271  CompactListList<label> cellCells;
273  (
274  mesh,
275  agglom,
276  agglomPoints.size(),
277  true,
278  cellCells
279  );
280 
281  // Decompose using default weights
282  labelList decomp;
283  decomposeGeneral
284  (
285  cellCells.values(),
286  cellCells.offsets(),
287  agglomWeights,
288  decomp
289  );
291  // From coarse back to fine for original mesh
292  return labelList(decomp, agglom);
293 }
294 
295 
297 (
298  const CompactListList<label>& globalCellCells,
299  const pointField& cellCentres,
300  const scalarField& cellWeights
301 ) const
302 {
303  if (!cellCentres.empty() && (cellCentres.size() != globalCellCells.size()))
304  {
306  << "Number of cell centres (" << cellCentres.size()
307  << ") != number of cells (" << globalCellCells.size() << ")"
308  << exit(FatalError);
309  }
310 
311  // CompactListList is already
312  // Metis CSR (Compressed Storage Format) storage
313  // adjncy : contains neighbours (= edges in graph)
314  // xadj(celli) : start of information in adjncy for celli
315 
316  // Decompose using default weights
317  labelList decomp;
318  decomposeGeneral
319  (
320  globalCellCells.values(),
321  globalCellCells.offsets(),
322  cellWeights,
323  decomp
324  );
325 
326  return decomp;
327 }
328 
329 
331 (
332  const labelListList& globalCellCells,
333  const pointField& cellCentres,
334  const scalarField& cellWeights
335 ) const
336 {
337  if (!cellCentres.empty() && (cellCentres.size() != globalCellCells.size()))
338  {
340  << "Number of cell centres (" << cellCentres.size()
341  << ") != number of cells (" << globalCellCells.size() << ")"
342  << exit(FatalError);
343  }
344 
345  // Make Metis CSR (Compressed Storage Format) storage
346  // adjncy : contains neighbours (= edges in graph)
347  // xadj(celli) : start of information in adjncy for celli
348 
349 
350  auto cellCells(CompactListList<label>::pack(globalCellCells));
351 
352  // Decompose using default weights
353  labelList decomp;
354  decomposeGeneral
355  (
356  cellCells.values(),
357  cellCells.offsets(),
358  cellWeights,
359  decomp
360  );
361 
362  return decomp;
363 }
364 
365 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
const labelList & offsets() const noexcept
Return the offset table (= size()+1)
static label read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label size() const noexcept
The primary size (the number of rows/sublists)
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
commsTypes
Communications types.
Definition: UPstream.H:72
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
List< bool > select(const label n, const labelUList &locations)
Construct a selection list of bools (all false) with the given pre-size, subsequently add specified l...
Definition: BitOps.C:134
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:175
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
static CompactListList< T > pack(const UList< SubListType > &lists, const bool checkOverflow=false)
Construct by packing together the list of lists.
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:409
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:286
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1538
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:279
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
A List obtained as a section of another List.
Definition: SubList.H:50
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
dynamicFvMesh & mesh
const pointField & points
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
A class for handling words, derived from Foam::string.
Definition: word.H:63
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1059
metisLikeDecomp(const metisLikeDecomp &)=delete
No copy construct.
Abstract base class for domain decomposition.
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.
A packed storage of objects of type <T> using an offset table for access.
int debug
Static debugging option.
virtual label decomposeSerial(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const =0
Decomposition with metis-like parameters.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
label nCells() const noexcept
Number of mesh cells.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents to given processor.
T & back()
Access last element of the list, position [size()-1].
Definition: UListI.H:251
"nonBlocking" : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
const List< T > & values() const noexcept
Return the packed values.
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:74
List< label > labelList
A List of labels.
Definition: List.H:62
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:293