00001 #ifndef DUNE_GENERICREFERENCEELEMENTS_HH
00002 #define DUNE_GENERICREFERENCEELEMENTS_HH
00003
00004
00005 #include <dune/grid/genericgeometry/referenceelements.hh>
00006 #include <dune/grid/genericgeometry/geometry.hh>
00007
00008 namespace Dune
00009 {
00010
00011
00012
00013
00014 template< class ctype, int dim >
00015 class GenericReferenceElement
00016 {
00017 typedef GenericReferenceElement< ctype, dim > This;
00018
00019 class SubEntityInfo;
00020 template< class Topology > class CornerStorage;
00021 template< class Topology > struct Initialize;
00022
00023 struct GeometryTraits
00024 : public GenericGeometry::DefaultGeometryTraits< ctype, dim, dim >
00025 {
00026 typedef GenericGeometry::DefaultGeometryTraits< ctype, dim, dim > Base;
00027
00028 typedef typename Base::CoordTraits CoordTraits;
00029
00030 template< class Topology >
00031 struct Mapping
00032 {
00033 typedef GenericGeometry::CornerMapping< CoordTraits, Topology, dim, CornerStorage< Topology >, true > type;
00034 };
00035
00036 struct Caching
00037 {
00038 static const GenericGeometry::EvaluationType evaluateJacobianTransposed = GenericGeometry::PreCompute;
00039 static const GenericGeometry::EvaluationType evaluateJacobianInverseTransposed = GenericGeometry::PreCompute;
00040 static const GenericGeometry::EvaluationType evaluateIntegrationElement = GenericGeometry::PreCompute;
00041 static const GenericGeometry::EvaluationType evaluateNormal = GenericGeometry::PreCompute;
00042 };
00043 };
00044
00045 public:
00046 template< int codim >
00047 struct Codim
00048 {
00049 typedef GenericGeometry::HybridMapping< dim-codim, GeometryTraits > Mapping;
00050 };
00051
00052 private:
00053 template< int codim >
00054 class MappingArray
00055 : public std::vector< typename Codim< codim >::Mapping * >
00056 {};
00057
00058 typedef GenericGeometry::CodimTable< MappingArray, dim > MappingsTable;
00059
00060 std::vector< SubEntityInfo > info_[ dim+1 ];
00061 double volume_;
00062 MappingsTable mappings_;
00063
00064 public:
00065 int size ( int c ) const
00066 {
00067 assert( (c >= 0) && (c <= dim) );
00068 return info_[ c ].size();
00069 }
00070
00071 int size ( int i, int c, int cc ) const
00072 {
00073 assert( (c >= 0) && (c <= dim) );
00074 return info_[ c ][ i ].size( cc );
00075 }
00076
00077 int subEntity ( int i, int c, int ii, int cc ) const
00078 {
00079 assert( (c >= 0) && (c <= dim) );
00080 return info_[ c ][ i ].number( ii, cc );
00081 }
00082
00083 const FieldVector< ctype, dim > &position( int i, int c ) const
00084 {
00085 assert( (c >= 0) && (c <= dim) );
00086 return info_[ c ][ i ].position();
00087 }
00088
00089 template< int codim >
00090 FieldVector< ctype, dim >
00091 global( const FieldVector< ctype, dim-codim > &local, int i, int c ) const
00092 {
00093 if( c != codim )
00094 DUNE_THROW( Exception, "Local Coordinate Type does not correspond to codimension c." );
00095 assert( c == codim );
00096 return mapping< codim >( i ).global( local );
00097 }
00098
00099 template< int codim >
00100 FieldVector< ctype, dim >
00101 global( const FieldVector< ctype, dim-codim > &local, int i ) const
00102 {
00103 return mapping< codim >( i ).global( local );
00104 }
00105
00106 template< int codim >
00107 typename Codim< codim >::Mapping &mapping( int i ) const
00108 {
00109 Int2Type< codim > codimVariable;
00110 return *(mappings_[ codimVariable ][ i ]);
00111 }
00112
00113 GeometryType type ( int i, int c ) const
00114 {
00115 assert( (c >= 0) && (c <= dim) );
00116 return info_[ c ][ i ].type();
00117 }
00118
00119 double volume () const
00120 {
00121 return volume_;
00122 }
00123
00124 template< GeometryType::BasicType geoType >
00125 void initialize ()
00126 {
00127 typedef typename GenericGeometry::Convert< geoType, dim >::type Topology;
00128 typedef Initialize< Topology > Init;
00129 typedef GenericGeometry::VirtualMapping< Topology, GeometryTraits > VirtualMapping;
00130
00131 Int2Type< 0 > codim0Variable;
00132 mappings_[ codim0Variable ].resize( 1 );
00133 mappings_[ codim0Variable ][ 0 ] = new VirtualMapping( codim0Variable );
00134
00135 GenericGeometry::ForLoop< Init::template Codim, 0, dim >::apply( info_, mappings_ );
00136 volume_ = GenericGeometry::ReferenceDomain< Topology >::template volume< double >();
00137 }
00138 };
00139
00140
00141 template< class ctype, int dim >
00142 class GenericReferenceElement< ctype, dim >::SubEntityInfo
00143 {
00144 template< class Topology, int codim > struct Initialize
00145 {
00146 template< int subcodim > struct SubCodim;
00147 };
00148
00149 int codim_;
00150 std :: vector< int > numbering_[ dim+1 ];
00151 FieldVector< ctype, dim > baryCenter_;
00152 GeometryType type_;
00153
00154 public:
00155 int size ( int cc ) const
00156 {
00157 assert( (cc >= codim_) && (cc <= dim) );
00158 return numbering_[ cc ].size();
00159 }
00160
00161 int number ( int ii, int cc ) const
00162 {
00163 assert( (cc >= codim_) && (cc <= dim) );
00164 return numbering_[ cc ][ ii ];
00165 }
00166
00167 const FieldVector< ctype, dim > &position () const
00168 {
00169 return baryCenter_;
00170 }
00171
00172 GeometryType type () const
00173 {
00174 return type_;
00175 }
00176
00177 template< class Topology, unsigned int codim, unsigned int i >
00178 void initialize ()
00179 {
00180 typedef Initialize< Topology, codim > Init;
00181 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00182
00183 const unsigned int iVariable = i;
00184 GenericGeometry::ForLoop< Init::template SubCodim, 0, dim-codim >::apply( iVariable, numbering_ );
00185 baryCenter_ = RefElement::template baryCenter< codim >( i );
00186
00187 typedef typename GenericGeometry::SubTopology< Topology, codim, i >::type SubTopology;
00188 type_ = GenericGeometry::DuneGeometryType< SubTopology, GeometryType::simplex >::type();
00189 }
00190 };
00191
00192
00193 template< class ctype, int dim >
00194 template< class Topology >
00195 class GenericReferenceElement< ctype, dim >::CornerStorage
00196 {
00197 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00198
00199 public:
00200 static const unsigned int size = Topology::numCorners;
00201
00202 template< class SubTopology >
00203 struct SubStorage
00204 {
00205 typedef CornerStorage< SubTopology > type;
00206 };
00207
00208 explicit CornerStorage ( const Int2Type< 0 > & )
00209 {
00210 for( unsigned int i = 0; i < size; ++i )
00211 coords_[ i ] = RefElement::corner( i );
00212 }
00213
00214 template< class Mapping, unsigned int codim >
00215 explicit
00216 CornerStorage ( const GenericGeometry::SubMappingCoords< Mapping, codim > &coords )
00217 {
00218 for( unsigned int i = 0; i < size; ++i )
00219 coords_[ i ] = coords[ i ];
00220 }
00221
00222 const FieldVector< ctype, dim > &operator[] ( unsigned int i ) const
00223 {
00224 return coords_[ i ];
00225 }
00226
00227 private:
00228 FieldVector< ctype, dim > coords_[ size ];
00229 };
00230
00231
00232 template< class ctype, int dim >
00233 template< class Topology, int codim >
00234 template< int subcodim >
00235 struct GenericReferenceElement< ctype, dim >::SubEntityInfo::Initialize< Topology, codim >::SubCodim
00236 {
00237 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00238
00239 static void apply ( unsigned int i, std::vector< int > (&numbering)[ dim+1 ] )
00240 {
00241 const unsigned int size = RefElement::template size< codim, subcodim >( i );
00242 numbering[ codim+subcodim ].resize( size );
00243 for( unsigned int j = 0; j < size; ++j )
00244 numbering[ codim+subcodim ][ j ] = RefElement::template subNumbering< codim, subcodim >( i, j );
00245 }
00246 };
00247
00248
00249 template< class ctype, int dim >
00250 template< class Topology >
00251 struct GenericReferenceElement< ctype, dim >::Initialize
00252 {
00253 typedef Dune::GenericReferenceElement< ctype, dim > GenericReferenceElement;
00254
00255 typedef typename GenericReferenceElement::template Codim< 0 >::Mapping ReferenceMapping;
00256
00257 template< int codim >
00258 struct Codim
00259 {
00260 template< int i >
00261 struct SubTopology
00262 {
00263 static void apply ( std::vector< SubEntityInfo > &info )
00264 {
00265 info[ i ].template initialize< Topology, codim, i >();
00266 }
00267 };
00268
00269 static void apply ( std::vector< SubEntityInfo > (&info)[ dim+1 ],
00270 MappingsTable &mappings )
00271 {
00272 const unsigned int size = GenericGeometry::Size< Topology, codim >::value;
00273 info[ codim ].resize( size );
00274 GenericGeometry::ForLoop< SubTopology, 0, size-1 >::apply( info[ codim ] );
00275
00276
00277
00278
00279
00280 if( codim > 0 )
00281 {
00282 Int2Type< 0 > codim0Variable;
00283 const ReferenceMapping &refMapping = *(mappings[ codim0Variable ][ 0 ]);
00284
00285 Int2Type< codim > codimVariable;
00286 mappings[ codimVariable ].resize( size );
00287 for( unsigned int i = 0; i < size; ++i )
00288 mappings[ codimVariable ][ i ] = refMapping.template trace< codim >( i );
00289 }
00290 }
00291 };
00292 };
00293
00294
00295
00296
00297
00298
00299 template< class ctype, int dim >
00300 struct GenericReferenceElementContainer
00301 {
00302 typedef GenericReferenceElement< ctype, dim > value_type;
00303
00304 const value_type &operator() ( const GeometryType &type ) const
00305 {
00306 assert( type.dim() == dim );
00307 switch( type.basicType() )
00308 {
00309 case GeometryType::simplex:
00310 return simplex_;
00311
00312 case GeometryType::cube:
00313 return cube_;
00314
00315 case GeometryType::pyramid:
00316 return pyramid_;
00317
00318 case GeometryType::prism:
00319 return prism_;
00320
00321 default:
00322 DUNE_THROW( RangeError, "Unknown geometry type: " << type );
00323 }
00324 }
00325
00326 const value_type &simplex () const
00327 {
00328 return simplex_;
00329 }
00330
00331 const value_type &cube () const
00332 {
00333 return cube_;
00334 }
00335
00336 static const GenericReferenceElementContainer &instance ()
00337 {
00338 static GenericReferenceElementContainer inst;
00339 return inst;
00340 }
00341
00342 private:
00343 GenericReferenceElementContainer ()
00344 {
00345 simplex_.template initialize< GeometryType::simplex >();
00346 cube_.template initialize< GeometryType::cube >();
00347 pyramid_.template initialize< GeometryType::pyramid >();
00348 prism_.template initialize< GeometryType::prism >();
00349 }
00350
00351 value_type simplex_;
00352 value_type cube_;
00353 value_type pyramid_;
00354 value_type prism_;
00355 };
00356
00357 template< class ctype >
00358 struct GenericReferenceElementContainer< ctype, 2 >
00359 {
00360 typedef GenericReferenceElement< ctype, 2 > value_type;
00361
00362 const value_type &operator() ( const GeometryType &type ) const
00363 {
00364 assert( type.dim() == 2 );
00365 switch( type.basicType() )
00366 {
00367 case GeometryType::simplex:
00368 return simplex_;
00369
00370 case GeometryType::cube:
00371 return cube_;
00372
00373 case GeometryType::pyramid:
00374 case GeometryType::prism:
00375 DUNE_THROW( RangeError, "Invalid geometry type: " << type );
00376
00377 default:
00378 DUNE_THROW( RangeError, "Unknown geometry type: " << type );
00379 }
00380 }
00381
00382 const value_type &simplex () const
00383 {
00384 return simplex_;
00385 }
00386
00387 const value_type &cube () const
00388 {
00389 return cube_;
00390 }
00391
00392 static const GenericReferenceElementContainer &instance ()
00393 {
00394 static GenericReferenceElementContainer inst;
00395 return inst;
00396 }
00397
00398 private:
00399 GenericReferenceElementContainer ()
00400 {
00401 simplex_.template initialize< GeometryType::simplex >();
00402 cube_.template initialize< GeometryType::cube >();
00403 }
00404
00405 value_type simplex_;
00406 value_type cube_;
00407 };
00408
00409 template< class ctype >
00410 struct GenericReferenceElementContainer< ctype, 1 >
00411 {
00412 typedef GenericReferenceElement< ctype, 1 > value_type;
00413
00414 const value_type &operator() ( const GeometryType &type ) const
00415 {
00416 assert( type.dim() == 1 );
00417 return line_;
00418 }
00419
00420 const value_type &simplex () const
00421 {
00422 return line_;
00423 }
00424
00425 const value_type &cube () const
00426 {
00427 return line_;
00428 }
00429
00430 static const GenericReferenceElementContainer &instance ()
00431 {
00432 static GenericReferenceElementContainer inst;
00433 return inst;
00434 }
00435
00436 private:
00437 GenericReferenceElementContainer ()
00438 {
00439 line_.template initialize< GeometryType::simplex >();
00440 }
00441
00442 value_type line_;
00443 };
00444
00445 template< class ctype >
00446 struct GenericReferenceElementContainer< ctype, 0 >
00447 {
00448 typedef GenericReferenceElement< ctype, 0 > value_type;
00449
00450 const value_type &operator() ( const GeometryType &type ) const
00451 {
00452 assert( type.dim() == 0 );
00453 return point_;
00454 }
00455
00456 const value_type &simplex () const
00457 {
00458 return point_;
00459 }
00460
00461 const value_type &cube () const
00462 {
00463 return point_;
00464 }
00465
00466 static
00467 const GenericReferenceElementContainer & instance()
00468 {
00469 static GenericReferenceElementContainer inst;
00470 return inst;
00471 }
00472
00473 private:
00474 GenericReferenceElementContainer ()
00475 {
00476 point_.template initialize< GeometryType::simplex >();
00477 }
00478
00479 value_type point_;
00480 };
00481
00482
00483
00484
00485
00486
00487 template< class ctype, int dim >
00488 struct GenericReferenceElements
00489 {
00490 static const GenericReferenceElement< ctype, dim > &
00491 general ( const GeometryType &type )
00492 {
00493 return GenericReferenceElementContainer< ctype, dim >::instance()( type );
00494 }
00495
00496 static const GenericReferenceElement< ctype, dim > &simplex ()
00497 {
00498 return GenericReferenceElementContainer< ctype, dim >::instance().simplex();
00499 }
00500
00501 static const GenericReferenceElement< ctype, dim > &cube ()
00502 {
00503 return GenericReferenceElementContainer< ctype, dim >::instance().cube();
00504 }
00505 };
00506
00507 }
00508
00509 #endif