genericgeometry/referenceelements.hh

00001 #ifndef DUNE_GENERICGEOMETRY_REFERENCEELEMENTS_HH
00002 #define DUNE_GENERICGEOMETRY_REFERENCEELEMENTS_HH
00003 
00004 #include <dune/common/fixedarray.hh>
00005 #include <dune/common/fvector.hh>
00006 
00007 #include <dune/grid/genericgeometry/misc.hh>
00008 #include <dune/grid/genericgeometry/topologytypes.hh>
00009 #include <dune/grid/genericgeometry/conversion.hh>
00010 #include <dune/grid/genericgeometry/subtopologies.hh>
00011 
00012 namespace Dune
00013 {
00014 
00015   namespace GenericGeometry
00016   {
00017 
00018     template< class Topology, class ctype >
00019     class ReferenceElement;
00020 
00021 
00022 
00023     // ReferenceDomain
00024     // ---------------
00025 
00026     template< class Topology >
00027     struct ReferenceDomainBase;
00028 
00029     template<>
00030     struct ReferenceDomainBase< Point >
00031     {
00032       typedef Point Topology;
00033 
00034       template< class > friend class ReferenceDomain;
00035       template< class > friend class ReferenceDomainBase;
00036 
00037       enum { numNormals = 0 }; 
00038 
00039       template< class ctype, int dim >
00040       static void corner ( unsigned int i, FieldVector< ctype, dim > &n )
00041       {
00042         assert( i < Topology :: numCorners );
00043       }
00044 
00045       template< class ctype, int dim >
00046       static bool
00047       checkInside ( const FieldVector< ctype, dim > &x, ctype factor )
00048       {
00049         return true;
00050       }
00051 
00052       template< class ctype, int dim >
00053       static void
00054       integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00055       {
00056         assert( i < numNormals );
00057       }
00058 
00059       template< class ctype >
00060       static ctype volume ()
00061       {
00062         return ctype( 1 );
00063       }
00064     };
00065 
00066     template< class BaseTopology >
00067     struct ReferenceDomainBase< Prism< BaseTopology > >
00068     {
00069       typedef Prism< BaseTopology > Topology;
00070 
00071       template< class > friend class ReferenceDomain;
00072       template< class > friend class ReferenceDomainBase;
00073 
00074       enum { numNormals = Size< Topology, 1 > :: value }; 
00075 
00076       static const unsigned int dimension = Topology :: dimension;
00077       static const unsigned int myindex = dimension - 1;
00078      
00079       template< bool >
00080       struct MultiDimensional
00081       {
00082         template< class ctype, int dim >
00083         static void
00084         integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00085         {
00086           if( i >= Size< BaseTopology, 1 > :: value )
00087           {
00088             const unsigned int j = i - Size< BaseTopology, 1 > :: value;
00089             n[ myindex ] = (j == 0 ? ctype( -1 ) : ctype( 1 ));
00090           }
00091           else
00092             ReferenceDomainBase< BaseTopology > :: integrationOuterNormal( i, n );
00093         }
00094       };
00095 
00096       template< bool >
00097       struct OneDimensional
00098       {
00099         template< class ctype, int dim >
00100         static void
00101         integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00102         {
00103           n[ myindex ] = (i > 0) ? ctype( 1 ) : ctype( -1 );
00104         }
00105       };
00106 
00107 
00108       template< class ctype, int dim >
00109       static void corner ( unsigned int i, FieldVector< ctype, dim > &x )
00110       {
00111         assert( i < Topology :: numCorners );
00112         const unsigned int j = i % BaseTopology :: numCorners;
00113         ReferenceDomainBase< BaseTopology > :: corner( j, x );
00114         if( i >= BaseTopology :: numCorners )
00115           x[ myindex ] = ctype( 1 );
00116       }
00117 
00118       template< class ctype, int dim >
00119       static bool
00120       checkInside ( const FieldVector< ctype, dim > &x, ctype factor )
00121       {
00122         const ctype xn = x[ myindex ];
00123         const ctype cxn = factor - xn;
00124         return (xn > -1e-12) && (cxn > -1e-12)
00125                && ReferenceDomainBase< BaseTopology > :: checkInside( x, factor );
00126       }
00127 
00128       template< class ctype, int dim >
00129       static void
00130       integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00131       {
00132         ProtectedIf< (dimension > 1), MultiDimensional, OneDimensional >
00133           :: integrationOuterNormal( i, n );
00134       }
00135 
00136       template< class ctype >
00137       static ctype volume ()
00138       {
00139         return ReferenceDomainBase< BaseTopology > :: template volume< ctype >();
00140       }
00141     };
00142    
00143     template< class BaseTopology >
00144     struct ReferenceDomainBase< Pyramid< BaseTopology > >
00145     {
00146       typedef Pyramid< BaseTopology > Topology;
00147 
00148       template< class > friend class ReferenceDomain;
00149       template< class > friend class ReferenceDomainBase;
00150       
00151       enum { numNormals = Size< Topology, 1 > :: value };
00152 
00153       static const unsigned int dimension = Topology :: dimension;
00154       static const unsigned int myindex = dimension - 1;
00155 
00156       template< bool >
00157       struct MultiDimensional
00158       {
00159         template< class ctype, int dim >
00160         static void
00161         integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00162         {
00163           typedef SubTopologyNumbering< BaseTopology,1,dimension-2 > Numbering;
00164           if( i > 0 )
00165           {
00166             const unsigned int j = Numbering :: number( i-1, 0 );
00167             FieldVector< ctype, dim > x( ctype( 0 ) );
00168             ReferenceDomainBase< BaseTopology > :: corner( j, x );
00169 
00170             ReferenceDomainBase< BaseTopology > :: integrationOuterNormal ( i-1, n );
00171             n[ myindex ] = (x * n);
00172           }
00173           else
00174             n[ myindex ] = ctype( -1 );
00175         }
00176       };
00177 
00178       template< bool >
00179       struct OneDimensional
00180       {
00181         template< class ctype, int dim >
00182         static void
00183         integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00184         {
00185           n[ myindex ] = (i > 0) ? ctype( 1 ) : ctype( -1 );
00186         }
00187       };
00188 
00189       template< class ctype, int dim >
00190       static void corner ( unsigned int i, FieldVector< ctype, dim > &x )
00191       {
00192         assert( i < Topology :: numCorners );
00193         if( i < BaseTopology :: numCorners )
00194           ReferenceDomainBase< BaseTopology > :: corner( i, x );
00195         else
00196           x[ myindex ] = ctype( 1 );
00197       }
00198 
00199       template< class ctype, int dim >
00200       static bool
00201       checkInside ( const FieldVector< ctype, dim > &x, ctype factor )
00202       {
00203         const ctype xn = x[ myindex ];
00204         const ctype cxn = factor - xn;
00205         return (xn > -1e-12) && (cxn > -1e-12)
00206                && ReferenceDomainBase< BaseTopology > :: checkInside( x, factor * cxn );
00207       }
00208 
00209       template< class ctype, int dim >
00210       static void
00211       integrationOuterNormal ( unsigned int i, FieldVector< ctype, dim > &n )
00212       {
00213         ProtectedIf< (dimension > 1), MultiDimensional, OneDimensional >
00214           :: integrationOuterNormal( i, n );
00215       }
00216 
00217       template< class ctype >
00218       static ctype volume ()
00219       {
00220         const ctype baseVolume
00221           = ReferenceDomainBase< BaseTopology > :: template volume< ctype >();
00222         return baseVolume / ctype( dimension );
00223       }
00224     };
00225 
00226 
00227 
00228     template< class Topology >
00229     struct ReferenceDomain
00230     {
00231       static const unsigned int numCorners = Topology :: numCorners;
00232       static const unsigned int dimension = Topology :: dimension;
00233       static const unsigned int numNormals
00234         = ReferenceDomainBase< Topology > :: numNormals;
00235 
00236       template< class ctype >
00237       static void corner ( unsigned int i, FieldVector< ctype, dimension > &x )
00238       {
00239         x = ctype( 0 );
00240         ReferenceDomainBase< Topology > :: corner( i, x );
00241       }
00242 
00243       template< class ctype >
00244       static bool checkInside ( const FieldVector< ctype, dimension > &x )
00245       {
00246         return ReferenceDomainBase< Topology > :: checkInside( x, ctype( 1 ) );
00247       }
00248 
00249       template< class ctype >
00250       static void
00251       integrationOuterNormal ( unsigned int i, FieldVector< ctype, dimension > &n )
00252       {
00253         n = ctype( 0 );
00254         return ReferenceDomainBase< Topology > :: integrationOuterNormal( i, n );
00255       }
00256 
00257       template< class ctype >
00258       static ctype volume ()
00259       {
00260         return ReferenceDomainBase< Topology > :: template volume< ctype >();
00261       }
00262     };
00263 
00264 
00265 
00266     // ReferenceElement
00267     // ----------------
00268 
00269     template< class Topology, class ctype >
00270     struct ReferenceElement
00271     {
00272       static const unsigned int topologyId = Topology :: id;
00273       static const unsigned int dimension = Topology :: dimension;
00274 
00275       static const unsigned int numCorners = Topology :: numCorners;
00276       static const unsigned int numNormals = ReferenceDomain< Topology > :: numNormals;
00277 
00278       typedef FieldVector< ctype, dimension > CoordinateType;
00279 
00280       template< unsigned int codim >
00281       struct Codim
00282       {
00283         enum { size = Size< Topology, codim > :: value };
00284       };
00285 
00286       template< unsigned int codim, unsigned int subcodim >
00287       static unsigned int subNumbering ( unsigned int i, unsigned int j )
00288       {
00289         return SubTopologyNumbering< Topology, codim, subcodim > :: number( i, j );
00290       }
00291 
00292       template< unsigned int codim, unsigned int subcodim >
00293       static unsigned int size ( unsigned int i )
00294       {
00295         return SubTopologySize< Topology, codim, subcodim > :: size( i );
00296       }
00297 
00298       template< unsigned int codim >
00299       static const FieldVector< ctype, dimension > &
00300       baryCenter ( unsigned int i )
00301       {
00302         Int2Type< codim > codimVariable;
00303         return instance().baryCenters_[ codimVariable ][ i ];
00304       }
00305 
00306       static const CoordinateType &corner ( unsigned int i )
00307       {
00308         assert( i < numCorners );
00309         return instance().corners_[ i ];
00310       }
00311 
00312       static bool checkInside ( const CoordinateType &x )
00313       {
00314         return ReferenceDomain< Topology > :: checkInside( x );
00315       }
00316 
00317       static const CoordinateType &
00318       integrationOuterNormal ( unsigned int i )
00319       {
00320         assert( i < numNormals );
00321         return instance().normals_[ i ];
00322       }
00323 
00324       static ctype volume ()
00325       {
00326         return ReferenceDomain< Topology > :: template volume< ctype >();
00327       }
00328 
00329       static const ReferenceElement &instance ()
00330       {
00331         static ReferenceElement inst;
00332         return inst;
00333       }
00334 
00335     private:
00336       template< int codim >
00337       class BaryCenterArray;
00338 
00339       ReferenceElement ()
00340       {
00341         for( unsigned int i = 0; i < numCorners; ++i )
00342           ReferenceDomain< Topology > :: corner( i, corners_[ i ] );
00343         for( unsigned int i = 0; i < numNormals; ++i )
00344           ReferenceDomain< Topology > :: integrationOuterNormal( i, normals_[ i ] );
00345       }
00346       
00347       Dune::array< CoordinateType, numCorners > corners_;
00348       CodimTable< BaryCenterArray, dimension > baryCenters_;
00349       Dune::array< CoordinateType, numNormals > normals_;
00350     };
00351 
00352 
00353 
00354     template< class Topology, class ctype >
00355     template< int codim >
00356     class ReferenceElement< Topology, ctype > :: BaryCenterArray
00357     {
00358       enum { Size = GenericGeometry :: Size< Topology, codim > :: value };
00359 
00360       typedef FieldVector< ctype, dimension > CoordinateType;
00361 
00362       template< int i >
00363       struct Builder;
00364       
00365       CoordinateType baryCenters_[ Size ];
00366 
00367     public:
00368       BaryCenterArray ()
00369       {
00370         ForLoop< Builder, 0, Size-1 > :: apply( baryCenters_ );
00371       }
00372       
00373       const CoordinateType &operator[] ( unsigned int i ) const
00374       {
00375         assert( i < Size );
00376         return baryCenters_[ i ];
00377       }
00378       
00379       static unsigned int size ()
00380       {
00381         return Size;
00382       }
00383     };
00384 
00385     template< class Topology, class ctype >
00386     template< int codim >
00387     template< int i >
00388     struct ReferenceElement< Topology, ctype > :: BaryCenterArray< codim > :: Builder
00389     {
00390       static void apply ( CoordinateType (&baryCenters)[ Size ] )
00391       {
00392         typedef SubTopologyNumbering< Topology, codim, dimension - codim > Numbering;
00393         typedef SubTopologySize< Topology, codim, dimension - codim > Size;
00394 
00395         CoordinateType &x = baryCenters[ i ];
00396         x = 0;
00397         const unsigned int numCorners = Size :: size( i );
00398         for( unsigned int k = 0; k < numCorners; ++k )
00399         {
00400           unsigned int j = Numbering :: number( i, k );
00401 
00402           CoordinateType y;
00403           ReferenceDomain< Topology > :: corner( j, y );
00404           x += y;
00405         }
00406         x *= ctype( 1 ) / ctype( numCorners );
00407       }
00408     };
00409 
00410   }
00411 
00412 }
00413 
00414 #endif

Generated on Tue Mar 3 12:06:53 2009 for dune-grid by  doxygen 1.5.6