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:"
107  << flatOutput(agglom.procCellOffsets_[levelI])
108  << nl
109  << " procAgglomMap:"
110  << flatOutput(agglom.procAgglomMap_[levelI])
111  << nl
112  << " procIDs:" << flatOutput(agglom.agglomProcIDs_[levelI])
113  << nl
114  << " comm:" << agglom.procCommunicator_[levelI]
115  << endl;
116  }
117 
118  os << endl;
119  }
120  os << endl;
121 }
122 
123 
125 (
126  const lduMesh& mesh
127 )
128 {
129  const lduAddressing& addr = mesh.lduAddr();
130  lduInterfacePtrsList interfaces = mesh.interfaces();
131 
132  const label myProci = UPstream::myProcNo(mesh.comm());
133 
134  const globalIndex globalNumbering
135  (
136  addr.size(),
137  mesh.comm(),
139  );
140 
141  const labelList globalIndices
142  (
143  Foam::identity(globalNumbering.range(myProci))
144  );
145 
146  // Get the interface cells
147  PtrList<labelList> nbrGlobalCells(interfaces.size());
148  {
149  const label startOfRequests = UPstream::nRequests();
150 
151  // Initialise transfer of restrict addressing on the interface
152  forAll(interfaces, inti)
153  {
154  if (interfaces.set(inti))
155  {
156  interfaces[inti].initInternalFieldTransfer
157  (
159  globalIndices
160  );
161  }
162  }
163 
164  UPstream::waitRequests(startOfRequests);
165 
166  forAll(interfaces, inti)
167  {
168  if (interfaces.set(inti))
169  {
170  nbrGlobalCells.set
171  (
172  inti,
173  new labelList
174  (
175  interfaces[inti].internalFieldTransfer
176  (
178  globalIndices
179  )
180  )
181  );
182  }
183  }
184  }
185 
186 
187  // Scan the neighbour list to find out how many times the cell
188  // appears as a neighbour of the face. Done this way to avoid guessing
189  // and resizing list
190  labelList nNbrs(addr.size(), 1);
191 
192  const labelUList& nbr = addr.upperAddr();
193  const labelUList& own = addr.lowerAddr();
194 
195  {
196  forAll(nbr, facei)
197  {
198  nNbrs[nbr[facei]]++;
199  nNbrs[own[facei]]++;
200  }
201 
202  forAll(interfaces, inti)
203  {
204  if (interfaces.set(inti))
205  {
206  const labelUList& faceCells = interfaces[inti].faceCells();
207 
208  forAll(faceCells, i)
209  {
210  nNbrs[faceCells[i]]++;
211  }
212  }
213  }
214  }
215 
216 
217  // Create cell-cells addressing
218  labelListList cellCells(addr.size());
219 
220  forAll(cellCells, celli)
221  {
222  cellCells[celli].setSize(nNbrs[celli], -1);
223  }
224 
225  // Reset the list of number of neighbours to zero
226  nNbrs = 0;
227 
228  // Scatter the neighbour faces
229  forAll(nbr, facei)
230  {
231  label c0 = own[facei];
232  label c1 = nbr[facei];
233 
234  cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
235  cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
236  }
237  forAll(interfaces, inti)
238  {
239  if (interfaces.set(inti))
240  {
241  const labelUList& faceCells = interfaces[inti].faceCells();
242 
243  forAll(faceCells, i)
244  {
245  label c0 = faceCells[i];
246  cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
247  }
248  }
249  }
250 
251  forAll(cellCells, celli)
252  {
253  Foam::stableSort(cellCells[celli]);
254  }
255 
256  // Replace the initial element (always -1) with the local cell
257  forAll(cellCells, celli)
258  {
259  cellCells[celli][0] = globalIndices[celli];
260  }
261 
262  return cellCells;
263 }
264 
265 
267 (
268  const label fineLevelIndex,
269  const labelList& procAgglomMap,
270  const labelList& masterProcs,
271  const List<label>& agglomProcIDs,
272  const label procAgglomComm
273 )
274 {
275  const lduMesh& levelMesh = agglom_.meshLevels_[fineLevelIndex];
276  label levelComm = levelMesh.comm();
277 
278  if (fineLevelIndex > 0 && Pstream::myProcNo(levelComm) != -1)
279  {
280  // Collect meshes and restrictAddressing onto master
281  // Overwrites the fine mesh (meshLevels_[index-1]) and addressing
282  // from fine mesh to coarse mesh (restrictAddressing_[index]).
283  agglom_.procAgglomerateLduAddressing
284  (
285  levelComm,
286  procAgglomMap,
287  agglomProcIDs,
288  procAgglomComm,
289 
290  fineLevelIndex //fine level index
291  );
292 
293  // Combine restrict addressing only onto master
294  for
295  (
296  label levelI = fineLevelIndex+1;
297  levelI < agglom_.meshLevels_.size();
298  levelI++
299  )
300  {
301  agglom_.procAgglomerateRestrictAddressing
302  (
303  levelComm,
304  agglomProcIDs,
305  levelI
306  );
307  }
308 
309  if (Pstream::myProcNo(levelComm) == agglomProcIDs[0])
310  {
311  // On master. Recreate coarse meshes from restrict addressing
312  for
313  (
314  label levelI = fineLevelIndex;
315  levelI < agglom_.meshLevels_.size();
316  levelI++
317  )
318  {
319  agglom_.agglomerateLduAddressing(levelI);
320  }
321  }
322  else
323  {
324  // Agglomerated away. Clear mesh storage.
325  for
326  (
327  label levelI = fineLevelIndex+1;
328  levelI <= agglom_.size();
329  levelI++
330  )
331  {
332  agglom_.clearLevel(levelI);
333  }
334  }
335  }
336 
337  // Should check!
338  return true;
339 }
340 
341 
342 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
343 
345 (
346  GAMGAgglomeration& agglom,
347  const dictionary& controlDict
348 )
349 :
350  agglom_(agglom)
351 {}
352 
353 
355 (
356  const word& type,
357  GAMGAgglomeration& agglom,
358  const dictionary& controlDict
359 )
360 {
361  DebugInFunction << "Constructing GAMGProcAgglomeration" << endl;
362 
363  auto* ctorPtr = GAMGAgglomerationConstructorTable(type);
364 
365  if (!ctorPtr)
366  {
368  << "Unknown GAMGProcAgglomeration type "
369  << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
370  << "Valid GAMGProcAgglomeration types :" << endl
371  << GAMGAgglomerationConstructorTablePtr_->sortedToc()
372  << exit(FatalError);
373  }
375  return autoPtr<GAMGProcAgglomeration>(ctorPtr(agglom, controlDict));
376 }
377 
378 
379 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
380 
382 {
383  clearCommunicators();
384 }
385 
386 
387 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
388 
390 {
391  forAllReverse(comms_, i)
392  {
393  UPstream::freeCommunicator(comms_[i]);
394  }
395  comms_.clear();
396 }
397 
398 
399 // ************************************************************************* //
InfoProxy< lduMesh > info() const noexcept
Return info proxy, used to print mesh information to a stream.
Definition: lduMesh.H:115
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:130
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
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:622
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:518
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1774
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1799
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:299
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:2619
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
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:400
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:805
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:415
dynamicFvMesh & mesh
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:707
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)
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:724
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:416
List< label > labelList
A List of labels.
Definition: List.H:61
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.
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...
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:217