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
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
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