1 #ifndef DUNE_CHECKLEAFCODIM1_HH
2 #define DUNE_CHECKLEAFCODIM1_HH
3 
4 #include <dune/fem/io/parameter.hh>
5 #include <dune/fem/quadrature/cachingquadrature.hh>
6 
7 namespace Dune {
8   namespace Fem {
9 
10 struct CachingQuadratureTest
11 {
12   template <class GridPartType>
checkLeafsCodimOneDune::Fem::CachingQuadratureTest13   static void checkLeafsCodimOne(GridPartType& gridPart,
14                                  const int quadOrd)
15   {
16     CachingQuadratureTest tester;
17     tester.checkLeafsCodim1( gridPart, quadOrd );
18   }
19 
doTestDune::Fem::CachingQuadratureTest20   static void doTest( const double& a, const double& b )
21   {
22     if( std::abs( a - b ) > 1e-12 )
23     {
24       assert( false );
25       std::abort();
26     }
27   }
28 
doTestDune::Fem::CachingQuadratureTest29   static void doTest( const bool value )
30   {
31     if( ! value )
32     {
33       assert( false );
34       std::abort();
35     }
36   }
37 
runDune::Fem::CachingQuadratureTest38   void run (){};
39 
40 protected:
41   template <class EntityType, class LocalGeometryType>
aluTwistCheckDune::Fem::CachingQuadratureTest42   int aluTwistCheck(const EntityType& en, const LocalGeometryType& localGeom,
43                     const int face, const bool neighbor, const bool output ) const
44   {
45     enum { dim = EntityType :: dimension };
46     typedef typename EntityType :: Geometry :: ctype ctype;
47 
48     typedef FaceTopologyMapping<tetra> SimplexFaceMapping;
49     typedef FaceTopologyMapping<hexa>  CubeFaceMapping;
50 
51     // get reference element
52     const auto refElem = Dune::referenceElement< ctype, dim >( en.type() );
53 
54     const int vxSize = refElem.size( face, 1, dim );
55     typedef  FieldVector<ctype,dim> CoordinateVectorType;
56 
57     // now calculate twist by trial and error for all possible twists
58     // the calculated twist is with respect to the ALUGrid
59     // reference face, see twistprovider.cc
60     int twistFound = -66;
61     for(int twist = -vxSize; twist<vxSize; ++twist)
62     {
63       bool twistOk = true;
64       // now check mapping with twist
65       for(int i=0; i<vxSize; ++i)
66       {
67         int twistedDuneIndex = -1;
68         if( localGeom.type().isCube() )
69         {
70           twistedDuneIndex = CubeFaceMapping::twistedDuneIndex( i, twist );
71         }
72         else
73         {
74           twistedDuneIndex = SimplexFaceMapping::twistedDuneIndex( i, twist );
75         }
76 
77         // get face vertices of number in self face
78         int vxIdx = refElem.subEntity( face, 1 , twistedDuneIndex , dim);
79 
80         // get position in reference element of vertex i
81         CoordinateVectorType refPos = refElem.position( vxIdx, dim );
82 
83         // check coordinates again
84         CoordinateVectorType localPos = localGeom.corner( i );
85         if( (refPos - localPos).infinity_norm() > 1e-8 )
86         {
87           twistOk = false;
88           break;
89         }
90       }
91 
92       if( twistOk )
93       {
94         twistFound = twist;
95         break ;
96       }
97     }
98 
99     // if no twist found, then something is wrong
100     if( twistFound == -66 )
101     {
102       assert(false);
103       DUNE_THROW(GridError,"Not matching twist found");
104     }
105 
106     if( output )
107     {
108       std::string twistIn( (neighbor) ? "twistInNeighbor()" : "twistInSelf" );
109       std::string numberIn( (neighbor) ? "indexInOutside()" : "indexInInside" );
110       std::cout << "ERROR: Face "<< face << " : twist = "<< twistFound << std::endl;
111       std::cout << "\nPut twist = "<< twistFound << " In TwistUtility::"<< twistIn << " for " << numberIn << " = " << face << " ! \n";
112       std::cout << "******************************************\n";
113     }
114 
115     return twistFound;
116   }
117 
118   template <class GridPartType>
checkLeafsCodim1Dune::Fem::CachingQuadratureTest119   void checkLeafsCodim1(GridPartType& gridPart,
120                         const int quadOrd)
121   {
122     enum { dim = GridPartType :: dimension };
123     enum { codim = 1 };
124     typedef typename GridPartType ::ctype ctype;
125 
126     typedef typename GridPartType::IntersectionIteratorType IntersectionIterator;
127     typedef typename IntersectionIterator::Intersection Intersection;
128     typedef typename GridPartType :: template Codim<0> :: IteratorType IteratorType;
129     typedef CachingQuadrature<GridPartType, codim> QuadratureType;
130     typedef PointProvider<ctype, dim, codim> PointProviderType;
131     typedef typename PointProviderType::GlobalPointVectorType PointVectorType;
132     typedef typename Intersection::LocalGeometry LocalGeometryType;
133     typedef typename  GridPartType :: template Codim<0> :: EntityType EntityType;
134 
135     IteratorType enditer = gridPart.template end<0> ();
136     for(IteratorType eiter = gridPart.template begin<0> ();
137         eiter != enditer; ++eiter)
138     {
139       const EntityType& entity = (*eiter);
140       const GeometryType geomType = entity.geometry().type();
141       const auto refElem = Dune::referenceElement< ctype, dim >( geomType );
142       const int numFaces = refElem.size(codim);
143       //std::cout << "For type " << geomType << " got " << numFaces << " numFaces\n";
144 
145       //int twist = -4;
146       const IntersectionIterator endit = gridPart.iend( entity );
147       for (IntersectionIterator it = gridPart.ibegin( entity );
148            it != endit; ++it)
149       {
150         const Intersection& inter=*it;
151         typedef typename GridPartType::TwistUtilityType TwistUtilityType;
152 
153         // set this flag to true for output of twists that have been calculated
154         const bool output = Parameter :: verbose() ;
155 
156         if( dim > 2 )
157         {
158           //const int twistFound = checkLocalIntersectionConsistency( entity,
159           //                      inter.geometryInInside(), inter.indexInInside() , false, false);
160           const int twistFound = aluTwistCheck( entity,
161                                 inter.geometryInInside(), inter.indexInInside() , false, false);
162           const int twistInside = TwistUtilityType::twistInSelf( gridPart.grid(), inter);
163           if( output && twistFound != twistInside )
164           {
165             std::cout << "Twist inconsistent: calculated twist " << twistFound << "  not equal to inside " << twistInside << "\n";
166           }
167 
168           if( inter.neighbor() )
169           {
170             EntityType neighbor = inter.outside();
171             //const int twstF = checkLocalIntersectionConsistency( neighbor,
172             //              inter.geometryInOutside(), inter.indexInOutside(), true, false);
173             const int twstF = aluTwistCheck( neighbor,
174                           inter.geometryInOutside(), inter.indexInOutside(), true, false);
175 
176             const int twistOutside = TwistUtilityType::twistInNeighbor( gridPart.grid(), inter);
177             if( output && twstF != twistOutside )
178             {
179               std::cout << "Twist inconsistent: calculated twist " << twstF << "  not equal to outside " << twistOutside << "\n";
180             }
181           }
182         }
183 
184         const LocalGeometryType& geo = inter.geometryInInside();
185 
186         QuadratureType quad(gridPart, inter, quadOrd , QuadratureType :: INSIDE);
187 
188         const PointVectorType& points =
189           PointProviderType::getPoints(quad.id(), geomType);
190 
191         doTest( points.size() == numFaces * quad.nop());
192         if ( output )
193         {
194           std::cout << points.size() << " ps | qnop " << numFaces * quad.nop() << "\n";
195           std::cout << "New Intersection: Twists: ";
196           std::cout << TwistUtilityType :: twistInSelf( gridPart.grid(), inter);
197           if( inter.neighbor() )
198             std::cout << " " << TwistUtilityType :: twistInNeighbor( gridPart.grid(), inter);
199           std::cout << std::endl;
200         }
201 
202         // this check is only ok if we are on the inside of
203         // the smaller element of the non-conforming intersection
204         // or if the intersection is conforming
205         if( inter.conforming() ||
206             (inter.neighbor() && entity.level() > inter.outside().level()) )
207         {
208           for (size_t i = 0; i < quad.nop(); ++i)
209           {
210             /*
211             {
212               std::cout << "nis: " << inter.indexInInside();
213               std::cout << " pt " << i << ": " << points[quad.cachingPoint(i)]
214                         << " == " << geo.global(quad.localPoint(i)) << std::endl;
215             }
216             */
217             for (int d = 0; d < dim; ++d)
218             {
219               assert( quad.cachingPoint(i) < points.size() );
220               doTest(points[quad.cachingPoint(i)][d],
221                      geo.global(quad.localPoint(i))[d]);
222             }
223 
224           }
225         }
226 
227         if( inter.neighbor ())
228         {
229           if( inter.conforming() )
230           {
231             const LocalGeometryType& nGeo = inter.geometryInOutside();
232             QuadratureType outerQuad(gridPart, inter, quadOrd , QuadratureType::OUTSIDE);
233 
234             for (size_t i = 0; i < outerQuad.nop(); ++i)
235             {
236               for (int d = 0; d < dim; ++d)
237               {
238                 assert( outerQuad.cachingPoint(i) < points.size() );
239                 doTest(points[outerQuad.cachingPoint(i)][d],
240                            nGeo.global(outerQuad.localPoint(i))[d]);
241               }
242 
243               /*
244               {
245                 std::cout << "nin: " << inter.indexInOutside();
246                 std::cout << " nis: " << inter.indexInInside();
247                 std::cout << " pt " << i << ": " << points[outerQuad.cachingPoint(i)]
248                           << " == " << nGeo.global(outerQuad.localPoint(i)) << std::endl;
249               }
250               */
251             }
252           }
253         }
254 
255       } // end iterator loop
256     }
257   }
258 #if 0
259   template <class EntityType, class LocalGeometryType>
260   int checkLocalIntersectionConsistency(
261       const EntityType& en, const LocalGeometryType& localGeom,
262       const int face, const bool neighbor, const bool output ) const
263   {
264     enum { dim = EntityType :: dimension };
265     typedef typename EntityType :: ctype ctype;
266 
267     typedef FaceTopologyMapping<tetra> SimplexFaceMapping;
268     typedef FaceTopologyMapping<hexa>  CubeFaceMapping;
269 
270     // get reference element
271     const  auto refElem = Dune::referenceElement< ctype, dim >( en.type() );
272 
273     const int vxSize = refElem.size( face, 1, dim );
274     std::vector<int> vx( vxSize ,-1);
275     for(int i=0; i<vxSize; ++i)
276     {
277       //const int idx = i;
278       const int idx = ( localGeom.type().isCube() ) ?
279             CubeFaceMapping::dune2aluVertex( i ) :
280             SimplexFaceMapping::dune2aluVertex( i );
281 
282       // get face vertices of number in self face
283       vx[i] = refElem.subEntity( face, 1 , idx , dim);
284     }
285 
286     // debugging output
287     if( output )
288     {
289       std::string neighout ((neighbor)?"outside":"inside");
290       std::cout << "\n******************************************\n";
291       std::cout << "Found ("<<neighout<<") face["<< face << "] vx = {";
292       for(size_t i=0; i<vx.size(); ++i)
293       {
294         std::cout << vx[i] << ",";
295       }
296       std::cout << "} \n";
297     }
298 
299     bool faceTwisted = false;
300     std::vector< int > faceMap ( vxSize , -1 );
301 
302     typedef  FieldVector<ctype,dim> CoordinateVectorType;
303 
304     for(int i=0; i<vxSize; ++i)
305     {
306       //const int idx = i;
307       const int idx = ( localGeom.type().isCube() ) ?
308             CubeFaceMapping::dune2aluVertex( i ) :
309             SimplexFaceMapping::dune2aluVertex( i );
310 
311       // standard face map is identity
312       faceMap[i] = idx;
313 
314       // get position in reference element of vertex i
315       CoordinateVectorType refPos = refElem.position( vx[i], dim );
316 
317       // get position as we get it from intersectionSelfLocal
318       // in the best case this should be the same
319       // at least the orientatation should be the same
320       CoordinateVectorType localPos = localGeom.corner( idx );
321 
322       if( (refPos - localPos).infinity_norm() > 1e-8 )
323       {
324         faceTwisted = true;
325         if( output )
326           std::cout << "RefPos (" << refPos << ") != (" << localPos << ") localPos !\n";
327       }
328     }
329 
330     if( faceTwisted )
331     {
332       if( output )
333       {
334         std::string neighout ((neighbor)?"outside":"inside");
335         std::cout <<"Face "<< face << " ("<<neighout<< ") is twisted! \n";
336       }
337 
338       // now calculate twist by trial and error for all possible twists
339       // the calculated twist is with respect to the ALUGrid
340       // reference face, see twistprovider.cc
341       int twistFound = -66;
342       for(int twist = -vxSize; twist<vxSize; ++twist)
343       {
344         bool twistOk = true;
345         // now check mapping with twist
346         for(int i=0; i<vxSize; ++i)
347         {
348           int twistedDuneIndex = -1;
349           if( localGeom.type().isCube() )
350           {
351             twistedDuneIndex = CubeFaceMapping::twistedDuneIndex( i, twist );
352           }
353           else
354           {
355             twistedDuneIndex = SimplexFaceMapping::twistedDuneIndex( i, twist );
356           }
357 
358           // get face vertices of number in self face
359           int vxIdx = refElem.subEntity( face, 1 , twistedDuneIndex , dim);
360 
361           // get position in reference element of vertex i
362           CoordinateVectorType refPos = refElem.position( vxIdx, dim );
363 
364           // check coordinates again
365           CoordinateVectorType localPos = localGeom.corner( i );
366           if( (refPos - localPos).infinity_norm() > 1e-8 )
367           {
368             twistOk = false;
369             break;
370           }
371         }
372 
373         if( twistOk )
374         {
375           twistFound = twist;
376           break ;
377         }
378       }
379 
380       // if no twist found, then something is wrong
381       if( twistFound == -66 )
382       {
383         assert(false);
384         DUNE_THROW(GridError,"Not matching twist found");
385       }
386 
387       if( output )
388       {
389         std::string twistIn( (neighbor) ? "twistInNeighbor()" : "twistInSelf" );
390         std::string numberIn( (neighbor) ? "indexInOutside()" : "indexInInside" );
391         std::cout << "Face "<< face << " : twist = "<< twistFound << std::endl;
392         std::cout << "\nPut twist = "<< twistFound << " In TwistUtility::"<< twistIn << " for " << numberIn << " = " << face << " ! \n";
393         std::cout << "******************************************\n";
394       }
395 
396       return twistFound;
397     }
398 
399     assert( ! faceTwisted );
400     return 0;
401   }
402 #endif
403 };
404 
405   } // end namespace Fem
406 } // namespace Dune
407 
408 #endif
409