GAMGProcAgglomeration.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) 2013-2017 OpenFOAM Foundation
9  Copyright (C) 2021-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "GAMGProcAgglomeration.H"
30 #include "GAMGAgglomeration.H"
31 #include "lduMesh.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(GAMGProcAgglomeration, 0);
39 }
40 
41 
42 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
43 
45 (
46  Ostream& os,
47  GAMGAgglomeration& agglom
48 ) const
49 {
50  for (label levelI = 0; levelI <= agglom.size(); levelI++)
51  {
52  if (agglom.hasMeshLevel(levelI))
53  {
54  os << "Level " << levelI << " mesh:"
55  << agglom.meshLevel(levelI).info() << endl;
56  }
57  else
58  {
59  os << "Level " << levelI << " has no fine mesh:" << endl;
60  }
61 
62  if
63  (
64  levelI < agglom.restrictAddressing_.size()
65  && agglom.restrictAddressing_.set(levelI)
66  )
67  {
68  const labelList& cellRestrict =
69  agglom.restrictAddressing(levelI);
70  const labelList& faceRestrict =
71  agglom.faceRestrictAddressing(levelI);
72 
73  os << "Level " << levelI << " agglomeration:" << nl
74  << " nCoarseCells:" << agglom.nCells(levelI) << nl
75  << " nCoarseFaces:" << agglom.nFaces(levelI) << nl
76  << " cellRestriction:"
77  << " size:" << cellRestrict.size()
78  << " max:" << max(cellRestrict)
79  << nl
80  << " faceRestriction:"
81  << " size:" << faceRestrict.size()
82  << " max:" << max(faceRestrict)
83  << nl;
84 
85  const labelListList& patchFaceRestrict =
86  agglom.patchFaceRestrictAddressing(levelI);
87  forAll(patchFaceRestrict, i)
88  {
89  if (patchFaceRestrict[i].size())
90  {
91  const labelList& faceRestrict =
92  patchFaceRestrict[i];
93  os << " " << i
94  << " size:" << faceRestrict.size()
95  << " max:" << max(faceRestrict)
96  << nl;
97  }
98  }
99  }
100  if
101  (
102  levelI < agglom.procCellOffsets_.size()
103  && agglom.procCellOffsets_.set(levelI)
104  )
105  {
106  os << " procCellOffsets:" << agglom.procCellOffsets_[levelI]
107  << nl
108  << " procAgglomMap:" << agglom.procAgglomMap_[levelI]
109  << nl
110  << " procIDs:" << agglom.agglomProcIDs_[levelI]
111  << nl
112  << " comm:" << agglom.procCommunicator_[levelI]
113  << endl;
114  }
115 
116  os << endl;
117  }
118  os << endl;
119 }
120 
121 
123 (
124  const lduMesh& mesh
125 )
126 {
127  const lduAddressing& addr = mesh.lduAddr();
128  lduInterfacePtrsList interfaces = mesh.interfaces();
129 
130  const label myProci = UPstream::myProcNo(mesh.comm());
131 
132  const globalIndex globalNumbering
133  (
134  addr.size(),
135  mesh.comm(),
137  );
138 
139  const labelList globalIndices
140  (
141  Foam::identity(globalNumbering.range(myProci))
142  );
143 
144  // Get the interface cells
145  PtrList<labelList> nbrGlobalCells(interfaces.size());
146  {
147  const label startOfRequests = UPstream::nRequests();
148 
149  // Initialise transfer of restrict addressing on the interface
150  forAll(interfaces, inti)
151  {
152  if (interfaces.set(inti))
153  {
154  interfaces[inti].initInternalFieldTransfer
155  (
157  globalIndices
158  );
159  }
160  }
161 
162  UPstream::waitRequests(startOfRequests);
163 
164  forAll(interfaces, inti)
165  {
166  if (interfaces.set(inti))
167  {
168  nbrGlobalCells.set
169  (
170  inti,
171  new labelList
172  (
173  interfaces[inti].internalFieldTransfer
174  (
176  globalIndices
177  )
178  )
179  );
180  }
181  }
182  }
183 
184 
185  // Scan the neighbour list to find out how many times the cell
186  // appears as a neighbour of the face. Done this way to avoid guessing
187  // and resizing list
188  labelList nNbrs(addr.size(), 1);
189 
190  const labelUList& nbr = addr.upperAddr();
191  const labelUList& own = addr.lowerAddr();
192 
193  {
194  forAll(nbr, facei)
195  {
196  nNbrs[nbr[facei]]++;
197  nNbrs[own[facei]]++;
198  }
199 
200  forAll(interfaces, inti)
201  {
202  if (interfaces.set(inti))
203  {
204  const labelUList& faceCells = interfaces[inti].faceCells();
205 
206  forAll(faceCells, i)
207  {
208  nNbrs[faceCells[i]]++;
209  }
210  }
211  }
212  }
213 
214 
215  // Create cell-cells addressing
216  labelListList cellCells(addr.size());
217 
218  forAll(cellCells, celli)
219  {
220  cellCells[celli].setSize(nNbrs[celli], -1);
221  }
222 
223  // Reset the list of number of neighbours to zero
224  nNbrs = 0;
225 
226  // Scatter the neighbour faces
227  forAll(nbr, facei)
228  {
229  label c0 = own[facei];
230  label c1 = nbr[facei];
231 
232  cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
233  cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
234  }
235  forAll(interfaces, inti)
236  {
237  if (interfaces.set(inti))
238  {
239  const labelUList& faceCells = interfaces[inti].faceCells();
240 
241  forAll(faceCells, i)
242  {
243  label c0 = faceCells[i];
244  cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
245  }
246  }
247  }
248 
249  forAll(cellCells, celli)
250  {
251  Foam::stableSort(cellCells[celli]);
252  }
253 
254  // Replace the initial element (always -1) with the local cell
255  forAll(cellCells, celli)
256  {
257  cellCells[celli][0] = globalIndices[celli];
258  }
259 
260  return cellCells;
261 }
262 
263 
265 (
266  const label fineLevelIndex,
267  const labelList& procAgglomMap,
268  const labelList& masterProcs,
269  const List<label>& agglomProcIDs,
270  const label procAgglomComm
271 )
272 {
273  const lduMesh& levelMesh = agglom_.meshLevels_[fineLevelIndex];
274  label levelComm = levelMesh.comm();
275 
276  if (fineLevelIndex > 0 && Pstream::myProcNo(levelComm) != -1)
277  {
278  // Collect meshes and restrictAddressing onto master
279  // Overwrites the fine mesh (meshLevels_[index-1]) and addressing
280  // from fine mesh to coarse mesh (restrictAddressing_[index]).
281  agglom_.procAgglomerateLduAddressing
282  (
283  levelComm,
284  procAgglomMap,
285  agglomProcIDs,
286  procAgglomComm,
287 
288  fineLevelIndex //fine level index
289  );
290 
291  // Combine restrict addressing only onto master
292  for
293  (
294  label levelI = fineLevelIndex+1;
295  levelI < agglom_.meshLevels_.size();
296  levelI++
297  )
298  {
299  agglom_.procAgglomerateRestrictAddressing
300  (
301  levelComm,
302  agglomProcIDs,
303  levelI
304  );
305  }
306 
307  if (Pstream::myProcNo(levelComm) == agglomProcIDs[0])
308  {
309  // On master. Recreate coarse meshes from restrict addressing
310  for
311  (
312  label levelI = fineLevelIndex;
313  levelI < agglom_.meshLevels_.size();
314  levelI++
315  )
316  {
317  agglom_.agglomerateLduAddressing(levelI);
318  }
319  }
320  else
321  {
322  // Agglomerated away. Clear mesh storage.
323  for
324  (
325  label levelI = fineLevelIndex+1;
326  levelI <= agglom_.size();
327  levelI++
328  )
329  {
330  agglom_.clearLevel(levelI);
331  }
332  }
333  }
334 
335  // Should check!
336  return true;
337 }
338 
339 
340 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
341 
343 (
344  GAMGAgglomeration& agglom,
345  const dictionary& controlDict
346 )
347 :
348  agglom_(agglom)
349 {}
350 
351 
353 (
354  const word& type,
355  GAMGAgglomeration& agglom,
356  const dictionary& controlDict
357 )
358 {
359  DebugInFunction << "Constructing GAMGProcAgglomeration" << endl;
360 
361  auto* ctorPtr = GAMGAgglomerationConstructorTable(type);
362 
363  if (!ctorPtr)
364  {
366  << "Unknown GAMGProcAgglomeration type "
367  << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
368  << "Valid GAMGProcAgglomeration types :" << endl
369  << GAMGAgglomerationConstructorTablePtr_->sortedToc()
370  << exit(FatalError);
371  }
373  return autoPtr<GAMGProcAgglomeration>(ctorPtr(agglom, controlDict));
374 }
375 
376 
377 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
378 
380 {
381  clearCommunicators();
382 }
383 
384 
385 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
386 
388 {
389  forAllReverse(comms_, i)
390  {
391  UPstream::freeCommunicator(comms_[i]);
392  }
393  comms_.clear();
394 }
395 
396 
397 // ************************************************************************* //
InfoProxy< lduMesh > info() const noexcept
Return info proxy, used to print mesh information to a stream.
Definition: lduMesh.H:116
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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:608
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
static void freeCommunicator(const label communicator, const bool withComponents=true)
Free a previously allocated communicator.
Definition: UPstream.C:567
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)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
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:1061
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:312
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
void printStats(Ostream &os, GAMGAgglomeration &agglom) const
Debug: write agglomeration info.
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1561
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
PtrList< labelList > agglomProcIDs_
Per level the set of processors to agglomerate. Element 0 is.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static autoPtr< GAMGProcAgglomeration > New(const word &type, GAMGAgglomeration &agglom, const dictionary &controlDict)
Return the selected agglomerator.
labelList procCommunicator_
Communicator for given level.
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
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:415
dynamicFvMesh & mesh
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 clearCommunicators()
Clear/free allocated communicators.
A class for handling words, derived from Foam::string.
Definition: word.H:63
#define DebugInFunction
Report an information message using Foam::Info.
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
Definition: fvMesh.C:752
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
GAMGProcAgglomeration(const GAMGProcAgglomeration &)=delete
No copy construct.
runTime controlDict().readEntry("adjustTimeStep"
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
PtrList< labelField > restrictAddressing_
Cell restriction addressing array.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
label nFaces(const label leveli) const
Return number of coarse faces (before processor agglomeration)
static labelListList globalCellCells(const lduMesh &)
Debug: calculate global cell-cells.
virtual bool agglomerate()=0
Modify agglomeration.
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.C:769
Processor agglomeration of GAMGAgglomerations.
PtrList< labelList > procAgglomMap_
Per level, per processor the processor it agglomerates into.
const labelField & restrictAddressing(const label leveli) const
Return cell restrict addressing of given level.
virtual ~GAMGProcAgglomeration()
Destructor. Clears allocated communicators.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:437
List< label > labelList
A List of labels.
Definition: List.H:62
const labelListList & patchFaceRestrictAddressing(const label leveli) const
Geometric agglomerated algebraic multigrid agglomeration class.
bool hasMeshLevel(const label leveli) const
Do we have mesh for given level?
label nCells(const label leveli) const
Return number of coarse cells (before processor agglomeration)
Namespace for OpenFOAM.