Forward compatibility: flex
[foam-extend-3.2.git] / src / finiteArea / interpolation / edgeInterpolation / edgeInterpolation.C
blob156f5ef1e0d572f5cc02a02f75e33a5615cf6ebb
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Description
25     Face to edge interpolation scheme. Included in faMesh.
27 \*---------------------------------------------------------------------------*/
29 #include "faMesh.H"
30 #include "areaFields.H"
31 #include "edgeFields.H"
32 #include "demandDrivenData.H"
33 #include "faPatchFields.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 namespace Foam
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(edgeInterpolation, 0);
45 // * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
47 void edgeInterpolation::clearOut()
49     deleteDemandDrivenData(lPN_);
50     deleteDemandDrivenData(weightingFactors_);
51     deleteDemandDrivenData(differenceFactors_);
52     deleteDemandDrivenData(correctionVectors_);
53     deleteDemandDrivenData(skewCorrectionVectors_);
54 //     deleteDemandDrivenData(leastSquarePvectors_);
55 //     deleteDemandDrivenData(leastSquareNvectors_);
59 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
61 edgeInterpolation::edgeInterpolation(const faMesh& fam)
63     faMesh_(fam),
64     schemesDict_(fam()),
65     solutionDict_(fam()),
66     lPN_(NULL),
67     weightingFactors_(NULL),
68     differenceFactors_(NULL),
69     orthogonal_(false),
70     correctionVectors_(NULL),
71     skew_(true),
72     skewCorrectionVectors_(NULL)
73 //     leastSquarePvectors_(NULL),
74 //     leastSquareNvectors_(NULL)
78 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
80 edgeInterpolation::~edgeInterpolation()
82     clearOut();
86 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
88 const edgeScalarField& edgeInterpolation::lPN() const
90     if (!lPN_)
91     {
92         makeLPN();
93     }
95     return (*lPN_);
99 const edgeScalarField& edgeInterpolation::weights() const
101     if (!weightingFactors_)
102     {
103         makeWeights();
104     }
106     return (*weightingFactors_);
110 const edgeScalarField& edgeInterpolation::deltaCoeffs() const
112     if (!differenceFactors_)
113     {
114         makeDeltaCoeffs();
115     }
117     return (*differenceFactors_);
121 bool edgeInterpolation::orthogonal() const
123     if (orthogonal_ == false && !correctionVectors_)
124     {
125         makeCorrectionVectors();
126     }
128     return orthogonal_;
132 const edgeVectorField& edgeInterpolation::correctionVectors() const
134     if (orthogonal())
135     {
136         FatalErrorIn("edgeInterpolation::correctionVectors()")
137             << "cannot return correctionVectors; mesh is orthogonal"
138             << abort(FatalError);
139     }
141     return (*correctionVectors_);
145 bool edgeInterpolation::skew() const
147     if (skew_ == true && !skewCorrectionVectors_)
148     {
149         makeSkewCorrectionVectors();
150     }
152     return skew_;
156 const edgeVectorField& edgeInterpolation::skewCorrectionVectors() const
158     if (!skew())
159     {
160         FatalErrorIn("edgeInterpolation::skewCorrectionVectors()")
161             << "cannot return skewCorrectionVectors; mesh is now skewed"
162             << abort(FatalError);
163     }
165     return (*skewCorrectionVectors_);
169 // const edgeVectorField& edgeInterpolation::leastSquarePvectors() const
170 // {
171 //     if (!leastSquarePvectors_)
172 //     {
173 //         makeLeastSquareVectors();
174 //     }
176 //     return (*leastSquarePvectors_);
177 // }
180 // const edgeVectorField& edgeInterpolation::leastSquareNvectors() const
181 // {
182 //     if (!leastSquareNvectors_)
183 //     {
184 //         makeLeastSquareVectors();
185 //     }
187 //     return (*leastSquareNvectors_);
188 // }
191 // Do what is neccessary if the mesh has moved
192 bool edgeInterpolation::movePoints() const
194     deleteDemandDrivenData(lPN_);
195     deleteDemandDrivenData(weightingFactors_);
196     deleteDemandDrivenData(differenceFactors_);
198     orthogonal_ = false;
199     deleteDemandDrivenData(correctionVectors_);
201     skew_ = true;
202     deleteDemandDrivenData(skewCorrectionVectors_);
204 //     deleteDemandDrivenData(leastSquarePvectors_);
205 //     deleteDemandDrivenData(leastSquareNvectors_);
207     return true;
211 void edgeInterpolation::makeLPN() const
213     if (debug)
214     {
215         Info<< "edgeInterpolation::makeLPN() : "
216             << "Constructing geodesic distance between points P and N"
217             << endl;
218     }
221     lPN_ = new edgeScalarField
222     (
223         IOobject
224         (
225             "lPN",
226             faMesh_.time().constant(),
227             faMesh_.db(),
228             IOobject::NO_READ,
229             IOobject::NO_WRITE,
230             false
231         ),
232         mesh(),
233         dimLength
234     );
235     edgeScalarField& lPN = *lPN_;
238     // Set local references to mesh data
239     const edgeVectorField& edgeCentres = mesh().edgeCentres();
240     const areaVectorField& faceCentres = mesh().areaCentres();
241     const unallocLabelList& owner = mesh().owner();
242     const unallocLabelList& neighbour = mesh().neighbour();
244     forAll(owner, edgeI)
245     {
246         vector curSkewCorrVec = vector::zero;
248         if (skew())
249         {
250             curSkewCorrVec = skewCorrectionVectors()[edgeI];
251         }
253         scalar lPE =
254             mag
255             (
256                 edgeCentres[edgeI]
257               - curSkewCorrVec
258               - faceCentres[owner[edgeI]]
259             );
261         scalar lEN =
262             mag
263             (
264                 faceCentres[neighbour[edgeI]]
265               - edgeCentres[edgeI]
266               + curSkewCorrVec
267             );
269         lPN.internalField()[edgeI] = (lPE + lEN);
270     }
273     forAll(lPN.boundaryField(), patchI)
274     {
275         mesh().boundary()[patchI].makeDeltaCoeffs
276         (
277             lPN.boundaryField()[patchI]
278         );
280         lPN.boundaryField()[patchI] = 1.0/lPN.boundaryField()[patchI];
281     }
284     if (debug)
285     {
286         Info<< "edgeInterpolation::makeLPN() : "
287             << "Finished constructing geodesic distance PN"
288             << endl;
289     }
293 void edgeInterpolation::makeWeights() const
295     if (debug)
296     {
297         Info<< "edgeInterpolation::makeWeights() : "
298             << "Constructing weighting factors for edge interpolation"
299             << endl;
300     }
303     weightingFactors_ = new edgeScalarField
304     (
305         IOobject
306         (
307             "weightingFactors",
308             mesh()().pointsInstance(),
309             mesh()(),
310             IOobject::NO_READ,
311             IOobject::NO_WRITE,
312             false
313         ),
314         mesh(),
315         dimless
316     );
317     edgeScalarField& weightingFactors = *weightingFactors_;
320     // Set local references to mesh data
321     const edgeVectorField& edgeCentres = mesh().edgeCentres();
322     const areaVectorField& faceCentres = mesh().areaCentres();
323     const unallocLabelList& owner = mesh().owner();
324     const unallocLabelList& neighbour = mesh().neighbour();
326     forAll(owner, edgeI)
327     {
328         vector curSkewCorrVec = vector::zero;
330         if (skew())
331         {
332             curSkewCorrVec = skewCorrectionVectors()[edgeI];
333         }
335         scalar lPE =
336             mag
337             (
338                 edgeCentres[edgeI]
339               - curSkewCorrVec
340               - faceCentres[owner[edgeI]]
341             );
343         scalar lEN =
344             mag
345             (
346                 faceCentres[neighbour[edgeI]]
347               - edgeCentres[edgeI]
348               + curSkewCorrVec
349             );
351         weightingFactors.internalField()[edgeI] =
352             lEN
353             /(
354                 lPE
355 #               ifdef BAD_MESH_STABILISATION
356               + VSMALL
357 #               endif
358               + lEN
359             );
360     }
362     forAll(mesh().boundary(), patchI)
363     {
364         mesh().boundary()[patchI].makeWeights
365         (
366             weightingFactors.boundaryField()[patchI]
367         );
368     }
370     if (debug)
371     {
372         Info<< "edgeInterpolation::makeWeights() : "
373             << "Finished constructing weighting factors for face interpolation"
374             << endl;
375     }
379 void edgeInterpolation::makeDeltaCoeffs() const
381     if (debug)
382     {
383         Info<< "edgeInterpolation::makeDeltaCoeffs() : "
384             << "Constructing differencing factors array for edge gradient"
385             << endl;
386     }
388     // Force the construction of the weighting factors
389     // needed to make sure deltaCoeffs are calculated for parallel runs.
390     weights();
392     differenceFactors_ = new edgeScalarField
393     (
394         IOobject
395         (
396             "differenceFactors_",
397             mesh()().pointsInstance(),
398             mesh()(),
399             IOobject::NO_READ,
400             IOobject::NO_WRITE,
401             false
402         ),
403         mesh(),
404         dimless/dimLength
405     );
406     edgeScalarField& DeltaCoeffs = *differenceFactors_;
407     scalarField& dc = DeltaCoeffs.internalField();
410     // Set local references to mesh data
411     const edgeVectorField& edgeCentres = mesh().edgeCentres();
412     const areaVectorField& faceCentres = mesh().areaCentres();
413     const unallocLabelList& owner = mesh().owner();
414     const unallocLabelList& neighbour = mesh().neighbour();
415     const edgeVectorField& lengths = mesh().Le();
417     const edgeList& edges = mesh().edges();
418     const pointField& points = mesh().points();
421     forAll(owner, edgeI)
422     {
423         // Edge normal - area normal
424         vector edgeNormal = lengths[edgeI]^edges[edgeI].vec(points);
425         edgeNormal /= mag(edgeNormal);
428         // Unit delta vector
429         vector unitDelta =
430             faceCentres[neighbour[edgeI]]
431           - faceCentres[owner[edgeI]];
433         unitDelta -=
434             edgeNormal*(edgeNormal&unitDelta);
436         unitDelta /= mag(unitDelta);
439         // Calc PN arc length
440         vector curSkewCorrVec = vector::zero;
442         if (skew())
443         {
444             curSkewCorrVec = skewCorrectionVectors()[edgeI];
445         }
447         scalar lPE =
448             mag
449             (
450                 edgeCentres[edgeI]
451               - curSkewCorrVec
452               - faceCentres[owner[edgeI]]
453             );
455         scalar lEN =
456             mag
457             (
458                 faceCentres[neighbour[edgeI]]
459               - edgeCentres[edgeI]
460               + curSkewCorrVec
461             );
463         scalar lPN = lPE + lEN;
466         // Edge normal - area tangent
467         edgeNormal = lengths[edgeI]/mag(lengths[edgeI]);
469         // Delta coefficient as per definition
470 //         dc[edgeI] = 1.0/(lPN*(unitDelta & edgeNormal));
472         // Stabilised form for bad meshes.  HJ, 23/Jul/2009
473         dc[edgeI] = 1.0/max((lPN*(unitDelta & edgeNormal)), 0.05*lPN);
474     }
477     forAll(DeltaCoeffs.boundaryField(), patchI)
478     {
479         mesh().boundary()[patchI].makeDeltaCoeffs
480         (
481             DeltaCoeffs.boundaryField()[patchI]
482         );
483     }
487 void edgeInterpolation::makeCorrectionVectors() const
489     if (debug)
490     {
491         Info<< "edgeInterpolation::makeCorrectionVectors() : "
492             << "Constructing non-orthogonal correction vectors"
493             << endl;
494     }
496     correctionVectors_ = new edgeVectorField
497     (
498         IOobject
499         (
500             "correctionVectors",
501             mesh()().pointsInstance(),
502             mesh()(),
503             IOobject::NO_READ,
504             IOobject::NO_WRITE,
505             false
506         ),
507         mesh(),
508         dimless
509     );
510     edgeVectorField& CorrVecs = *correctionVectors_;
512     // Set local references to mesh data
513     const areaVectorField& faceCentres = mesh().areaCentres();
515     const unallocLabelList& owner = mesh().owner();
516     const unallocLabelList& neighbour = mesh().neighbour();
518     const edgeVectorField& lengths = mesh().Le();
519     const edgeScalarField& magLengths = mesh().magLe();
521     const edgeList& edges = mesh().edges();
522     const pointField& points = mesh().points();
524     scalarField deltaCoeffs(owner.size());
526     forAll(owner, edgeI)
527     {
528         // Edge normal - area normal
529         vector edgeNormal = lengths[edgeI] ^ edges[edgeI].vec(points);
530         edgeNormal /= mag(edgeNormal);
532         // Unit delta vector
533         vector unitDelta =
534             faceCentres[neighbour[edgeI]]
535           - faceCentres[owner[edgeI]];
537         unitDelta -= edgeNormal*(edgeNormal & unitDelta);
539         unitDelta /= mag(unitDelta);
541         // Edge normal - area tangent
542         edgeNormal = lengths[edgeI]/magLengths[edgeI];
544         // Delta coeffs
545         deltaCoeffs[edgeI] = 1.0/(unitDelta & edgeNormal);
547         // Edge correction vector
548         CorrVecs.internalField()[edgeI] =
549             edgeNormal
550           - deltaCoeffs[edgeI]*unitDelta;
551     }
553     forAll(CorrVecs.boundaryField(), patchI)
554     {
555         faePatchVectorField& patchCorrVecs = CorrVecs.boundaryField()[patchI];
557         patchCorrVecs = vector::zero;
558     }
560     scalar NonOrthogCoeff = 0.0;
562     if (owner.size() > 0)
563     {
564         scalarField sinAlpha = deltaCoeffs*mag(CorrVecs.internalField());
566         forAll(sinAlpha, edgeI)
567         {
568             sinAlpha[edgeI] = max(-1, min(sinAlpha[edgeI], 1));
569         }
571         NonOrthogCoeff = max(Foam::asin(sinAlpha)*180.0/M_PI);
572     }
574     // ZT, 12/Nov/2010
575     reduce(NonOrthogCoeff, maxOp<scalar>());
577     if (debug)
578     {
579         Info<< "edgeInterpolation::makeCorrectionVectors() : "
580             << "non-orthogonality coefficient = " << NonOrthogCoeff << " deg."
581             << endl;
582     }
584     if (NonOrthogCoeff < 0.1)
585     {
586         orthogonal_ = true;
587         deleteDemandDrivenData(correctionVectors_);
588     }
589     else
590     {
591         orthogonal_ = false;
592     }
594     if (debug)
595     {
596         Info<< "edgeInterpolation::makeCorrectionVectors() : "
597             << "Finished constructing non-orthogonal correction vectors"
598             << endl;
599     }
603 void edgeInterpolation::makeSkewCorrectionVectors() const
605     if (debug)
606     {
607         Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
608             << "Constructing skew correction vectors"
609             << endl;
610     }
612     skewCorrectionVectors_ = new edgeVectorField
613     (
614         IOobject
615         (
616             "skewCorrectionVectors",
617             mesh()().pointsInstance(),
618             mesh()(),
619             IOobject::NO_READ,
620             IOobject::NO_WRITE,
621             false
622         ),
623         mesh(),
624         dimless
625     );
626     edgeVectorField& SkewCorrVecs = *skewCorrectionVectors_;
628     // Set local references to mesh data
629     const areaVectorField& C = mesh().areaCentres();
630     const edgeVectorField& Ce = mesh().edgeCentres();
632     const unallocLabelList& owner = mesh().owner();
633     const unallocLabelList& neighbour = mesh().neighbour();
635     const pointField& points = mesh().points();
636     const edgeList& edges = mesh().edges();
639     forAll(neighbour, edgeI)
640     {
641         vector P = C[owner[edgeI]];
642         vector N = C[neighbour[edgeI]];
643         vector S = points[edges[edgeI].start()];
644         vector e = edges[edgeI].vec(points);
646         scalar alpha = - ( ( (N - P)^(S - P) )&( (N - P)^e ) )/
647             ( ( (N - P)^e )&( (N - P)^e ) );
649         vector E = S + alpha*e;
651         SkewCorrVecs[edgeI] = Ce[edgeI] - E;
652     }
655     forAll(SkewCorrVecs.boundaryField(), patchI)
656     {
657         faePatchVectorField& patchSkewCorrVecs =
658             SkewCorrVecs.boundaryField()[patchI];
660         if (patchSkewCorrVecs.coupled())
661         {
662             const unallocLabelList& edgeFaces =
663                 mesh().boundary()[patchI].edgeFaces();
665             const edgeList::subList patchEdges =
666                 mesh().boundary()[patchI].patchSlice(edges);
668             vectorField ngbC =
669                 C.boundaryField()[patchI].patchNeighbourField();
671             forAll (patchSkewCorrVecs, edgeI)
672             {
673                 vector P = C[edgeFaces[edgeI]];
674                 vector N = ngbC[edgeI];
675                 vector S = points[patchEdges[edgeI].start()];
676                 vector e = patchEdges[edgeI].vec(points);
678                 scalar alpha = - ( ( (N - P)^(S - P) )&( (N - P)^e ) )/
679                     ( ( (N - P)^e )&( (N - P)^e ) );
681                 vector E = S + alpha*e;
683                 patchSkewCorrVecs[edgeI] =
684                     Ce.boundaryField()[patchI][edgeI] - E;
685             }
686         }
687         else
688         {
689             patchSkewCorrVecs = vector::zero;
690         }
691     }
694     scalar skewCoeff = 0.0;
696     // Calculating PN arc length
697     scalarField lPN(owner.size());
699     forAll (owner, edgeI)
700     {
701         lPN[edgeI] =
702             mag
703             (
704                 Ce[edgeI]
705               - SkewCorrVecs[edgeI]
706               - C[owner[edgeI]]
707             )
708           + mag
709             (
710                 C[neighbour[edgeI]]
711               - Ce[edgeI]
712               + SkewCorrVecs[edgeI]
713             );
714     }
716     if (lPN.size() > 0)
717     {
718         skewCoeff = max(mag(SkewCorrVecs.internalField())/mag(lPN));
719     }
721     if (debug)
722     {
723         Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
724             << "skew coefficient = " << skewCoeff << endl;
725     }
727     if (skewCoeff < 0.1)
728     {
729         skew_ = false;
730         deleteDemandDrivenData(skewCorrectionVectors_);
731     }
732     else
733     {
734         skew_ = true;
735     }
737     if (debug)
738     {
739         Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
740             << "Finished constructing skew correction vectors"
741             << endl;
742     }
746 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
748 } // End namespace Foam
750 // ************************************************************************* //