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