fvMeshGeometry.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-2017,2022 OpenFOAM Foundation
9  Copyright (C) 2020-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 
29 #include "fvMesh.H"
30 #include "Time.H"
31 #include "volFields.H"
32 #include "surfaceFields.H"
33 #include "slicedVolFields.H"
35 #include "SubField.H"
36 #include "cyclicFvPatchFields.H"
37 #include "cyclicAMIFvPatchFields.H"
38 
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 
41 void Foam::fvMesh::makeSf() const
42 {
43  DebugInFunction << "Assembling face areas" << endl;
44 
45  // It is an error to attempt to recalculate
46  // if the pointer is already set
47  if (SfPtr_)
48  {
50  << "face areas already exist"
51  << abort(FatalError);
52  }
53 
55  (
56  IOobject
57  (
58  "S",
60  meshSubDir,
61  *this,
65  ),
66  *this,
67  dimArea,
69  );
70 
72 }
73 
74 
75 void Foam::fvMesh::makeMagSf() const
76 {
77  DebugInFunction << "Assembling mag face areas" << endl;
78 
79  // It is an error to attempt to recalculate
80  // if the pointer is already set
81  if (magSfPtr_)
82  {
84  << "mag face areas already exist"
85  << abort(FatalError);
86  }
87 
88  // Note: Added stabilisation for faces with exactly zero area.
89  // These should be caught on mesh checking but at least this stops
90  // the code from producing Nans.
91  magSfPtr_ = new surfaceScalarField
92  (
93  IOobject
94  (
95  "magSf",
96  pointsInstance(),
97  meshSubDir,
98  *this,
102  ),
103  mag(Sf()) + dimensionedScalar("vs", dimArea, VSMALL)
104  );
105 }
106 
107 
108 void Foam::fvMesh::makeC() const
109 {
110  DebugInFunction << "Assembling cell centres" << endl;
111 
112  // It is an error to attempt to recalculate
113  // if the pointer is already set
114  if (CPtr_)
115  {
117  << "cell centres already exist"
118  << abort(FatalError);
119  }
120 
121  // Construct as slices. Only preserve processor (not e.g. cyclic)
122 
123  CPtr_ = new slicedVolVectorField
124  (
125  IOobject
126  (
127  "C",
128  pointsInstance(),
129  meshSubDir,
130  *this,
134  ),
135  *this,
136  dimLength,
137  cellCentres(),
138  faceCentres(),
139  true, //preserveCouples
140  true //preserveProcOnly
141  );
142 }
143 
144 
145 void Foam::fvMesh::makeCf() const
146 {
147  DebugInFunction << "Assembling face centres" << endl;
148 
149  // It is an error to attempt to recalculate
150  // if the pointer is already set
151  if (CfPtr_)
152  {
154  << "face centres already exist"
155  << abort(FatalError);
156  }
157 
158  CfPtr_ = new slicedSurfaceVectorField
159  (
160  IOobject
161  (
162  "Cf",
163  pointsInstance(),
164  meshSubDir,
165  *this,
169  ),
170  *this,
171  dimLength,
172  faceCentres()
173  );
174 }
175 
176 
177 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
178 
180 {
181  if (!VPtr_)
182  {
184  << "Constructing from primitiveMesh::cellVolumes()" << endl;
185 
187  (
188  IOobject
189  (
190  "V",
191  time().timeName(),
192  *this,
196  ),
197  *this,
198  dimVolume,
199  cellVolumes()
200  );
201  }
202 
203  return *VPtr_;
204 }
205 
206 
208 {
209  if (!V0Ptr_)
210  {
212  << "V0 is not available"
214  }
215 
216  return *V0Ptr_;
217 }
218 
219 
221 {
222  if (!V0Ptr_)
223  {
225  << "V0 is not available"
227  }
228 
229  return *V0Ptr_;
230 }
231 
232 
234 {
235  if (!V00Ptr_)
236  {
237  DebugInFunction << "Constructing from V0" << endl;
238 
239  V00Ptr_ = new DimensionedField<scalar, volMesh>
240  (
241  IOobject
242  (
243  "V00",
244  time().timeName(),
245  *this,
249  ),
250  V0()
251  );
252 
253 
254  // If V00 is used then V0 should be stored for restart
255  V0Ptr_->writeOpt(IOobject::AUTO_WRITE);
256  }
257 
258  return *V00Ptr_;
259 }
260 
261 
263 {
264  if (!steady() && moving() && time().subCycling())
265  {
266  const TimeState& ts = time();
267  const TimeState& ts0 = time().prevTimeState();
268 
269  scalar tFrac =
270  (
271  ts.value() - (ts0.value() - ts0.deltaTValue())
272  )/ts0.deltaTValue();
273 
274  if (tFrac < (1 - SMALL))
275  {
276  return V0() + tFrac*(V() - V0());
277  }
278  }
279 
280  return V();
281 }
282 
283 
285 {
286  if (!steady() && moving() && time().subCycling())
287  {
288  const TimeState& ts = time();
289  const TimeState& ts0 = time().prevTimeState();
290 
291  scalar t0Frac =
292  (
293  (ts.value() - ts.deltaTValue())
294  - (ts0.value() - ts0.deltaTValue())
295  )/ts0.deltaTValue();
296 
297  if (t0Frac > SMALL)
298  {
299  return V0() + t0Frac*(V() - V0());
300  }
301  }
302 
303  return V0();
304 }
305 
306 
308 {
309  if (!SfPtr_)
310  {
311  makeSf();
312  }
313 
314  return *SfPtr_;
315 }
316 
317 
319 {
320  if (!magSfPtr_)
321  {
322  makeMagSf();
323  }
324 
325  return *magSfPtr_;
326 }
327 
328 
330 {
331  auto tunitVectors = tmp<surfaceVectorField>::New
332  (
333  IOobject
334  (
335  "unit(Sf)",
336  pointsInstance(),
337  meshSubDir,
338  *this,
342  ),
343  *this,
344  dimless,
345  (this->Sf() / this->magSf())
346  );
347 
348  tunitVectors.ref().oriented() = this->Sf().oriented();
349  return tunitVectors;
350 }
351 
352 
354 {
355  if (!CPtr_)
356  {
357  makeC();
358  }
359 
360  return *CPtr_;
361 }
362 
363 
365 {
366  if (!CfPtr_)
367  {
368  makeCf();
369  }
370 
371  return *CfPtr_;
372 }
373 
374 
376 {
377  DebugInFunction << "Calculating face deltas" << endl;
378 
379  auto tdelta = tmp<surfaceVectorField>::New
380  (
381  IOobject
382  (
383  "delta",
384  pointsInstance(),
385  meshSubDir,
386  *this,
390  ),
391  *this,
392  dimLength
393  );
394  auto& delta = tdelta.ref();
395  delta.setOriented();
396 
397  const volVectorField& C = this->C();
398  const labelUList& owner = this->owner();
399  const labelUList& neighbour = this->neighbour();
400 
401  forAll(owner, facei)
402  {
403  delta[facei] = C[neighbour[facei]] - C[owner[facei]];
404  }
405 
406  auto& deltabf = delta.boundaryFieldRef();
407 
408  forAll(deltabf, patchi)
409  {
410  deltabf[patchi] = boundary()[patchi].delta();
411  }
412 
413  return tdelta;
414 }
415 
416 
418 {
419  if (!phiPtr_)
420  {
422  << "mesh flux field does not exist, is the mesh actually moving?"
423  << abort(FatalError);
424  }
425 
426  // Set zero current time
427  // mesh motion fluxes if the time has been incremented
428  if (!time().subCycling() && phiPtr_->timeIndex() != time().timeIndex())
429  {
431  }
433  phiPtr_->setOriented();
434 
435  return *phiPtr_;
436 }
437 
438 
440 {
442 
443  // Return non-const reference, or nullptr if not available
444  phiref.ref(phiPtr_.get());
445 
446  return phiref;
447 }
448 
449 
450 // ************************************************************************* //
Foam::surfaceFields.
faceListList boundary
scalar delta
const surfaceVectorField & Sf() const
Return cell face area vectors.
void makeC() const
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Specialisation of DimensionedField that holds a slice of a given field so that it acts as a Dimension...
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:411
const surfaceScalarField & phi() const
Return cell face motion fluxes.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
const DimensionedField< scalar, volMesh > & V00() const
Return old-old-time cell volumes.
void makeCf() const
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
DimensionedField< scalar, volMesh > & setV0()
Return old-time cell volumes.
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:76
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
word timeName
Definition: getTimeIndex.H:3
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:58
tmp< DimensionedField< scalar, volMesh > > Vsc() const
Return sub-cycle cell volumes.
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:853
const DimensionedField< scalar, volMesh > & V0() const
Return old-time cell volumes.
SlicedGeometricField< vector, fvsPatchField, slicedFvsPatchField, surfaceMesh > slicedSurfaceVectorField
#define DebugInFunction
Report an information message using Foam::Info.
void setOriented(bool on=true) noexcept
Set the oriented flag: on/off.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
refPtr< surfaceScalarField > setPhi()
Return cell face motion fluxes, if any (can be nullptr)
SlicedGeometricField< vector, fvPatchField, slicedFvPatchField, volMesh > slicedVolVectorField
errorManip< error > abort(error &err)
Definition: errorManip.H:139
tmp< DimensionedField< scalar, volMesh > > Vsc0() const
Return sub-cycle old-time cell volumes.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
void makeMagSf() const
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: refPtrI.H:230
tmp< surfaceVectorField > delta() const
Return face deltas as surfaceVectorField.
volScalarField & C
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const vectorField & faceAreas() const
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Nothing to be read.
Automatically write from objectRegistry::writeObject()
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
slicedSurfaceVectorField * SfPtr_
Face area vectors.
Definition: fvMesh.H:127
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
const volVectorField & C() const
Return cell centres as volVectorField.
A class for managing temporary objects.
Definition: HashPtrTable.H:50
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Request registration (bool: true)
tmp< surfaceVectorField > unitSf() const
Return cell face unit normals.
void makeSf() const
Do not request registration (bool: false)
const dimensionSet dimArea(sqr(dimLength))
Definition: dimensionSets.H:57