edgeInterpolation.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) 2016-2017 Wikki Ltd
9  Copyright (C) 2020-2022 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 "faMesh.H"
30 #include "areaFields.H"
31 #include "edgeFields.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
38 }
39 
40 
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
42 
44 :
45  faMesh_(fam),
46  orthogonal_(false),
47  skew_(true)
48 {}
49 
50 
51 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
52 
54 {
55  if (!lPNptr_)
56  {
57  makeLPN();
58  }
59 
60  return (*lPNptr_);
61 }
62 
63 
65 {
66  if (!weightingFactorsPtr_)
67  {
68  makeWeights();
69  }
70 
71  return (*weightingFactorsPtr_);
72 }
73 
74 
76 {
77  if (!differenceFactorsPtr_)
78  {
79  makeDeltaCoeffs();
80  }
81 
82  return (*differenceFactorsPtr_);
83 }
84 
85 
87 {
88  if (orthogonal_ == false && !correctionVectorsPtr_)
89  {
90  makeCorrectionVectors();
91  }
92 
93  return orthogonal_;
94 }
95 
96 
98 {
99  if (orthogonal())
100  {
102  (
103  IOobject
104  (
105  "correctionVectors",
106  mesh().pointsInstance(),
107  mesh().thisDb()
108  ),
109  mesh(),
111  );
112  }
113 
114  return (*correctionVectorsPtr_);
115 }
116 
117 
119 {
120  if (skew_ == true && !skewCorrectionVectorsPtr_)
121  {
122  makeSkewCorrectionVectors();
123  }
124 
125  return skew_;
126 }
127 
128 
131 {
132  if (!skew())
133  {
135  (
136  IOobject
137  (
138  "skewCorrectionVectors",
139  mesh().pointsInstance(),
140  mesh().thisDb()
141  ),
142  mesh(),
144  );
145  }
146 
147  return (*skewCorrectionVectorsPtr_);
148 }
149 
150 
152 {
153  lPNptr_.reset(nullptr);
154  weightingFactorsPtr_.reset(nullptr);
155  differenceFactorsPtr_.reset(nullptr);
156 
157  orthogonal_ = false;
158  correctionVectorsPtr_.reset(nullptr);
159 
160  skew_ = true;
161  skewCorrectionVectorsPtr_.reset(nullptr);
162 
163  return true;
164 }
165 
166 
167 const Foam::vector& Foam::edgeInterpolation::skewCorr(const label edgeI) const
168 {
169  #ifdef FA_SKEW_CORRECTION
170 
171  return
172  (
173  skewCorrectionVectorsPtr_
174  ? (*skewCorrectionVectorsPtr_)[edgeI]
175  : pTraits<vector>::zero
176  );
177 
178  #else
179 
180  return (*skewCorrectionVectorsPtr_)[edgeI];
181 
182  #endif
183 }
184 
185 
186 void Foam::edgeInterpolation::makeLPN() const
187 {
189  << "Constructing geodesic distance between points P and N"
190  << endl;
191 
192 
193  lPNptr_ = std::make_unique<edgeScalarField>
194  (
195  IOobject
196  (
197  "lPN",
198  mesh().time().constant(),
199  mesh().thisDb(),
203  ),
204  mesh(),
205  dimLength
206  );
207  edgeScalarField& lPN = *lPNptr_;
208 
209  // Set local references to mesh data
210  const edgeVectorField& edgeCentres = mesh().edgeCentres();
211  const areaVectorField& faceCentres = mesh().areaCentres();
212  const labelUList& owner = mesh().owner();
213  const labelUList& neighbour = mesh().neighbour();
214 
215  scalarField& lPNIn = lPN.primitiveFieldRef();
216 
217  // Calculate skewness correction vectors if necessary
218  (void) skew();
219 
220  forAll(owner, edgeI)
221  {
222  const vector& skewCorrEdge = skewCorr(edgeI);
223 
224  scalar lPE =
225  mag
226  (
227  edgeCentres[edgeI]
228  - skewCorrEdge
229  - faceCentres[owner[edgeI]]
230  );
231 
232  scalar lEN =
233  mag
234  (
235  faceCentres[neighbour[edgeI]]
236  - edgeCentres[edgeI]
237  + skewCorrEdge
238  );
239 
240  lPNIn[edgeI] = (lPE + lEN);
241 
242  // Do not allow any mag(val) < SMALL
243  if (mag(lPNIn[edgeI]) < SMALL)
244  {
245  lPNIn[edgeI] = SMALL;
246  }
247  }
248 
249 
250  forAll(lPN.boundaryField(), patchI)
251  {
252  mesh().boundary()[patchI].makeLPN
253  (
254  lPN.boundaryFieldRef()[patchI]
255  );
256  }
257 
258 
260  << "Finished constructing geodesic distance PN"
261  << endl;
262 }
263 
264 
265 void Foam::edgeInterpolation::makeWeights() const
266 {
268  << "Constructing weighting factors for edge interpolation"
269  << endl;
270 
271 
272  weightingFactorsPtr_ = std::make_unique<edgeScalarField>
273  (
274  IOobject
275  (
276  "weightingFactors",
277  mesh().pointsInstance(),
278  mesh().thisDb(),
282  ),
283  mesh(),
285  );
286  edgeScalarField& weightingFactors = *weightingFactorsPtr_;
287 
288 
289  // Set local references to mesh data
290  const edgeVectorField& edgeCentres = mesh().edgeCentres();
291  const areaVectorField& faceCentres = mesh().areaCentres();
292  const labelUList& owner = mesh().owner();
293  const labelUList& neighbour = mesh().neighbour();
294 
295  scalarField& weightingFactorsIn = weightingFactors.primitiveFieldRef();
296 
297  // Calculate skewness correction vectors if necessary
298  (void) skew();
299 
300  forAll(owner, edgeI)
301  {
302  const vector& skewCorrEdge = skewCorr(edgeI);
303 
304  scalar lPE =
305  mag
306  (
307  edgeCentres[edgeI]
308  - skewCorrEdge
309  - faceCentres[owner[edgeI]]
310  );
311 
312  scalar lEN =
313  mag
314  (
315  faceCentres[neighbour[edgeI]]
316  - edgeCentres[edgeI]
317  + skewCorrEdge
318  );
319 
320  // weight = (0,1]
321  const scalar lPN = lPE + lEN;
322 
323  if (mag(lPN) > SMALL)
324  {
325  weightingFactorsIn[edgeI] = lEN/lPN;
326  }
327  }
328 
329  forAll(mesh().boundary(), patchI)
330  {
331  mesh().boundary()[patchI].makeWeights
332  (
333  weightingFactors.boundaryFieldRef()[patchI]
334  );
335  }
336 
338  << "Finished constructing weighting factors for face interpolation"
339  << endl;
340 }
341 
342 
343 void Foam::edgeInterpolation::makeDeltaCoeffs() const
344 {
346  << "Constructing differencing factors array for edge gradient"
347  << endl;
348 
349  // Force the construction of the weighting factors
350  // needed to make sure deltaCoeffs are calculated for parallel runs.
351  weights();
352 
353  differenceFactorsPtr_ = std::make_unique<edgeScalarField>
354  (
355  IOobject
356  (
357  "differenceFactors",
358  mesh().pointsInstance(),
359  mesh().thisDb(),
363  ),
364  mesh(),
366  );
367  edgeScalarField& DeltaCoeffs = *differenceFactorsPtr_;
368  scalarField& dc = DeltaCoeffs.primitiveFieldRef();
369 
370  // Set local references to mesh data
371  const edgeVectorField& edgeCentres = mesh().edgeCentres();
372  const areaVectorField& faceCentres = mesh().areaCentres();
373  const labelUList& owner = mesh().owner();
374  const labelUList& neighbour = mesh().neighbour();
375  const edgeVectorField& lengths = mesh().Le();
376 
377  const edgeList& edges = mesh().edges();
378  const pointField& points = mesh().points();
379 
380  // Calculate skewness correction vectors if necessary
381  (void) skew();
382 
383  forAll(owner, edgeI)
384  {
385  // Edge normal - area normal
386  vector edgeNormal =
387  normalised(lengths[edgeI] ^ edges[edgeI].vec(points));
388 
389  // Unit delta vector
390  vector unitDelta =
391  faceCentres[neighbour[edgeI]]
392  - faceCentres[owner[edgeI]];
393 
394  unitDelta.removeCollinear(edgeNormal);
395  unitDelta.normalise();
396 
397 
398  const vector& skewCorrEdge = skewCorr(edgeI);
399 
400  scalar lPE =
401  mag
402  (
403  edgeCentres[edgeI]
404  - skewCorrEdge
405  - faceCentres[owner[edgeI]]
406  );
407 
408  scalar lEN =
409  mag
410  (
411  faceCentres[neighbour[edgeI]]
412  - edgeCentres[edgeI]
413  + skewCorrEdge
414  );
415 
416  scalar lPN = lPE + lEN;
417 
418 
419  // Edge normal - area tangent
420  edgeNormal = normalised(lengths[edgeI]);
421 
422  // Do not allow any mag(val) < SMALL
423  const scalar alpha = lPN*(unitDelta & edgeNormal);
424  if (mag(alpha) > SMALL)
425  {
426  dc[edgeI] = scalar(1)/max(alpha, 0.05*lPN);
427  }
428  }
429 
430 
431  forAll(DeltaCoeffs.boundaryField(), patchI)
432  {
433  mesh().boundary()[patchI].makeDeltaCoeffs
434  (
435  DeltaCoeffs.boundaryFieldRef()[patchI]
436  );
437  }
438 }
439 
440 
441 void Foam::edgeInterpolation::makeCorrectionVectors() const
442 {
444  << "Constructing non-orthogonal correction vectors"
445  << endl;
446 
447  correctionVectorsPtr_ = std::make_unique<edgeVectorField>
448  (
449  IOobject
450  (
451  "correctionVectors",
452  mesh().pointsInstance(),
453  mesh().thisDb(),
457  ),
458  mesh(),
459  dimless
460  );
461  edgeVectorField& CorrVecs = *correctionVectorsPtr_;
462 
463  // Set local references to mesh data
464  const areaVectorField& faceCentres = mesh().areaCentres();
465 
466  const labelUList& owner = mesh().owner();
467  const labelUList& neighbour = mesh().neighbour();
468 
469  const edgeVectorField& lengths = mesh().Le();
470 
471  const edgeList& edges = mesh().edges();
472  const pointField& points = mesh().points();
473 
474  scalarField deltaCoeffs(owner.size(), SMALL);
475 
476  vectorField& CorrVecsIn = CorrVecs.primitiveFieldRef();
477 
478  forAll(owner, edgeI)
479  {
480  // Edge normal - area normal
481  vector edgeNormal =
482  normalised(lengths[edgeI] ^ edges[edgeI].vec(points));
483 
484  // Unit delta vector
485  vector unitDelta =
486  faceCentres[neighbour[edgeI]]
487  - faceCentres[owner[edgeI]];
488 
489  unitDelta.removeCollinear(edgeNormal);
490  unitDelta.normalise();
491 
492  // Edge normal - area tangent
493  edgeNormal = normalised(lengths[edgeI]);
494 
495  // Do not allow any mag(val) < SMALL
496  const scalar alpha = unitDelta & edgeNormal;
497  if (mag(alpha) > SMALL)
498  {
499  deltaCoeffs[edgeI] = scalar(1)/alpha;
500  }
501 
502  // Edge correction vector
503  CorrVecsIn[edgeI] =
504  edgeNormal
505  - deltaCoeffs[edgeI]*unitDelta;
506  }
507 
508 
509  edgeVectorField::Boundary& CorrVecsbf = CorrVecs.boundaryFieldRef();
510 
511  forAll(CorrVecs.boundaryField(), patchI)
512  {
513  mesh().boundary()[patchI].makeCorrectionVectors(CorrVecsbf[patchI]);
514  }
515 
516 
518  << "Finished constructing non-orthogonal correction vectors"
519  << endl;
520 }
521 
522 
523 void Foam::edgeInterpolation::makeSkewCorrectionVectors() const
524 {
526  << "Constructing skew correction vectors"
527  << endl;
528 
529  skewCorrectionVectorsPtr_ = std::make_unique<edgeVectorField>
530  (
531  IOobject
532  (
533  "skewCorrectionVectors",
534  mesh().pointsInstance(),
535  mesh().thisDb(),
539  ),
540  mesh(),
542  );
543  edgeVectorField& SkewCorrVecs = *skewCorrectionVectorsPtr_;
544 
545  // Set local references to mesh data
546  const areaVectorField& C = mesh().areaCentres();
547  const edgeVectorField& Ce = mesh().edgeCentres();
548 
549  const labelUList& owner = mesh().owner();
550  const labelUList& neighbour = mesh().neighbour();
551 
552  const pointField& points = mesh().points();
553  const edgeList& edges = mesh().edges();
554 
555 
556  forAll(neighbour, edgeI)
557  {
558  const vector& P = C[owner[edgeI]];
559  const vector& N = C[neighbour[edgeI]];
560  const vector& S = points[edges[edgeI].start()];
561 
562  // (T:Eq. 5.4)
563  const vector d(N - P);
564  const vector e(edges[edgeI].vec(points));
565  const vector de(d^e);
566  const scalar alpha = magSqr(de);
567 
568  if (alpha < SMALL)
569  {
570  // Too small - skew correction remains zero
571  continue;
572  }
573  const scalar beta = -((d^(S - P)) & de)/alpha;
574 
575  // (T:Eq. 5.3)
576  const vector E(S + beta*e);
577 
578  SkewCorrVecs[edgeI] = Ce[edgeI] - E;
579  }
580 
581 
582  edgeVectorField::Boundary& bSkewCorrVecs =
583  SkewCorrVecs.boundaryFieldRef();
584 
585  forAll(SkewCorrVecs.boundaryField(), patchI)
586  {
587  faePatchVectorField& patchSkewCorrVecs = bSkewCorrVecs[patchI];
588 
589  if (patchSkewCorrVecs.coupled())
590  {
591  const labelUList& edgeFaces =
592  mesh().boundary()[patchI].edgeFaces();
593 
594  const edgeList::subList patchEdges =
595  mesh().boundary()[patchI].patchSlice(edges);
596 
597  vectorField ngbC(C.boundaryField()[patchI].patchNeighbourField());
598 
599  forAll(patchSkewCorrVecs, edgeI)
600  {
601  const vector& P = C[edgeFaces[edgeI]];
602  const vector& N = ngbC[edgeI];
603  const vector& S = points[patchEdges[edgeI].start()];
604 
605  // (T:Eq. 5.4)
606  const vector d(N - P);
607  const vector e(patchEdges[edgeI].vec(points));
608  const vector de(d^e);
609  const scalar alpha = magSqr(de);
610 
611  if (alpha < SMALL)
612  {
613  // Too small - skew correction remains zero
614  continue;
615  }
616  const scalar beta = -((d^(S - P)) & de)/alpha;
617 
618  const vector E(S + beta*e);
619 
620  patchSkewCorrVecs[edgeI] =
621  Ce.boundaryField()[patchI][edgeI] - E;
622  }
623  }
624  }
625 
626  #ifdef FA_SKEW_CORRECTION
627 
628  constexpr scalar maxSkewRatio = 0.1;
629  scalar skewCoeff = 0;
630 
631  forAll(own, edgeI)
632  {
633  const scalar magSkew = mag(skewCorrVecs[edgeI]);
634 
635  const scalar lPN =
636  mag
637  (
638  Ce[edgeI]
639  - skewCorrVecs[edgeI]
640  - C[owner[edgeI]]
641  )
642  + mag
643  (
644  C[neighbour[edgeI]]
645  - Ce[edgeI]
646  + skewCorrVecs[edgeI]
647  );
648 
649  const scalar ratio = magSkew/lPN;
650 
651  if (skewCoeff < ratio)
652  {
653  skewCoeff = ratio;
654 
655  if (skewCoeff > maxSkewRatio)
656  {
657  break;
658  }
659  }
660  }
661 
663  << "skew coefficient = " << skewCoeff << endl;
664 
665  if (skewCoeff < maxSkewRatio)
666  {
667  skewCorrectionVectorsPtr_.reset(nullptr);
668  }
669 
670  #endif
671 
672  skew_ = bool(skewCorrectionVectorsPtr_);
673 
674 
676  << "Finished constructing skew correction vectors"
677  << endl;
678 }
679 
680 
681 // ************************************************************************* //
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:133
faceListList boundary
const edgeVectorField & skewCorrectionVectors() const
Return reference to skew vectors array.
const edgeScalarField & weights() const
Return reference to weighting factors array.
const edgeScalarField & deltaCoeffs() const
Return reference to difference factors array.
const edgeVectorField & correctionVectors() const
Return reference to non-orthogonality correction vectors array.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
dimensionedTensor skew(const dimensionedTensor &dt)
edgeInterpolation(const edgeInterpolation &)=delete
No copy construct.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
Face to edge interpolation scheme. Included in faMesh.
Vector< Cmpt > & normalise(const scalar tol=ROOTVSMALL)
Inplace normalise the vector by its magnitude.
Definition: VectorI.H:114
GeometricBoundaryField< Type, PatchField, GeoMesh > Boundary
Type of boundary fields.
SubList< edge > subList
Declare type of subList.
Definition: List.H:149
Ignore writing from objectRegistry::writeObject()
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
Definition: quaternionI.H:674
const dimensionSet dimless
Dimensionless.
bool movePoints() const
Do what is necessary if the mesh has moved.
const edgeScalarField & lPN() const
Return reference to PN geodesic distance.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
const labelUList & neighbour() const
Internal face neighbour.
Definition: fvMesh.H:580
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1063
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
const pointField & points
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ const Field< vector > edgeCentres(faMeshTools::flattenEdgeField(aMesh.edgeCentres(), true))
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
#define DebugInFunction
Report an information message using Foam::Info.
GeometricField< vector, faePatchField, edgeMesh > edgeVectorField
Definition: edgeFieldsFwd.H:60
bool orthogonal() const
Return whether mesh is orthogonal or not.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
Vector< scalar > vector
Definition: vector.H:57
GeometricField< scalar, faePatchField, edgeMesh > edgeScalarField
Definition: edgeFieldsFwd.H:43
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
defineTypeNameAndDebug(combustionModel, 0)
volScalarField & C
bool skew() const
Return whether mesh is skew or not.
const Vector< label > N(dict.get< Vector< label >>("N"))
const labelUList & owner() const
Internal face owner. Note bypassing virtual mechanism so.
Definition: fvMesh.H:572
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Nothing to be read.
faePatchField< vector > faePatchVectorField
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition: fvMesh.H:395
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
Field< vector > vectorField
Specialisation of Field<T> for vector.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Vector< Cmpt > & removeCollinear(const Vector< Cmpt > &unitVec)
Inplace removal of components that are collinear to the given unit vector.
Definition: VectorI.H:136
Calculate the matrix for the second temporal derivative.
GeometricField< vector, faPatchField, areaMesh > areaVectorField
Definition: areaFieldsFwd.H:76
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
Do not request registration (bool: false)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127