dune-geometry
2.2.0
|
00001 #ifndef DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH 00002 #define DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH 00003 00004 #include <cassert> 00005 #include <vector> 00006 00007 #include <dune/common/forloop.hh> 00008 #include <dune/common/static_assert.hh> 00009 #include <dune/common/typetraits.hh> 00010 00011 #include <dune/geometry/genericgeometry/topologytypes.hh> 00012 #include <dune/geometry/genericgeometry/codimtable.hh> 00013 00014 namespace Dune 00015 { 00016 00017 namespace GenericGeometry 00018 { 00019 00020 template< class Topology, unsigned int codim > 00021 struct Size; 00022 00023 template< class Topology, unsigned int codim, unsigned int i > 00024 struct SubTopology; 00025 00026 template< class Topology, unsigned int codim, unsigned int subcodim > 00027 class SubTopologySize; 00028 00029 template< class Topology, unsigned int codim, unsigned int subcodim > 00030 class GenericSubTopologyNumbering; 00031 00032 template< class Topology, unsigned int codim, unsigned int subcodim > 00033 class SubTopologyNumbering; 00034 00035 00036 00037 // Size 00038 // ---- 00039 00040 template< class Topology, unsigned int dim, unsigned int codim > 00041 class SizeImpl; 00042 00043 template< unsigned int dim, unsigned int codim > 00044 class SizeImpl< Point, dim, codim > 00045 { 00046 typedef Point Topology; 00047 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00048 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00049 00050 public: 00051 enum { value = 1 }; 00052 }; 00053 00054 template< class BaseTopology, unsigned int dim, unsigned int codim > 00055 class SizeImpl< Prism< BaseTopology >, dim, codim > 00056 { 00057 typedef Prism< BaseTopology > Topology; 00058 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00059 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00060 00061 enum { m = Size< BaseTopology, codim-1 > :: value }; 00062 enum { n = Size< BaseTopology, codim > :: value }; 00063 00064 public: 00065 enum { value = n + 2*m }; 00066 }; 00067 00068 template< class BaseTopology, unsigned int dim > 00069 class SizeImpl< Prism< BaseTopology >, dim, 0 > 00070 { 00071 typedef Prism< BaseTopology > Topology; 00072 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00073 00074 public: 00075 enum { value = 1 }; 00076 }; 00077 00078 template< class BaseTopology, unsigned int dim > 00079 class SizeImpl< Prism< BaseTopology >, dim, dim > 00080 { 00081 typedef Prism< BaseTopology > Topology; 00082 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00083 00084 enum { m = Size< BaseTopology, dim-1 > :: value }; 00085 00086 public: 00087 enum { value = 2*m }; 00088 }; 00089 00090 template< class BaseTopology, unsigned int dim, unsigned int codim > 00091 class SizeImpl< Pyramid< BaseTopology >, dim, codim > 00092 { 00093 typedef Pyramid< BaseTopology > Topology; 00094 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00095 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00096 00097 enum { m = Size< BaseTopology, codim-1 > :: value }; 00098 enum { n = Size< BaseTopology, codim > :: value }; 00099 00100 public: 00101 enum { value = m+n }; 00102 }; 00103 00104 template< class BaseTopology, unsigned int dim > 00105 class SizeImpl< Pyramid< BaseTopology >, dim, 0 > 00106 { 00107 typedef Pyramid< BaseTopology > Topology; 00108 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00109 00110 public: 00111 enum { value = 1 }; 00112 }; 00113 00114 template< class BaseTopology, unsigned int dim > 00115 class SizeImpl< Pyramid< BaseTopology >, dim, dim > 00116 { 00117 typedef Pyramid< BaseTopology > Topology; 00118 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00119 00120 enum { m = Size< BaseTopology, dim-1 > :: value }; 00121 00122 public: 00123 enum { value = m+1 }; 00124 }; 00125 00126 00127 template< class Topology, unsigned int codim > 00128 struct Size 00129 { 00130 enum { value = SizeImpl< Topology, Topology :: dimension, codim > :: value }; 00131 }; 00132 00133 00134 00135 // SubTopology 00136 // ----------- 00137 00138 template< class Topology, unsigned int dim, unsigned int codim, unsigned int i > 00139 class SubTopologyImpl; 00140 00141 template< unsigned int dim, unsigned int codim, unsigned int i > 00142 class SubTopologyImpl< Point, dim, codim, i > 00143 { 00144 typedef Point Topology; 00145 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00146 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00147 dune_static_assert( (i < Size< Topology, codim > :: value), 00148 "Invalid subentity index" ); 00149 00150 public: 00151 typedef Topology type; 00152 }; 00153 00154 template< class BaseTopology, unsigned int dim, unsigned int codim, unsigned int i > 00155 class SubTopologyImpl< Prism< BaseTopology >, dim, codim, i > 00156 { 00157 typedef Prism< BaseTopology > Topology; 00158 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00159 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00160 dune_static_assert( (i < Size< Topology, codim > :: value), 00161 "Invalid subentity index" ); 00162 00163 enum { m = Size< BaseTopology, codim-1 > :: value }; 00164 enum { n = Size< BaseTopology, codim > :: value }; 00165 00166 enum { s = (i < n+m ? 0 : 1) }; 00167 00168 template< bool > 00169 struct PrismSub 00170 { 00171 typedef Prism< typename SubTopology< BaseTopology, codim, i > :: type > type; 00172 }; 00173 00174 template< bool > 00175 struct BaseSub 00176 { 00177 typedef typename SubTopology< BaseTopology, codim-1, i-(n+s*m) > :: type type; 00178 }; 00179 00180 public: 00181 typedef typename SelectType< (i < n), PrismSub<true>, BaseSub<false> > :: Type :: type type; 00182 }; 00183 00184 template< class BaseTopology, unsigned int dim, unsigned int i > 00185 class SubTopologyImpl< Prism< BaseTopology >, dim, 0, i > 00186 { 00187 typedef Prism< BaseTopology > Topology; 00188 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00189 dune_static_assert( (i < Size< Topology, 0 > :: value), 00190 "Invalid subentity index" ); 00191 public: 00192 typedef Topology type; 00193 }; 00194 00195 template< class BaseTopology, unsigned int dim, unsigned int i > 00196 class SubTopologyImpl< Prism< BaseTopology >, dim, dim, i > 00197 { 00198 typedef Prism< BaseTopology > Topology; 00199 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00200 dune_static_assert( (i < Size< Topology, dim > :: value), 00201 "Invalid subentity index" ); 00202 public: 00203 typedef Point type; 00204 }; 00205 00206 template< class BaseTopology, unsigned int dim, unsigned int codim, unsigned int i > 00207 class SubTopologyImpl< Pyramid< BaseTopology >, dim, codim, i > 00208 { 00209 typedef Pyramid< BaseTopology > Topology; 00210 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00211 dune_static_assert( (codim <= dim), "Invalid codimension" ); 00212 dune_static_assert( (i < Size< Topology, codim > :: value), 00213 "Invalid subentity index" ); 00214 00215 enum { m = Size< BaseTopology, codim-1 > :: value }; 00216 00217 template< bool > 00218 struct BaseSub 00219 { 00220 typedef typename SubTopology< BaseTopology, codim-1, i > :: type type; 00221 }; 00222 00223 template< bool > 00224 struct PyramidSub 00225 { 00226 typedef Pyramid< typename SubTopology< BaseTopology, codim, i-m > :: type > type; 00227 }; 00228 00229 public: 00230 typedef typename SelectType< (i < m), BaseSub<true>, PyramidSub<false> > :: Type :: type type; 00231 }; 00232 00233 template< class BaseTopology, unsigned int dim, unsigned int i > 00234 class SubTopologyImpl< Pyramid< BaseTopology >, dim, 0, i > 00235 { 00236 typedef Pyramid< BaseTopology > Topology; 00237 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00238 dune_static_assert( (i < Size< Topology, 0 > :: value), 00239 "Invalid subentity index" ); 00240 00241 public: 00242 typedef Topology type; 00243 }; 00244 00245 template< class BaseTopology, unsigned int dim, unsigned int i > 00246 class SubTopologyImpl< Pyramid< BaseTopology >, dim, dim, i > 00247 { 00248 typedef Pyramid< BaseTopology > Topology; 00249 dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" ); 00250 dune_static_assert( (i < Size< Topology, dim > :: value), 00251 "Invalid subentity index" ); 00252 00253 public: 00254 typedef Point type; 00255 }; 00256 00257 template< class Topology, unsigned int codim, unsigned int i > 00258 struct SubTopology 00259 { 00260 typedef typename SubTopologyImpl< Topology, Topology :: dimension, codim, i > :: type type; 00261 }; 00262 00263 00264 00265 // SubTopologySize 00266 // --------------- 00267 00268 template< class Topology, unsigned int codim, unsigned int subcodim > 00269 class SubTopologySize 00270 { 00271 template< int i > 00272 struct Builder; 00273 00274 unsigned int size_[ Size< Topology, codim > :: value ]; 00275 00276 SubTopologySize () 00277 { 00278 ForLoop< Builder, 0, Size< Topology, codim > :: value-1 > 00279 :: apply( *this ); 00280 } 00281 00282 SubTopologySize ( const SubTopologySize & ); 00283 00284 static const SubTopologySize &instance () 00285 { 00286 static SubTopologySize inst; 00287 return inst; 00288 } 00289 00290 public: 00291 static unsigned int size ( unsigned int i ) 00292 { 00293 assert( (i < Size< Topology, codim > :: value) ); 00294 return instance().size_[ i ]; 00295 } 00296 }; 00297 00298 template< class Topology, unsigned int codim, unsigned int subcodim > 00299 template< int i > 00300 struct SubTopologySize< Topology, codim, subcodim > :: Builder 00301 { 00302 typedef GenericGeometry :: SubTopologySize< Topology, codim, subcodim > 00303 SubTopologySize; 00304 typedef typename GenericGeometry :: SubTopology< Topology, codim, i > :: type 00305 SubTopology; 00306 00307 static void apply ( SubTopologySize &subTopologySize ) 00308 { 00309 subTopologySize.size_[ i ] = Size< SubTopology, subcodim > :: value; 00310 } 00311 }; 00312 00313 00314 00315 // GenericSubTopologyNumbering 00316 // --------------------------- 00317 00318 template< class Topology, unsigned int codim, 00319 unsigned int subdim, unsigned int subcodim > 00320 struct GenericSubTopologyNumberingHelper; 00321 00322 template< class BaseTopology, unsigned int codim, 00323 unsigned int subdim, unsigned int subcodim > 00324 struct GenericSubTopologyNumberingHelper 00325 < Prism< BaseTopology >, codim, subdim, subcodim > 00326 { 00327 typedef Prism< BaseTopology > Topology; 00328 00329 enum { m = Size< BaseTopology, codim-1 > :: value }; 00330 enum { n = Size< BaseTopology, codim > :: value }; 00331 00332 enum { mb = Size< BaseTopology, codim+subcodim-1 > :: value }; 00333 enum { nb = Size< BaseTopology, codim+subcodim > :: value }; 00334 00335 static unsigned int number ( unsigned int i, unsigned int j ) 00336 { 00337 const unsigned int s = (i < n+m ? 0 : 1); 00338 if( i < n ) 00339 { 00340 const unsigned int ms = SubTopologySize< BaseTopology, codim, subcodim-1 > :: size( i ); 00341 const unsigned int ns = SubTopologySize< BaseTopology, codim, subcodim > :: size( i ); 00342 const unsigned int ss = (j < ns+ms ? 0 : 1); 00343 if( j < ns ) 00344 return GenericSubTopologyNumbering< BaseTopology, codim, subcodim > 00345 :: number( i, j ); 00346 else 00347 return GenericSubTopologyNumbering< BaseTopology, codim, subcodim-1 > 00348 :: number( i, j-(ns+ss*ms) ) + nb + ss*mb; 00349 } 00350 else 00351 return GenericSubTopologyNumbering< BaseTopology, codim-1, subcodim > 00352 :: number( i-(n+s*m), j ) + nb + s*mb; 00353 } 00354 }; 00355 00356 template< class BaseTopology, unsigned int codim, unsigned int subdim > 00357 struct GenericSubTopologyNumberingHelper 00358 < Prism< BaseTopology >, codim, subdim, 0 > 00359 { 00360 typedef Prism< BaseTopology > Topology; 00361 00362 static unsigned int number ( unsigned int i, unsigned int j ) 00363 { 00364 return i; 00365 } 00366 }; 00367 00368 template< class BaseTopology, unsigned int codim, unsigned int subdim > 00369 struct GenericSubTopologyNumberingHelper 00370 < Prism< BaseTopology >, codim, subdim, subdim > 00371 { 00372 typedef Prism< BaseTopology > Topology; 00373 00374 enum { m = Size< BaseTopology, codim-1 > :: value }; 00375 enum { n = Size< BaseTopology, codim > :: value }; 00376 00377 enum { mb = Size< BaseTopology, codim+subdim-1 > :: value }; 00378 00379 static unsigned int number ( unsigned int i, unsigned int j ) 00380 { 00381 const unsigned int s = (i < n+m ? 0 : 1); 00382 if( i < n ) 00383 { 00384 const unsigned int ms = SubTopologySize< BaseTopology, codim, subdim-1 > :: size( i ); 00385 const unsigned int ss = (j < ms ? 0 : 1); 00386 return GenericSubTopologyNumbering< BaseTopology, codim, subdim-1 > 00387 :: number( i, j-ss*ms ) + ss*mb; 00388 } 00389 else 00390 return GenericSubTopologyNumbering< BaseTopology, codim-1, subdim > 00391 :: number( i-(n+s*m), j ) + s*mb; 00392 } 00393 }; 00394 00395 template< class BaseTopology, unsigned int codim, 00396 unsigned int subdim, unsigned int subcodim > 00397 struct GenericSubTopologyNumberingHelper 00398 < Pyramid< BaseTopology >, codim, subdim, subcodim > 00399 { 00400 typedef Pyramid< BaseTopology > Topology; 00401 00402 enum { m = Size< BaseTopology, codim-1 > :: value }; 00403 00404 enum { mb = Size< BaseTopology, codim+subcodim-1 > :: value }; 00405 00406 static unsigned int number ( unsigned int i, unsigned int j ) 00407 { 00408 if( i < m ) 00409 return GenericSubTopologyNumbering< BaseTopology, codim-1, subcodim > 00410 :: number( i, j ); 00411 else 00412 { 00413 const unsigned int ms = SubTopologySize< BaseTopology, codim, subcodim-1 > :: size( i-m ); 00414 if( j < ms ) 00415 return GenericSubTopologyNumbering< BaseTopology, codim, subcodim-1 > 00416 :: number( i-m, j ); 00417 else 00418 return GenericSubTopologyNumbering< BaseTopology, codim, subcodim > 00419 :: number( i-m, j-ms ) + mb; 00420 } 00421 } 00422 }; 00423 00424 template< class BaseTopology, unsigned int codim, unsigned int subdim > 00425 struct GenericSubTopologyNumberingHelper 00426 < Pyramid< BaseTopology >, codim, subdim, 0 > 00427 { 00428 typedef Pyramid< BaseTopology > Topology; 00429 00430 static unsigned int number ( unsigned int i, unsigned int j ) 00431 { 00432 return i; 00433 } 00434 }; 00435 00436 template< class BaseTopology, unsigned int codim, unsigned int subdim > 00437 struct GenericSubTopologyNumberingHelper 00438 < Pyramid< BaseTopology >, codim, subdim, subdim > 00439 { 00440 typedef Pyramid< BaseTopology > Topology; 00441 00442 enum { m = Size< BaseTopology, codim-1 > :: value }; 00443 00444 enum { mb = Size< BaseTopology, codim+subdim-1 > :: value }; 00445 00446 static unsigned int number ( unsigned int i, unsigned int j ) 00447 { 00448 if( i < m ) 00449 return GenericSubTopologyNumbering< BaseTopology, codim-1, subdim > 00450 :: number( i, j ); 00451 else 00452 { 00453 const unsigned int ms = SubTopologySize< BaseTopology, codim, subdim-1 > :: size( i-m ); 00454 if( j < ms ) 00455 return GenericSubTopologyNumbering< BaseTopology, codim, subdim-1 > 00456 :: number( i-m, j ); 00457 else 00458 return mb; 00459 } 00460 } 00461 }; 00462 00463 template< class Topology, unsigned int codim, unsigned int subcodim > 00464 class GenericSubTopologyNumbering 00465 { 00466 dune_static_assert( (codim <= Topology :: dimension), "Invalid codimension" ); 00467 dune_static_assert( (codim + subcodim <= Topology :: dimension), 00468 "Invalid subcodimension" ); 00469 00470 template< bool > 00471 struct BorderCodim 00472 { 00473 static unsigned int number ( unsigned int i, unsigned int j ) 00474 { 00475 return (codim == 0 ? j : i ); 00476 } 00477 }; 00478 00479 template< bool > 00480 struct InnerCodim 00481 { 00482 static unsigned int number ( unsigned int i, unsigned int j ) 00483 { 00484 return GenericSubTopologyNumberingHelper 00485 < Topology, codim, Topology :: dimension - codim, subcodim > 00486 :: number( i, j ); 00487 } 00488 }; 00489 00490 public: 00491 static unsigned int number ( unsigned int i, unsigned int j ) 00492 { 00493 assert( (j <= SubTopologySize< Topology, codim, subcodim > :: size( i )) ); 00494 return SelectType 00495 < (codim == 0) || (codim == Topology :: dimension), BorderCodim<true>, InnerCodim<false> > 00496 :: Type :: number( i, j ); 00497 } 00498 }; 00499 00500 00501 00502 // SubTopologyNumbering 00503 // -------------------- 00504 00505 template< class Topology, unsigned int codim, unsigned int subcodim > 00506 class SubTopologyNumbering 00507 { 00508 typedef GenericSubTopologyNumbering< Topology, codim, subcodim > 00509 GenericNumbering; 00510 00511 std :: vector< unsigned int > numbering_[ Size< Topology, codim > :: value ]; 00512 00513 public: 00514 static unsigned int number ( unsigned int i, unsigned int j ) 00515 { 00516 assert( (j <= SubTopologySize< Topology, codim, subcodim > :: size( i )) ); 00517 return instance().numbering_[ i ][ j ]; 00518 } 00519 00520 private: 00521 SubTopologyNumbering () 00522 { 00523 for( unsigned int i = 0; i < Size< Topology, codim > :: value; ++i ) 00524 { 00525 const unsigned int size = SubTopologySize< Topology, codim, subcodim > :: size( i ); 00526 numbering_[ i ].resize( size ); 00527 for( unsigned int j = 0; j < size; ++j ) 00528 numbering_[ i ][ j ] = GenericNumbering :: number( i, j ); 00529 } 00530 } 00531 00532 static const SubTopologyNumbering &instance () 00533 { 00534 static SubTopologyNumbering inst; 00535 return inst; 00536 } 00537 }; 00538 00539 00540 00541 // IsCodimHybrid 00542 // ------------- 00543 00544 template< class Topology, unsigned int codim > 00545 struct IsCodimHybrid 00546 { 00547 static const bool value = (codim != 0) && IsHybrid< Topology >::value; 00548 }; 00549 00550 00551 00552 // SubTopologyMapper 00553 // ----------------- 00554 00555 template< class Topology > 00556 class SubTopologyMapper 00557 { 00558 static const unsigned int dimension = Topology::dimension; 00559 00560 template< class A, class B > 00561 struct StaticSum 00562 { 00563 static const unsigned int value = A::value + B::value; 00564 }; 00565 00566 template< int codim > 00567 struct Size 00568 { 00569 static const unsigned int value = GenericGeometry::Size< Topology, codim >::value; 00570 }; 00571 00572 template< int codim > 00573 struct CalcOffset 00574 { 00575 static void apply ( unsigned int (&offsets)[ dimension+2 ] ) 00576 { 00577 offsets[ codim+1 ] = offsets[ codim ] + Size< codim >::value; 00578 } 00579 }; 00580 00581 public: 00582 static const unsigned int staticSize = GenericForLoop< StaticSum, Size, 0, dimension >::value; 00583 00584 SubTopologyMapper () 00585 { 00586 offsets_[ 0 ] = 0; 00587 ForLoop< CalcOffset, 0, dimension >::apply( offsets_ ); 00588 assert( size() == staticSize ); 00589 }; 00590 00591 unsigned int operator() ( const unsigned int codim, const unsigned int subEntity ) const 00592 { 00593 const unsigned int offset = offsets_[ codim ]; 00594 assert( offset + subEntity < offsets_[ codim+1 ] ); 00595 return offset + subEntity; 00596 } 00597 00598 unsigned int size () const 00599 { 00600 return offsets_[ dimension+1 ]; 00601 } 00602 00603 private: 00604 unsigned int offsets_[ dimension+2 ]; 00605 }; 00606 00607 } 00608 00609 } 00610 00611 #endif // #ifndef DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH