1#ifndef DUNE_ALU3DGRID_MESHQUALITY_HH
2#define DUNE_ALU3DGRID_MESHQUALITY_HH
11#include <dune/grid/common/rangegenerators.hh>
12#include <dune/geometry/referenceelements.hh>
16 template <
class Gr
idView>
17 static void meshQuality(
const GridView& gridView,
const double time, std::ostream& out )
20 if ( dim < 3 ) return ;
22 double minVolShortestEdgeRatio = 1e308;
23 double maxVolShortestEdgeRatio = 0;
24 double avgVolShortestEdgeRatio = 0;
26 double minVolLongestEdgeRatio = 1e308;
27 double maxVolLongestEdgeRatio = 0;
28 double avgVolLongestEdgeRatio = 0;
30 double minVolSmallestFaceRatio = 1e308;
31 double maxVolSmallestFaceRatio = 0;
32 double avgVolSmallestFaceRatio = 0;
34 double minVolBiggestFaceRatio = 1e308;
35 double maxVolBiggestFaceRatio = 0;
36 double avgVolBiggestFaceRatio = 0;
38 double minAreaShortestEdgeRatio = 1e308;
39 double maxAreaShortestEdgeRatio = 0;
40 double avgAreaShortestEdgeRatio = 0;
42 double minAreaLongestEdgeRatio = 1e308;
43 double maxAreaLongestEdgeRatio = 0;
44 double avgAreaLongestEdgeRatio = 0;
46 double minSine = 1e308;
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 ) ;
61 std::vector< double > faceVols;
63 const auto& indexSet = gridView.indexSet();
65 std::vector< int > nElementsPerEdge( indexSet.size( dim-1 ), 0 );
66 std::vector< int > nElementsPerVertex( indexSet.size( dim ), 0 );
71 const double vol = element.geometry().volume();
76 static bool firstCall =
true;
77 if( gridView.comm().rank() == 0 && firstCall )
80 std::cout <<
"MeshQuality check only works for simplex grids, skipping check!" << std::endl;
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;
89 double shortestEdge = 1e308 ;
90 double longestEdge = 0;
92 const int edges = element.subEntities( dim-1 );
93 for(
int e = 0 ; e < edges ; ++ e )
95 const auto& edge = element.template subEntity<dim-1>( e );
96 const auto& geo = edge.geometry();
97 assert( geo.corners() == 2 );
99 double edgeLength = geo.volume();
100 shortestEdge = std::min( shortestEdge, edgeLength );
101 longestEdge = std::max( longestEdge, edgeLength );
103 const int idx = indexSet.subIndex( element, e, dim-1 );
104 ++(nElementsPerEdge[ idx ]);
107 double smallestFace = 1e308 ;
108 double biggestFace = 0;
110 const int faces = element.subEntities( dim-2 );
112 faceVols.reserve( faces );
113 for(
int f = 0 ; f < faces ; ++ f )
115 const auto& face = element.template subEntity<dim-2>( f );
116 const auto& geo = face.geometry();
119 double faceSize = geo.volume();
120 faceVols.push_back( faceSize );
122 smallestFace = std::min( smallestFace, faceSize );
123 biggestFace = std::max( biggestFace, faceSize );
125 double shortestFaceEdge = 1e308 ;
126 double longestFaceEdge = 0;
128 const int faceEdges = face.subEntities( dim-1 );
129 for(
int e = 0 ; e < faceEdges ; ++ e )
132 const auto& edge = element.template subEntity<dim-1>( fe );
133 const auto& geo = edge.geometry();
134 assert( geo.corners() == 2 );
136 double edgeLength = geo.volume();
137 shortestFaceEdge = std::min( shortestFaceEdge, edgeLength );
138 longestFaceEdge = std::max( longestFaceEdge, edgeLength );
143 shortestFaceEdge = factorFaceEdge * std::pow( shortestFaceEdge, 2 );
144 longestFaceEdge = factorFaceEdge * std::pow( longestFaceEdge, 2 );
147 const double areaShortest = faceSize / shortestFaceEdge ;
148 minAreaShortestEdgeRatio = std::min( minAreaShortestEdgeRatio, areaShortest );
149 maxAreaShortestEdgeRatio = std::max( maxAreaShortestEdgeRatio, areaShortest );
150 avgAreaShortestEdgeRatio += areaShortest;
152 const double areaLongest = faceSize / longestFaceEdge ;
153 minAreaLongestEdgeRatio = std::min( minAreaLongestEdgeRatio, areaLongest );
154 maxAreaLongestEdgeRatio = std::max( maxAreaLongestEdgeRatio, areaLongest );
155 avgAreaLongestEdgeRatio += areaLongest;
158 const int vertices = element.subEntities( dim );
161 for (
int i=0; i<vertices; ++i )
163 const int idx = indexSet.subIndex( element, i, dim );
164 ++(nElementsPerVertex[ idx ]);
166 double sine = (vol * 6.0);
168 for(
int f=0; f<faces; ++f )
170 if( f == 3-i ) continue ;
171 sine /= (faceVols[ f ] * 2.0);
174 minSine = std::min( minSine, sine );
175 maxSine = std::max( maxSine, sine );
179 sumSine /= double(vertices);
184 shortestEdge = factorEdge * std::pow( shortestEdge, 3 );
185 longestEdge = factorEdge * std::pow( longestEdge, 3 );
187 const double volShortest = vol / shortestEdge;
188 minVolShortestEdgeRatio = std::min( minVolShortestEdgeRatio, volShortest );
189 maxVolShortestEdgeRatio = std::max( maxVolShortestEdgeRatio, volShortest );
190 avgVolShortestEdgeRatio += volShortest;
192 const double volLongest = vol / longestEdge ;
193 minVolLongestEdgeRatio = std::min( minVolLongestEdgeRatio, volLongest );
194 maxVolLongestEdgeRatio = std::max( maxVolLongestEdgeRatio, volLongest );
195 avgVolLongestEdgeRatio += volLongest;
200 smallestFace = factorFace * std::pow( smallestFace, 1.5 );
201 biggestFace = factorFace * std::pow( biggestFace, 1.5 );
203 const double volSmallest = vol / smallestFace;
204 minVolSmallestFaceRatio = std::min( minVolSmallestFaceRatio, volSmallest );
205 maxVolSmallestFaceRatio = std::max( maxVolSmallestFaceRatio, volSmallest );
206 avgVolSmallestFaceRatio += volSmallest;
208 const double volBiggest = vol / biggestFace ;
209 minVolBiggestFaceRatio = std::min( minVolBiggestFaceRatio, volBiggest );
210 maxVolBiggestFaceRatio = std::max( maxVolBiggestFaceRatio, volBiggest );
211 avgVolBiggestFaceRatio += volBiggest;
216 int maxElementsEdge = 0;
217 int minElementsEdge = 100000000;
218 double avgElementsEdge = 0;
219 double nEdges = nElementsPerEdge.size();
220 for(
const auto& nElem : nElementsPerEdge )
222 maxElementsEdge = std::max( maxElementsEdge, nElem );
223 minElementsEdge = std::min( minElementsEdge, nElem );
224 avgElementsEdge += nElem;
227 int maxElementsVertex = 0;
228 int minElementsVertex = 100000000;
229 double avgElementsVertex = 0;
230 double nVertices = nElementsPerVertex.size();
231 for(
const auto& nElem : nElementsPerVertex )
233 minElementsVertex = std::min( minElementsVertex, nElem );
234 maxElementsVertex = std::max( maxElementsVertex, nElem );
235 avgElementsVertex += nElem;
238 nElements = gridView.grid().comm().sum( nElements );
240 minVolShortestEdgeRatio = gridView.grid().comm().min( minVolShortestEdgeRatio );
241 maxVolShortestEdgeRatio = gridView.grid().comm().max( maxVolShortestEdgeRatio );
242 avgVolShortestEdgeRatio = gridView.grid().comm().sum( avgVolShortestEdgeRatio );
244 minVolLongestEdgeRatio = gridView.grid().comm().min( minVolLongestEdgeRatio );
245 maxVolLongestEdgeRatio = gridView.grid().comm().max( maxVolLongestEdgeRatio );
246 avgVolLongestEdgeRatio = gridView.grid().comm().sum( avgVolLongestEdgeRatio );
248 avgVolShortestEdgeRatio /= double(nElements);
249 avgVolLongestEdgeRatio /= double(nElements);
251 minVolSmallestFaceRatio = gridView.grid().comm().min( minVolSmallestFaceRatio );
252 maxVolSmallestFaceRatio = gridView.grid().comm().max( maxVolSmallestFaceRatio );
253 avgVolSmallestFaceRatio = gridView.grid().comm().sum( avgVolSmallestFaceRatio );
255 minVolBiggestFaceRatio = gridView.grid().comm().min( minVolBiggestFaceRatio );
256 maxVolBiggestFaceRatio = gridView.grid().comm().max( maxVolBiggestFaceRatio );
257 avgVolBiggestFaceRatio = gridView.grid().comm().sum( avgVolBiggestFaceRatio );
259 avgVolSmallestFaceRatio /= double(nElements);
260 avgVolBiggestFaceRatio /= double(nElements);
262 minAreaShortestEdgeRatio = gridView.grid().comm().min( minAreaShortestEdgeRatio );
263 maxAreaShortestEdgeRatio = gridView.grid().comm().max( maxAreaShortestEdgeRatio );
264 avgAreaShortestEdgeRatio = gridView.grid().comm().sum( avgAreaShortestEdgeRatio );
266 minAreaLongestEdgeRatio = gridView.grid().comm().min( minAreaLongestEdgeRatio );
267 maxAreaLongestEdgeRatio = gridView.grid().comm().max( maxAreaLongestEdgeRatio );
268 avgAreaLongestEdgeRatio = gridView.grid().comm().sum( avgAreaLongestEdgeRatio );
270 avgSine /= double(nElements);
272 minSine = gridView.grid().comm().min( minSine );
273 maxSine = gridView.grid().comm().max( maxSine );
274 avgSine = gridView.grid().comm().sum( avgSine );
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 );
281 nEdges = gridView.grid().comm().sum( nEdges );
282 nVertices = gridView.grid().comm().sum( nVertices );
284 avgElementsVertex = gridView.grid().comm().sum( avgElementsVertex );
285 avgElementsEdge = gridView.grid().comm().sum( avgElementsEdge );
287 avgElementsEdge /= nEdges;
288 avgElementsVertex /= nVertices;
290 avgAreaShortestEdgeRatio /= double(4 * nElements);
291 avgAreaLongestEdgeRatio /= double(4 * nElements);
293 if( gridView.grid().comm().rank() == 0 )
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;
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 <<
" ";
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