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-2022 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 
29 #include "Time.H"
30 #include "globalIndex.H"
31 
32 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
33 
35 (
36  const labelList& adjncy,
37  const labelList& xadj,
38  const List<scalar>& cWeights,
39  labelList& decomp
40 ) const
41 {
42  if (!Pstream::parRun())
43  {
44  return decomposeSerial
45  (
46  adjncy,
47  xadj,
48  cWeights,
49  decomp
50  );
51  }
52 
53  if (debug)
54  {
55  Info<< type() << "Decomp : running in parallel."
56  << " Decomposing all of graph on master processor." << endl;
57  }
58 
59  // Protect against zero-sized offset list
60  const label numCells = max(0, (xadj.size()-1));
61 
62  const globalIndex globalAdjncy(adjncy.size());
63  const globalIndex globalCells(numCells);
64 
65  List<label> allAdjncy(globalAdjncy.gather(adjncy));
66 
67  // Gathering xadj to master is similar to globalIndex gather()
68  // except for the following:
69  //
70  // - gathered list is size+1
71  // - apply local to global renumbering
72 
74  const label startOfRequests = UPstream::nRequests();
75 
76 
77  List<label> allXadj;
78  if (Pstream::master())
79  {
80  allXadj.resize(globalCells.totalSize()+1);
81  allXadj.last() = globalAdjncy.totalSize(); // Final end offset
82 
83  // My values - no renumbering required
84  SubList<label>(allXadj, globalCells.localSize(0)) =
85  SubList<label>(xadj, globalCells.localSize(0));
86 
87  for (const int proci : globalCells.subProcs())
88  {
89  SubList<label> procSlot(allXadj, globalCells.range(proci));
90 
91  if (procSlot.empty())
92  {
93  // Nothing to do
94  }
95  else
96  {
98  (
99  commsType,
100  proci,
101  procSlot.data_bytes(),
102  procSlot.size_bytes(),
105  );
106  }
107  }
108  }
109  else
110  {
111  // Send my part of the graph (local numbering)
112 
113  if (!numCells)
114  {
115  // Nothing to do
116  }
117  else
118  {
119  SubList<label> procSlot(xadj, numCells);
120 
122  (
123  commsType,
125  procSlot.cdata_bytes(),
126  procSlot.size_bytes(),
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 (Pstream::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  // Ignore zero-sized weights ... and poorly sized ones too
151  List<scalar> allWeights;
152  if (returnReduceAnd(cWeights.size() == globalCells.localSize()))
153  {
154  allWeights = globalCells.gather(cWeights);
155  }
156 
157 
158  // Global decomposition
159  labelList allDecomp;
160 
161  if (Pstream::master())
162  {
164  (
165  allAdjncy,
166  allXadj,
167  allWeights,
168  allDecomp
169  );
170 
171  allAdjncy.clear(); // Not needed anymore
172  allXadj.clear(); // ...
173  allWeights.clear(); // ...
174  }
175 
176  // The processor-local decomposition (output)
177  decomp.resize_nocopy(globalCells.localSize());
178  globalCells.scatter(allDecomp, decomp);
179 
180  return 0;
181 }
182 
183 
184 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
185 
187 (
188  const word& derivedType,
189  const dictionary& decompDict,
190  const word& regionName,
191  int select
192 )
193 :
194  decompositionMethod(decompDict, regionName),
195  coeffsDict_(findCoeffsDict(derivedType + "Coeffs", select))
196 {}
197 
198 
199 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
200 
202 (
203  const polyMesh& mesh,
204  const pointField& points,
205  const scalarField& pointWeights
206 ) const
207 {
208  if (points.size() != mesh.nCells())
209  {
211  << "Can only use this decomposition method for entire mesh" << nl
212  << "and supply one coordinate (cellCentre) for every cell." << nl
213  << "The number of coordinates " << points.size() << nl
214  << "The number of cells in the mesh " << mesh.nCells() << nl
215  << exit(FatalError);
216  }
217 
218  CompactListList<label> cellCells;
219  calcCellCells
220  (
221  mesh,
222  identity(mesh.nCells()),
223  mesh.nCells(),
224  true,
225  cellCells
226  );
227 
228  // Decompose using default weights
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  << "Size of cell-to-coarse map " << agglom.size()
254  << " differs from number of cells in mesh " << 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;
263  calcCellCells
264  (
265  mesh,
266  agglom,
267  agglomPoints.size(),
268  true,
269  cellCells
270  );
271 
272  // Decompose using default weights
273  labelList decomp;
274  decomposeGeneral
275  (
276  cellCells.values(),
277  cellCells.offsets(),
278  agglomWeights,
279  decomp
280  );
281 
282 
283  // Rework back into decomposition for original mesh
284  labelList fineDistribution(agglom.size());
285 
286  forAll(fineDistribution, i)
287  {
288  fineDistribution[i] = decomp[agglom[i]];
289  }
290 
291  return fineDistribution;
292 }
293 
294 
296 (
297  const labelListList& globalCellCells,
298  const pointField& cellCentres,
299  const scalarField& cellWeights
300 ) const
301 {
302  if (cellCentres.size() != globalCellCells.size())
303  {
305  << "Inconsistent number of cells (" << globalCellCells.size()
306  << ") and number of cell centres (" << cellCentres.size()
307  << ")." << exit(FatalError);
308  }
309 
310  // Make Metis CSR (Compressed Storage Format) storage
311  // adjncy : contains neighbours (= edges in graph)
312  // xadj(celli) : start of information in adjncy for celli
313 
314 
315  auto cellCells(CompactListList<label>::pack(globalCellCells));
316 
317  // Decompose using default weights
318  labelList decomp;
319  decomposeGeneral
320  (
321  cellCells.values(),
322  cellCells.offsets(),
323  cellWeights,
324  decomp
325  );
326 
327  return decomp;
328 }
329 
330 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
commsTypes
Communications types.
Definition: UPstream.H:74
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
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
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:139
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1184
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:411
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:243
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1536
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:236
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
Foam::word regionName(Foam::polyMesh::defaultRegion)
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:62
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.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
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)
Definition: labelList.C:31
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1014
virtual labelList decompose(const polyMesh &mesh, const pointField &points, const scalarField &pointWeights) const
Return for every coordinate the wanted processor number.
metisLikeDecomp(const metisLikeDecomp &)=delete
No copy construct.
Abstract base class for domain decomposition.
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.
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:828
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:1037
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.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
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:73
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:250