displacementPointSmoothingMotionSolver.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) 2024 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
30 #include "syncTools.H"
31 #include "pointConstraints.H"
32 #include "motionSmootherAlgo.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineTypeNameAndDebug(displacementPointSmoothingMotionSolver, 0);
39 
41  (
42  motionSolver,
43  displacementPointSmoothingMotionSolver,
44  dictionary
45  );
46 
48  (
49  displacementMotionSolver,
50  displacementPointSmoothingMotionSolver,
51  displacement
52  );
53 }
54 
55 
56 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
57 
59 (
60  const labelHashSet& changedFaces,
61  labelHashSet& affectedFaces
62 )
63 {
64  PackedBoolList affectedPoints(mesh().nPoints(), false);
65 
66  forAllConstIter(labelHashSet, changedFaces, iter)
67  {
68  const label faceI(iter.key());
69 
70  const face& fPoints(mesh().faces()[faceI]);
71 
72  forAll(fPoints, fPointI)
73  {
74  const label pointI(fPoints[fPointI]);
75 
76  affectedPoints[pointI] = true;
77  }
78  }
79 
81  (
82  mesh(),
83  affectedPoints,
84  orEqOp<unsigned int>(),
85  0U
86  );
87 
88  forAll(affectedPoints, pointI)
89  {
90  if (affectedPoints[pointI])
91  {
92  const labelList& pCells(mesh().pointCells()[pointI]);
93 
94  forAll(pCells, pointCellI)
95  {
96  const label cellI(pCells[pointCellI]);
97 
98  const labelList& cFaces(mesh().cells()[cellI]);
99 
100  affectedFaces.insert(cFaces);
101  }
102  }
103  }
104 }
105 
106 
108 {
109  if
110  (
111  (relaxationFactors_.size() == 0)
112  || (relaxationFactors_.size() == 1 && relaxationFactors_[0] == 1.0)
113  )
114  {
115  relaxedPoints_ = points0() + pointDisplacement().internalField();
116  return true;
117  }
118 
119 
120  const pointField oldRelaxedPoints(relaxedPoints_);
121 
122  labelHashSet affectedFaces(facesToMove_);
123 
124  // Create a list of relaxation levels
125  // -1 indicates a point which is not to be moved
126  // 0 is the starting value for a moving point
127  labelList relaxationLevel(mesh().nPoints(), -1);
128  forAllConstIter(labelHashSet, affectedFaces, iter)
129  {
130  const label faceI(iter.key());
131 
132  const face& fPoints(mesh().faces()[faceI]);
133 
134  forAll(fPoints, fPointI)
135  {
136  const label pointI(fPoints[fPointI]);
137 
138  relaxationLevel[pointI] = 0;
139  }
140  }
141 
143  (
144  mesh(),
145  relaxationLevel,
146  maxEqOp<label>(),
147  label(-1)
148  );
149 
150  // Loop whilst relaxation levels are being incremented
151  bool complete(false);
152  while (!complete)
153  {
154  //scalar nAffectedFaces(affectedFaces.size());
155  //reduce(nAffectedFaces, sumOp<scalar>());
156  //Info << " Moving " << nAffectedFaces << " faces" << endl;
157 
158  // Move the points
159  forAll(relaxationLevel, pointI)
160  {
161  if (relaxationLevel[pointI] >= 0)
162  {
163  const scalar x
164  (
165  relaxationFactors_[relaxationLevel[pointI]]
166  );
167 
168  relaxedPoints_[pointI] =
169  (1 - x)*oldRelaxedPoints[pointI]
170  + x*(points0()[pointI] + pointDisplacement()[pointI]);
171  }
172  }
173 
174  // Get a list of changed faces
175  labelHashSet markedFaces;
176  markAffectedFaces(affectedFaces, markedFaces);
177  labelList markedFacesList(markedFaces.toc());
178 
179  // Update the geometry
180  meshGeometry_.correct(relaxedPoints_, markedFacesList);
181 
182  // Check the modified face quality
183  markedFaces.clear();
185  (
186  false,
187  meshQualityDict_,
188  meshGeometry_,
189  relaxedPoints_,
190  markedFacesList,
191  markedFaces
192  );
193 
194  // Mark the affected faces
195  affectedFaces.clear();
196  markAffectedFaces(markedFaces, affectedFaces);
197 
198  // Increase relaxation and check convergence
199  PackedBoolList pointsToRelax(mesh().nPoints(), false);
200  complete = true;
201  forAllConstIter(labelHashSet, affectedFaces, iter)
202  {
203  const label faceI(iter.key());
204 
205  const face& fPoints(mesh().faces()[faceI]);
206 
207  forAll(fPoints, fPointI)
208  {
209  const label pointI(fPoints[fPointI]);
210 
211  pointsToRelax[pointI] = true;
212  }
213  }
214 
215  forAll(pointsToRelax, pointI)
216  {
217  if
218  (
219  pointsToRelax[pointI]
220  && (relaxationLevel[pointI] < relaxationFactors_.size() - 1)
221  )
222  {
223  ++ relaxationLevel[pointI];
224 
225  complete = false;
226  }
227  }
228 
229  // Synchronise relaxation levels
231  (
232  mesh(),
233  relaxationLevel,
234  maxEqOp<label>(),
235  label(0)
236  );
237 
238  // Synchronise completion
239  reduce(complete, andOp<bool>());
240  }
241 
242  // Check for convergence
243  bool converged(true);
244  forAll(mesh().faces(), faceI)
245  {
246  const face& fPoints(mesh().faces()[faceI]);
247 
248  forAll(fPoints, fPointI)
249  {
250  const label pointI(fPoints[fPointI]);
251 
252  if (relaxationLevel[pointI] > 0)
253  {
254  facesToMove_.insert(faceI);
255 
256  converged = false;
257 
258  break;
259  }
260  }
261  }
262 
263  // Syncronise convergence
264  reduce(converged, andOp<bool>());
265 
266  //if (converged)
267  //{
268  // Info<< "... Converged" << endl << endl;
269  //}
270  //else
271  //{
272  // Info<< "... Not converged" << endl << endl;
273  //}
274 
275  return converged;
276 }
277 
278 
280 (
281  const dictionary& dict
282 )
283 {
284  if (dict.getOrDefault<bool>("moveInternalFaces", true))
285  {
286  facesToMove_.resize(2*mesh().nFaces());
287  forAll(mesh().faces(), faceI)
288  {
289  facesToMove_.insert(faceI);
290  }
291  }
292  else
293  {
294  facesToMove_.resize(2*(mesh().nBoundaryFaces()));
295  for
296  (
297  label faceI = mesh().nInternalFaces();
298  faceI < mesh().nFaces();
299  ++ faceI
300  )
301  {
302  facesToMove_.insert(faceI);
303  }
304  }
305 }
306 
307 
308 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
309 
312 (
313  const polyMesh& mesh,
314  const IOdictionary& dict
315 )
316 :
317  displacementMotionSolver(mesh, dict, typeName),
318  meshGeometry_(mesh),
319  pointSmoother_(pointSmoother::New(mesh, coeffDict())),
320  nPointSmootherIter_
321  (
322  readLabel(coeffDict().lookup("nPointSmootherIter"))
323  ),
324  relaxedPoints_(mesh.points())
325 {
326  if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
327  {
328  meshQualityDict_ = coeffDict().subDict("meshQuality");
329  }
331 }
332 
333 
336 (
337  const polyMesh& mesh,
338  const IOdictionary& dict,
339  const pointVectorField& pointDisplacement,
340  const pointIOField& points0
341 )
342 :
343  displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
344  meshGeometry_(mesh),
345  pointSmoother_
346  (
347  pointSmoother::New
348  (
349  mesh,
350  coeffDict()
351  )
352  ),
353  nPointSmootherIter_
354  (
355  readLabel(coeffDict().lookup("nPointSmootherIter"))
356  ),
357  relaxedPoints_(mesh.points())
358 {
359  if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
360  {
361  meshQualityDict_ = coeffDict().subDict("meshQuality");
362  }
364 }
365 
366 
367 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
368 
371 {
372  //Note: twoDCorrect already done by ::solve
373 
374  return relaxedPoints_;
375 }
376 
377 
379 {
380  //Pout<< "time:" << mesh().time().timeName()
381  // << " mesh faceCentres:" << gAverage(mesh().faceCentres())
382  // << " mesh cellCentres:" << gAverage(mesh().cellCentres())
383  // << endl;
384 
385  movePoints(curPoints());
386 
387  // Update values on pointDisplacement
388  pointDisplacement().boundaryFieldRef().updateCoeffs();
389 
390  // Extend: face-to-point-to-cell-to-faces
391  labelHashSet affectedFaces;
392  markAffectedFaces(facesToMove_, affectedFaces);
393 
394  for(label i = 0; i < nPointSmootherIter_; i ++)
395  {
396  meshGeometry_.correct
397  (
398  points0() + pointDisplacement().internalField(),
399  affectedFaces.toc()
400  );
401  //Pout<< "iter:" << i
402  // << " faceCentres:" << gAverage(meshGeometry_.faceCentres())
403  // << " cellCentres:" << gAverage(meshGeometry_.cellCentres())
404  // << endl;
405 
406  pointSmoother_->update
407  (
408  affectedFaces.toc(),
409  points0(),
410  points0() + pointDisplacement().internalField(),
411  meshGeometry_,
412  pointDisplacement()
413  );
414  }
415 
416  relax();
417 
418  twoDCorrectPoints(relaxedPoints_);
419 
420  // Update pointDisplacement for actual relaxedPoints. Keep fixed-value
421  // bcs.
422  pointDisplacement().primitiveFieldRef() = relaxedPoints_-points0();
423 
424  // Adhere to multi-point constraints
425  const pointConstraints& pcs =
426  pointConstraints::New(pointDisplacement().mesh());
427  pcs.constrainDisplacement(pointDisplacement(), false);
428 
429  // Update relaxedPoints to take constraints into account
430  relaxedPoints_ = points0() + pointDisplacement().internalField();
431 }
432 
433 
434 // ************************************************************************* //
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces, const bool dryRun=false)
Check mesh with mesh settings in dict. Collects incorrect faces.
dictionary dict
Virtual base class for displacement motion solver.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
UEqn relax()
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
Abstract base class for point smoothing methods. Handles parallel communication via reset and average...
Definition: pointSmoother.H:50
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:38
static const pointConstraints & New(const pointMesh &mesh, Args &&... args)
Get existing or create MeshObject registered with typeName.
Definition: MeshObject.C:53
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
virtual tmp< pointField > curPoints() const
Return point location obtained from the current motion field.
GeometricField< vector, pointPatchField, pointMesh > pointVectorField
const dictionary & coeffDict() const
Const access to the coefficients dictionary.
Definition: motionSolver.H:173
label nFaces() const noexcept
Number of mesh faces.
Lookup type of boundary radiation properties.
Definition: lookup.H:57
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:478
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:441
Macros for easy insertion into run-time selection tables.
displacementPointSmoothingMotionSolver(const polyMesh &, const IOdictionary &)
Construct from a polyMesh and an IOdictionary.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const cellShapeList & cells
const pointField & points
scalarList relaxationFactors_
Relaxation factors to use in each iteration.
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
label nPoints
void clear()
Remove all entries from table.
Definition: HashTable.C:749
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
void markAffectedFaces(const labelHashSet &changedFaces, labelHashSet &affectedFaces)
Mark affected faces.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
defineTypeNameAndDebug(combustionModel, 0)
virtual void setFacesToMove(const dictionary &)
Set all the faces to be moved.
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))
U
Definition: pEqn.H:72
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< Key > toc() const
The table of contents (the keys) in unsorted order.
Definition: HashTable.C:148
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
List< label > labelList
A List of labels.
Definition: List.H:62
const polyMesh & mesh() const
Return reference to mesh.
Definition: motionSolver.H:165
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void reduce(T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) using linear/tree communication schedule.
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
bitSet PackedBoolList