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

quadraticFitSnGradData.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 "quadraticFitSnGradData.H"
00027 #include <finiteVolume/surfaceFields.H>
00028 #include <finiteVolume/volFields.H>
00029 #include <OpenFOAM/SVD.H>
00030 #include <OpenFOAM/syncTools.H>
00031 
00032 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00033 
00034 namespace Foam
00035 {
00036     defineTypeNameAndDebug(quadraticFitSnGradData, 0);
00037 }
00038 
00039 
00040 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
00041 
00042 Foam::quadraticFitSnGradData::quadraticFitSnGradData
00043 (
00044     const fvMesh& mesh,
00045     const scalar cWeight
00046 )
00047 :
00048     MeshObject<fvMesh, quadraticFitSnGradData>(mesh),
00049     centralWeight_(cWeight),
00050     #ifdef SPHERICAL_GEOMETRY
00051         dim_(2),
00052     #else
00053         dim_(mesh.nGeometricD()),
00054     #endif
00055     minSize_
00056     (
00057         dim_ == 1 ? 3 :
00058         dim_ == 2 ? 6 :
00059         dim_ == 3 ? 9 : 0
00060     ),
00061     stencil_(mesh),
00062     fit_(mesh.nInternalFaces())
00063 {
00064     if (debug)
00065     {
00066         Info << "Contructing quadraticFitSnGradData" << endl;
00067     }
00068 
00069     // check input
00070     if (centralWeight_ < 1 - SMALL)
00071     {
00072         FatalErrorIn("quadraticFitSnGradData::quadraticFitSnGradData")
00073             << "centralWeight requested = " << centralWeight_
00074             << " should not be less than one"
00075             << exit(FatalError);
00076     }
00077 
00078     if (minSize_ == 0)
00079     {
00080         FatalErrorIn("quadraticFitSnGradData")
00081             << " dimension must be 1,2 or 3, not" << dim_ << exit(FatalError);
00082     }
00083 
00084     // store the polynomial size for each face to write out
00085     surfaceScalarField snGradPolySize
00086     (
00087         IOobject
00088         (
00089             "quadraticFitSnGradPolySize",
00090             "constant",
00091             mesh,
00092             IOobject::NO_READ,
00093             IOobject::NO_WRITE
00094         ),
00095         mesh,
00096         dimensionedScalar("quadraticFitSnGradPolySize", dimless, scalar(0))
00097     );
00098 
00099     // Get the cell/face centres in stencil order.
00100     // Centred face stencils no good for triangles of tets. Need bigger stencils
00101     List<List<point> > stencilPoints(stencil_.stencil().size());
00102     stencil_.collectData
00103     (
00104         mesh.C(),
00105         stencilPoints
00106     );
00107 
00108     // find the fit coefficients for every face in the mesh
00109 
00110     for(label faci = 0; faci < mesh.nInternalFaces(); faci++)
00111     {
00112         snGradPolySize[faci] = calcFit(stencilPoints[faci], faci);
00113     }
00114 
00115     if (debug)
00116     {
00117         snGradPolySize.write();
00118         Info<< "quadraticFitSnGradData::quadraticFitSnGradData() :"
00119             << "Finished constructing polynomialFit data"
00120             << endl;
00121     }
00122 }
00123 
00124 
00125 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00126 
00127 void Foam::quadraticFitSnGradData::findFaceDirs
00128 (
00129     vector& idir,        // value changed in return
00130     vector& jdir,        // value changed in return
00131     vector& kdir,        // value changed in return
00132     const fvMesh& mesh,
00133     const label faci
00134 )
00135 {
00136     idir = mesh.Sf()[faci];
00137     idir /= mag(idir);
00138 
00139     #ifndef SPHERICAL_GEOMETRY
00140         if (mesh.nGeometricD() <= 2) // find the normal direcion
00141         {
00142             if (mesh.geometricD()[0] == -1)
00143             {
00144                 kdir = vector(1, 0, 0);
00145             }
00146             else if (mesh.geometricD()[1] == -1)
00147             {
00148                 kdir = vector(0, 1, 0);
00149             }
00150             else
00151             {
00152                 kdir = vector(0, 0, 1);
00153             }
00154         }
00155         else // 3D so find a direction in the plane of the face
00156         {
00157             const face& f = mesh.faces()[faci];
00158             kdir = mesh.points()[f[0]] - mesh.points()[f[1]];
00159         }
00160     #else
00161         // Spherical geometry so kdir is the radial direction
00162         kdir = mesh.Cf()[faci];
00163     #endif
00164 
00165     if (mesh.nGeometricD() == 3)
00166     {
00167         // Remove the idir component from kdir and normalise
00168         kdir -= (idir & kdir)*idir;
00169 
00170         scalar magk = mag(kdir);
00171 
00172         if (magk < SMALL)
00173         {
00174             FatalErrorIn("findFaceDirs") << " calculated kdir = zero"
00175                 << exit(FatalError);
00176         }
00177         else
00178         {
00179             kdir /= magk;
00180         }
00181     }
00182 
00183     jdir = kdir ^ idir;
00184 }
00185 
00186 
00187 Foam::label Foam::quadraticFitSnGradData::calcFit
00188 (
00189     const List<point>& C,
00190     const label faci
00191 )
00192 {
00193     vector idir(1,0,0);
00194     vector jdir(0,1,0);
00195     vector kdir(0,0,1);
00196     findFaceDirs(idir, jdir, kdir, mesh(), faci);
00197 
00198     scalarList wts(C.size(), scalar(1));
00199     wts[0] = centralWeight_;
00200     wts[1] = centralWeight_;
00201 
00202     point p0 = mesh().faceCentres()[faci];
00203     scalar scale = 0;
00204 
00205     // calculate the matrix of the polynomial components
00206     scalarRectangularMatrix B(C.size(), minSize_, scalar(0));
00207 
00208     for(label ip = 0; ip < C.size(); ip++)
00209     {
00210         const point& p = C[ip];
00211 
00212         scalar px = (p - p0)&idir;
00213         scalar py = (p - p0)&jdir;
00214         #ifdef SPHERICAL_GEOMETRY
00215             scalar pz = mag(p) - mag(p0);
00216         #else
00217             scalar pz = (p - p0)&kdir;
00218         #endif
00219 
00220         if (ip == 0) scale = max(max(mag(px), mag(py)), mag(pz));
00221 
00222         px /= scale;
00223         py /= scale;
00224         pz /= scale;
00225 
00226         label is = 0;
00227 
00228         B[ip][is++] = wts[0]*wts[ip];
00229         B[ip][is++] = wts[0]*wts[ip]*px;
00230         B[ip][is++] = wts[ip]*sqr(px);
00231 
00232         if (dim_ >= 2)
00233         {
00234             B[ip][is++] = wts[ip]*py;
00235             B[ip][is++] = wts[ip]*px*py;
00236             B[ip][is++] = wts[ip]*sqr(py);
00237         }
00238         if (dim_ == 3)
00239         {
00240             B[ip][is++] = wts[ip]*pz;
00241             B[ip][is++] = wts[ip]*px*pz;
00242             //B[ip][is++] = wts[ip]*py*pz;
00243             B[ip][is++] = wts[ip]*sqr(pz);
00244         }
00245     }
00246 
00247     // Set the fit
00248     label stencilSize = C.size();
00249     fit_[faci].setSize(stencilSize);
00250     scalarList singVals(minSize_);
00251     label nSVDzeros = 0;
00252 
00253     const scalar& deltaCoeff = mesh().deltaCoeffs()[faci];
00254 
00255     bool goodFit = false;
00256     for(int iIt = 0; iIt < 10 && !goodFit; iIt++)
00257     {
00258         SVD svd(B, SMALL);
00259 
00260         scalar fit0 = wts[0]*wts[0]*svd.VSinvUt()[1][0]/scale;
00261         scalar fit1 = wts[0]*wts[1]*svd.VSinvUt()[1][1]/scale;
00262 
00263         goodFit =
00264             fit0 < 0 && fit1 > 0
00265          && mag(fit0 + deltaCoeff) < 0.5*deltaCoeff
00266          && mag(fit1 - deltaCoeff) < 0.5*deltaCoeff;
00267 
00268         if (goodFit)
00269         {
00270             fit_[faci][0] = fit0;
00271             fit_[faci][1] = fit1;
00272             for(label i = 2; i < stencilSize; i++)
00273             {
00274                 fit_[faci][i] = wts[0]*wts[i]*svd.VSinvUt()[1][i]/scale;
00275             }
00276             singVals = svd.S();
00277             nSVDzeros = svd.nZeros();
00278         }
00279         else // (not good fit so increase weight in the centre and for linear)
00280         {
00281             wts[0] *= 10;
00282             wts[1] *= 10;
00283 
00284             for(label i = 0; i < B.n(); i++)
00285             {
00286                 B[i][0] *= 10;
00287                 B[i][1] *= 10;
00288             }
00289 
00290             for(label j = 0; j < B.m(); j++)
00291             {
00292                 B[0][j] *= 10;
00293                 B[1][j] *= 10;
00294             }
00295         }
00296     }
00297 
00298     if (goodFit)
00299     {
00300         // remove the uncorrected snGradScheme coefficients
00301         fit_[faci][0] += deltaCoeff;
00302         fit_[faci][1] -= deltaCoeff;
00303     }
00304     else
00305     {
00306         Pout<< "quadratifFitSnGradData could not fit face " << faci
00307             << " fit_[faci][0] =  " << fit_[faci][0]
00308             << " fit_[faci][1] =  " << fit_[faci][1]
00309             << " deltaCoeff =  " << deltaCoeff << endl;
00310         fit_[faci] = 0;
00311     }
00312 
00313     return minSize_ - nSVDzeros;
00314 }
00315 
00316 bool Foam::quadraticFitSnGradData::movePoints()
00317 {
00318     notImplemented("quadraticFitSnGradData::movePoints()");
00319 
00320     return true;
00321 }
00322 
00323 
00324 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines