1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Face to edge interpolation scheme. Included in faMesh.
28 \*---------------------------------------------------------------------------*/
31 #include "areaFields.H"
32 #include "edgeFields.H"
33 #include "demandDrivenData.H"
34 #include "faPatchFields.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(edgeInterpolation, 0);
46 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
48 void edgeInterpolation::clearOut()
50 deleteDemandDrivenData(lPN_);
51 deleteDemandDrivenData(weightingFactors_);
52 deleteDemandDrivenData(differenceFactors_);
53 deleteDemandDrivenData(correctionVectors_);
54 deleteDemandDrivenData(skewCorrectionVectors_);
55 // deleteDemandDrivenData(leastSquarePvectors_);
56 // deleteDemandDrivenData(leastSquareNvectors_);
60 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
62 edgeInterpolation::edgeInterpolation(const faMesh& fam)
68 weightingFactors_(NULL),
69 differenceFactors_(NULL),
71 correctionVectors_(NULL),
73 skewCorrectionVectors_(NULL)
74 // leastSquarePvectors_(NULL),
75 // leastSquareNvectors_(NULL)
79 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
81 edgeInterpolation::~edgeInterpolation()
87 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
89 const edgeScalarField& edgeInterpolation::lPN() const
100 const edgeScalarField& edgeInterpolation::weights() const
102 if (!weightingFactors_)
107 return (*weightingFactors_);
111 const edgeScalarField& edgeInterpolation::deltaCoeffs() const
113 if (!differenceFactors_)
118 return (*differenceFactors_);
122 bool edgeInterpolation::orthogonal() const
124 if (orthogonal_ == false && !correctionVectors_)
126 makeCorrectionVectors();
133 const edgeVectorField& edgeInterpolation::correctionVectors() const
137 FatalErrorIn("edgeInterpolation::correctionVectors()")
138 << "cannot return correctionVectors; mesh is orthogonal"
139 << abort(FatalError);
142 return (*correctionVectors_);
146 bool edgeInterpolation::skew() const
148 if (skew_ == true && !skewCorrectionVectors_)
150 makeSkewCorrectionVectors();
157 const edgeVectorField& edgeInterpolation::skewCorrectionVectors() const
161 FatalErrorIn("edgeInterpolation::skewCorrectionVectors()")
162 << "cannot return skewCorrectionVectors; mesh is now skewed"
163 << abort(FatalError);
166 return (*skewCorrectionVectors_);
170 // const edgeVectorField& edgeInterpolation::leastSquarePvectors() const
172 // if (!leastSquarePvectors_)
174 // makeLeastSquareVectors();
177 // return (*leastSquarePvectors_);
181 // const edgeVectorField& edgeInterpolation::leastSquareNvectors() const
183 // if (!leastSquareNvectors_)
185 // makeLeastSquareVectors();
188 // return (*leastSquareNvectors_);
192 // Do what is neccessary if the mesh has moved
193 bool edgeInterpolation::movePoints()
195 deleteDemandDrivenData(lPN_);
196 deleteDemandDrivenData(weightingFactors_);
197 deleteDemandDrivenData(differenceFactors_);
200 deleteDemandDrivenData(correctionVectors_);
203 deleteDemandDrivenData(skewCorrectionVectors_);
205 // deleteDemandDrivenData(leastSquarePvectors_);
206 // deleteDemandDrivenData(leastSquareNvectors_);
212 void edgeInterpolation::makeLPN() const
216 Info<< "edgeInterpolation::makeLPN() : "
217 << "Constructing geodesic distance between points P and N"
222 lPN_ = new edgeScalarField
227 faSolution::time().constant(),
236 edgeScalarField& lPN = *lPN_;
239 // Set local references to mesh data
240 const edgeVectorField& edgeCentres = mesh().edgeCentres();
241 const areaVectorField& faceCentres = mesh().areaCentres();
242 const unallocLabelList& owner = mesh().owner();
243 const unallocLabelList& neighbour = mesh().neighbour();
247 vector curSkewCorrVec = vector::zero;
251 curSkewCorrVec = skewCorrectionVectors()[edgeI];
259 - faceCentres[owner[edgeI]]
265 faceCentres[neighbour[edgeI]]
270 lPN.internalField()[edgeI] = (lPE + lEN);
274 forAll(lPN.boundaryField(), patchI)
276 mesh().boundary()[patchI].makeDeltaCoeffs
278 lPN.boundaryField()[patchI]
281 lPN.boundaryField()[patchI] = 1.0/lPN.boundaryField()[patchI];
287 Info<< "edgeInterpolation::makeLPN() : "
288 << "Finished constructing geodesic distance PN"
294 void edgeInterpolation::makeWeights() const
298 Info<< "edgeInterpolation::makeWeights() : "
299 << "Constructing weighting factors for edge interpolation"
304 weightingFactors_ = new edgeScalarField
309 mesh()().pointsInstance(),
318 edgeScalarField& weightingFactors = *weightingFactors_;
321 // Set local references to mesh data
322 const edgeVectorField& edgeCentres = mesh().edgeCentres();
323 const areaVectorField& faceCentres = mesh().areaCentres();
324 const unallocLabelList& owner = mesh().owner();
325 const unallocLabelList& neighbour = mesh().neighbour();
329 vector curSkewCorrVec = vector::zero;
333 curSkewCorrVec = skewCorrectionVectors()[edgeI];
341 - faceCentres[owner[edgeI]]
347 faceCentres[neighbour[edgeI]]
352 weightingFactors.internalField()[edgeI] =
356 # ifdef BAD_MESH_STABILISATION
363 forAll(mesh().boundary(), patchI)
365 mesh().boundary()[patchI].makeWeights
367 weightingFactors.boundaryField()[patchI]
373 Info<< "edgeInterpolation::makeWeights() : "
374 << "Finished constructing weighting factors for face interpolation"
380 void edgeInterpolation::makeDeltaCoeffs() const
384 Info<< "edgeInterpolation::makeDeltaCoeffs() : "
385 << "Constructing differencing factors array for edge gradient"
389 // Force the construction of the weighting factors
390 // needed to make sure deltaCoeffs are calculated for parallel runs.
393 differenceFactors_ = new edgeScalarField
397 "differenceFactors_",
398 mesh()().pointsInstance(),
407 edgeScalarField& DeltaCoeffs = *differenceFactors_;
408 scalarField& dc = DeltaCoeffs.internalField();
411 // Set local references to mesh data
412 const edgeVectorField& edgeCentres = mesh().edgeCentres();
413 const areaVectorField& faceCentres = mesh().areaCentres();
414 const unallocLabelList& owner = mesh().owner();
415 const unallocLabelList& neighbour = mesh().neighbour();
416 const edgeVectorField& lengths = mesh().Le();
418 const edgeList& edges = mesh().edges();
419 const pointField& points = mesh().points();
424 // Edge normal - area normal
425 vector edgeNormal = lengths[edgeI]^edges[edgeI].vec(points);
426 edgeNormal /= mag(edgeNormal);
431 faceCentres[neighbour[edgeI]]
432 - faceCentres[owner[edgeI]];
435 edgeNormal*(edgeNormal&unitDelta);
437 unitDelta /= mag(unitDelta);
440 // Calc PN arc length
441 vector curSkewCorrVec = vector::zero;
445 curSkewCorrVec = skewCorrectionVectors()[edgeI];
453 - faceCentres[owner[edgeI]]
459 faceCentres[neighbour[edgeI]]
464 scalar lPN = lPE + lEN;
467 // Edge normal - area tangent
468 edgeNormal = lengths[edgeI]/mag(lengths[edgeI]);
470 // Delta coefficient as per definition
471 // dc[edgeI] = 1.0/(lPN*(unitDelta & edgeNormal));
473 // Stabilised form for bad meshes. HJ, 23/Jul/2009
474 dc[edgeI] = 1.0/max((lPN*(unitDelta & edgeNormal)), 0.05*lPN);
478 forAll(DeltaCoeffs.boundaryField(), patchI)
480 mesh().boundary()[patchI].makeDeltaCoeffs
482 DeltaCoeffs.boundaryField()[patchI]
488 void edgeInterpolation::makeCorrectionVectors() const
492 Info<< "edgeInterpolation::makeCorrectionVectors() : "
493 << "Constructing non-orthogonal correction vectors"
497 correctionVectors_ = new edgeVectorField
502 mesh()().pointsInstance(),
511 edgeVectorField& CorrVecs = *correctionVectors_;
513 // Set local references to mesh data
514 const areaVectorField& faceCentres = mesh().areaCentres();
516 const unallocLabelList& owner = mesh().owner();
517 const unallocLabelList& neighbour = mesh().neighbour();
519 const edgeVectorField& lengths = mesh().Le();
520 const edgeScalarField& magLengths = mesh().magLe();
522 const edgeList& edges = mesh().edges();
523 const pointField& points = mesh().points();
525 scalarField deltaCoeffs(owner.size());
529 // Edge normal - area normal
530 vector edgeNormal = lengths[edgeI] ^ edges[edgeI].vec(points);
531 edgeNormal /= mag(edgeNormal);
535 faceCentres[neighbour[edgeI]]
536 - faceCentres[owner[edgeI]];
538 unitDelta -= edgeNormal*(edgeNormal & unitDelta);
540 unitDelta /= mag(unitDelta);
542 // Edge normal - area tangent
543 edgeNormal = lengths[edgeI]/magLengths[edgeI];
546 deltaCoeffs[edgeI] = 1.0/(unitDelta & edgeNormal);
548 // Edge correction vector
549 CorrVecs.internalField()[edgeI] =
551 - deltaCoeffs[edgeI]*unitDelta;
554 forAll(CorrVecs.boundaryField(), patchI)
556 faePatchVectorField& patchCorrVecs = CorrVecs.boundaryField()[patchI];
558 patchCorrVecs = vector::zero;
561 scalar NonOrthogCoeff = 0.0;
563 if (owner.size() > 0)
565 scalarField sinAlpha = deltaCoeffs*mag(CorrVecs.internalField());
567 forAll(sinAlpha, edgeI)
569 sinAlpha[edgeI] = max(-1, min(sinAlpha[edgeI], 1));
572 NonOrthogCoeff = max(Foam::asin(sinAlpha)*180.0/M_PI);
577 Info<< "edgeInterpolation::makeCorrectionVectors() : "
578 << "non-orthogonality coefficient = " << NonOrthogCoeff << " deg."
582 if (NonOrthogCoeff < 0.1)
585 deleteDemandDrivenData(correctionVectors_);
594 Info<< "edgeInterpolation::makeCorrectionVectors() : "
595 << "Finished constructing non-orthogonal correction vectors"
601 void edgeInterpolation::makeSkewCorrectionVectors() const
605 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
606 << "Constructing skew correction vectors"
610 skewCorrectionVectors_ = new edgeVectorField
614 "skewCorrectionVectors",
615 mesh()().pointsInstance(),
624 edgeVectorField& SkewCorrVecs = *skewCorrectionVectors_;
626 // Set local references to mesh data
627 const areaVectorField& C = mesh().areaCentres();
628 const edgeVectorField& Ce = mesh().edgeCentres();
630 const unallocLabelList& owner = mesh().owner();
631 const unallocLabelList& neighbour = mesh().neighbour();
633 const pointField& points = mesh().points();
634 const edgeList& edges = mesh().edges();
637 forAll(neighbour, edgeI)
639 vector P = C[owner[edgeI]];
640 vector N = C[neighbour[edgeI]];
641 vector S = points[edges[edgeI].start()];
642 vector e = edges[edgeI].vec(points);
644 scalar alpha = - ( ( (N - P)^(S - P) )&( (N - P)^e ) )/
645 ( ( (N - P)^e )&( (N - P)^e ) );
647 vector E = S + alpha*e;
649 SkewCorrVecs[edgeI] = Ce[edgeI] - E;
653 forAll(SkewCorrVecs.boundaryField(), patchI)
655 faePatchVectorField& patchSkewCorrVecs =
656 SkewCorrVecs.boundaryField()[patchI];
658 if (patchSkewCorrVecs.coupled())
660 const unallocLabelList& edgeFaces =
661 mesh().boundary()[patchI].edgeFaces();
663 const edgeList::subList patchEdges =
664 mesh().boundary()[patchI].patchSlice(edges);
667 C.boundaryField()[patchI].patchNeighbourField();
669 forAll (patchSkewCorrVecs, edgeI)
671 vector P = C[edgeFaces[edgeI]];
672 vector N = ngbC[edgeI];
673 vector S = points[patchEdges[edgeI].start()];
674 vector e = patchEdges[edgeI].vec(points);
676 scalar alpha = - ( ( (N - P)^(S - P) )&( (N - P)^e ) )/
677 ( ( (N - P)^e )&( (N - P)^e ) );
679 vector E = S + alpha*e;
681 patchSkewCorrVecs[edgeI] =
682 Ce.boundaryField()[patchI][edgeI] - E;
687 patchSkewCorrVecs = vector::zero;
692 scalar skewCoeff = 0.0;
694 // Calculating PN arc length
695 scalarField lPN(owner.size());
697 forAll (owner, edgeI)
703 - SkewCorrVecs[edgeI]
710 + SkewCorrVecs[edgeI]
716 skewCoeff = max(mag(SkewCorrVecs.internalField())/mag(lPN));
721 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
722 << "skew coefficient = " << skewCoeff << endl;
728 deleteDemandDrivenData(skewCorrectionVectors_);
737 Info<< "edgeInterpolation::makeSkewCorrectionVectors() : "
738 << "Finished constructing skew correction vectors"
744 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
746 } // End namespace Foam
748 // ************************************************************************* //