1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
25 Class calculates cell quality measures.
27 \*---------------------------------------------------------------------------*/
29 #include "cellQuality.H"
30 #include "mathematicalConstants.H"
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 // Construct from mesh
35 Foam::cellQuality::cellQuality(const polyMesh& mesh)
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 Foam::tmp<Foam::scalarField> Foam::cellQuality::nonOrthogonality() const
45 tmp<scalarField> tresult
53 scalarField& result = tresult();
55 scalarField sumArea(mesh_.nCells(), 0.0);
57 const vectorField& centres = mesh_.cellCentres();
58 const vectorField& areas = mesh_.faceAreas();
60 const labelList& own = mesh_.faceOwner();
61 const labelList& nei = mesh_.faceNeighbour();
65 vector d = centres[nei[faceI]] - centres[own[faceI]];
66 vector s = areas[faceI];
70 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
71 *180.0/mathematicalConstant::pi;
73 result[own[faceI]] = max(cosDDotS, result[own[faceI]]);
75 result[nei[faceI]] = max(cosDDotS, result[nei[faceI]]);
78 forAll (mesh_.boundaryMesh(), patchI)
80 const unallocLabelList& faceCells =
81 mesh_.boundaryMesh()[patchI].faceCells();
83 const vectorField::subField faceCentres =
84 mesh_.boundaryMesh()[patchI].faceCentres();
86 const vectorField::subField faceAreas =
87 mesh_.boundaryMesh()[patchI].faceAreas();
89 forAll(faceCentres, faceI)
91 vector d = faceCentres[faceI] - centres[faceCells[faceI]];
92 vector s = faceAreas[faceI];
96 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
97 *180.0/mathematicalConstant::pi;
99 result[faceCells[faceI]] = max(cosDDotS, result[faceCells[faceI]]);
107 Foam::tmp<Foam::scalarField> Foam::cellQuality::skewness() const
109 tmp<scalarField> tresult
116 scalarField& result = tresult();
118 scalarField sumArea(mesh_.nCells(), 0.0);
120 const vectorField& cellCtrs = mesh_.cellCentres();
121 const vectorField& faceCtrs = mesh_.faceCentres();
122 const vectorField& areas = mesh_.faceAreas();
124 const labelList& own = mesh_.faceOwner();
125 const labelList& nei = mesh_.faceNeighbour();
131 (faceCtrs[faceI] - cellCtrs[own[faceI]]) & areas[faceI]
136 (cellCtrs[nei[faceI]] - faceCtrs[faceI]) & areas[faceI]
139 point faceIntersection =
141 + (dOwn/(dOwn+dNei))*(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]);
144 mag(faceCtrs[faceI] - faceIntersection)
145 /(mag(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]) + VSMALL);
147 result[own[faceI]] = max(skewness, result[own[faceI]]);
149 result[nei[faceI]] = max(skewness, result[nei[faceI]]);
152 forAll (mesh_.boundaryMesh(), patchI)
154 const unallocLabelList& faceCells =
155 mesh_.boundaryMesh()[patchI].faceCells();
157 const vectorField::subField faceCentres =
158 mesh_.boundaryMesh()[patchI].faceCentres();
160 const vectorField::subField faceAreas =
161 mesh_.boundaryMesh()[patchI].faceAreas();
163 forAll(faceCentres, faceI)
165 vector n = faceAreas[faceI]/mag(faceAreas[faceI]);
167 point faceIntersection =
168 cellCtrs[faceCells[faceI]]
169 + ((faceCentres[faceI] - cellCtrs[faceCells[faceI]])&n)*n;
172 mag(faceCentres[faceI] - faceIntersection)
174 mag(faceCentres[faceI] - cellCtrs[faceCells[faceI]])
178 result[faceCells[faceI]] = max(skewness, result[faceCells[faceI]]);
186 Foam::tmp<Foam::scalarField> Foam::cellQuality::faceNonOrthogonality() const
188 tmp<scalarField> tresult
195 scalarField& result = tresult();
198 const vectorField& centres = mesh_.cellCentres();
199 const vectorField& areas = mesh_.faceAreas();
201 const labelList& own = mesh_.faceOwner();
202 const labelList& nei = mesh_.faceNeighbour();
206 vector d = centres[nei[faceI]] - centres[own[faceI]];
207 vector s = areas[faceI];
208 scalar magS = mag(s);
211 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
212 *180.0/mathematicalConstant::pi;
214 result[faceI] = cosDDotS;
217 label globalFaceI = mesh_.nInternalFaces();
219 forAll (mesh_.boundaryMesh(), patchI)
221 const unallocLabelList& faceCells =
222 mesh_.boundaryMesh()[patchI].faceCells();
224 const vectorField::subField faceCentres =
225 mesh_.boundaryMesh()[patchI].faceCentres();
227 const vectorField::subField faceAreas =
228 mesh_.boundaryMesh()[patchI].faceAreas();
230 forAll(faceCentres, faceI)
232 vector d = faceCentres[faceI] - centres[faceCells[faceI]];
233 vector s = faceAreas[faceI];
234 scalar magS = mag(s);
237 Foam::acos(min(1.0, (d & s)/(mag(d)*magS + VSMALL)))
238 *180.0/mathematicalConstant::pi;
240 result[globalFaceI++] = cosDDotS;
248 Foam::tmp<Foam::scalarField> Foam::cellQuality::faceSkewness() const
250 tmp<scalarField> tresult
257 scalarField& result = tresult();
260 const vectorField& cellCtrs = mesh_.cellCentres();
261 const vectorField& faceCtrs = mesh_.faceCentres();
262 const vectorField& areas = mesh_.faceAreas();
264 const labelList& own = mesh_.faceOwner();
265 const labelList& nei = mesh_.faceNeighbour();
271 (faceCtrs[faceI] - cellCtrs[own[faceI]]) & areas[faceI]
276 (cellCtrs[nei[faceI]] - faceCtrs[faceI]) & areas[faceI]
279 point faceIntersection =
281 + (dOwn/(dOwn+dNei))*(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]);
284 mag(faceCtrs[faceI] - faceIntersection)
285 /(mag(cellCtrs[nei[faceI]] - cellCtrs[own[faceI]]) + VSMALL);
289 label globalFaceI = mesh_.nInternalFaces();
291 forAll (mesh_.boundaryMesh(), patchI)
293 const unallocLabelList& faceCells =
294 mesh_.boundaryMesh()[patchI].faceCells();
296 const vectorField::subField faceCentres =
297 mesh_.boundaryMesh()[patchI].faceCentres();
299 const vectorField::subField faceAreas =
300 mesh_.boundaryMesh()[patchI].faceAreas();
302 forAll(faceCentres, faceI)
304 vector n = faceAreas[faceI]/mag(faceAreas[faceI]);
306 point faceIntersection =
307 cellCtrs[faceCells[faceI]]
308 + ((faceCentres[faceI] - cellCtrs[faceCells[faceI]])&n)*n;
310 result[globalFaceI++] =
311 mag(faceCentres[faceI] - faceIntersection)
313 mag(faceCentres[faceI] - cellCtrs[faceCells[faceI]])
323 // ************************************************************************* //