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 myProcID = UPstream::myProcNo(mesh.comm());
131 
132  const globalIndex globalNumbering
133  (
134  addr.size(),
135  mesh.comm(),
137  );
138 
139  const labelList globalIndices
140  (
141  identity
142  (
143  globalNumbering.localSize(myProcID),
144  globalNumbering.localStart(myProcID)
145  )
146  );
147 
148  // Get the interface cells
149  PtrList<labelList> nbrGlobalCells(interfaces.size());
150  {
151  const label startOfRequests = UPstream::nRequests();
152 
153  // Initialise transfer of restrict addressing on the interface
154  forAll(interfaces, inti)
155  {
156  if (interfaces.set(inti))
157  {
158  interfaces[inti].initInternalFieldTransfer
159  (
161  globalIndices
162  );
163  }
164  }
165 
166  UPstream::waitRequests(startOfRequests);
167 
168  forAll(interfaces, inti)
169  {
170  if (interfaces.set(inti))
171  {
172  nbrGlobalCells.set
173  (
174  inti,
175  new labelList
176  (
177  interfaces[inti].internalFieldTransfer
178  (
180  globalIndices
181  )
182  )
183  );
184  }
185  }
186  }
187 
188 
189  // Scan the neighbour list to find out how many times the cell
190  // appears as a neighbour of the face. Done this way to avoid guessing
191  // and resizing list
192  labelList nNbrs(addr.size(), 1);
193 
194  const labelUList& nbr = addr.upperAddr();
195  const labelUList& own = addr.lowerAddr();
196 
197  {
198  forAll(nbr, facei)
199  {
200  nNbrs[nbr[facei]]++;
201  nNbrs[own[facei]]++;
202  }
203 
204  forAll(interfaces, inti)
205  {
206  if (interfaces.set(inti))
207  {
208  const labelUList& faceCells = interfaces[inti].faceCells();
209 
210  forAll(faceCells, i)
211  {
212  nNbrs[faceCells[i]]++;
213  }
214  }
215  }
216  }
217 
218 
219  // Create cell-cells addressing
220  labelListList cellCells(addr.size());
221 
222  forAll(cellCells, celli)
223  {
224  cellCells[celli].setSize(nNbrs[celli], -1);
225  }
226 
227  // Reset the list of number of neighbours to zero
228  nNbrs = 0;
229 
230  // Scatter the neighbour faces
231  forAll(nbr, facei)
232  {
233  label c0 = own[facei];
234  label c1 = nbr[facei];
235 
236  cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
237  cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
238  }
239  forAll(interfaces, inti)
240  {
241  if (interfaces.set(inti))
242  {
243  const labelUList& faceCells = interfaces[inti].faceCells();
244 
245  forAll(faceCells, i)
246  {
247  label c0 = faceCells[i];
248  cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
249  }
250  }
251  }
252 
253  forAll(cellCells, celli)
254  {
255  Foam::stableSort(cellCells[celli]);
256  }
257 
258  // Replace the initial element (always -1) with the local cell
259  forAll(cellCells, celli)
260  {
261  cellCells[celli][0] = globalIndices[celli];
262  }
263 
264  return cellCells;
265 }
266 
267 
269 (
270  const label fineLevelIndex,
271  const labelList& procAgglomMap,
272  const labelList& masterProcs,
273  const List<label>& agglomProcIDs,
274  const label procAgglomComm
275 )
276 {
277  const lduMesh& levelMesh = agglom_.meshLevels_[fineLevelIndex];
278  label levelComm = levelMesh.comm();
279 
280  if (fineLevelIndex > 0 && Pstream::myProcNo(levelComm) != -1)
281  {
282  // Collect meshes and restrictAddressing onto master
283  // Overwrites the fine mesh (meshLevels_[index-1]) and addressing
284  // from fine mesh to coarse mesh (restrictAddressing_[index]).
285  agglom_.procAgglomerateLduAddressing
286  (
287  levelComm,
288  procAgglomMap,
289  agglomProcIDs,
290  procAgglomComm,
291 
292  fineLevelIndex //fine level index
293  );
294 
295  // Combine restrict addressing only onto master
296  for
297  (
298  label levelI = fineLevelIndex+1;
299  levelI < agglom_.meshLevels_.size();
300  levelI++
301  )
302  {
303  agglom_.procAgglomerateRestrictAddressing
304  (
305  levelComm,
306  agglomProcIDs,
307  levelI
308  );
309  }
310 
311  if (Pstream::myProcNo(levelComm) == agglomProcIDs[0])
312  {
313  // On master. Recreate coarse meshes from restrict addressing
314  for
315  (
316  label levelI = fineLevelIndex;
317  levelI < agglom_.meshLevels_.size();
318  levelI++
319  )
320  {
321  agglom_.agglomerateLduAddressing(levelI);
322  }
323  }
324  else
325  {
326  // Agglomerated away. Clear mesh storage.
327  for
328  (
329  label levelI = fineLevelIndex+1;
330  levelI <= agglom_.size();
331  levelI++
332  )
333  {
334  agglom_.clearLevel(levelI);
335  }
336  }
337  }
338 
339  // Should check!
340  return true;
341 }
342 
343 
344 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
345 
347 (
348  GAMGAgglomeration& agglom,
349  const dictionary& controlDict
350 )
351 :
352  agglom_(agglom)
353 {}
354 
355 
357 (
358  const word& type,
359  GAMGAgglomeration& agglom,
360  const dictionary& controlDict
361 )
362 {
363  DebugInFunction << "Constructing GAMGProcAgglomeration" << endl;
364 
365  auto* ctorPtr = GAMGAgglomerationConstructorTable(type);
366 
367  if (!ctorPtr)
368  {
370  << "Unknown GAMGProcAgglomeration type "
371  << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
372  << "Valid GAMGProcAgglomeration types :" << endl
373  << GAMGAgglomerationConstructorTablePtr_->sortedToc()
374  << exit(FatalError);
375  }
377  return autoPtr<GAMGProcAgglomeration>(ctorPtr(agglom, controlDict));
378 }
379 
380 
381 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
382 
384 {
385  clearCommunicators();
386 }
387 
388 
389 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
390 
392 {
393  forAllReverse(comms_, i)
394  {
395  UPstream::freeCommunicator(comms_[i]);
396  }
397  comms_.clear();
398 }
399 
400 
401 // ************************************************************************* //
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:598
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:565
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:1049
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:1074
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:1538
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:741
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:758
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" : (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.