faceAreaPairGAMGAgglomeration.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2023-2024 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 
30 #include "fvMesh.H"
31 #include "surfaceFields.H"
33 #include "cyclicAMIGAMGInterface.H"
35 //#include "processorGAMGInterface.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41  defineTypeNameAndDebug(faceAreaPairGAMGAgglomeration, 0);
42 
44  (
45  GAMGAgglomeration,
46  faceAreaPairGAMGAgglomeration,
47  lduMesh
48  );
49 
51  (
52  GAMGAgglomeration,
53  faceAreaPairGAMGAgglomeration,
54  geometry
55  );
56 }
57 
58 
59 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60 
62 (
63  const lduMesh& mesh,
64  const dictionary& controlDict
65 )
66 :
68 {
69  const fvMesh& fvmesh = refCast<const fvMesh>(mesh);
70 
72  {
73  // This is the <=2406 logic. Apply perturbation to avoid jagged
74  // agglomerations on axis-aligned meshes
75 
76  DebugPoutInFunction<< "Agglomerate with perturbation" << endl;
77 
78  //agglomerate(mesh, sqrt(fvmesh.magSf().primitiveField()));
80  (
82  0, //mesh,
83  mag
84  (
86  (
87  fvmesh.Sf().primitiveField()
88  /sqrt(fvmesh.magSf().primitiveField()),
89  vector(1, 1.01, 1.02)
90  //vector::one
91  )
92  ),
93  true
94  );
95  }
96  else
97  {
98  // In partial updating mode. Use Galilean invariant agglomeration
99  // to e.g. have constant agglomeration for solid body rotation. Also
100  // scale with face area to be consistent with (most) discretisation.
101 
102  DebugPoutInFunction<< "Agglomerate with faceArea magnitude" << endl;
103 
105  (
107  0, //mesh,
108  mag(fvmesh.magSf().primitiveField()),
109  true
110  );
111  }
112 }
113 
114 
116 (
117  const lduMesh& mesh,
118  const scalarField& cellVolumes,
119  const vectorField& faceAreas,
120  const dictionary& controlDict
121 )
122 :
123  pairGAMGAgglomeration(mesh, controlDict)
124 {
126  {
127  // This is the <=2406 logic. Apply perturbation to avoid jagged
128  // agglomerations on axis-aligned meshes
129 
130  DebugPoutInFunction<< "Agglomerate with perturbation" << endl;
131 
132  //agglomerate(mesh, sqrt(mag(faceAreas)));
134  (
136  0, //mesh,
137  mag
138  (
140  (
141  faceAreas
142  /sqrt(mag(faceAreas)),
143  vector(1, 1.01, 1.02)
144  //vector::one
145  )
146  ),
147  true
148  );
149  }
150  else
151  {
152  // In partial updating mode. Use Galilean invariant agglomeration
153  // to e.g. have constant agglomeration for solid body rotation. Also
154  // scale with face area to be consistent with (most) discretisation.
155 
156  DebugPoutInFunction<< "Agglomerate with faceArea magnitude" << endl;
157 
159  (
161  0, //mesh,
162  mag(faceAreas),
163  true
164  );
165  }
166 }
167 
168 
169 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
170 
172 {
173  const bool ok = pairGAMGAgglomeration::movePoints();
174 
175  if (!requireUpdate_)
176  {
177  // movePoints lower down did not trigger update. Update in case of
178  // cyclicAMI since contains addressing across patches and patches
179  // have moved.
180 
181  bool hasCyclicAMI = false;
182  if (!processorAgglomerate())
183  {
184  const auto& fineInterfaces = interfaceLevel(0);
185  forAll(fineInterfaces, inti)
186  {
187  if (fineInterfaces.set(inti))
188  {
189  const auto& intf = fineInterfaces[inti];
190  if
191  (
192  isA<cyclicAMILduInterface>(intf)
193  || isA<cyclicACMILduInterface>(intf)
194  )
195  {
196  hasCyclicAMI = true;
197 
199  << "Detected cyclicA(C)MI at interface " << inti
200  << ".Redoing patch agglomeration" << endl;
201 
202  break;
203  }
204  }
205  }
206  }
207 
208 
209  if (hasCyclicAMI)
210  {
211  // Redo the interface agglomeration
212  for
213  (
214  label fineLevelIndex = 0;
215  fineLevelIndex < size();
216  fineLevelIndex++
217  )
218  {
219  // Near complete copy of boundary handling in
220  // GAMGAgglomeration::agglomerateLduAddressing
221 
222  const auto& fineMesh = meshLevel(fineLevelIndex);
223  const auto& fineInterfaces = interfaceLevel(fineLevelIndex);
224  const lduAddressing& fineMeshAddr = fineMesh.lduAddr();
225 
226  // Get restriction map for current level
227  const labelField& restrictMap =
228  restrictAddressing(fineLevelIndex);
229 
230  const label startOfRequests = UPstream::nRequests();
231  forAll(fineInterfaces, inti)
232  {
233  if (fineInterfaces.set(inti))
234  {
235  const auto& intf = fineInterfaces[inti];
236 
237  if
238  (
239  isA<cyclicAMILduInterface>(intf)
240  || isA<cyclicACMILduInterface>(intf)
241  )
242  {
243  if (fineLevelIndex == 0)
244  {
245  intf.initInternalFieldTransfer
246  (
248  restrictMap,
249  fineMeshAddr.patchAddr(inti)
250  );
251  }
252  else
253  {
254  intf.initInternalFieldTransfer
255  (
257  restrictMap
258  );
259  }
260  }
261  }
262  }
263 
264  // Wait for comms to finised
265  UPstream::waitRequests(startOfRequests);
266 
267  // New coarse-level interfaces
268  //lduInterfacePtrsList coarseInterfaces(fineInterfaces.size());
269 
270  forAll(fineInterfaces, inti)
271  {
272  if (fineInterfaces.set(inti))
273  {
274  const auto& intf = fineInterfaces[inti];
275 
276  if
277  (
278  isA<cyclicAMILduInterface>(intf)
279  || isA<cyclicACMILduInterface>(intf)
280  )
281  {
282  tmp<labelField> restrictMapInternalField;
283 
284  // The finest mesh uses patchAddr from the
285  // original lduAdressing.
286  // the coarser levels create thei own adressing for
287  // faceCells
288  if (fineLevelIndex == 0)
289  {
290  restrictMapInternalField =
291  intf.interfaceInternalField
292  (
293  restrictMap,
294  fineMeshAddr.patchAddr(inti)
295  );
296  }
297  else
298  {
299  restrictMapInternalField =
300  intf.interfaceInternalField
301  (
302  restrictMap
303  );
304  }
305 
306  tmp<labelField> nbrRestrictMapInternalField =
307  intf.internalFieldTransfer
308  (
310  restrictMap
311  );
312 
313  lduPrimitiveMesh& coarseMesh =
314  meshLevels_[fineLevelIndex];
315 
316  autoPtr<GAMGInterface> coarseIntf
317  (
319  (
320  inti,
321  coarseMesh.rawInterfaces(),
322  intf,
323  restrictMapInternalField(),
324  nbrRestrictMapInternalField(),
325  fineLevelIndex,
326  fineMesh.comm()
327  )
328  );
329 
330  //coarseInterfaces.set(inti, coarseIntf.ptr());
331  coarseMesh.interfaces().set
332  (
333  inti,
334  coarseIntf.ptr()
335  );
336  coarseMesh.primitiveInterfaces().set
337  (
338  inti,
339  &coarseMesh.interfaces()[inti]
340  );
341  }
342  }
343  }
344 
345  //meshLevels_[fineLevelIndex].addInterfaces
346  //(
347  // coarseInterfaces,
348  // lduPrimitiveMesh::nonBlockingSchedule
349  // <
350  // processorGAMGInterface
351  // >
352  // (
353  // coarseInterfaces
354  // )
355  //);
356  }
357  }
358 
359  if (debug)
360  {
361  printLevels();
362  }
363  }
364 
365  return ok;
366 }
367 
368 
369 // ************************************************************************* //
Foam::surfaceFields.
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:48
const surfaceVectorField & Sf() const
Return cell face area vectors.
static autoPtr< GAMGInterface > New(const label index, const lduInterfacePtrsList &coarseInterfaces, const lduInterface &fineInterface, const labelField &localRestrictAddressing, const labelField &neighbourRestrictAddressing, const label fineLevelIndex, const label coarseComm)
Return a pointer to a new interface created on freestore given.
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
Agglomerate using the pair algorithm.
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:53
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:2189
Macros for easy insertion into run-time selection tables.
faceAreaPairGAMGAgglomeration(const lduMesh &mesh, const dictionary &controlDict)
Construct given mesh and controls.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
static tmp< labelField > agglomerate(label &nCoarseCells, const lduAddressing &fineMatrixAddressing, const scalarField &faceWeights)
Calculate and return agglomeration.
bool requiresUpdate() const
Does the agglomeration need to be fully updated?
virtual bool movePoints()
Update when the mesh moves.
dynamicFvMesh & mesh
const lduMesh & mesh() const noexcept
Reference to the mesh.
Definition: MeshObject.H:257
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Vector< scalar > vector
Definition: vector.H:57
virtual bool movePoints()
Update when the mesh moves.
runTime controlDict().readEntry("adjustTimeStep"
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
dimensioned< Type > cmptMultiply(const dimensioned< Type > &, const dimensioned< Type > &)
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Field< vector > vectorField
Specialisation of Field<T> for vector.
label nCellsInCoarsestLevel_
Number of cells in coarsest level.
Namespace for OpenFOAM.
#define DebugPoutInFunction
Report an information message using Foam::Pout.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)