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-------------------------------------------------------------------------------
11License
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
30#include "GAMGAgglomeration.H"
31#include "lduMesh.H"
32
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
35namespace Foam
36{
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 (
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 nReq = Pstream::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 if (UPstream::parRun())
166 {
168 }
169
170 forAll(interfaces, inti)
171 {
172 if (interfaces.set(inti))
173 {
174 nbrGlobalCells.set
175 (
176 inti,
177 new labelList
178 (
179 interfaces[inti].internalFieldTransfer
180 (
182 globalIndices
183 )
184 )
185 );
186 }
187 }
188 }
189
190
191 // Scan the neighbour list to find out how many times the cell
192 // appears as a neighbour of the face. Done this way to avoid guessing
193 // and resizing list
194 labelList nNbrs(addr.size(), 1);
195
196 const labelUList& nbr = addr.upperAddr();
197 const labelUList& own = addr.lowerAddr();
198
199 {
200 forAll(nbr, facei)
201 {
202 nNbrs[nbr[facei]]++;
203 nNbrs[own[facei]]++;
204 }
205
206 forAll(interfaces, inti)
207 {
208 if (interfaces.set(inti))
209 {
210 const labelUList& faceCells = interfaces[inti].faceCells();
211
212 forAll(faceCells, i)
213 {
214 nNbrs[faceCells[i]]++;
215 }
216 }
217 }
218 }
219
220
221 // Create cell-cells addressing
222 labelListList cellCells(addr.size());
223
224 forAll(cellCells, celli)
225 {
226 cellCells[celli].setSize(nNbrs[celli], -1);
227 }
228
229 // Reset the list of number of neighbours to zero
230 nNbrs = 0;
231
232 // Scatter the neighbour faces
233 forAll(nbr, facei)
234 {
235 label c0 = own[facei];
236 label c1 = nbr[facei];
237
238 cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
239 cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
240 }
241 forAll(interfaces, inti)
242 {
243 if (interfaces.set(inti))
244 {
245 const labelUList& faceCells = interfaces[inti].faceCells();
246
247 forAll(faceCells, i)
248 {
249 label c0 = faceCells[i];
250 cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
251 }
252 }
253 }
254
255 forAll(cellCells, celli)
256 {
257 Foam::stableSort(cellCells[celli]);
258 }
259
260 // Replace the initial element (always -1) with the local cell
261 forAll(cellCells, celli)
262 {
263 cellCells[celli][0] = globalIndices[celli];
264 }
265
266 return cellCells;
267}
268
269
271(
272 const label fineLevelIndex,
273 const labelList& procAgglomMap,
274 const labelList& masterProcs,
275 const List<label>& agglomProcIDs,
276 const label procAgglomComm
277)
278{
279 const lduMesh& levelMesh = agglom_.meshLevels_[fineLevelIndex];
280 label levelComm = levelMesh.comm();
281
282 if (fineLevelIndex > 0 && Pstream::myProcNo(levelComm) != -1)
283 {
284 // Collect meshes and restrictAddressing onto master
285 // Overwrites the fine mesh (meshLevels_[index-1]) and addressing
286 // from fine mesh to coarse mesh (restrictAddressing_[index]).
287 agglom_.procAgglomerateLduAddressing
288 (
289 levelComm,
290 procAgglomMap,
291 agglomProcIDs,
292 procAgglomComm,
293
294 fineLevelIndex //fine level index
295 );
296
297 // Combine restrict addressing only onto master
298 for
299 (
300 label levelI = fineLevelIndex+1;
301 levelI < agglom_.meshLevels_.size();
302 levelI++
303 )
304 {
305 agglom_.procAgglomerateRestrictAddressing
306 (
307 levelComm,
308 agglomProcIDs,
309 levelI
310 );
311 }
312
313 if (Pstream::myProcNo(levelComm) == agglomProcIDs[0])
314 {
315 // On master. Recreate coarse meshes from restrict addressing
316 for
317 (
318 label levelI = fineLevelIndex;
319 levelI < agglom_.meshLevels_.size();
320 levelI++
321 )
322 {
323 agglom_.agglomerateLduAddressing(levelI);
324 }
325 }
326 else
327 {
328 // Agglomerated away. Clear mesh storage.
329 for
330 (
331 label levelI = fineLevelIndex+1;
332 levelI <= agglom_.size();
333 levelI++
334 )
335 {
336 agglom_.clearLevel(levelI);
337 }
338 }
339 }
340
341 // Should check!
342 return true;
343}
344
345
346// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
347
349(
350 GAMGAgglomeration& agglom,
352)
353:
354 agglom_(agglom)
355{}
356
357
359(
360 const word& type,
361 GAMGAgglomeration& agglom,
363)
364{
365 DebugInFunction << "Constructing GAMGProcAgglomeration" << endl;
366
367 auto* ctorPtr = GAMGAgglomerationConstructorTable(type);
368
369 if (!ctorPtr)
370 {
372 << "Unknown GAMGProcAgglomeration type "
373 << type << " for GAMGAgglomeration " << agglom.type() << nl << nl
374 << "Valid GAMGProcAgglomeration types :" << endl
375 << GAMGAgglomerationConstructorTablePtr_->sortedToc()
376 << exit(FatalError);
377 }
378
379 return autoPtr<GAMGProcAgglomeration>(ctorPtr(agglom, controlDict));
380}
381
382
383// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
384
386{}
387
388
389// ************************************************************************* //
Geometric agglomerated algebraic multigrid agglomeration class.
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
const labelListList & patchFaceRestrictAddressing(const label leveli) const
labelList procCommunicator_
Communicator for given level.
PtrList< labelList > agglomProcIDs_
Per level the set of processors to agglomerate. Element 0 is.
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.
void printStats(Ostream &os, GAMGAgglomeration &agglom) const
Debug: write agglomeration info.
static labelListList globalCellCells(const lduMesh &)
Debug: calculate global cell-cells.
virtual ~GAMGProcAgglomeration()
Destructor.
void setSize(const label n)
Alias for resize()
Definition: List.H:218
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
@ nonBlocking
"nonBlocking"
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:100
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
const T * set(const label i) const
Definition: UPtrList.H:248
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:59
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.C:735
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
Definition: fvMesh.C:718
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:326
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
label localSize() const
My local size.
Definition: globalIndexI.H:207
label localStart() const
My local start.
Definition: globalIndexI.H:195
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
label size() const
Return number of equations.
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:63
virtual label comm() const =0
Return communicator used for parallel communication.
InfoProxy< lduMesh > info() const
Return info proxy.
Definition: lduMesh.H:110
int myProcNo() const noexcept
Return processor number.
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
runTime controlDict().readEntry("adjustTimeStep"
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
#define DebugInFunction
Report an information message using Foam::Info.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:356
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333