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-2018 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 {
34  defineTypeNameAndDebug(GAMGProcAgglomeration, 0);
35  defineRunTimeSelectionTable(GAMGProcAgglomeration, GAMGAgglomeration);
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.agglomProcIDs_[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 // ************************************************************************* //
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch.
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
InfoProxy< lduMesh > info() const
Return info proxy.
Definition: lduMesh.H:105
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:59
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
virtual label comm() const =0
Return communicator used for parallel communication.
void printStats(Ostream &os, GAMGAgglomeration &agglom) const
Debug: write agglomeration info.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
PtrList< labelList > agglomProcIDs_
Per level the set of processors to agglomerate. Element 0 is.
static autoPtr< GAMGProcAgglomeration > New(const word &type, GAMGAgglomeration &agglom, const dictionary &controlDict)
Return the selected agglomerator.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m^2].
labelList procCommunicator_
Communicator for given level.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
A class for handling words, derived from string.
Definition: word.H:59
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
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:54
static const char nl
Definition: Ostream.H:260
bool set(const label) const
Is element set.
Definition: UPtrListI.H:78
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
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:147
static labelListList globalCellCells(const lduMesh &)
Debug: calculate global cell-cells.
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
virtual bool agglomerate()=0
Modify agglomeration. Return true if modified.
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:70
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.
The class contains the addressing required by the lduMatrix: upper, lower and losort.
const labelListList & patchFaceRestrictAddressing(const label leveli) const
void stableSort(UList< T > &)
Definition: UList.C:129
GAMGProcAgglomeration(GAMGAgglomeration &agglom, const dictionary &controlDict)
Construct given agglomerator and controls.
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.
label size() const
Return number of equations.
#define InfoInFunction
Report an information message using Foam::Info.