solidBodyFvGeometryScheme.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) 2021-2022 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 "surfaceFields.H"
31 #include "primitiveMeshTools.H"
32 #include "emptyPolyPatch.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineTypeNameAndDebug(solidBodyFvGeometryScheme, 0);
40  (
41  fvGeometryScheme,
42  solidBodyFvGeometryScheme,
43  dict
44  );
45 }
46 
47 
48 bool Foam::solidBodyFvGeometryScheme::markChanges
49 (
50  const pointField& oldPoints,
51  const pointField& currPoints,
52  bitSet& isChangedPoint,
53  bitSet& isChangedFace,
54  bitSet& isChangedCell
55 ) const
56 {
57  isChangedPoint.setSize(oldPoints.size());
58 
59  // Check for non-identical points
60  forAll(isChangedPoint, pointi)
61  {
62  isChangedPoint.set(pointi, oldPoints[pointi] != currPoints[pointi]);
63  }
64 
65  DebugInfo
66  << "SBM --- Changed points:"
67  << returnReduce(isChangedPoint.count(), sumOp<label>())
68  << endl;
69 
70  // Quick return if no points have moved
71  if (returnReduceAnd(isChangedPoint.none()))
72  {
73  return false;
74  }
75 
76  isChangedFace.setSize(mesh_.nFaces());
77  isChangedFace = false;
78 
79  isChangedCell.setSize(mesh_.nCells());
80  isChangedCell = false;
81 
82  const auto& pointFaces = mesh_.pointFaces();
83  const auto& own = mesh_.faceOwner();
84  const auto& nbr = mesh_.faceNeighbour();
85 
86  // Identify faces and cells attached to moving points
87  for (const label pointi : isChangedPoint)
88  {
89  for (const auto facei : pointFaces[pointi])
90  {
91  isChangedFace.set(facei);
92 
93  isChangedCell.set(own[facei]);
94  if (facei < mesh_.nInternalFaces())
95  {
96  isChangedCell.set(nbr[facei]);
97  }
98  }
99  }
100 
101  DebugInfo
102  << "SBM --- Changed cells:"
103  << returnReduce(isChangedCell.count(), sumOp<label>())
104  << endl;
105 
106  return true;
107 }
108 
109 
110 void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
111 {
112  if (!cacheInitialised_ || !cacheMotion_)
113  {
114  DebugInFunction << "Creating cache" << endl;
115 
116  changedFaceIDs_.clear(); // used for face areas, meshPhi
117  changedPatchIDs_.clear(); // used for meshPhi
118  changedCellIDs_.clear(); // used for cell volumes
119 
120  const pointField& oldPoints = mesh_.oldPoints();
121  const pointField& currPoints = mesh_.points();
122 
123  if (oldPoints.size() != currPoints.size())
124  {
126  << "Old and current points sizes must be the same. "
127  << "Old points:" << oldPoints.size()
128  << " Current points:" << currPoints.size()
129  << abort(FatalError);
130  }
131 
132  //bitSet changedPoints(oldPoints.size());
133  //
135  //forAll(changedPoints, pointi)
136  //{
137  // changedPoints.set
138  // (
139  // pointi,
140  // oldPoints[pointi] != currPoints[pointi]
141  // );
142  //}
143  //
144  //DebugInfo
145  // << "SBM --- Changed points:"
146  // << returnReduce(changedPoints.count(), sumOp<label>())
147  // << endl;
148  //
150  //if (returnReduceAnd(changedPoints.none()))
151  //{
152  // return;
153  //}
154  //
155  //bitSet cellIDs(mesh_.nCells());
156  //bitSet faceIDs(mesh_.nFaces());
157  //
158  //const auto& pointFaces = mesh_.pointFaces();
159  //const auto& own = mesh_.faceOwner();
160  //const auto& nbr = mesh_.faceNeighbour();
161  //
163  //for (const label pointi : changedPoints)
164  //{
165  // for (const auto facei : pointFaces[pointi])
166  // {
167  // faceIDs.set(facei);
168  //
169  // cellIDs.set(own[facei]);
170  // if (facei < mesh_.nInternalFaces())
171  // {
172  // cellIDs.set(nbr[facei]);
173  // }
174  // }
175  //}
176  //
177  //changedCellIDs_ = cellIDs.toc();
178  //
179  //DebugInfo
180  // << "SBM --- Changed cells:"
181  // << returnReduce(changedCellIDs_.size(), sumOp<label>())
182  // << endl;
183 
184  bitSet isChangedPoint;
185  bitSet isChangedFace;
186  bitSet isChangedCell;
187  const bool changed = markChanges
188  (
189  oldPoints,
190  currPoints,
191  isChangedPoint,
192  isChangedFace,
193  isChangedCell
194  );
195 
196  // Quick return if no points have moved
197  if (!changed)
198  {
199  return;
200  }
201 
202  changedCellIDs_ = isChangedCell.toc();
203 
204 
205  // Construct face and patch ID info
206 
207  DynamicList<label> changedFaceIDs(isChangedFace.count());
208  DynamicList<label> changedPatchIDs(changedFaceIDs.capacity());
209  for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
210  {
211  if (isChangedFace[facei])
212  {
213  changedFaceIDs.append(facei);
214  changedPatchIDs.append(-1);
215  }
216  }
217 
218  const auto& pbm = mesh_.boundaryMesh();
219  for (label patchi = 0; patchi < pbm.size(); ++patchi)
220  {
221  const polyPatch& pp = pbm[patchi];
222 
223  for (const label meshFacei : pp.range())
224  {
225  if (isChangedFace[meshFacei])
226  {
227  changedFaceIDs.append(meshFacei);
228  changedPatchIDs.append(patchi);
229  }
230  }
231  }
232 
233  changedFaceIDs_.transfer(changedFaceIDs);
234  changedPatchIDs_.transfer(changedPatchIDs);
235  }
236 
237  cacheInitialised_ = true;
238 }
239 
240 
241 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
242 
243 Foam::solidBodyFvGeometryScheme::solidBodyFvGeometryScheme
244 (
245  const fvMesh& mesh,
246  const dictionary& dict
247 )
248 :
250  partialUpdate_(dict.getOrDefault<bool>("partialUpdate", true)),
251  cacheMotion_(dict.getOrDefault<bool>("cacheMotion", true)),
252  cacheInitialised_(false),
253  changedFaceIDs_(),
254  changedPatchIDs_(),
255  changedCellIDs_()
256 {
258  << "partialUpdate:" << partialUpdate_
259  << " cacheMotion:" << cacheMotion_
260  << endl;
261 }
262 
263 
264 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
265 
267 {
268  // Note: not calling fvGeometryScheme::movePoints since we want to perform
269  // our own geometry manipulations
270 
271  bool haveGeometry =
272  mesh_.hasCellCentres()
273  && mesh_.hasFaceCentres()
274  && mesh_.hasCellVolumes()
275  && mesh_.hasFaceAreas();
276 
277  if (!haveGeometry)
278  {
280  << "Creating initial geometry using primitiveMesh::updateGeom"
281  << endl;
282 
283  const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
284  return;
285  }
286 
287  if (mesh_.moving())
288  {
289  setMeshMotionData();
290 
291  DebugInFunction << "Performing partial meshPhi construction" << endl;
292 
293  const pointField& oldPoints = mesh_.oldPoints();
294  const pointField& currPoints = mesh_.points();
295 
296  if (oldPoints.size() != currPoints.size())
297  {
299  << "Old and current points sizes must be the same. "
300  << "Old points:" << oldPoints.size()
301  << " Current points:" << currPoints.size()
302  << abort(FatalError);
303  }
304 
305  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
306  const faceList& faces = mesh_.faces();
307 
308  auto tmeshPhi(const_cast<fvMesh&>(mesh_).setPhi());
309  if (tmeshPhi)
310  {
311  const scalar rdt = 1.0/mesh_.time().deltaTValue();
312 
313  // Set the mesh flux
314  auto& meshPhi = tmeshPhi.ref();
315  auto& meshPhii = meshPhi.primitiveFieldRef();
316  auto& meshPhiBf = meshPhi.boundaryFieldRef();
317 
318  //meshPhi == dimensionedScalar(dimVolume/dimTime, Zero);
319  meshPhii = Zero;
320  meshPhiBf == Zero;
321 
322  forAll(changedFaceIDs_, i)
323  {
324  const face& f = faces[changedFaceIDs_[i]];
325 
326  if (changedPatchIDs_[i] == -1)
327  {
328  const label facei = changedFaceIDs_[i];
329  meshPhii[facei] = f.sweptVol(oldPoints, currPoints)*rdt;
330  }
331  else
332  {
333  const label patchi = changedPatchIDs_[i];
334  const polyPatch& pp = pbm[patchi];
335 
336  if (isA<emptyPolyPatch>(pp))
337  {
338  continue;
339  }
340 
341  const label patchFacei = changedFaceIDs_[i] - pp.start();
342 
343  meshPhiBf[patchi][patchFacei] =
344  f.sweptVol(oldPoints, currPoints)*rdt;
345  }
346  }
347  }
348 
349  if (partialUpdate_ && haveGeometry)
350  {
351  // Keep base geometry and update as needed
352  DebugInFunction << "Performing partial geometry update" << endl;
353 
354  // Initialise geometry using the old/existing values
355  vectorField faceCentres(mesh_.faceCentres());
356  vectorField faceAreas(mesh_.faceAreas());
357 
358  // Make face centres and areas consistent with new points
360  (
361  mesh_,
362  changedFaceIDs_,
363  mesh_.points(),
364  faceCentres,
365  faceAreas
366  );
367 
368  vectorField cellCentres(mesh_.cellCentres());
369  scalarField cellVolumes(mesh_.cellVolumes());
370 
372  (
373  mesh_,
374  faceCentres,
375  faceAreas,
376  changedCellIDs_,
377  mesh_.cells(),
378  cellCentres,
379  cellVolumes
380  );
381 
382  const_cast<fvMesh&>(mesh_).primitiveMesh::resetGeometry
383  (
384  std::move(faceCentres),
385  std::move(faceAreas),
386  std::move(cellCentres),
387  std::move(cellVolumes)
388  );
389 
390  if (debug)
391  {
392  for (const auto& p : mesh_.boundaryMesh())
393  {
394  Pout<< "SBM --- " << p.name()
395  << " sum(Sf)=" << sum(p.faceAreas())
396  << " sum(mag(Sf))=" << sum(mag(p.faceAreas()))
397  << endl;
398  }
399  }
400  }
401  else
402  {
404  << "Performing complete geometry clear and update" << endl;
405 
406  // Clear out old geometry
407  // Note: this recreates the old primitiveMesh::movePoints behaviour
408  const_cast<fvMesh&>(mesh_).primitiveMesh::clearGeom();
409 
410  // Use lower level to calculate the geometry
411  const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
412  }
413  }
414  else
415  {
416  DebugInFunction << "Performing complete geometry update" << endl;
418  // Use lower level to calculate the geometry
419  const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
420  }
421 }
422 
423 
425 {
426  cacheInitialised_ = false;
427 }
428 
429 
431 (
432  const pointField& points,
433  const refPtr<pointField>& oldPoints,
434  pointField& faceCentres,
435  vectorField& faceAreas,
436  pointField& cellCentres,
437  scalarField& cellVolumes
438 ) const
439 {
440  if
441  (
442  (faceCentres.size() != mesh_.nFaces())
443  || (faceAreas.size() != mesh_.nFaces())
444  || (cellCentres.size() != mesh_.nCells())
445  || (cellVolumes.size() != mesh_.nCells())
446  || !oldPoints
447  )
448  {
449  // Do all
451  (
452  points,
453  oldPoints,
454  faceCentres,
455  faceAreas,
456  cellCentres,
457  cellVolumes
458  );
459  }
460  else
461  {
462  // Since oldPoints provided assume that face & cell geometry is
463  // up to date with it
464 
465  bitSet isChangedPoint;
466  bitSet isChangedFace;
467  bitSet isChangedCell;
468  const bool changed = markChanges
469  (
470  oldPoints(),
471  points,
472  isChangedPoint,
473  isChangedFace,
474  isChangedCell
475  );
476 
477  if (!changed)
478  {
479  return false;
480  }
481 
482  // Make face centres and areas consistent with new points
484  (
485  mesh_,
486  isChangedFace.toc(),
487  points,
488  faceCentres,
489  faceAreas
490  );
491 
493  (
494  mesh_,
495  faceCentres,
496  faceAreas,
497  isChangedCell.toc(),
498  mesh_.cells(),
499  cellCentres,
500  cellVolumes
501  );
502 
503  return true;
504  }
505 }
506 
507 
508 // ************************************************************************* //
Foam::surfaceFields.
const polyBoundaryMesh & pbm
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
const fvMesh & mesh_
Hold reference to mesh.
virtual bool updateGeom(const pointField &points, const refPtr< pointField > &oldPoints, pointField &faceCentres, vectorField &faceAreas, pointField &cellCentres, scalarField &cellVolumes) const
Calculate geometry quantities using mesh topology and provided points. If oldPoints provided only doe...
static void updateCellCentresAndVols(const primitiveMesh &mesh, const vectorField &fCtrs, const vectorField &fAreas, const List< label > &cellIDs, const List< cell > &cells, vectorField &cellCtrs_s, scalarField &cellVols_s)
Update cell centres and volumes for the cells in the set cellIDs.
virtual void movePoints()
Do what is necessary if the mesh has moved.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:493
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
label nFaces() const noexcept
Number of mesh faces.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
Macros for easy insertion into run-time selection tables.
Default geometry calculation scheme. Slight stabilisation for bad meshes.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
void resetGeometry(pointField &&faceCentres, pointField &&faceAreas, pointField &&cellCentres, scalarField &&cellVolumes)
Reset the local geometry.
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
void clearGeom()
Clear geometry.
dynamicFvMesh & mesh
const pointField & points
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
#define DebugInFunction
Report an information message using Foam::Info.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
virtual void updateGeom()
Update all geometric data.
label nInternalFaces() const noexcept
Number of internal faces.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
#define DebugInfo
Report an information message using Foam::Info.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
Definition: PtrList.H:344
virtual bool updateGeom(const pointField &points, const refPtr< pointField > &oldPoints, pointField &faceCentres, vectorField &faceAreas, pointField &cellCentres, scalarField &cellVolumes) const
Calculate geometry quantities using mesh topology and provided points. If oldPoints provided only doe...
label nCells() const noexcept
Number of mesh cells.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
tmp< surfaceScalarField > meshPhi(const volVectorField &U)
Definition: fvcMeshPhi.C:29
const labelListList & pointFaces() const
Field< vector > vectorField
Specialisation of Field<T> for vector.
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh for topology changes.
volScalarField & p
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static void updateFaceCentresAndAreas(const primitiveMesh &mesh, const UList< label > &faceIDs, const pointField &p, vectorField &fCtrs, vectorField &fAreas)
Update face centres and areas for the faces in the set faceIDs.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127