1 /*---------------------------------------------------------------------------*\
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 -------------------------------------------------------------------------------
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/>.
25 Face to edge interpolation scheme. Included in faMesh.
27 \*---------------------------------------------------------------------------*/
30 #include "areaFields.H"
31 #include "edgeFields.H"
32 #include "demandDrivenData.H"
33 #include "faPatchFields.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
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)
67 weightingFactors_(NULL),
68 differenceFactors_(NULL),
70 correctionVectors_(NULL),
72 skewCorrectionVectors_(NULL)
73 // leastSquarePvectors_(NULL),
74 // leastSquareNvectors_(NULL)
78 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
80 edgeInterpolation::~edgeInterpolation()
86 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
88 const edgeScalarField& edgeInterpolation::lPN() const
99 const edgeScalarField& edgeInterpolation::weights() const
101 if (!weightingFactors_)
106 return (*weightingFactors_);
110 const edgeScalarField& edgeInterpolation::deltaCoeffs() const
112 if (!differenceFactors_)
117 return (*differenceFactors_);
121 bool edgeInterpolation::orthogonal() const
123 if (orthogonal_ == false && !correctionVectors_)
125 makeCorrectionVectors();
132 const edgeVectorField& edgeInterpolation::correctionVectors() const
136 FatalErrorIn("edgeInterpolation::correctionVectors()")
137 << "cannot return correctionVectors; mesh is orthogonal"
138 << abort(FatalError);
141 return (*correctionVectors_);
145 bool edgeInterpolation::skew() const
147 if (skew_ == true && !skewCorrectionVectors_)
149 makeSkewCorrectionVectors();
156 const edgeVectorField& edgeInterpolation::skewCorrectionVectors() const
160 FatalErrorIn("edgeInterpolation::skewCorrectionVectors()")
161 << "cannot return skewCorrectionVectors; mesh is now skewed"
162 << abort(FatalError);
165 return (*skewCorrectionVectors_);
169 // const edgeVectorField& edgeInterpolation::leastSquarePvectors() const
171 // if (!leastSquarePvectors_)
173 // makeLeastSquareVectors();
176 // return (*leastSquarePvectors_);
180 // const edgeVectorField& edgeInterpolation::leastSquareNvectors() const
182 // if (!leastSquareNvectors_)
184 // makeLeastSquareVectors();
187 // return (*leastSquareNvectors_);
191 // Do what is neccessary if the mesh has moved
192 bool edgeInterpolation::movePoints() const
194 deleteDemandDrivenData(lPN_);
195 deleteDemandDrivenData(weightingFactors_);
196 deleteDemandDrivenData(differenceFactors_);
199 deleteDemandDrivenData(correctionVectors_);
202 deleteDemandDrivenData(skewCorrectionVectors_);
204 // deleteDemandDrivenData(leastSquarePvectors_);
205 // deleteDemandDrivenData(leastSquareNvectors_);
211 void edgeInterpolation::makeLPN() const
215 Info<< "edgeInterpolation::makeLPN() : "
216 << "Constructing geodesic distance between points P and N"
221 lPN_ = new edgeScalarField
226 faMesh_.time().constant(),
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();
246 vector curSkewCorrVec = vector::zero;
250 curSkewCorrVec = skewCorrectionVectors()[edgeI];
258 - faceCentres[owner[edgeI]]
264 faceCentres[neighbour[edgeI]]
269 lPN.internalField()[edgeI] = (lPE + lEN);
273 forAll(lPN.boundaryField(), patchI)
275 mesh().boundary()[patchI].makeDeltaCoeffs
277 lPN.boundaryField()[patchI]
280 lPN.boundaryField()[patchI] = 1.0/lPN.boundaryField()[patchI];
286 Info<< "edgeInterpolation::makeLPN() : "
287 << "Finished constructing geodesic distance PN"
293 void edgeInterpolation::makeWeights() const
297 Info<< "edgeInterpolation::makeWeights() : "
298 << "Constructing weighting factors for edge interpolation"
303 weightingFactors_ = new edgeScalarField
308 mesh()().pointsInstance(),
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();
328 vector curSkewCorrVec = vector::zero;
332 curSkewCorrVec = skewCorrectionVectors()[edgeI];
340 - faceCentres[owner[edgeI]]
346 faceCentres[neighbour[edgeI]]
351 weightingFactors.internalField()[edgeI] =
355 # ifdef BAD_MESH_STABILISATION
362 forAll(mesh().boundary(), patchI)
364 mesh().boundary()[patchI].makeWeights
366 weightingFactors.boundaryField()[patchI]
372 Info<< "edgeInterpolation::makeWeights() : "
373 << "Finished constructing weighting factors for face interpolation"
379 void edgeInterpolation::makeDeltaCoeffs() const
383 Info<< "edgeInterpolation::makeDeltaCoeffs() : "
384 << "Constructing differencing factors array for edge gradient"
388 // Force the construction of the weighting factors
389 // needed to make sure deltaCoeffs are calculated for parallel runs.
392 differenceFactors_ = new edgeScalarField
396 "differenceFactors_",
397 mesh()().pointsInstance(),
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();
423 // Edge normal - area normal
424 vector edgeNormal = lengths[edgeI]^edges[edgeI].vec(points);
425 edgeNormal /= mag(edgeNormal);
430 faceCentres[neighbour[edgeI]]
431 - faceCentres[owner[edgeI]];
434 edgeNormal*(edgeNormal&unitDelta);
436 unitDelta /= mag(unitDelta);
439 // Calc PN arc length
440 vector curSkewCorrVec = vector::zero;
444 curSkewCorrVec = skewCorrectionVectors()[edgeI];
452 - faceCentres[owner[edgeI]]
458 faceCentres[neighbour[edgeI]]
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);
477 forAll(DeltaCoeffs.boundaryField(), patchI)
479 mesh().boundary()[patchI].makeDeltaCoeffs
481 DeltaCoeffs.boundaryField()[patchI]
487 void edgeInterpolation::makeCorrectionVectors() const
491 Info<< "edgeInterpolation::makeCorrectionVectors() : "
492 << "Constructing non-orthogonal correction vectors"
496 correctionVectors_ = new edgeVectorField
501 mesh()().pointsInstance(),
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());
528 // Edge normal - area normal
529 vector edgeNormal = lengths[edgeI] ^ edges[edgeI].vec(points);
530 edgeNormal /= mag(edgeNormal);
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];
545 deltaCoeffs[edgeI] = 1.0/(unitDelta & edgeNormal);
547 // Edge correction vector
548 CorrVecs.internalField()[edgeI] =
550 - deltaCoeffs[edgeI]*unitDelta;
553 forAll(CorrVecs.boundaryField(), patchI)
555 faePatchVectorField& patchCorrVecs = CorrVecs.boundaryField()[patchI];
557 patchCorrVecs = vector::zero;
560 scalar NonOrthogCoeff = 0.0;
562 if (owner.size() > 0)
564 scalarField sinAlpha = deltaCoeffs*mag(CorrVecs.internalField());
566 forAll(sinAlpha, edgeI)
568 sinAlpha[edgeI] = max(-1, min(sinAlpha[edgeI], 1));
571 NonOrthogCoeff = max(Foam::asin(sinAlpha)*180.0/M_PI);
575 reduce(NonOrthogCoeff, maxOp<scalar>());
579 Info<< "edgeInterpolation::makeCorrectionVectors() : "
580 << "non-orthogonality coefficient = " << NonOrthogCoeff << " deg."
584 if (NonOrthogCoeff < 0.1)
587 deleteDemandDrivenData(correctionVectors_);
596 Info<< "edgeInterpolation::makeCorrectionVectors() : "
597 << "Finished constructing non-orthogonal correction vectors"
603 void edgeInterpolation::makeSkewCorrectionVectors() const
607 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
608 << "Constructing skew correction vectors"
612 skewCorrectionVectors_ = new edgeVectorField
616 "skewCorrectionVectors",
617 mesh()().pointsInstance(),
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)
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;
655 forAll(SkewCorrVecs.boundaryField(), patchI)
657 faePatchVectorField& patchSkewCorrVecs =
658 SkewCorrVecs.boundaryField()[patchI];
660 if (patchSkewCorrVecs.coupled())
662 const unallocLabelList& edgeFaces =
663 mesh().boundary()[patchI].edgeFaces();
665 const edgeList::subList patchEdges =
666 mesh().boundary()[patchI].patchSlice(edges);
669 C.boundaryField()[patchI].patchNeighbourField();
671 forAll (patchSkewCorrVecs, edgeI)
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;
689 patchSkewCorrVecs = vector::zero;
694 scalar skewCoeff = 0.0;
696 // Calculating PN arc length
697 scalarField lPN(owner.size());
699 forAll (owner, edgeI)
705 - SkewCorrVecs[edgeI]
712 + SkewCorrVecs[edgeI]
718 skewCoeff = max(mag(SkewCorrVecs.internalField())/mag(lPN));
723 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
724 << "skew coefficient = " << skewCoeff << endl;
730 deleteDemandDrivenData(skewCorrectionVectors_);
739 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
740 << "Finished constructing skew correction vectors"
746 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
748 } // End namespace Foam
750 // ************************************************************************* //