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

cellQuality.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 Description
00025     Class calculates cell quality measures.
00026 
00027 \*---------------------------------------------------------------------------*/
00028 
00029 #include "cellQuality.H"
00030 #include <OpenFOAM/mathematicalConstants.H>
00031 
00032 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00033 
00034 // Construct from mesh
00035 Foam::cellQuality::cellQuality(const polyMesh& mesh)
00036 :
00037     mesh_(mesh)
00038 {}
00039 
00040 
00041 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00042 
00043 Foam::tmp<Foam::scalarField> Foam::cellQuality::nonOrthogonality() const
00044 {
00045     tmp<scalarField> tresult
00046     (
00047         new scalarField
00048         (
00049             mesh_.nCells(), 0.0
00050         )
00051     );
00052 
00053     scalarField& result = tresult();
00054 
00055     scalarField sumArea(mesh_.nCells(), 0.0);
00056 
00057     const vectorField& centres = mesh_.cellCentres();
00058     const vectorField& areas = mesh_.faceAreas();
00059 
00060     const labelList& own = mesh_.faceOwner();
00061     const labelList& nei = mesh_.faceNeighbour();
00062 
00063     forAll (nei, faceI)
00064     {
00065         vector d = centres[nei[faceI]] - centres[own[faceI]];
00066         vector s = areas[faceI];
00067         scalar magS = mag(s);
00068 
00069         scalar cosDDotS =
00070             Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
00071             *180.0/mathematicalConstant::pi;
00072 
00073         result[own[faceI]] = max(cosDDotS, result[own[faceI]]);
00074 
00075         result[nei[faceI]] = max(cosDDotS, result[nei[faceI]]);
00076     }
00077 
00078     forAll (mesh_.boundaryMesh(), patchI)
00079     {
00080         const unallocLabelList& faceCells = 
00081             mesh_.boundaryMesh()[patchI].faceCells();
00082 
00083         const vectorField::subField faceCentres =
00084             mesh_.boundaryMesh()[patchI].faceCentres();
00085 
00086         const vectorField::subField faceAreas =
00087             mesh_.boundaryMesh()[patchI].faceAreas();
00088 
00089         forAll(faceCentres, faceI)
00090         {
00091             vector d = faceCentres[faceI] - centres[faceCells[faceI]];
00092             vector s = faceAreas[faceI];
00093             scalar magS = mag(s);
00094 
00095             scalar cosDDotS =
00096                 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
00097                *180.0/mathematicalConstant::pi;
00098 
00099             result[faceCells[faceI]] = max(cosDDotS, result[faceCells[faceI]]);
00100         }
00101     }
00102 
00103     return tresult;
00104 }
00105 
00106 
00107 Foam::tmp<Foam::scalarField> Foam::cellQuality::skewness() const
00108 {
00109     tmp<scalarField> tresult
00110     (
00111         new scalarField
00112         (
00113             mesh_.nCells(), 0.0
00114         )
00115     );
00116     scalarField& result = tresult();
00117 
00118     scalarField sumArea(mesh_.nCells(), 0.0);
00119 
00120     const vectorField& cellCtrs = mesh_.cellCentres();
00121     const vectorField& faceCtrs = mesh_.faceCentres();
00122     const vectorField& areas = mesh_.faceAreas();
00123 
00124     const labelList& own = mesh_.faceOwner();
00125     const labelList& nei = mesh_.faceNeighbour();
00126 
00127     forAll (nei, faceI)
00128     {
00129         scalar dOwn = mag
00130         (
00131             (faceCtrs[faceI] - cellCtrs[own[faceI]]) & areas[faceI]
00132         )/mag(areas[faceI]);
00133 
00134         scalar dNei = mag
00135         (
00136             (cellCtrs[nei[faceI]] - faceCtrs[faceI]) & areas[faceI]
00137         )/mag(areas[faceI]);
00138 
00139         point faceIntersection =
00140             cellCtrs[own[faceI]]
00141           + (dOwn/(dOwn+dNei))*(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]);
00142 
00143         scalar skewness = 
00144             mag(faceCtrs[faceI] - faceIntersection)
00145            /(mag(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]) + VSMALL);
00146 
00147         result[own[faceI]] = max(skewness, result[own[faceI]]);
00148 
00149         result[nei[faceI]] = max(skewness, result[nei[faceI]]);
00150     }
00151 
00152     forAll (mesh_.boundaryMesh(), patchI)
00153     {
00154         const unallocLabelList& faceCells = 
00155             mesh_.boundaryMesh()[patchI].faceCells();
00156 
00157         const vectorField::subField faceCentres =
00158             mesh_.boundaryMesh()[patchI].faceCentres();
00159 
00160         const vectorField::subField faceAreas =
00161             mesh_.boundaryMesh()[patchI].faceAreas();
00162 
00163         forAll(faceCentres, faceI)
00164         {
00165             vector n = faceAreas[faceI]/mag(faceAreas[faceI]);
00166 
00167             point faceIntersection =
00168                 cellCtrs[faceCells[faceI]]
00169               + ((faceCentres[faceI] - cellCtrs[faceCells[faceI]])&n)*n;
00170 
00171             scalar skewness = 
00172                 mag(faceCentres[faceI] - faceIntersection)
00173                /(
00174                     mag(faceCentres[faceI] - cellCtrs[faceCells[faceI]]) 
00175                   + VSMALL
00176                 );
00177 
00178             result[faceCells[faceI]] = max(skewness, result[faceCells[faceI]]);
00179         }
00180     }
00181 
00182     return tresult;
00183 }
00184 
00185 
00186 Foam::tmp<Foam::scalarField> Foam::cellQuality::faceNonOrthogonality() const
00187 {
00188     tmp<scalarField> tresult
00189     (
00190         new scalarField
00191         (
00192             mesh_.nFaces(), 0.0
00193         )
00194     );
00195     scalarField& result = tresult();
00196 
00197 
00198     const vectorField& centres = mesh_.cellCentres();
00199     const vectorField& areas = mesh_.faceAreas();
00200 
00201     const labelList& own = mesh_.faceOwner();
00202     const labelList& nei = mesh_.faceNeighbour();
00203 
00204     forAll (nei, faceI)
00205     {
00206         vector d = centres[nei[faceI]] - centres[own[faceI]];
00207         vector s = areas[faceI];
00208         scalar magS = mag(s);
00209 
00210         scalar cosDDotS =
00211             Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
00212             *180.0/mathematicalConstant::pi;
00213 
00214         result[faceI] = cosDDotS;
00215     }
00216 
00217     label globalFaceI = mesh_.nInternalFaces();
00218 
00219     forAll (mesh_.boundaryMesh(), patchI)
00220     {
00221         const unallocLabelList& faceCells = 
00222             mesh_.boundaryMesh()[patchI].faceCells();
00223 
00224         const vectorField::subField faceCentres =
00225             mesh_.boundaryMesh()[patchI].faceCentres();
00226 
00227         const vectorField::subField faceAreas =
00228             mesh_.boundaryMesh()[patchI].faceAreas();
00229 
00230         forAll(faceCentres, faceI)
00231         {
00232             vector d = faceCentres[faceI] - centres[faceCells[faceI]];
00233             vector s = faceAreas[faceI];
00234             scalar magS = mag(s);
00235 
00236             scalar cosDDotS =
00237                 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
00238                *180.0/mathematicalConstant::pi;
00239 
00240             result[globalFaceI++] = cosDDotS;
00241         }
00242     }
00243 
00244     return tresult;
00245 }
00246 
00247 
00248 Foam::tmp<Foam::scalarField> Foam::cellQuality::faceSkewness() const
00249 {
00250     tmp<scalarField> tresult
00251     (
00252         new scalarField
00253         (
00254             mesh_.nFaces(), 0.0
00255         )
00256     );
00257     scalarField& result = tresult();
00258 
00259 
00260     const vectorField& cellCtrs = mesh_.cellCentres();
00261     const vectorField& faceCtrs = mesh_.faceCentres();
00262     const vectorField& areas = mesh_.faceAreas();
00263 
00264     const labelList& own = mesh_.faceOwner();
00265     const labelList& nei = mesh_.faceNeighbour();
00266 
00267     forAll (nei, faceI)
00268     {
00269         scalar dOwn = mag
00270         (
00271             (faceCtrs[faceI] - cellCtrs[own[faceI]]) & areas[faceI]
00272         )/mag(areas[faceI]);
00273 
00274         scalar dNei = mag
00275         (
00276             (cellCtrs[nei[faceI]] - faceCtrs[faceI]) & areas[faceI]
00277         )/mag(areas[faceI]);
00278 
00279         point faceIntersection =
00280             cellCtrs[own[faceI]]
00281           + (dOwn/(dOwn+dNei))*(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]);
00282 
00283         result[faceI] = 
00284             mag(faceCtrs[faceI] - faceIntersection)
00285            /(mag(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]) + VSMALL);
00286     }
00287 
00288 
00289     label globalFaceI = mesh_.nInternalFaces();
00290 
00291     forAll (mesh_.boundaryMesh(), patchI)
00292     {
00293         const unallocLabelList& faceCells = 
00294             mesh_.boundaryMesh()[patchI].faceCells();
00295 
00296         const vectorField::subField faceCentres =
00297             mesh_.boundaryMesh()[patchI].faceCentres();
00298 
00299         const vectorField::subField faceAreas =
00300             mesh_.boundaryMesh()[patchI].faceAreas();
00301 
00302         forAll(faceCentres, faceI)
00303         {
00304             vector n = faceAreas[faceI]/mag(faceAreas[faceI]);
00305 
00306             point faceIntersection =
00307                 cellCtrs[faceCells[faceI]]
00308               + ((faceCentres[faceI] - cellCtrs[faceCells[faceI]])&n)*n;
00309 
00310             result[globalFaceI++] = 
00311                 mag(faceCentres[faceI] - faceIntersection)
00312                /(
00313                     mag(faceCentres[faceI] - cellCtrs[faceCells[faceI]]) 
00314                   + VSMALL
00315                 );
00316         }
00317     }
00318 
00319     return tresult;
00320 }
00321 
00322 
00323 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines