dune-geometry  2.2.0
subtopologies.hh
Go to the documentation of this file.
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