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
00023 template< class ctype, int dim >
00024 class GenericReferenceElement
00025 {
00026 typedef GenericReferenceElement< ctype, dim > This;
00027
00028 class SubEntityInfo;
00029 template< class Topology > class CornerStorage;
00030 template< class Topology > struct Initialize;
00031
00032 struct GeometryTraits
00033 : public GenericGeometry::DefaultGeometryTraits< ctype, dim, dim >
00034 {
00035 typedef GenericGeometry::DefaultGeometryTraits< ctype, dim, dim > Base;
00036
00037 typedef typename Base::CoordTraits CoordTraits;
00038
00039 template< class Topology >
00040 struct Mapping
00041 {
00042 typedef GenericGeometry::CornerMapping< CoordTraits, Topology, dim, CornerStorage< Topology >, true > type;
00043 };
00044
00045 struct Caching
00046 {
00047 static const GenericGeometry::EvaluationType evaluateJacobianTransposed = GenericGeometry::PreCompute;
00048 static const GenericGeometry::EvaluationType evaluateJacobianInverseTransposed = GenericGeometry::PreCompute;
00049 static const GenericGeometry::EvaluationType evaluateIntegrationElement = GenericGeometry::PreCompute;
00050 static const GenericGeometry::EvaluationType evaluateNormal = GenericGeometry::PreCompute;
00051 };
00052 };
00053
00054 public:
00056 template< int codim >
00057 struct Codim
00058 {
00060 typedef GenericGeometry::HybridMapping< dim-codim, GeometryTraits > Mapping;
00061 };
00062
00063 private:
00064 template< int codim >
00065 class MappingArray
00066 : public std::vector< typename Codim< codim >::Mapping * >
00067 {};
00068
00069 typedef GenericGeometry::CodimTable< MappingArray, dim > MappingsTable;
00070
00071 std::vector< SubEntityInfo > info_[ dim+1 ];
00072 double volume_;
00073 MappingsTable mappings_;
00074
00075 public:
00080 int size ( int c ) const
00081 {
00082 assert( (c >= 0) && (c <= dim) );
00083 return info_[ c ].size();
00084 }
00085
00097 int size ( int i, int c, int cc ) const
00098 {
00099 assert( (c >= 0) && (c <= dim) );
00100 return info_[ c ][ i ].size( cc );
00101 }
00102
00116 int subEntity ( int i, int c, int ii, int cc ) const
00117 {
00118 assert( (c >= 0) && (c <= dim) );
00119 return info_[ c ][ i ].number( ii, cc );
00120 }
00121
00131 const FieldVector< ctype, dim > &position( int i, int c ) const
00132 {
00133 assert( (c >= 0) && (c <= dim) );
00134 return info_[ c ][ i ].position();
00135 }
00136
00150 template< int codim >
00151 bool checkInside ( const FieldVector< ctype, dim-codim > &local, int i ) const
00152 {
00153 return mapping< codim >( i ).checkInside( local );
00154 }
00155
00163 bool checkInside ( const FieldVector< ctype, dim > &local ) const
00164 {
00165 return checkInside< 0 >( local, 0 );
00166 }
00167
00168
00185 template< int codim >
00186 FieldVector< ctype, dim >
00187 global( const FieldVector< ctype, dim-codim > &local, int i, int c ) const
00188 {
00189 if( c != codim )
00190 DUNE_THROW( Exception, "Local Coordinate Type does not correspond to codimension c." );
00191 assert( c == codim );
00192 return mapping< codim >( i ).global( local );
00193 }
00194
00208 template< int codim >
00209 FieldVector< ctype, dim >
00210 global( const FieldVector< ctype, dim-codim > &local, int i ) const
00211 {
00212 return mapping< codim >( i ).global( local );
00213 }
00214
00230 template< int codim >
00231 typename Codim< codim >::Mapping &mapping( int i ) const
00232 {
00233 Int2Type< codim > codimVariable;
00234 return *(mappings_[ codimVariable ][ i ]);
00235 }
00236
00245 GeometryType type ( int i, int c ) const
00246 {
00247 assert( (c >= 0) && (c <= dim) );
00248 return info_[ c ][ i ].type();
00249 }
00250
00252 double volume () const
00253 {
00254 return volume_;
00255 }
00256
00263 template< GeometryType::BasicType geoType >
00264 void initialize ()
00265 {
00266 typedef typename GenericGeometry::Convert< geoType, dim >::type Topology;
00267 typedef Initialize< Topology > Init;
00268 typedef GenericGeometry::VirtualMapping< Topology, GeometryTraits > VirtualMapping;
00269
00270 Int2Type< 0 > codim0Variable;
00271 mappings_[ codim0Variable ].resize( 1 );
00272 mappings_[ codim0Variable ][ 0 ] = new VirtualMapping( codim0Variable );
00273
00274 GenericGeometry::ForLoop< Init::template Codim, 0, dim >::apply( info_, mappings_ );
00275 volume_ = GenericGeometry::ReferenceDomain< Topology >::template volume< double >();
00276 }
00277 };
00278
00279
00280 template< class ctype, int dim >
00281 class GenericReferenceElement< ctype, dim >::SubEntityInfo
00282 {
00283 template< class Topology, int codim > struct Initialize
00284 {
00285 template< int subcodim > struct SubCodim;
00286 };
00287
00288 int codim_;
00289 std::vector< int > numbering_[ dim+1 ];
00290 FieldVector< ctype, dim > baryCenter_;
00291 GeometryType type_;
00292
00293 public:
00294 int size ( int cc ) const
00295 {
00296 assert( (cc >= codim_) && (cc <= dim) );
00297 return numbering_[ cc ].size();
00298 }
00299
00300 int number ( int ii, int cc ) const
00301 {
00302 assert( (cc >= codim_) && (cc <= dim) );
00303 return numbering_[ cc ][ ii ];
00304 }
00305
00306 const FieldVector< ctype, dim > &position () const
00307 {
00308 return baryCenter_;
00309 }
00310
00311 GeometryType type () const
00312 {
00313 return type_;
00314 }
00315
00316 template< class Topology, unsigned int codim, unsigned int i >
00317 void initialize ()
00318 {
00319 typedef Initialize< Topology, codim > Init;
00320 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00321
00322 codim_ = codim;
00323
00324 const unsigned int iVariable = i;
00325 GenericGeometry::ForLoop< Init::template SubCodim, 0, dim-codim >::apply( iVariable, numbering_ );
00326
00327 baryCenter_ = RefElement::template baryCenter< codim >( i );
00328
00329 typedef typename GenericGeometry::SubTopology< Topology, codim, i >::type SubTopology;
00330 type_ = GenericGeometry::DuneGeometryType< SubTopology, GeometryType::simplex >::type();
00331 }
00332 };
00333
00334
00335 template< class ctype, int dim >
00336 template< class Topology >
00337 class GenericReferenceElement< ctype, dim >::CornerStorage
00338 {
00339 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00340
00341 public:
00342 static const unsigned int size = Topology::numCorners;
00343
00344 template< class SubTopology >
00345 struct SubStorage
00346 {
00347 typedef CornerStorage< SubTopology > type;
00348 };
00349
00350 explicit CornerStorage ( const Int2Type< 0 > & )
00351 {
00352 for( unsigned int i = 0; i < size; ++i )
00353 coords_[ i ] = RefElement::corner( i );
00354 }
00355
00356 template< class Mapping, unsigned int codim >
00357 explicit
00358 CornerStorage ( const GenericGeometry::SubMappingCoords< Mapping, codim > &coords )
00359 {
00360 for( unsigned int i = 0; i < size; ++i )
00361 coords_[ i ] = coords[ i ];
00362 }
00363
00364 const FieldVector< ctype, dim > &operator[] ( unsigned int i ) const
00365 {
00366 return coords_[ i ];
00367 }
00368
00369 private:
00370 FieldVector< ctype, dim > coords_[ size ];
00371 };
00372
00373
00374 template< class ctype, int dim >
00375 template< class Topology, int codim >
00376 template< int subcodim >
00377 struct GenericReferenceElement< ctype, dim >::SubEntityInfo::Initialize< Topology, codim >::SubCodim
00378 {
00379 typedef GenericGeometry::ReferenceElement< Topology, ctype > RefElement;
00380
00381 static void apply ( unsigned int i, std::vector< int > (&numbering)[ dim+1 ] )
00382 {
00383 const unsigned int size = RefElement::template size< codim, subcodim >( i );
00384 numbering[ codim+subcodim ].resize( size );
00385 for( unsigned int j = 0; j < size; ++j )
00386 numbering[ codim+subcodim ][ j ] = RefElement::template subNumbering< codim, subcodim >( i, j );
00387 }
00388 };
00389
00390
00391 template< class ctype, int dim >
00392 template< class Topology >
00393 struct GenericReferenceElement< ctype, dim >::Initialize
00394 {
00395 typedef Dune::GenericReferenceElement< ctype, dim > GenericReferenceElement;
00396
00397 typedef typename GenericReferenceElement::template Codim< 0 >::Mapping ReferenceMapping;
00398
00399 template< int codim >
00400 struct Codim
00401 {
00402 template< int i >
00403 struct SubTopology
00404 {
00405 static void apply ( std::vector< SubEntityInfo > &info )
00406 {
00407 info[ i ].template initialize< Topology, codim, i >();
00408 }
00409 };
00410
00411 static void apply ( std::vector< SubEntityInfo > (&info)[ dim+1 ],
00412 MappingsTable &mappings )
00413 {
00414 const unsigned int size = GenericGeometry::Size< Topology, codim >::value;
00415 info[ codim ].resize( size );
00416 GenericGeometry::ForLoop< SubTopology, 0, size-1 >::apply( info[ codim ] );
00417
00418
00419
00420
00421
00422 if( codim > 0 )
00423 {
00424 Int2Type< 0 > codim0Variable;
00425 const ReferenceMapping &refMapping = *(mappings[ codim0Variable ][ 0 ]);
00426
00427 Int2Type< codim > codimVariable;
00428 mappings[ codimVariable ].resize( size );
00429 for( unsigned int i = 0; i < size; ++i )
00430 mappings[ codimVariable ][ i ] = refMapping.template trace< codim >( i );
00431 }
00432 }
00433 };
00434 };
00435
00436
00437
00438
00439
00440
00441 template< class ctype, int dim >
00442 struct GenericReferenceElementContainer
00443 {
00444 typedef GenericReferenceElement< ctype, dim > value_type;
00445
00446 const value_type &operator() ( const GeometryType &type ) const
00447 {
00448 assert( type.dim() == dim );
00449 switch( type.basicType() )
00450 {
00451 case GeometryType::simplex:
00452 return simplex_;
00453
00454 case GeometryType::cube:
00455 return cube_;
00456
00457 case GeometryType::pyramid:
00458 return pyramid_;
00459
00460 case GeometryType::prism:
00461 return prism_;
00462
00463 default:
00464 DUNE_THROW( RangeError, "Unknown geometry type: " << type );
00465 }
00466 }
00467
00468 const value_type &simplex () const
00469 {
00470 return simplex_;
00471 }
00472
00473 const value_type &cube () const
00474 {
00475 return cube_;
00476 }
00477
00478 static const GenericReferenceElementContainer &instance ()
00479 {
00480 static GenericReferenceElementContainer inst;
00481 return inst;
00482 }
00483
00484 private:
00485 GenericReferenceElementContainer ()
00486 {
00487 simplex_.template initialize< GeometryType::simplex >();
00488 cube_.template initialize< GeometryType::cube >();
00489 pyramid_.template initialize< GeometryType::pyramid >();
00490 prism_.template initialize< GeometryType::prism >();
00491 }
00492
00493 value_type simplex_;
00494 value_type cube_;
00495 value_type pyramid_;
00496 value_type prism_;
00497 };
00498
00499 template< class ctype >
00500 struct GenericReferenceElementContainer< ctype, 2 >
00501 {
00502 typedef GenericReferenceElement< ctype, 2 > value_type;
00503
00504 const value_type &operator() ( const GeometryType &type ) const
00505 {
00506 assert( type.dim() == 2 );
00507 switch( type.basicType() )
00508 {
00509 case GeometryType::simplex:
00510 return simplex_;
00511
00512 case GeometryType::cube:
00513 return cube_;
00514
00515 case GeometryType::pyramid:
00516 case GeometryType::prism:
00517 DUNE_THROW( RangeError, "Invalid geometry type: " << type );
00518
00519 default:
00520 DUNE_THROW( RangeError, "Unknown geometry type: " << type );
00521 }
00522 }
00523
00524 const value_type &simplex () const
00525 {
00526 return simplex_;
00527 }
00528
00529 const value_type &cube () const
00530 {
00531 return cube_;
00532 }
00533
00534 static const GenericReferenceElementContainer &instance ()
00535 {
00536 static GenericReferenceElementContainer inst;
00537 return inst;
00538 }
00539
00540 private:
00541 GenericReferenceElementContainer ()
00542 {
00543 simplex_.template initialize< GeometryType::simplex >();
00544 cube_.template initialize< GeometryType::cube >();
00545 }
00546
00547 value_type simplex_;
00548 value_type cube_;
00549 };
00550
00551 template< class ctype >
00552 struct GenericReferenceElementContainer< ctype, 1 >
00553 {
00554 typedef GenericReferenceElement< ctype, 1 > value_type;
00555
00556 const value_type &operator() ( const GeometryType &type ) const
00557 {
00558 assert( type.dim() == 1 );
00559 return line_;
00560 }
00561
00562 const value_type &simplex () const
00563 {
00564 return line_;
00565 }
00566
00567 const value_type &cube () const
00568 {
00569 return line_;
00570 }
00571
00572 static const GenericReferenceElementContainer &instance ()
00573 {
00574 static GenericReferenceElementContainer inst;
00575 return inst;
00576 }
00577
00578 private:
00579 GenericReferenceElementContainer ()
00580 {
00581 line_.template initialize< GeometryType::simplex >();
00582 }
00583
00584 value_type line_;
00585 };
00586
00587 template< class ctype >
00588 struct GenericReferenceElementContainer< ctype, 0 >
00589 {
00590 typedef GenericReferenceElement< ctype, 0 > value_type;
00591
00592 const value_type &operator() ( const GeometryType &type ) const
00593 {
00594 assert( type.dim() == 0 );
00595 return point_;
00596 }
00597
00598 const value_type &simplex () const
00599 {
00600 return point_;
00601 }
00602
00603 const value_type &cube () const
00604 {
00605 return point_;
00606 }
00607
00608 static
00609 const GenericReferenceElementContainer & instance()
00610 {
00611 static GenericReferenceElementContainer inst;
00612 return inst;
00613 }
00614
00615 private:
00616 GenericReferenceElementContainer ()
00617 {
00618 point_.template initialize< GeometryType::simplex >();
00619 }
00620
00621 value_type point_;
00622 };
00623
00624
00625
00626
00627
00628
00629 template< class ctype, int dim >
00630 struct GenericReferenceElements
00631 {
00632 static const GenericReferenceElement< ctype, dim > &
00633 general ( const GeometryType &type )
00634 {
00635 return GenericReferenceElementContainer< ctype, dim >::instance()( type );
00636 }
00637
00638 static const GenericReferenceElement< ctype, dim > &simplex ()
00639 {
00640 return GenericReferenceElementContainer< ctype, dim >::instance().simplex();
00641 }
00642
00643 static const GenericReferenceElement< ctype, dim > &cube ()
00644 {
00645 return GenericReferenceElementContainer< ctype, dim >::instance().cube();
00646 }
00647 };
00648
00649 }
00650
00651 #endif