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

leastSquaresVectors.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 "leastSquaresVectors.H"
00027 #include <finiteVolume/surfaceFields.H>
00028 #include <finiteVolume/volFields.H>
00029 
00030 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00031 
00032 namespace Foam
00033 {
00034     defineTypeNameAndDebug(leastSquaresVectors, 0);
00035 }
00036 
00037 
00038 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
00039 
00040 Foam::leastSquaresVectors::leastSquaresVectors(const fvMesh& mesh)
00041 :
00042     MeshObject<fvMesh, leastSquaresVectors>(mesh),
00043     pVectorsPtr_(NULL),
00044     nVectorsPtr_(NULL)
00045 {}
00046 
00047 
00048 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
00049 
00050 Foam::leastSquaresVectors::~leastSquaresVectors()
00051 {
00052     deleteDemandDrivenData(pVectorsPtr_);
00053     deleteDemandDrivenData(nVectorsPtr_);
00054 }
00055 
00056 
00057 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00058 
00059 void Foam::leastSquaresVectors::makeLeastSquaresVectors() const
00060 {
00061     if (debug)
00062     {
00063         Info<< "leastSquaresVectors::makeLeastSquaresVectors() :"
00064             << "Constructing least square gradient vectors"
00065             << endl;
00066     }
00067 
00068     const fvMesh& mesh = mesh_;
00069 
00070     pVectorsPtr_ = new surfaceVectorField
00071     (
00072         IOobject
00073         (
00074             "LeastSquaresP",
00075             mesh_.pointsInstance(),
00076             mesh_,
00077             IOobject::NO_READ,
00078             IOobject::NO_WRITE,
00079             false
00080         ),
00081         mesh_,
00082         dimensionedVector("zero", dimless/dimLength, vector::zero)
00083     );
00084     surfaceVectorField& lsP = *pVectorsPtr_;
00085 
00086     nVectorsPtr_ = new surfaceVectorField
00087     (
00088         IOobject
00089         (
00090             "LeastSquaresN",
00091             mesh_.pointsInstance(),
00092             mesh_,
00093             IOobject::NO_READ,
00094             IOobject::NO_WRITE,
00095             false
00096         ),
00097         mesh_,
00098         dimensionedVector("zero", dimless/dimLength, vector::zero)
00099     );
00100     surfaceVectorField& lsN = *nVectorsPtr_;
00101 
00102     // Set local references to mesh data
00103     const unallocLabelList& owner = mesh_.owner();
00104     const unallocLabelList& neighbour = mesh_.neighbour();
00105 
00106     const volVectorField& C = mesh.C();
00107     const surfaceScalarField& w = mesh.weights();
00108     const surfaceScalarField& magSf = mesh.magSf();
00109 
00110 
00111     // Set up temporary storage for the dd tensor (before inversion)
00112     symmTensorField dd(mesh_.nCells(), symmTensor::zero);
00113 
00114     forAll(owner, facei)
00115     {
00116         label own = owner[facei];
00117         label nei = neighbour[facei];
00118 
00119         vector d = C[nei] - C[own];
00120         symmTensor wdd = (magSf[facei]/magSqr(d))*sqr(d);
00121 
00122         dd[own] += (1 - w[facei])*wdd;
00123         dd[nei] += w[facei]*wdd;
00124     }
00125 
00126 
00127     forAll(lsP.boundaryField(), patchi)
00128     {
00129         const fvsPatchScalarField& pw = w.boundaryField()[patchi];
00130         const fvsPatchScalarField& pMagSf = magSf.boundaryField()[patchi];
00131 
00132         const fvPatch& p = pw.patch();
00133         const unallocLabelList& faceCells = p.patch().faceCells();
00134 
00135         // Build the d-vectors
00136         vectorField pd =
00137             mesh.Sf().boundaryField()[patchi]
00138            /(
00139                mesh.magSf().boundaryField()[patchi]
00140               *mesh.deltaCoeffs().boundaryField()[patchi]
00141            );
00142 
00143         if (!mesh.orthogonal())
00144         {
00145             pd -= mesh.correctionVectors().boundaryField()[patchi]
00146                 /mesh.deltaCoeffs().boundaryField()[patchi];
00147         }
00148 
00149         if (p.coupled())
00150         {
00151             forAll(pd, patchFacei)
00152             {
00153                 const vector& d = pd[patchFacei];
00154 
00155                 dd[faceCells[patchFacei]] +=
00156                     ((1 - pw[patchFacei])*pMagSf[patchFacei]/magSqr(d))*sqr(d);
00157             }
00158         }
00159         else
00160         {
00161             forAll(pd, patchFacei)
00162             {
00163                 const vector& d = pd[patchFacei];
00164 
00165                 dd[faceCells[patchFacei]] +=
00166                     (pMagSf[patchFacei]/magSqr(d))*sqr(d);
00167             }
00168         }
00169     }
00170 
00171 
00172     // Invert the dd tensor
00173     symmTensorField invDd = inv(dd);
00174 
00175 
00176     // Revisit all faces and calculate the lsP and lsN vectors
00177     forAll(owner, facei)
00178     {
00179         label own = owner[facei];
00180         label nei = neighbour[facei];
00181 
00182         vector d = C[nei] - C[own];
00183         scalar magSfByMagSqrd = magSf[facei]/magSqr(d);
00184 
00185         lsP[facei] = (1 - w[facei])*magSfByMagSqrd*(invDd[own] & d);
00186         lsN[facei] = -w[facei]*magSfByMagSqrd*(invDd[nei] & d);
00187     }
00188 
00189     forAll(lsP.boundaryField(), patchi)
00190     {
00191         fvsPatchVectorField& patchLsP = lsP.boundaryField()[patchi];
00192 
00193         const fvsPatchScalarField& pw = w.boundaryField()[patchi];
00194         const fvsPatchScalarField& pMagSf = magSf.boundaryField()[patchi];
00195 
00196         const fvPatch& p = pw.patch();
00197         const unallocLabelList& faceCells = p.faceCells();
00198 
00199         // Build the d-vectors
00200         vectorField pd =
00201             mesh.Sf().boundaryField()[patchi]
00202            /(
00203                mesh.magSf().boundaryField()[patchi]
00204               *mesh.deltaCoeffs().boundaryField()[patchi]
00205            );
00206 
00207         if (!mesh.orthogonal())
00208         {
00209             pd -= mesh.correctionVectors().boundaryField()[patchi]
00210                 /mesh.deltaCoeffs().boundaryField()[patchi];
00211         }
00212 
00213 
00214         if (p.coupled())
00215         {
00216             forAll(pd, patchFacei)
00217             {
00218                 const vector& d = pd[patchFacei];
00219 
00220                 patchLsP[patchFacei] =
00221                     ((1 - pw[patchFacei])*pMagSf[patchFacei]/magSqr(d))
00222                    *(invDd[faceCells[patchFacei]] & d);
00223             }
00224         }
00225         else
00226         {
00227             forAll(pd, patchFacei)
00228             {
00229                 const vector& d = pd[patchFacei];
00230 
00231                 patchLsP[patchFacei] =
00232                     pMagSf[patchFacei]*(1.0/magSqr(d))
00233                    *(invDd[faceCells[patchFacei]] & d);
00234             }
00235         }
00236     }
00237 
00238 
00239     // For 3D meshes check the determinant of the dd tensor and switch to
00240     // Gauss if it is less than 3
00241     /* Currently the det(dd[celli]) criterion is incorrect: dd is weighted by Sf
00242     if (mesh.nGeometricD() == 3)
00243     {
00244         label nBadCells = 0;
00245 
00246         const cellList& cells = mesh.cells();
00247         const scalarField& V = mesh.V();
00248         const surfaceVectorField& Sf = mesh.Sf();
00249         const surfaceScalarField& w = mesh.weights();
00250 
00251         forAll (dd, celli)
00252         {
00253             if (det(dd[celli]) < 3)
00254             {
00255                 nBadCells++;
00256 
00257                 const cell& c = cells[celli];
00258 
00259                 forAll(c, cellFacei)
00260                 {
00261                     label facei = c[cellFacei];
00262 
00263                     if (mesh.isInternalFace(facei))
00264                     {
00265                         scalar wf = max(min(w[facei], 0.8), 0.2);
00266 
00267                         if (celli == owner[facei])
00268                         {
00269                             lsP[facei] = (1 - wf)*Sf[facei]/V[celli];
00270                         }
00271                         else
00272                         {
00273                             lsN[facei] = -wf*Sf[facei]/V[celli];
00274                         }
00275                     }
00276                     else
00277                     {
00278                         label patchi = mesh.boundaryMesh().whichPatch(facei);
00279 
00280                         if (mesh.boundary()[patchi].size())
00281                         {
00282                             label patchFacei =
00283                                 facei - mesh.boundaryMesh()[patchi].start();
00284 
00285                             if (mesh.boundary()[patchi].coupled())
00286                             {
00287                                 scalar wf = max
00288                                 (
00289                                     min
00290                                     (
00291                                         w.boundaryField()[patchi][patchFacei],
00292                                         0.8
00293                                     ),
00294                                     0.2
00295                                 );
00296 
00297                                 lsP.boundaryField()[patchi][patchFacei] =
00298                                     (1 - wf)
00299                                    *Sf.boundaryField()[patchi][patchFacei]
00300                                    /V[celli];
00301                             }
00302                             else
00303                             {
00304                                 lsP.boundaryField()[patchi][patchFacei] =
00305                                     Sf.boundaryField()[patchi][patchFacei]
00306                                    /V[celli];
00307                             }
00308                         }
00309                     }
00310                 }
00311             }
00312         }
00313 
00314         if (debug)
00315         {
00316             InfoIn("leastSquaresVectors::makeLeastSquaresVectors()")
00317                 << "number of bad cells switched to Gauss = " << nBadCells
00318                 << endl;
00319         }
00320     }
00321     */
00322 
00323     if (debug)
00324     {
00325         Info<< "leastSquaresVectors::makeLeastSquaresVectors() :"
00326             << "Finished constructing least square gradient vectors"
00327             << endl;
00328     }
00329 }
00330 
00331 
00332 const Foam::surfaceVectorField& Foam::leastSquaresVectors::pVectors() const
00333 {
00334     if (!pVectorsPtr_)
00335     {
00336         makeLeastSquaresVectors();
00337     }
00338 
00339     return *pVectorsPtr_;
00340 }
00341 
00342 
00343 const Foam::surfaceVectorField& Foam::leastSquaresVectors::nVectors() const
00344 {
00345     if (!nVectorsPtr_)
00346     {
00347         makeLeastSquaresVectors();
00348     }
00349 
00350     return *nVectorsPtr_;
00351 }
00352 
00353 
00354 bool Foam::leastSquaresVectors::movePoints()
00355 {
00356     deleteDemandDrivenData(pVectorsPtr_);
00357     deleteDemandDrivenData(nVectorsPtr_);
00358 
00359     return true;
00360 }
00361 
00362 
00363 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines