1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Given a set of points, find out if the mesh resulting from point motion will
27 be valid without actually changing the mesh.
29 \*---------------------------------------------------------------------------*/
31 #include "primitiveMesh.H"
32 #include "pyramidPointFaceRef.H"
34 #include "mathematicalConstants.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 bool Foam::primitiveMesh::checkMeshMotion
43 const pointField& newPoints,
49 Pout<< "bool primitiveMesh::checkMeshMotion("
50 << "const pointField& newPoints, const bool report) const: "
51 << "checking mesh motion" << endl;
56 const faceList& f = faces();
58 const labelList& own = faceOwner();
59 const labelList& nei = faceNeighbour();
61 vectorField fCtrs(nFaces());
62 vectorField fAreas(nFaces());
64 makeFaceCentresAndAreas(newPoints, fCtrs, fAreas);
66 // Check cell volumes and calculate new cell centres
67 vectorField cellCtrs(nCells());
68 scalarField cellVols(nCells());
70 makeCellCentresAndVols(fCtrs, fAreas, cellCtrs, cellVols);
72 scalar minVolume = GREAT;
75 forAll (cellVols, cellI)
77 if (cellVols[cellI] < VSMALL)
81 Pout<< "Zero or negative cell volume detected for cell "
82 << cellI << ". Volume = " << cellVols[cellI] << endl;
88 minVolume = min(minVolume, cellVols[cellI]);
95 Pout<< "Zero or negative cell volume in mesh motion in " << nNegVols
96 << " cells. Min volume: " << minVolume << endl;
102 Pout<< "Min volume = " << minVolume
103 << ". Total volume = " << sum(cellVols)
104 << ". Cell volumes OK." << endl;
110 scalar minArea = GREAT;
112 label nPyrErrors = 0;
113 label nDotProductErrors = 0;
117 const scalar a = Foam::mag(fAreas[faceI]);
123 if (isInternalFace(faceI))
125 Pout<< "Zero or negative face area detected for "
126 << "internal face "<< faceI << " between cells "
127 << own[faceI] << " and " << nei[faceI]
128 << ". Face area magnitude = " << a << endl;
132 Pout<< "Zero or negative face area detected for "
133 << "boundary face " << faceI << " next to cell "
134 << own[faceI] << ". Face area magnitude = "
142 minArea = min(minArea, a);
144 // Create the owner pyramid - it will have negative volume
146 pyramidPointFaceRef(f[faceI], cellCtrs[own[faceI]]).mag(newPoints);
152 Pout<< "Negative pyramid volume: " << -pyrVol
153 << " for face " << faceI << " " << f[faceI]
154 << " and owner cell: " << own[faceI] << endl
155 << "Owner cell vertex labels: "
156 << cells()[own[faceI]].labels(f)
163 if (isInternalFace(faceI))
165 // Create the neighbour pyramid - it will have positive volume
177 Pout<< "Negative pyramid volume: " << pyrVol
178 << " for face " << faceI << " " << f[faceI]
179 << " and neighbour cell: " << nei[faceI] << nl
180 << "Neighbour cell vertex labels: "
181 << cells()[nei[faceI]].labels(f)
188 const vector d = cellCtrs[nei[faceI]] - cellCtrs[own[faceI]];
189 const vector& s = fAreas[faceI];
190 scalar dDotS = (d & s)/(mag(d)*mag(s) + VSMALL);
192 // Only write full message the first time
193 if (dDotS < SMALL && nDotProductErrors == 0)
195 // Non-orthogonality greater than 90 deg
198 "primitiveMesh::checkMeshMotion"
199 "(const pointField& newPoints, const bool report) const"
200 ) << "Severe non-orthogonality in mesh motion for face "
202 << " between cells " << own[faceI] << " and " << nei[faceI]
203 << ": Angle = " << ::acos(dDotS)/mathematicalConstant::pi*180.0
217 "primitiveMesh::checkMeshMotion"
218 "(const pointField& newPoints, const bool report) const"
219 ) << "Zero or negative face area in mesh motion in " << nNegAreas
220 << " faces. Min area: " << minArea << endl;
226 Pout<< "Min area = " << minArea
227 << ". Face areas OK." << endl;
233 Pout<< "Detected " << nPyrErrors
234 << " negative pyramid volume in mesh motion" << endl;
242 Pout<< "Pyramid volumes OK." << endl;
246 if (nDotProductErrors > 0)
248 Pout<< "Detected " << nDotProductErrors
249 << " in non-orthogonality in mesh motion." << endl;
257 Pout<< "Non-orthogonality check OK." << endl;
261 if (!error && (debug || report))
263 Pout << "Mesh motion check OK." << endl;
270 // ************************************************************************* //