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