Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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
35namespace Foam
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();
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
167const Foam::vector& Foam::edgeInterpolation::skewCorr(const label edgeI) const
168{
169 #ifdef FA_SKEW_CORRECTION
170
171 return
172 (
173 skewCorrectionVectorsPtr_
174 ? (*skewCorrectionVectorsPtr_)[edgeI]
176 );
177
178 #else
179
180 return (*skewCorrectionVectorsPtr_)[edgeI];
181
182 #endif
183}
184
185
186void 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 (
196 (
197 "lPN",
198 mesh().time().constant(),
199 mesh().thisDb(),
203 ),
204 mesh(),
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
265void Foam::edgeInterpolation::makeWeights() const
266{
268 << "Constructing weighting factors for edge interpolation"
269 << endl;
270
271
272 weightingFactorsPtr_ = std::make_unique<edgeScalarField>
273 (
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
343void 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 (
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
441void Foam::edgeInterpolation::makeCorrectionVectors() const
442{
444 << "Constructing non-orthogonal correction vectors"
445 << endl;
446
447 correctionVectorsPtr_ = std::make_unique<edgeVectorField>
448 (
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
523void Foam::edgeInterpolation::makeSkewCorrectionVectors() const
524{
526 << "Constructing skew correction vectors"
527 << endl;
528
529 skewCorrectionVectorsPtr_ = std::make_unique<edgeVectorField>
530 (
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// ************************************************************************* //
Info<< " "<< writer.output().name()<< nl;}{ const Field< vector > edgeCentres(faMeshTools::flattenEdgeField(aMesh.edgeCentres(), true))
Graphite solid properties.
Definition C.H:49
GeometricBoundaryField< vector, faePatchField, edgeMesh > Boundary
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
SubList< edge > subList
Definition List.H:129
Face to edge interpolation scheme. Included in faMesh.
bool movePoints() const
Do what is necessary if the mesh has moved.
edgeInterpolation(const edgeInterpolation &)=delete
No copy construct.
const edgeScalarField & deltaCoeffs() const
Return reference to difference factors array.
const edgeVectorField & correctionVectors() const
Return reference to non-orthogonality correction vectors array.
bool orthogonal() const
Return whether mesh is orthogonal or not.
const edgeScalarField & lPN() const
Return reference to PN geodesic distance.
const edgeScalarField & weights() const
Return reference to weighting factors array.
bool skew() const
Return whether mesh is skew or not.
const edgeVectorField & skewCorrectionVectors() const
Return reference to skew vectors array.
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition faMesh.H:140
const labelUList & owner() const
Internal face owner. Note bypassing virtual mechanism so.
Definition fvMesh.H:572
const labelUList & neighbour() const
Internal face neighbour.
Definition fvMesh.H:580
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition fvMesh.H:395
A traits class, which is primarily used for primitives and vector-space.
Definition pTraits.H:64
constant condensation/saturation model.
virtual const pointField & points() const
Return raw points.
Definition polyMesh.C:1063
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition tmp.H:215
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
faceListList boundary
dynamicFvMesh & mesh
const pointField & points
#define DebugInFunction
Report an information message using Foam::Info.
Different types of constants.
Namespace for OpenFOAM.
List< edge > edgeList
List of edge.
Definition edgeList.H:32
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
GeometricField< vector, faePatchField, edgeMesh > edgeVectorField
const dimensionSet dimless
Dimensionless.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
GeometricField< vector, faPatchField, areaMesh > areaVectorField
GeometricField< scalar, faePatchField, edgeMesh > edgeScalarField
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
faePatchField< vector > faePatchVectorField
vectorField pointField
pointField is a vectorField.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Vector< scalar > vector
Definition vector.H:57
UList< label > labelUList
A UList of labels.
Definition UList.H:75
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dimensionedTensor skew(const dimensionedTensor &dt)
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Calculate the matrix for the second temporal derivative.
volScalarField & alpha
volScalarField & e
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
const Vector< label > N(dict.get< Vector< label > >("N"))