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-2022 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 << agglom.meshLevel(levelI).info() << endl;
55  }
56  else
57  {
58  os << "Level " << levelI << " has no fine mesh:" << endl;
59  }
60 
61  if
62  (
63  levelI < agglom.restrictAddressing_.size()
64  && agglom.restrictAddressing_.set(levelI)
65  )
66  {
67  const labelList& cellRestrict =
68  agglom.restrictAddressing(levelI);
69  const labelList& faceRestrict =
70  agglom.faceRestrictAddressing(levelI);
71 
72  os << "Level " << levelI << " agglomeration:" << nl
73  << " nCoarseCells:" << agglom.nCells(levelI) << nl
74  << " nCoarseFaces:" << agglom.nFaces(levelI) << nl
75  << " cellRestriction:"
76  << " size:" << cellRestrict.size()
77  << " max:" << max(cellRestrict)
78  << nl
79  << " faceRestriction:"
80  << " size:" << faceRestrict.size()
81  << " max:" << max(faceRestrict)
82  << nl;
83 
84  const labelListList& patchFaceRestrict =
85  agglom.patchFaceRestrictAddressing(levelI);
86  forAll(patchFaceRestrict, i)
87  {
88  if (patchFaceRestrict[i].size())
89  {
90  const labelList& faceRestrict =
91  patchFaceRestrict[i];
92  os << " " << i
93  << " size:" << faceRestrict.size()
94  << " max:" << max(faceRestrict)
95  << nl;
96  }
97  }
98  }
99  if
100  (
101  levelI < agglom.procCellOffsets_.size()
102  && agglom.procCellOffsets_.set(levelI)
103  )
104  {
105  os << " procCellOffsets:" << agglom.procCellOffsets_[levelI]
106  << nl
107  << " procAgglomMap:" << agglom.procAgglomMap_[levelI]
108  << nl
109  << " procIDs:" << agglom.agglomProcIDs_[levelI]
110  << nl
111  << " comm:" << agglom.procCommunicator_[levelI]
112  << endl;
113  }
114 
115  os << endl;
116  }
117  os << endl;
118 }
119 
120 
122 (
123  const lduMesh& mesh
124 )
125 {
126  const lduAddressing& addr = mesh.lduAddr();
127  lduInterfacePtrsList interfaces = mesh.interfaces();
128 
129  const label myProcID = UPstream::myProcNo(mesh.comm());
130 
131  const globalIndex globalNumbering
132  (
133  addr.size(),
134  mesh.comm(),
136  );
137 
138  const labelList globalIndices
139  (
140  identity
141  (
142  globalNumbering.localSize(myProcID),
143  globalNumbering.localStart(myProcID)
144  )
145  );
146 
147  // Get the interface cells
148  PtrList<labelList> nbrGlobalCells(interfaces.size());
149  {
150  const label startOfRequests = UPstream::nRequests();
151 
152  // Initialise transfer of restrict addressing on the interface
153  forAll(interfaces, inti)
154  {
155  if (interfaces.set(inti))
156  {
157  interfaces[inti].initInternalFieldTransfer
158  (
160  globalIndices
161  );
162  }
163  }
164 
165  UPstream::waitRequests(startOfRequests);
166 
167  forAll(interfaces, inti)
168  {
169  if (interfaces.set(inti))
170  {
171  nbrGlobalCells.set
172  (
173  inti,
174  new labelList
175  (
176  interfaces[inti].internalFieldTransfer
177  (
179  globalIndices
180  )
181  )
182  );
183  }
184  }
185  }
186 
187 
188  // Scan the neighbour list to find out how many times the cell
189  // appears as a neighbour of the face. Done this way to avoid guessing
190  // and resizing list
191  labelList nNbrs(addr.size(), 1);
192 
193  const labelUList& nbr = addr.upperAddr();
194  const labelUList& own = addr.lowerAddr();
195 
196  {
197  forAll(nbr, facei)
198  {
199  nNbrs[nbr[facei]]++;
200  nNbrs[own[facei]]++;
201  }
202 
203  forAll(interfaces, inti)
204  {
205  if (interfaces.set(inti))
206  {
207  const labelUList& faceCells = interfaces[inti].faceCells();
208 
209  forAll(faceCells, i)
210  {
211  nNbrs[faceCells[i]]++;
212  }
213  }
214  }
215  }
216 
217 
218  // Create cell-cells addressing
219  labelListList cellCells(addr.size());
220 
221  forAll(cellCells, celli)
222  {
223  cellCells[celli].setSize(nNbrs[celli], -1);
224  }
225 
226  // Reset the list of number of neighbours to zero
227  nNbrs = 0;
228 
229  // Scatter the neighbour faces
230  forAll(nbr, facei)
231  {
232  label c0 = own[facei];
233  label c1 = nbr[facei];
234 
235  cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
236  cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
237  }
238  forAll(interfaces, inti)
239  {
240  if (interfaces.set(inti))
241  {
242  const labelUList& faceCells = interfaces[inti].faceCells();
243 
244  forAll(faceCells, i)
245  {
246  label c0 = faceCells[i];
247  cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
248  }
249  }
250  }
251 
252  forAll(cellCells, celli)
253  {
254  Foam::stableSort(cellCells[celli]);
255  }
256 
257  // Replace the initial element (always -1) with the local cell
258  forAll(cellCells, celli)
259  {
260  cellCells[celli][0] = globalIndices[celli];
261  }
262 
263  return cellCells;
264 }
265 
266 
268 (
269  const label fineLevelIndex,
270  const labelList& procAgglomMap,
271  const labelList& masterProcs,
272  const List<label>& agglomProcIDs,
273  const label procAgglomComm
274 )
275 {
276  const lduMesh& levelMesh = agglom_.meshLevels_[fineLevelIndex];
277  label levelComm = levelMesh.comm();
278 
279  if (fineLevelIndex > 0 && Pstream::myProcNo(levelComm) != -1)
280  {
281  // Collect meshes and restrictAddressing onto master
282  // Overwrites the fine mesh (meshLevels_[index-1]) and addressing
283  // from fine mesh to coarse mesh (restrictAddressing_[index]).
284  agglom_.procAgglomerateLduAddressing
285  (
286  levelComm,
287  procAgglomMap,
288  agglomProcIDs,
289  procAgglomComm,
290 
291  fineLevelIndex //fine level index
292  );
293 
294  // Combine restrict addressing only onto master
295  for
296  (
297  label levelI = fineLevelIndex+1;
298  levelI < agglom_.meshLevels_.size();
299  levelI++
300  )
301  {
302  agglom_.procAgglomerateRestrictAddressing
303  (
304  levelComm,
305  agglomProcIDs,
306  levelI
307  );
308  }
309 
310  if (Pstream::myProcNo(levelComm) == agglomProcIDs[0])
311  {
312  // On master. Recreate coarse meshes from restrict addressing
313  for
314  (
315  label levelI = fineLevelIndex;
316  levelI < agglom_.meshLevels_.size();
317  levelI++
318  )
319  {
320  agglom_.agglomerateLduAddressing(levelI);
321  }
322  }
323  else
324  {
325  // Agglomerated away. Clear mesh storage.
326  for
327  (
328  label levelI = fineLevelIndex+1;
329  levelI <= agglom_.size();
330  levelI++
331  )
332  {
333  agglom_.clearLevel(levelI);
334  }
335  }
336  }
337 
338  // Should check!
339  return true;
340 }
341 
342 
343 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
344 
345 Foam::GAMGProcAgglomeration::GAMGProcAgglomeration
346 (
347  GAMGAgglomeration& agglom,
348  const dictionary& controlDict
349 )
350 :
351  agglom_(agglom)
352 {}
353 
354 
356 (
357  const word& type,
358  GAMGAgglomeration& agglom,
359  const dictionary& controlDict
360 )
361 {
362  DebugInFunction << "Constructing GAMGProcAgglomeration" << endl;
363 
364  auto* ctorPtr = GAMGAgglomerationConstructorTable(type);
365 
366  if (!ctorPtr)
367  {
369  << "Unknown GAMGProcAgglomeration type "
370  << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
371  << "Valid GAMGProcAgglomeration types :" << endl
372  << GAMGAgglomerationConstructorTablePtr_->sortedToc()
373  << exit(FatalError);
374  }
376  return autoPtr<GAMGProcAgglomeration>(ctorPtr(agglom, controlDict));
377 }
378 
379 
380 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
381 
383 {}
384 
385 
386 // ************************************************************************* //
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
InfoProxy< lduMesh > info() const
Return info proxy.
Definition: lduMesh.H:117
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
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.
Definition: UPstream.C:83
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:639
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:348
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
void printStats(Ostream &os, GAMGAgglomeration &agglom) const
Debug: write agglomeration info.
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
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:413
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:752
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:413
dynamicFvMesh & mesh
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
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:711
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
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:55
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 void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:93
static labelListList globalCellCells(const lduMesh &)
Debug: calculate global cell-cells.
virtual bool agglomerate()=0
Modify agglomeration. Return true if modified.
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.C:728
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.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
"nonBlocking" : (MPI_Isend, MPI_Irecv)
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.