surfaceInterpolation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25  Cell to face interpolation scheme. Included in fvMesh.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "fvMesh.H"
30 #include "volFields.H"
31 #include "surfaceFields.H"
32 #include "demandDrivenData.H"
33 #include "coupledFvPatch.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
40 }
41 
42 
43 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
44 
46 {
47  deleteDemandDrivenData(weights_);
48  deleteDemandDrivenData(deltaCoeffs_);
49  deleteDemandDrivenData(nonOrthDeltaCoeffs_);
50  deleteDemandDrivenData(nonOrthCorrectionVectors_);
51 }
52 
53 
54 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 
57 :
58  mesh_(fvm),
59  weights_(nullptr),
60  deltaCoeffs_(nullptr),
61  nonOrthDeltaCoeffs_(nullptr),
62  nonOrthCorrectionVectors_(nullptr)
63 {}
64 
65 
66 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
67 
69 {
70  clearOut();
71 }
72 
73 
74 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
75 
78 {
79  if (!weights_)
80  {
81  makeWeights();
82  }
83 
84  return (*weights_);
85 }
86 
87 
90 {
91  if (!deltaCoeffs_)
92  {
93  makeDeltaCoeffs();
94  }
95 
96  return (*deltaCoeffs_);
97 }
98 
99 
102 {
103  if (!nonOrthDeltaCoeffs_)
104  {
105  makeNonOrthDeltaCoeffs();
106  }
107 
108  return (*nonOrthDeltaCoeffs_);
109 }
110 
111 
114 {
115  if (!nonOrthCorrectionVectors_)
116  {
117  makeNonOrthCorrectionVectors();
118  }
119 
120  return (*nonOrthCorrectionVectors_);
121 }
122 
123 
125 {
126  deleteDemandDrivenData(weights_);
127  deleteDemandDrivenData(deltaCoeffs_);
128  deleteDemandDrivenData(nonOrthDeltaCoeffs_);
129  deleteDemandDrivenData(nonOrthCorrectionVectors_);
130 
131  return true;
132 }
133 
134 
135 void Foam::surfaceInterpolation::makeWeights() const
136 {
137  if (debug)
138  {
139  Pout<< "surfaceInterpolation::makeWeights() : "
140  << "Constructing weighting factors for face interpolation"
141  << endl;
142  }
143 
144  weights_ = new surfaceScalarField
145  (
146  IOobject
147  (
148  "weights",
149  mesh_.pointsInstance(),
150  mesh_,
153  false // Do not register
154  ),
155  mesh_,
156  dimless,
158  );
159  surfaceScalarField& weights = *weights_;
160 
161  // Set local references to mesh data
162  const labelUList& owner = mesh_.owner();
163  const labelUList& neighbour = mesh_.neighbour();
164  const surfaceVectorField& Sf = mesh_.Sf();
165  const surfaceVectorField& Cf = mesh_.Cf();
166  const volVectorField& C = mesh_.C();
167 
168  // ... and reference to the internal field of the weighting factors
169  scalarField& w = weights.primitiveFieldRef();
170 
171  forAll(owner, facei)
172  {
173  // Note: mag in the dot-product.
174  // For all valid meshes, the non-orthogonality will be less that
175  // 90 deg and the dot-product will be positive. For invalid
176  // meshes (d & s <= 0), this will stabilise the calculation
177  // but the result will be poor.
178  const scalar SfdOwn = mag(Sf[facei]&(Cf[facei] - C[owner[facei]]));
179  const scalar SfdNei = mag(Sf[facei]&(C[neighbour[facei]] - Cf[facei]));
180  const scalar SfdOwnNei = SfdOwn + SfdNei;
181 
182  if (SfdNei/vGreat < SfdOwnNei)
183  {
184  w[facei] = SfdNei/SfdOwnNei;
185  }
186  else
187  {
188  const scalar dOwn = mag(Cf[facei] - C[owner[facei]]);
189  const scalar dNei = mag(C[neighbour[facei]] - Cf[facei]);
190  const scalar dOwnNei = dOwn + dNei;
191 
192  w[facei] = dNei/dOwnNei;
193  }
194  }
195 
197  weights.boundaryFieldRef();
198 
199  forAll(mesh_.boundary(), patchi)
200  {
201  mesh_.boundary()[patchi].makeWeights(wBf[patchi]);
202  }
203 
204  if (debug)
205  {
206  Pout<< "surfaceInterpolation::makeWeights() : "
207  << "Finished constructing weighting factors for face interpolation"
208  << endl;
209  }
210 }
211 
212 
213 void Foam::surfaceInterpolation::makeDeltaCoeffs() const
214 {
215  if (debug)
216  {
217  Pout<< "surfaceInterpolation::makeDeltaCoeffs() : "
218  << "Constructing interpolation factors array for face gradient"
219  << endl;
220  }
221 
222  // Force the construction of the weighting factors
223  // needed to make sure deltaCoeffs are calculated for parallel runs.
224  weights();
225 
226  deltaCoeffs_ = new surfaceScalarField
227  (
228  IOobject
229  (
230  "deltaCoeffs",
231  mesh_.pointsInstance(),
232  mesh_,
235  false // Do not register
236  ),
237  mesh_,
240  );
241  surfaceScalarField& deltaCoeffs = *deltaCoeffs_;
242 
243 
244  // Set local references to mesh data
245  const volVectorField& C = mesh_.C();
246  const labelUList& owner = mesh_.owner();
247  const labelUList& neighbour = mesh_.neighbour();
248 
249  forAll(owner, facei)
250  {
251  deltaCoeffs[facei] = 1.0/mag(C[neighbour[facei]] - C[owner[facei]]);
252  }
253 
254  surfaceScalarField::Boundary& deltaCoeffsBf =
255  deltaCoeffs.boundaryFieldRef();
256 
257  forAll(deltaCoeffsBf, patchi)
258  {
259  deltaCoeffsBf[patchi] = 1.0/mag(mesh_.boundary()[patchi].delta());
260  }
261 }
262 
263 
264 void Foam::surfaceInterpolation::makeNonOrthDeltaCoeffs() const
265 {
266  if (debug)
267  {
268  Pout<< "surfaceInterpolation::makeNonOrthDeltaCoeffs() : "
269  << "Constructing interpolation factors array for face gradient"
270  << endl;
271  }
272 
273  // Force the construction of the weighting factors
274  // needed to make sure deltaCoeffs are calculated for parallel runs.
275  weights();
276 
277  nonOrthDeltaCoeffs_ = new surfaceScalarField
278  (
279  IOobject
280  (
281  "nonOrthDeltaCoeffs",
282  mesh_.pointsInstance(),
283  mesh_,
286  false // Do not register
287  ),
288  mesh_,
291  );
292  surfaceScalarField& nonOrthDeltaCoeffs = *nonOrthDeltaCoeffs_;
293 
294 
295  // Set local references to mesh data
296  const volVectorField& C = mesh_.C();
297  const labelUList& owner = mesh_.owner();
298  const labelUList& neighbour = mesh_.neighbour();
299  const surfaceVectorField& Sf = mesh_.Sf();
300  const surfaceScalarField& magSf = mesh_.magSf();
301 
302  forAll(owner, facei)
303  {
304  vector delta = C[neighbour[facei]] - C[owner[facei]];
305  vector unitArea = Sf[facei]/magSf[facei];
306 
307  // Standard cell-centre distance form
308  // NonOrthDeltaCoeffs[facei] = (unitArea & delta)/magSqr(delta);
309 
310  // Slightly under-relaxed form
311  // NonOrthDeltaCoeffs[facei] = 1.0/mag(delta);
312 
313  // More under-relaxed form
314  // NonOrthDeltaCoeffs[facei] = 1.0/(mag(unitArea & delta) + vSmall);
315 
316  // Stabilised form for bad meshes
317  nonOrthDeltaCoeffs[facei] = 1.0/max(unitArea & delta, 0.05*mag(delta));
318  }
319 
320  surfaceScalarField::Boundary& nonOrthDeltaCoeffsBf =
321  nonOrthDeltaCoeffs.boundaryFieldRef();
322 
323  forAll(nonOrthDeltaCoeffsBf, patchi)
324  {
325  vectorField delta(mesh_.boundary()[patchi].delta());
326 
327  nonOrthDeltaCoeffsBf[patchi] =
328  1.0/max(mesh_.boundary()[patchi].nf() & delta, 0.05*mag(delta));
329  }
330 }
331 
332 
333 void Foam::surfaceInterpolation::makeNonOrthCorrectionVectors() const
334 {
335  if (debug)
336  {
337  Pout<< "surfaceInterpolation::makeNonOrthCorrectionVectors() : "
338  << "Constructing non-orthogonal correction vectors"
339  << endl;
340  }
341 
342  nonOrthCorrectionVectors_ = new surfaceVectorField
343  (
344  IOobject
345  (
346  "nonOrthCorrectionVectors",
347  mesh_.pointsInstance(),
348  mesh_,
351  false // Do not register
352  ),
353  mesh_,
354  dimless,
356  );
357  surfaceVectorField& corrVecs = *nonOrthCorrectionVectors_;
358 
359  // Set local references to mesh data
360  const volVectorField& C = mesh_.C();
361  const labelUList& owner = mesh_.owner();
362  const labelUList& neighbour = mesh_.neighbour();
363  const surfaceVectorField& Sf = mesh_.Sf();
364  const surfaceScalarField& magSf = mesh_.magSf();
365  const surfaceScalarField& NonOrthDeltaCoeffs = nonOrthDeltaCoeffs();
366 
367  forAll(owner, facei)
368  {
369  vector unitArea = Sf[facei]/magSf[facei];
370  vector delta = C[neighbour[facei]] - C[owner[facei]];
371 
372  corrVecs[facei] = unitArea - delta*NonOrthDeltaCoeffs[facei];
373  }
374 
375  // Boundary correction vectors set to zero for boundary patches
376  // and calculated consistently with internal corrections for
377  // coupled patches
378 
379  surfaceVectorField::Boundary& corrVecsBf =
380  corrVecs.boundaryFieldRef();
381 
382  forAll(corrVecsBf, patchi)
383  {
384  fvsPatchVectorField& patchCorrVecs = corrVecsBf[patchi];
385 
386  if (!patchCorrVecs.coupled())
387  {
388  patchCorrVecs = Zero;
389  }
390  else
391  {
392  const fvsPatchScalarField& patchNonOrthDeltaCoeffs
393  = NonOrthDeltaCoeffs.boundaryField()[patchi];
394 
395  const fvPatch& p = patchCorrVecs.patch();
396 
397  const vectorField patchDeltas(mesh_.boundary()[patchi].delta());
398 
399  forAll(p, patchFacei)
400  {
401  vector unitArea =
402  Sf.boundaryField()[patchi][patchFacei]
403  /magSf.boundaryField()[patchi][patchFacei];
404 
405  const vector& delta = patchDeltas[patchFacei];
406 
407  patchCorrVecs[patchFacei] =
408  unitArea - delta*patchNonOrthDeltaCoeffs[patchFacei];
409  }
410  }
411  }
412 
413  if (debug)
414  {
415  Pout<< "surfaceInterpolation::makeNonOrthCorrectionVectors() : "
416  << "Finished constructing non-orthogonal correction vectors"
417  << endl;
418  }
419 }
420 
421 
423 {
424  Pout<< "surfaceInterpolation allocated :" << endl;
425 
426  if (weights_)
427  {
428  Pout<< " Weights" << endl;
429  }
430 
431  if (deltaCoeffs_)
432  {
433  Pout<< " Delta coefficients" << endl;
434  }
435 
436  if (nonOrthDeltaCoeffs_)
437  {
438  Pout<< " Non-orthogonal delta coefficients" << endl;
439  }
440 
441  if (nonOrthCorrectionVectors_)
442  {
443  Pout<< " Non-orthogonal correction vectors" << endl;
444  }
445 }
446 
447 
448 // ************************************************************************* //
scalar delta
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Generic GeometricField class.
GeometricBoundaryField< Type, GeoMesh, PrimitiveField > Boundary
Type of the boundary field.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
static const word & calculatedType()
Return the type of the calculated for of fvsPatchField.
Cell to surface interpolation scheme. Included in fvMesh.
bool movePoints()
Do what is necessary if the mesh has moved.
const surfaceVectorField & nonOrthCorrectionVectors() const
Return reference to non-orthogonality correction vectors.
const surfaceScalarField & weights() const
Return reference to linear difference weighting factors.
const surfaceScalarField & deltaCoeffs() const
Return reference to cell-centre difference coefficients.
surfaceInterpolation(const fvMesh &)
Construct given an fvMesh.
void printAllocated() const
Print a list of all the currently allocated data.
const surfaceScalarField & nonOrthDeltaCoeffs() const
Return reference to non-orthogonal cell-centre difference.
void clearOut()
Clear all geometry and addressing.
Template functions to aid in the implementation of demand driven data.
label patchi
const dimensionSet dimless
static const coefficient C("C", dimTemperature, 234.5)
Namespace for OpenFOAM.
static const zero Zero
Definition: zero.H:97
VolField< vector > volVectorField
Definition: volFieldsFwd.H:63
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:276
void deleteDemandDrivenData(DataType *&dataPtr)
SurfaceField< scalar > surfaceScalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Field< vector > vectorField
Specialisation of Field<T> for vector.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
SurfaceField< vector > surfaceVectorField
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
UList< label > labelUList
Definition: UList.H:65
fvsPatchField< vector > fvsPatchVectorField
fvsPatchField< scalar > fvsPatchScalarField
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
volScalarField & p
Foam::surfaceFields.