GAMGProcAgglomeration.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2013-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "GAMGProcAgglomeration.H"
27 #include "GAMGAgglomeration.H"
28 #include "lduMesh.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
36 }
37 
38 
39 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
40 
42 (
43  Ostream& os,
44  GAMGAgglomeration& agglom
45 ) const
46 {
47  for (label levelI = 0; levelI <= agglom.size(); levelI++)
48  {
49  if (agglom.hasMeshLevel(levelI))
50  {
51  os << agglom.meshLevel(levelI).info() << endl;
52  }
53  else
54  {
55  os << "Level " << levelI << " has no fine mesh:" << endl;
56  }
57 
58  if
59  (
60  levelI < agglom.restrictAddressing_.size()
61  && agglom.restrictAddressing_.set(levelI)
62  )
63  {
64  const labelList& cellRestrict =
65  agglom.restrictAddressing(levelI);
66  const labelList& faceRestrict =
67  agglom.faceRestrictAddressing(levelI);
68 
69  os << "Level " << levelI << " agglomeration:" << nl
70  << " nCoarseCells:" << agglom.nCells(levelI) << nl
71  << " nCoarseFaces:" << agglom.nFaces(levelI) << nl
72  << " cellRestriction:"
73  << " size:" << cellRestrict.size()
74  << " max:" << max(cellRestrict)
75  << nl
76  << " faceRestriction:"
77  << " size:" << faceRestrict.size()
78  << " max:" << max(faceRestrict)
79  << nl;
80 
81  const labelListList& patchFaceRestrict =
82  agglom.patchFaceRestrictAddressing(levelI);
83  forAll(patchFaceRestrict, i)
84  {
85  if (patchFaceRestrict[i].size())
86  {
87  const labelList& faceRestrict =
88  patchFaceRestrict[i];
89  os << " " << i
90  << " size:" << faceRestrict.size()
91  << " max:" << max(faceRestrict)
92  << nl;
93  }
94  }
95  }
96  if
97  (
98  levelI < agglom.procCellOffsets_.size()
99  && agglom.procCellOffsets_.set(levelI)
100  )
101  {
102  os << " procCellOffsets:" << agglom.procCellOffsets_[levelI]
103  << nl
104  << " procAgglomMap:" << agglom.procAgglomMap_[levelI]
105  << nl
106  << " procIDs:" << agglom.agglomProcIndices_[levelI]
107  << nl
108  << " comm:" << agglom.procCommunicator_[levelI]
109  << endl;
110  }
111 
112  os << endl;
113  }
114  os << endl;
115 }
116 
117 
119 (
120  const lduMesh& mesh
121 )
122 {
123  const lduAddressing& addr = mesh.lduAddr();
124  lduInterfacePtrsList interfaces = mesh.interfaces();
125 
126  const label myProcID = Pstream::myProcNo(mesh.comm());
127 
128  globalIndex globalNumbering
129  (
130  addr.size(),
132  mesh.comm(),
134  );
135 
136  labelList globalIndices(addr.size());
137  forAll(globalIndices, celli)
138  {
139  globalIndices[celli] = globalNumbering.toGlobal(myProcID, celli);
140  }
141 
142 
143  // Get the interface cells
144  PtrList<labelList> nbrGlobalCells(interfaces.size());
145  {
146  // Initialise transfer of restrict addressing on the interface
147  forAll(interfaces, inti)
148  {
149  if (interfaces.set(inti))
150  {
151  interfaces[inti].initInternalFieldTransfer
152  (
154  globalIndices
155  );
156  }
157  }
158 
159  if (Pstream::parRun())
160  {
162  }
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 (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  if (debug)
360  {
361  InfoInFunction << "Constructing GAMGProcAgglomeration" << endl;
362  }
363 
364  GAMGAgglomerationConstructorTable::iterator cstrIter =
365  GAMGAgglomerationConstructorTablePtr_->find(type);
366 
367  if (cstrIter == GAMGAgglomerationConstructorTablePtr_->end())
368  {
370  << "Unknown GAMGProcAgglomeration type "
371  << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
372  << "Valid GAMGProcAgglomeration types are :" << endl
373  << GAMGAgglomerationConstructorTablePtr_->sortedToc()
374  << exit(FatalError);
375  }
376 
377  return autoPtr<GAMGProcAgglomeration>(cstrIter()(agglom, controlDict));
378 }
379 
380 
381 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
382 
384 {}
385 
386 
387 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
virtual const word & type() const
Runtime type information.
Geometric agglomerated algebraic multigrid agglomeration class.
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
PtrList< labelList > agglomProcIndices_
Per level the set of processors to agglomerate. Element 0 is.
const labelListList & patchFaceRestrictAddressing(const label leveli) const
labelList procCommunicator_
Communicator for given level.
PtrList< labelList > procAgglomMap_
Per level, per processor the processor it agglomerates into.
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
PtrList< labelField > restrictAddressing_
Cell restriction addressing array.
const labelField & restrictAddressing(const label leveli) const
Return cell restrict addressing of given level.
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)
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
label nFaces(const label leveli) const
Return number of coarse faces (before processor agglomeration)
Processor agglomeration of GAMGAgglomerations.
virtual bool agglomerate()=0
Modify agglomeration. Return true if modified.
static autoPtr< GAMGProcAgglomeration > New(const word &type, GAMGAgglomeration &agglom, const dictionary &controlDict)
Return the selected agglomerator.
void printStats(Ostream &os, GAMGAgglomeration &agglom) const
Debug: write agglomeration info.
static labelListList globalCellCells(const lduMesh &)
Debug: calculate global cell-cells.
virtual ~GAMGProcAgglomeration()
Destructor.
GAMGProcAgglomeration(GAMGAgglomeration &agglom, const dictionary &controlDict)
Construct given agglomerator and controls.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
bool set(const label) const
Is element set.
Definition: PtrListI.H:62
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:147
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
bool set(const label) const
Is element set.
Definition: UPtrListI.H:87
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
The class contains the addressing required by the lduMatrix: upper, lower and losort.
label size() const
Return number of equations.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:60
virtual label comm() const =0
Return communicator used for parallel communication.
InfoProxy< lduMesh > info() const
Return info proxy.
Definition: lduMesh.H:105
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
#define InfoInFunction
Report an information message using Foam::Info.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m^2].
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError
void stableSort(UList< T > &)
Definition: UList.C:129
static const char nl
Definition: Ostream.H:266
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep