FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

surfaceInterpolation.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include <finiteVolume/fvMesh.H>
00027 #include <finiteVolume/volFields.H>
00028 #include <finiteVolume/surfaceFields.H>
00029 #include <OpenFOAM/demandDrivenData.H>
00030 #include <finiteVolume/coupledFvPatch.H>
00031 #include <OpenFOAM/mathematicalConstants.H>
00032 
00033 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00034 
00035 namespace Foam
00036 {
00037     defineTypeNameAndDebug(surfaceInterpolation, 0);
00038 }
00039 
00040 // * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
00041 
00042 void Foam::surfaceInterpolation::clearOut()
00043 {
00044     deleteDemandDrivenData(weightingFactors_);
00045     deleteDemandDrivenData(differenceFactors_);
00046     deleteDemandDrivenData(correctionVectors_);
00047 }
00048 
00049 
00050 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
00051 
00052 Foam::surfaceInterpolation::surfaceInterpolation(const fvMesh& fvm)
00053 :
00054     fvSchemes(static_cast<const objectRegistry&>(fvm)),
00055     fvSolution(static_cast<const objectRegistry&>(fvm)),
00056     mesh_(fvm),
00057     weightingFactors_(NULL),
00058     differenceFactors_(NULL),
00059     orthogonal_(false),
00060     correctionVectors_(NULL)
00061 {}
00062 
00063 
00064 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
00065 
00066 Foam::surfaceInterpolation::~surfaceInterpolation()
00067 {
00068     clearOut();
00069 }
00070 
00071 
00072 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00073 
00074 const Foam::surfaceScalarField& Foam::surfaceInterpolation::weights() const
00075 {
00076     if (!weightingFactors_)
00077     {
00078         makeWeights();
00079     }
00080 
00081     return (*weightingFactors_);
00082 }
00083 
00084 
00085 const Foam::surfaceScalarField& Foam::surfaceInterpolation::deltaCoeffs() const
00086 {
00087     if (!differenceFactors_)
00088     {
00089         makeDeltaCoeffs();
00090     }
00091 
00092     return (*differenceFactors_);
00093 }
00094 
00095 
00096 bool Foam::surfaceInterpolation::orthogonal() const
00097 {
00098     if (orthogonal_ == false && !correctionVectors_)
00099     {
00100         makeCorrectionVectors();
00101     }
00102 
00103     return orthogonal_;
00104 }
00105 
00106 
00107 const Foam::surfaceVectorField&
00108 Foam::surfaceInterpolation::correctionVectors() const
00109 {
00110     if (orthogonal())
00111     {
00112         FatalErrorIn("surfaceInterpolation::correctionVectors()")
00113             << "cannot return correctionVectors; mesh is orthogonal"
00114             << abort(FatalError);
00115     }
00116 
00117     return (*correctionVectors_);
00118 }
00119 
00120 
00121 bool Foam::surfaceInterpolation::movePoints()
00122 {
00123     deleteDemandDrivenData(weightingFactors_);
00124     deleteDemandDrivenData(differenceFactors_);
00125 
00126     orthogonal_ = false;
00127     deleteDemandDrivenData(correctionVectors_);
00128 
00129     return true;
00130 }
00131 
00132 
00133 void Foam::surfaceInterpolation::makeWeights() const
00134 {
00135     if (debug)
00136     {
00137         Info<< "surfaceInterpolation::makeWeights() : "
00138             << "Constructing weighting factors for face interpolation"
00139             << endl;
00140     }
00141 
00142 
00143     weightingFactors_ = new surfaceScalarField
00144     (
00145         IOobject
00146         (
00147             "weightingFactors",
00148             mesh_.pointsInstance(),
00149             mesh_
00150         ),
00151         mesh_,
00152         dimless
00153     );
00154     surfaceScalarField& weightingFactors = *weightingFactors_;
00155 
00156 
00157     // Set local references to mesh data
00158     // (note that we should not use fvMesh sliced fields at this point yet
00159     //  since this causes a loop when generating weighting factors in
00160     //  coupledFvPatchField evaluation phase)
00161     const unallocLabelList& owner = mesh_.owner();
00162     const unallocLabelList& neighbour = mesh_.neighbour();
00163 
00164     const vectorField& Cf = mesh_.faceCentres();
00165     const vectorField& C = mesh_.cellCentres();
00166     const vectorField& Sf = mesh_.faceAreas();
00167 
00168     // ... and reference to the internal field of the weighting factors
00169     scalarField& w = weightingFactors.internalField();
00170 
00171     forAll(owner, facei)
00172     {
00173         // Note: mag in the dot-product.
00174         // For all valid meshes, the non-orthogonality will be less that
00175         // 90 deg and the dot-product will be positive.  For invalid
00176         // meshes (d & s <= 0), this will stabilise the calculation
00177         // but the result will be poor.
00178         scalar SfdOwn = mag(Sf[facei] & (Cf[facei] - C[owner[facei]]));
00179         scalar SfdNei = mag(Sf[facei] & (C[neighbour[facei]] - Cf[facei]));
00180         w[facei] = SfdNei/(SfdOwn + SfdNei);
00181     }
00182 
00183     forAll(mesh_.boundary(), patchi)
00184     {
00185         mesh_.boundary()[patchi].makeWeights
00186         (
00187             weightingFactors.boundaryField()[patchi]
00188         );
00189     }
00190 
00191 
00192     if (debug)
00193     {
00194         Info<< "surfaceInterpolation::makeWeights() : "
00195             << "Finished constructing weighting factors for face interpolation"
00196             << endl;
00197     }
00198 }
00199 
00200 
00201 void Foam::surfaceInterpolation::makeDeltaCoeffs() const
00202 {
00203     if (debug)
00204     {
00205         Info<< "surfaceInterpolation::makeDeltaCoeffs() : "
00206             << "Constructing differencing factors array for face gradient"
00207             << endl;
00208     }
00209 
00210     // Force the construction of the weighting factors
00211     // needed to make sure deltaCoeffs are calculated for parallel runs.
00212     weights();
00213 
00214     differenceFactors_ = new surfaceScalarField
00215     (
00216         IOobject
00217         (
00218             "differenceFactors_",
00219             mesh_.pointsInstance(),
00220             mesh_
00221         ),
00222         mesh_,
00223         dimless/dimLength
00224     );
00225     surfaceScalarField& DeltaCoeffs = *differenceFactors_;
00226 
00227 
00228     // Set local references to mesh data
00229     const volVectorField& C = mesh_.C();
00230     const unallocLabelList& owner = mesh_.owner();
00231     const unallocLabelList& neighbour = mesh_.neighbour();
00232     const surfaceVectorField& Sf = mesh_.Sf();
00233     const surfaceScalarField& magSf = mesh_.magSf();
00234 
00235     forAll(owner, facei)
00236     {
00237         vector delta = C[neighbour[facei]] - C[owner[facei]];
00238         vector unitArea = Sf[facei]/magSf[facei];
00239 
00240         // Standard cell-centre distance form
00241         //DeltaCoeffs[facei] = (unitArea & delta)/magSqr(delta);
00242 
00243         // Slightly under-relaxed form
00244         //DeltaCoeffs[facei] = 1.0/mag(delta);
00245 
00246         // More under-relaxed form
00247         //DeltaCoeffs[facei] = 1.0/(mag(unitArea & delta) + VSMALL);
00248 
00249         // Stabilised form for bad meshes
00250         DeltaCoeffs[facei] = 1.0/max(unitArea & delta, 0.05*mag(delta));
00251     }
00252 
00253     forAll(DeltaCoeffs.boundaryField(), patchi)
00254     {
00255         mesh_.boundary()[patchi].makeDeltaCoeffs
00256         (
00257             DeltaCoeffs.boundaryField()[patchi]
00258         );
00259     }
00260 }
00261 
00262 
00263 void Foam::surfaceInterpolation::makeCorrectionVectors() const
00264 {
00265     if (debug)
00266     {
00267         Info<< "surfaceInterpolation::makeCorrectionVectors() : "
00268             << "Constructing non-orthogonal correction vectors"
00269             << endl;
00270     }
00271 
00272     correctionVectors_ = new surfaceVectorField
00273     (
00274         IOobject
00275         (
00276             "correctionVectors",
00277             mesh_.pointsInstance(),
00278             mesh_
00279         ),
00280         mesh_,
00281         dimless
00282     );
00283     surfaceVectorField& corrVecs = *correctionVectors_;
00284 
00285     // Set local references to mesh data
00286     const volVectorField& C = mesh_.C();
00287     const unallocLabelList& owner = mesh_.owner();
00288     const unallocLabelList& neighbour = mesh_.neighbour();
00289     const surfaceVectorField& Sf = mesh_.Sf();
00290     const surfaceScalarField& magSf = mesh_.magSf();
00291     const surfaceScalarField& DeltaCoeffs = deltaCoeffs();
00292 
00293     forAll(owner, facei)
00294     {
00295         vector unitArea = Sf[facei]/magSf[facei];
00296         vector delta = C[neighbour[facei]] - C[owner[facei]];
00297 
00298         corrVecs[facei] = unitArea - delta*DeltaCoeffs[facei];
00299     }
00300 
00301     // Boundary correction vectors set to zero for boundary patches
00302     // and calculated consistently with internal corrections for
00303     // coupled patches
00304 
00305     forAll(corrVecs.boundaryField(), patchi)
00306     {
00307         fvsPatchVectorField& patchcorrVecs = corrVecs.boundaryField()[patchi];
00308 
00309         if (!patchcorrVecs.coupled())
00310         {
00311             patchcorrVecs = vector::zero;
00312         }
00313         else
00314         {
00315             const fvsPatchScalarField& patchDeltaCoeffs
00316                 = DeltaCoeffs.boundaryField()[patchi];
00317 
00318             const fvPatch& p = patchcorrVecs.patch();
00319 
00320             vectorField patchDeltas = mesh_.boundary()[patchi].delta();
00321 
00322             forAll(p, patchFacei)
00323             {
00324                 vector unitArea =
00325                     Sf.boundaryField()[patchi][patchFacei]
00326                    /magSf.boundaryField()[patchi][patchFacei];
00327 
00328                 const vector& delta = patchDeltas[patchFacei];
00329 
00330                 patchcorrVecs[patchFacei] =
00331                     unitArea - delta*patchDeltaCoeffs[patchFacei];
00332             }
00333         }
00334     }
00335 
00336     scalar MaxNonOrthog = 0.0;
00337 
00338     // Calculate the non-orthogonality for meshes with 1 face or more
00339     if (returnReduce(magSf.size(), sumOp<label>()) > 0)
00340     {
00341         MaxNonOrthog =
00342             asin
00343             (
00344                 min
00345                 (
00346                     max(mag(corrVecs)).value(),
00347                     1.0
00348                 )
00349             )*180.0/mathematicalConstant::pi;
00350     }
00351 
00352     if (debug)
00353     {
00354         Info<< "surfaceInterpolation::makeCorrectionVectors() : "
00355             << "maximum non-orthogonality = " << MaxNonOrthog << " deg."
00356             << endl;
00357     }
00358 
00359     //MaxNonOrthog = 0.0;
00360 
00361     if (MaxNonOrthog < 5)
00362     {
00363         orthogonal_ = true;
00364         deleteDemandDrivenData(correctionVectors_);
00365     }
00366     else
00367     {
00368         orthogonal_ = false;
00369     }
00370 
00371     if (debug)
00372     {
00373         Info<< "surfaceInterpolation::makeCorrectionVectors() : "
00374             << "Finished constructing non-orthogonal correction vectors"
00375             << endl;
00376     }
00377 }
00378 
00379 
00380 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines