Dune Core Modules (2.9.0)

meshquality.hh
1#ifndef DUNE_ALU3DGRID_MESHQUALITY_HH
2#define DUNE_ALU3DGRID_MESHQUALITY_HH
3
4#include <iomanip>
5#include <string>
6#include <sstream>
7#include <fstream>
8#include <vector>
9#include <cmath>
10
11#include <dune/grid/common/rangegenerators.hh>
12#include <dune/geometry/referenceelements.hh>
13
14namespace Dune {
15
16 template <class GridView>
17 static void meshQuality( const GridView& gridView, const double time, std::ostream& out )
18 {
19 static const int dim = GridView::dimension;
20 if ( dim < 3 ) return ;
21
22 double minVolShortestEdgeRatio = 1e308;
23 double maxVolShortestEdgeRatio = 0;
24 double avgVolShortestEdgeRatio = 0;
25
26 double minVolLongestEdgeRatio = 1e308;
27 double maxVolLongestEdgeRatio = 0;
28 double avgVolLongestEdgeRatio = 0;
29
30 double minVolSmallestFaceRatio = 1e308;
31 double maxVolSmallestFaceRatio = 0;
32 double avgVolSmallestFaceRatio = 0;
33
34 double minVolBiggestFaceRatio = 1e308;
35 double maxVolBiggestFaceRatio = 0;
36 double avgVolBiggestFaceRatio = 0;
37
38 double minAreaShortestEdgeRatio = 1e308;
39 double maxAreaShortestEdgeRatio = 0;
40 double avgAreaShortestEdgeRatio = 0;
41
42 double minAreaLongestEdgeRatio = 1e308;
43 double maxAreaLongestEdgeRatio = 0;
44 double avgAreaLongestEdgeRatio = 0;
45
46 double minSine = 1e308;
47 double maxSine = 0;
48 double avgSine = 0;
49
50 // TODO: number of elements connected to one edge
51 // TODO: number of elements connected to one vertex
52
53 //in a regular tetrahedron, we have
54 // volume = (sqrt(2)/12)*edge^3
55 // faceArea = (sqrt(3)/4) *edge^2
56
57 const double factorEdgeTet = std::sqrt(2.) / double(12);
58 const double factorFaceEdgeTet = std::sqrt( 3. ) / 4.;
59 const double factorFaceTet = factorEdgeTet * std::pow( ( 1. / factorFaceEdgeTet ), 1.5 ) ;
60
61 std::vector< double > faceVols;
62
63 const auto& indexSet = gridView.indexSet();
64
65 std::vector< int > nElementsPerEdge( indexSet.size( dim-1 ), 0 );
66 std::vector< int > nElementsPerVertex( indexSet.size( dim ), 0 );
67
68 size_t nElements = 0;
69 for( const auto& element : elements( gridView, Dune::Partitions::interiorBorder ) )
70 {
71 const double vol = element.geometry().volume();
72 const Dune::GeometryType geomType = element.type();
73
74 if( ! geomType.isSimplex() )
75 {
76 static bool firstCall = true;
77 if( gridView.comm().rank() == 0 && firstCall )
78 {
79 firstCall = false;
80 std::cout << "MeshQuality check only works for simplex grids, skipping check!" << std::endl;
81 }
82 return ;
83 }
84
85 const double factorEdge = geomType.isCube() ? 1.0 : factorEdgeTet;
86 const double factorFaceEdge = geomType.isCube() ? 1.0 : factorFaceEdgeTet;
87 const double factorFace = geomType.isCube() ? 1.0 : factorFaceTet;
88
89 double shortestEdge = 1e308 ;
90 double longestEdge = 0;
91
92 const int edges = element.subEntities( dim-1 );
93 for( int e = 0 ; e < edges ; ++ e )
94 {
95 const auto& edge = element.template subEntity<dim-1>( e );
96 const auto& geo = edge.geometry();
97 assert( geo.corners() == 2 );
98 //( geo.corner( 1 ) - geo.corner( 0 ) ).two_norm();
99 double edgeLength = geo.volume();
100 shortestEdge = std::min( shortestEdge, edgeLength );
101 longestEdge = std::max( longestEdge, edgeLength );
102
103 const int idx = indexSet.subIndex( element, e, dim-1 );
104 ++(nElementsPerEdge[ idx ]);
105 }
106
107 double smallestFace = 1e308 ;
108 double biggestFace = 0;
109
110 const int faces = element.subEntities( dim-2 );
111 faceVols.clear();
112 faceVols.reserve( faces );
113 for( int f = 0 ; f < faces ; ++ f )
114 {
115 const auto& face = element.template subEntity<dim-2>( f );
116 const auto& geo = face.geometry();
117 //assert( geo.corners() == 3 );
118 //( geo.corner( 1 ) - geo.corner( 0 ) ).two_norm();
119 double faceSize = geo.volume();
120 faceVols.push_back( faceSize );
121
122 smallestFace = std::min( smallestFace, faceSize );
123 biggestFace = std::max( biggestFace, faceSize );
124
125 double shortestFaceEdge = 1e308 ;
126 double longestFaceEdge = 0;
127
128 const int faceEdges = face.subEntities( dim-1 );
129 for( int e = 0 ; e < faceEdges ; ++ e )
130 {
131 const int fe = Dune::ReferenceElements<double, dim>::simplex().subEntity(f,1,e,2);
132 const auto& edge = element.template subEntity<dim-1>( fe );
133 const auto& geo = edge.geometry();
134 assert( geo.corners() == 2 );
135 //( geo.corner( 1 ) - geo.corner( 0 ) ).two_norm();
136 double edgeLength = geo.volume();
137 shortestFaceEdge = std::min( shortestFaceEdge, edgeLength );
138 longestFaceEdge = std::max( longestFaceEdge, edgeLength );
139 }
140
141 //in a regular tetrahedron, we have
142 // volume = (sqrt(2)/12)*edge^3
143 shortestFaceEdge = factorFaceEdge * std::pow( shortestFaceEdge, 2 );
144 longestFaceEdge = factorFaceEdge * std::pow( longestFaceEdge, 2 );
145
146
147 const double areaShortest = faceSize / shortestFaceEdge ;
148 minAreaShortestEdgeRatio = std::min( minAreaShortestEdgeRatio, areaShortest );
149 maxAreaShortestEdgeRatio = std::max( maxAreaShortestEdgeRatio, areaShortest );
150 avgAreaShortestEdgeRatio += areaShortest;
151
152 const double areaLongest = faceSize / longestFaceEdge ;
153 minAreaLongestEdgeRatio = std::min( minAreaLongestEdgeRatio, areaLongest );
154 maxAreaLongestEdgeRatio = std::max( maxAreaLongestEdgeRatio, areaLongest );
155 avgAreaLongestEdgeRatio += areaLongest;
156 }
157
158 const int vertices = element.subEntities( dim );
159
160 double sumSine = 0 ;
161 for ( int i=0; i<vertices; ++i )
162 {
163 const int idx = indexSet.subIndex( element, i, dim );
164 ++(nElementsPerVertex[ idx ]);
165
166 double sine = (vol * 6.0);
167 sine *= sine;
168 for( int f=0; f<faces; ++f )
169 {
170 if( f == 3-i ) continue ;
171 sine /= (faceVols[ f ] * 2.0);
172 }
173
174 minSine = std::min( minSine, sine );
175 maxSine = std::max( maxSine, sine );
176 sumSine += sine ;
177 }
178
179 sumSine /= double(vertices);
180 avgSine += sumSine ;
181
182 //in a regular tetrahedron, we have
183 // volume = (sqrt(2)/12)*edge^3
184 shortestEdge = factorEdge * std::pow( shortestEdge, 3 );
185 longestEdge = factorEdge * std::pow( longestEdge, 3 );
186
187 const double volShortest = vol / shortestEdge;
188 minVolShortestEdgeRatio = std::min( minVolShortestEdgeRatio, volShortest );
189 maxVolShortestEdgeRatio = std::max( maxVolShortestEdgeRatio, volShortest );
190 avgVolShortestEdgeRatio += volShortest;
191
192 const double volLongest = vol / longestEdge ;
193 minVolLongestEdgeRatio = std::min( minVolLongestEdgeRatio, volLongest );
194 maxVolLongestEdgeRatio = std::max( maxVolLongestEdgeRatio, volLongest );
195 avgVolLongestEdgeRatio += volLongest;
196
197 //in a regular tetrahedron, we have
198 // volume = (sqrt(2)/12)*edge^3
199 // faceArea = (sqrt(3)/4) *edge^2
200 smallestFace = factorFace * std::pow( smallestFace, 1.5 );
201 biggestFace = factorFace * std::pow( biggestFace, 1.5 );
202
203 const double volSmallest = vol / smallestFace;
204 minVolSmallestFaceRatio = std::min( minVolSmallestFaceRatio, volSmallest );
205 maxVolSmallestFaceRatio = std::max( maxVolSmallestFaceRatio, volSmallest );
206 avgVolSmallestFaceRatio += volSmallest;
207
208 const double volBiggest = vol / biggestFace ;
209 minVolBiggestFaceRatio = std::min( minVolBiggestFaceRatio, volBiggest );
210 maxVolBiggestFaceRatio = std::max( maxVolBiggestFaceRatio, volBiggest );
211 avgVolBiggestFaceRatio += volBiggest;
212
213 ++ nElements;
214 }
215
216 int maxElementsEdge = 0;
217 int minElementsEdge = 100000000;
218 double avgElementsEdge = 0;
219 double nEdges = nElementsPerEdge.size();
220 for( const auto& nElem : nElementsPerEdge )
221 {
222 maxElementsEdge = std::max( maxElementsEdge, nElem );
223 minElementsEdge = std::min( minElementsEdge, nElem );
224 avgElementsEdge += nElem;
225 }
226
227 int maxElementsVertex = 0;
228 int minElementsVertex = 100000000;
229 double avgElementsVertex = 0;
230 double nVertices = nElementsPerVertex.size();
231 for( const auto& nElem : nElementsPerVertex )
232 {
233 minElementsVertex = std::min( minElementsVertex, nElem );
234 maxElementsVertex = std::max( maxElementsVertex, nElem );
235 avgElementsVertex += nElem;
236 }
237
238 nElements = gridView.grid().comm().sum( nElements );
239
240 minVolShortestEdgeRatio = gridView.grid().comm().min( minVolShortestEdgeRatio );
241 maxVolShortestEdgeRatio = gridView.grid().comm().max( maxVolShortestEdgeRatio );
242 avgVolShortestEdgeRatio = gridView.grid().comm().sum( avgVolShortestEdgeRatio );
243
244 minVolLongestEdgeRatio = gridView.grid().comm().min( minVolLongestEdgeRatio );
245 maxVolLongestEdgeRatio = gridView.grid().comm().max( maxVolLongestEdgeRatio );
246 avgVolLongestEdgeRatio = gridView.grid().comm().sum( avgVolLongestEdgeRatio );
247
248 avgVolShortestEdgeRatio /= double(nElements);
249 avgVolLongestEdgeRatio /= double(nElements);
250
251 minVolSmallestFaceRatio = gridView.grid().comm().min( minVolSmallestFaceRatio );
252 maxVolSmallestFaceRatio = gridView.grid().comm().max( maxVolSmallestFaceRatio );
253 avgVolSmallestFaceRatio = gridView.grid().comm().sum( avgVolSmallestFaceRatio );
254
255 minVolBiggestFaceRatio = gridView.grid().comm().min( minVolBiggestFaceRatio );
256 maxVolBiggestFaceRatio = gridView.grid().comm().max( maxVolBiggestFaceRatio );
257 avgVolBiggestFaceRatio = gridView.grid().comm().sum( avgVolBiggestFaceRatio );
258
259 avgVolSmallestFaceRatio /= double(nElements);
260 avgVolBiggestFaceRatio /= double(nElements);
261
262 minAreaShortestEdgeRatio = gridView.grid().comm().min( minAreaShortestEdgeRatio );
263 maxAreaShortestEdgeRatio = gridView.grid().comm().max( maxAreaShortestEdgeRatio );
264 avgAreaShortestEdgeRatio = gridView.grid().comm().sum( avgAreaShortestEdgeRatio );
265
266 minAreaLongestEdgeRatio = gridView.grid().comm().min( minAreaLongestEdgeRatio );
267 maxAreaLongestEdgeRatio = gridView.grid().comm().max( maxAreaLongestEdgeRatio );
268 avgAreaLongestEdgeRatio = gridView.grid().comm().sum( avgAreaLongestEdgeRatio );
269
270 avgSine /= double(nElements);
271
272 minSine = gridView.grid().comm().min( minSine );
273 maxSine = gridView.grid().comm().max( maxSine );
274 avgSine = gridView.grid().comm().sum( avgSine );
275
276 minElementsEdge = gridView.grid().comm().min( minElementsEdge );
277 minElementsVertex = gridView.grid().comm().min( minElementsVertex );
278 maxElementsEdge = gridView.grid().comm().max( maxElementsEdge );
279 maxElementsVertex = gridView.grid().comm().max( maxElementsVertex );
280
281 nEdges = gridView.grid().comm().sum( nEdges );
282 nVertices = gridView.grid().comm().sum( nVertices );
283
284 avgElementsVertex = gridView.grid().comm().sum( avgElementsVertex );
285 avgElementsEdge = gridView.grid().comm().sum( avgElementsEdge );
286
287 avgElementsEdge /= nEdges;
288 avgElementsVertex /= nVertices;
289
290 avgAreaShortestEdgeRatio /= double(4 * nElements);
291 avgAreaLongestEdgeRatio /= double(4 * nElements);
292
293 if( gridView.grid().comm().rank() == 0 )
294 {
295 int space = 18;
296 out << "# MeshQuality: time=1 V/LE(min=2,max=3,avg=4) V/SE(min=5,max=6,avg=7) V/LF(min=8,max=9,avg=10) V/SF(min=11,max=12,avg=13) A/LE(min=14,max=15,avg=16) A/SE(min=17,max=18,avg=19) " << std::endl;
297 out << time << " ";
298 out << std::setw(space) << minVolLongestEdgeRatio << " " << maxVolLongestEdgeRatio << " " << avgVolLongestEdgeRatio << " ";
299 out << std::setw(space) << minVolShortestEdgeRatio << " " << maxVolShortestEdgeRatio << " " << avgVolShortestEdgeRatio << " " ;
300 out << std::setw(space) << minVolBiggestFaceRatio << " " << maxVolBiggestFaceRatio << " " << avgVolBiggestFaceRatio << " ";
301 out << std::setw(space) << minVolSmallestFaceRatio << " " << maxVolSmallestFaceRatio << " " << avgVolSmallestFaceRatio << " ";
302 out << std::setw(space) << minAreaLongestEdgeRatio << " " << maxAreaLongestEdgeRatio << " " << avgAreaLongestEdgeRatio << " ";
303 out << std::setw(space) << minAreaShortestEdgeRatio << " " << maxAreaShortestEdgeRatio << " " << avgAreaShortestEdgeRatio << " ";
304 out << std::setw(space) << minSine << " " << maxSine << " " << avgSine << " ";
305 out << std::setw(space) << minElementsEdge << " " << maxElementsEdge << " " << avgElementsEdge << " ";
306 out << std::setw(space) << minElementsVertex << " " << maxElementsVertex << " " << avgElementsVertex << " ";
307 out << std::endl;
308 }
309 }
310
311} // end namespace Dune
312
313#endif // #ifndef DUNE_ALU3DGRID_MESHQUALITY_HH
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:125
constexpr bool isCube() const
Return true if entity is a cube of any dimension.
Definition: type.hh:335
constexpr bool isSimplex() const
Return true if entity is a simplex of any dimension.
Definition: type.hh:330
static constexpr int dimension
The dimension of the grid.
Definition: gridview.hh:148
constexpr InteriorBorder interiorBorder
PartitionSet for the interior and border partitions.
Definition: partitionset.hh:287
Dune namespace.
Definition: alignedallocator.hh:13
static const ReferenceElement & simplex()
get simplex reference elements
Definition: referenceelements.hh:204
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)