1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_GRID_TEST_CHECKTWISTS_HH
4 #define DUNE_GRID_TEST_CHECKTWISTS_HH
5
6 #include <dune/geometry/referenceelements.hh>
7
applyTwist(const int twist,const int i,const int numCorners)8 int applyTwist ( const int twist, const int i, const int numCorners )
9 {
10 return (twist < 0 ? (2*numCorners + 1 - i + twist) : i + twist) % numCorners;
11 }
12
inverseTwist(const int twist,const int numCorners)13 int inverseTwist ( const int twist, const int numCorners )
14 {
15 return (twist <= 0 ? twist : numCorners - twist);
16 }
17
18
19 struct NoMapTwist
20 {
operator ()NoMapTwist21 int operator() ( const int twist ) const
22 {
23 return twist;
24 }
25 };
26
27
28 template< class Intersection, class MapTwist >
checkTwistOnIntersection(const Intersection & intersection,const MapTwist & mapTwist)29 int checkTwistOnIntersection ( const Intersection &intersection, const MapTwist &mapTwist )
30 {
31 const int dimension = Intersection::dimension;
32
33 typedef typename Intersection::Entity Entity;
34 typedef typename Entity::Geometry Geometry;
35 typedef typename Geometry::ctype ctype;
36
37 typedef typename Intersection::LocalGeometry LocalGeometry;
38
39 typedef Dune::FieldVector< typename Geometry::ctype, Geometry::coorddimension >
40 WorldVector;
41 typedef Dune::FieldVector< typename LocalGeometry::ctype, LocalGeometry::coorddimension >
42 LocalVector;
43
44 if( !intersection.neighbor() || intersection.boundary() || !intersection.conforming() )
45 return 0;
46
47 int errors = 0;
48 const ctype tolerance = std::numeric_limits< ctype >::epsilon();
49
50 const int tIn = mapTwist( intersection.twistInInside() );
51 const int tOut = mapTwist( intersection.twistInOutside() );
52
53 const Entity entityIn = intersection.inside();
54 const Entity entityOut = intersection.outside();
55
56 const Geometry &geoIn = entityIn.geometry();
57 const Geometry &geoOut = entityOut.geometry();
58
59 const int nIn = intersection.indexInInside();
60 const int nOut = intersection.indexInOutside();
61
62 auto refIn = referenceElement( geoIn );
63 auto refOut = referenceElement( geoOut );
64
65 const int numCorners = refIn.size( nIn, 1, dimension );
66 assert( refOut.size( nOut, 1, dimension ) == numCorners );
67 for( int i = 0; i < numCorners; ++i )
68 {
69 const int iIn = applyTwist( inverseTwist( tIn, numCorners ), i, numCorners );
70 const int iOut = applyTwist( inverseTwist( tOut, numCorners ), i, numCorners );
71
72 WorldVector xIn = geoIn.corner( refIn.subEntity( nIn, 1, iIn, dimension ) );
73 WorldVector xOut = geoOut.corner( refOut.subEntity( nOut, 1, iOut, dimension ) );
74
75 if( (xIn - xOut).two_norm() < tolerance )
76 continue;
77
78 std::cout << "Error: corner( " << iIn << " ) = " << xIn
79 << " != " << xOut << " = corner( " << iOut << " )."
80 << std::endl;
81 ++errors;
82 }
83
84 const LocalGeometry &lGeoIn = intersection.geometryInInside();
85 const LocalGeometry &lGeoOut = intersection.geometryInOutside();
86
87 bool twistInside = true ;
88 bool twistOutside = true;
89 for( int i = 0; i < numCorners; ++i )
90 {
91 const int gi = i;
92
93 const int iIn = applyTwist( inverseTwist( tIn, numCorners ), i, numCorners );
94 LocalVector xIn = refIn.position( refIn.subEntity( nIn, 1, iIn, dimension ), dimension );
95 if( (xIn - lGeoIn.corner( gi )).two_norm() >= tolerance )
96 {
97 std::cout << "Error: twisted inside reference corner( " << iIn << " ) = " << xIn
98 << " != " << lGeoIn.corner( gi ) << " = local corner( " << i << " )."
99 << std::endl;
100 twistInside = false ;
101 ++errors;
102 }
103
104 const int iOut = applyTwist( inverseTwist( tOut, numCorners ), i, numCorners );
105 LocalVector xOut = refOut.position( refOut.subEntity( nOut, 1, iOut, dimension ), dimension );
106 if( (xOut - lGeoOut.corner( gi )).two_norm() >= tolerance )
107 {
108 std::cout << "Error: twisted outside reference corner( " << iOut << " ) = " << xOut
109 << " != " << lGeoOut.corner( gi ) << " = local corner( " << i << " )."
110 << std::endl;
111 twistOutside = false;
112 ++errors;
113 }
114 }
115
116 // calculate inside twist
117 if( ! twistInside )
118 {
119 for( int nTwist = numCorners-1; nTwist>= -numCorners; --nTwist )
120 {
121 twistInside = true ;
122 for( int i = 0; i < numCorners; ++i )
123 {
124 const int gi = i;
125 const int iIn = applyTwist( inverseTwist( nTwist, numCorners ), i, numCorners );
126 LocalVector xIn = refIn.position( refIn.subEntity( nIn, 1, iIn, dimension ), dimension );
127 if( (xIn - lGeoIn.corner( gi )).two_norm() >= tolerance )
128 {
129 twistInside = false ;
130 }
131 }
132
133 if( twistInside )
134 {
135 std::cout << "\ninside " << nIn << "\n";
136 std::cout << "twist " << tIn << " should be replaced by " << nTwist << "\n";
137 break ;
138 }
139 }
140 }
141
142 // calculate outside twist
143 if( ! twistOutside )
144 {
145 for( int nTwist = numCorners-1; nTwist>=-numCorners; --nTwist )
146 {
147 twistOutside = true ;
148 for( int i = 0; i < numCorners; ++i )
149 {
150 const int gi = i;
151 const int iOut = applyTwist( inverseTwist( nTwist, numCorners ), i, numCorners );
152 LocalVector xOut = refOut.position( refOut.subEntity( nOut, 1, iOut, dimension ), dimension );
153 if( (xOut - lGeoOut.corner( gi )).two_norm() >= tolerance )
154 {
155 twistOutside = false;
156 }
157 }
158
159 if( twistOutside )
160 {
161 std::cout << "\noutside " << nOut << " (inside = " << nIn << ")\n";
162 std::cout << "twist " << tOut << " should be replaced by " << nTwist << "\n";
163 break ;
164 }
165 }
166 }
167
168 return errors;
169 }
170
171
172 template< class GridView, class MapTwist >
checkTwists(const GridView & gridView,const MapTwist & mapTwist)173 void checkTwists ( const GridView &gridView, const MapTwist &mapTwist )
174 {
175 typedef typename GridView::template Codim< 0 >::Iterator Iterator;
176 typedef typename GridView::IntersectionIterator IntersectionIterator;
177
178 int errors = 0;
179
180 const Iterator end = gridView.template end< 0 >();
181 for( Iterator it = gridView.template begin< 0 >(); it != end; ++it )
182 {
183 const IntersectionIterator iend = gridView.iend( *it );
184 for( IntersectionIterator iit = gridView.ibegin( *it ); iit != iend; ++iit )
185 errors += checkTwistOnIntersection( iit->impl(), mapTwist );
186 }
187
188 if( errors > 0 )
189 std::cerr << "Error: Intersection twists contain errors." << std::endl;
190 }
191
192 #endif // DUNE_GRID_TEST_CHECKTWISTS_HH
193