1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 Implementation of tetrahedral mesh-quality metrics.
30 Most measures are referenced from:
31 Jonathan R. Shewchuk. What is a good linear finite element?
32 Interpolation, Conditioning, Anisotropy and Quality Measures.
33 Eleventh International Meshing Roundtable (Ithaca, NY), pp 115-126, 2002.
36 For metrics involving volume the function assumes points (p0-p1-p2)
37 are in counter-clockwise fashion when viewed from p3.
41 University of Massachusetts Amherst
44 \*----------------------------------------------------------------------------*/
46 #include "tetMetrics.H"
47 #include "addToMemberFunctionSelectionTable.H"
52 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
54 defineTypeNameAndDebug(Knupp,0);
55 defineTypeNameAndDebug(Dihedral,0);
56 defineTypeNameAndDebug(cubicMeanRatio,0);
57 defineTypeNameAndDebug(Frobenius,0);
58 defineTypeNameAndDebug(PGH,0);
59 defineTypeNameAndDebug(CSG,0);
62 addToMemberFunctionSelectionTable(tetMetric, Knupp, metric, Point);
63 addToMemberFunctionSelectionTable(tetMetric, Dihedral, metric, Point);
64 addToMemberFunctionSelectionTable(tetMetric, cubicMeanRatio, metric, Point);
65 addToMemberFunctionSelectionTable(tetMetric, Frobenius, metric, Point);
66 addToMemberFunctionSelectionTable(tetMetric, PGH, metric, Point);
67 addToMemberFunctionSelectionTable(tetMetric, CSG, metric, Point);
70 // Enumeration for tets
71 label Dihedral::tetEnum[6][4] =
81 // * * * * * * * * * * * * * Static Members Functions * * * * * * * * * * * //
83 // Tetrahedral mesh-quality metric suggested by Knupp [2003].
92 // Obtain signed tet volume
93 scalar V = (1.0/6.0)*(((p1 - p0) ^ (p2 - p0)) & (p3 - p0));
95 // Obtain the magSqr edge-lengths
96 scalar Le = ((p1-p0) & (p1-p0))
100 + ((p3-p1) & (p3-p1))
101 + ((p3-p2) & (p3-p2));
103 // Return signed quality
104 return sign(V)*((24.96100588*::cbrt(V*V))/Le);
108 // Minimum dihedral angle among six edges of the tetrahedron. Normalized
109 // by 70.529 degrees (equilateral tet) and signed by volume.
110 scalar Dihedral::metric
118 scalar minAngle = 0.0;
119 FixedList<scalar,6> cosAngles(1.0);
120 FixedList<vector,4> pts(vector::zero);
122 // Assign point-positions
128 // Permute over all six edges
129 for (label i = 0; i < 6; i++)
131 // Normalize the axis
132 vector v0 = (pts[tetEnum[i][1]] - pts[tetEnum[i][0]])
133 /mag(pts[tetEnum[i][1]] - pts[tetEnum[i][0]]);
135 // Obtain plane-vectors
136 vector v1 = (pts[tetEnum[i][2]] - pts[tetEnum[i][0]]);
137 vector v2 = (pts[tetEnum[i][3]] - pts[tetEnum[i][0]]);
142 cosAngles[i] = acos((v1/mag(v1)) & (v2/mag(v2)));
144 // Compute minimum angle on-the-fly
147 minAngle = minAngle < cosAngles[i] ? minAngle : cosAngles[i];
151 minAngle = cosAngles[0];
155 // Compute signed volume and multiply by the normalized angle
156 return sign(((p1 - p0) ^ (p2 - p0)) & (p3 - p0))*(minAngle/1.2309632);
160 // Cubic Mean Ratio Tetrahedral mesh metric
161 // Liu,A. and Joe, B., “On the shape of tetrahedra from bisection”
162 // Mathematics of Computation, Vol. 63, 1994, pp. 141–154.
163 scalar cubicMeanRatio::metric
171 // Obtain signed tet volume
172 scalar V = (1.0/6.0)*(((p1 - p0) ^ (p2 - p0)) & (p3 - p0));
174 // Obtain the magSqr edge-lengths
175 scalar Le = ((p1-p0) & (p1-p0))
176 + ((p2-p0) & (p2-p0))
177 + ((p3-p0) & (p3-p0))
178 + ((p2-p1) & (p2-p1))
179 + ((p3-p1) & (p3-p1))
180 + ((p3-p2) & (p3-p2));
182 // Return signed quality
183 return sign(V)*((15552.0*V*V)/(Le*Le*Le));
187 // Tetrahedral mesh-metric based on the Frobenius Condition Number
188 // Patrick M. Knupp. Matrix Norms & the Condition Number: A General Framework
189 // to Improve Mesh Quality via Node-Movement. Eighth International Meshing
190 // Roundtable (Lake Tahoe, California), pages 13–22, October 1999.
191 scalar Frobenius::metric
199 // Obtain signed tet volume
200 scalar V = (1.0/6.0)*(((p1 - p0) ^ (p2 - p0)) & (p3 - p0));
202 // Obtain the magSqr edge-lengths
203 scalar Le = ((p1-p0) & (p1-p0))
204 + ((p2-p0) & (p2-p0))
205 + ((p3-p0) & (p3-p0))
206 + ((p2-p1) & (p2-p1))
207 + ((p3-p1) & (p3-p1))
208 + ((p3-p2) & (p3-p2));
210 // Compute magSqr of face-areas
211 scalar A = magSqr(0.5*((p1-p0) ^ (p2-p0)))
212 + magSqr(0.5*((p1-p0) ^ (p3-p0)))
213 + magSqr(0.5*((p2-p0) ^ (p3-p0)))
214 + magSqr(0.5*((p3-p1) ^ (p2-p1)));
216 // Return signed quality
217 return 3.67423461*(V/sqrt((Le/6.0)*(A/4.0)));
221 // Tetrahedral mesh-metric suggested by:
222 // V. N. Parthasarathy, C. M. Graichen, and A. F. Hathaway.
223 // Fast Evaluation & Improvement of Tetrahedral 3-D Grid Quality. [1991]
232 // Obtain signed tet volume
233 scalar V = (1.0/6.0)*(((p1 - p0) ^ (p2 - p0)) & (p3 - p0));
235 // Obtain the magSqr edge-lengths
236 scalar Le = ((p1-p0) & (p1-p0))
237 + ((p2-p0) & (p2-p0))
238 + ((p3-p0) & (p3-p0))
239 + ((p2-p1) & (p2-p1))
240 + ((p3-p1) & (p3-p1))
241 + ((p3-p2) & (p3-p2));
243 // Return signed quality
244 return 8.48528137*(V/pow(Le/4.0,1.5));
248 // Metric suggested by:
249 // Hugues L. de Cougny, Mark S. Shephard, and Marcel K. Georges.
250 // Explicit Node Point Smoothing Within Octree. Technical Report 10-1990,
251 // Scientific Computation Research Center, Rensselaer Polytechnic Institute,
252 // Troy, New York. [1990]
261 // Obtain signed tet volume
262 scalar V = (1.0/6.0)*(((p1 - p0) ^ (p2 - p0)) & (p3 - p0));
264 // Compute magSqr of face-areas
265 scalar A = magSqr(0.5*((p1-p0) ^ (p2-p0)))
266 + magSqr(0.5*((p1-p0) ^ (p3-p0)))
267 + magSqr(0.5*((p2-p0) ^ (p3-p0)))
268 + magSqr(0.5*((p3-p1) ^ (p2-p1)));
270 // Return signed quality
271 return 6.83852117*(V/pow(A,0.75));
275 } // End namespace Foam
277 // ************************************************************************* //