00001 #ifndef DUNE_GENERICGEOMETRY_CONVERSION_HH
00002 #define DUNE_GENERICGEOMETRY_CONVERSION_HH
00003
00004 #include <dune/common/static_assert.hh>
00005 #include <dune/common/geometrytype.hh>
00006
00007 #include <dune/grid/genericgeometry/misc.hh>
00008 #include <dune/grid/genericgeometry/topologytypes.hh>
00009 #include <dune/grid/genericgeometry/subtopologies.hh>
00010
00011 namespace Dune
00012 {
00013
00014 namespace GenericGeometry
00015 {
00016
00017
00018
00019
00020 template< class Topology, GeometryType :: BasicType defaultType >
00021 class DuneGeometryType;
00022
00023 template< GeometryType :: BasicType defaultType >
00024 class DuneGeometryType< Point, defaultType >
00025 {
00026 dune_static_assert( (defaultType == GeometryType :: simplex)
00027 || (defaultType == GeometryType :: cube),
00028 "defaultType may only be a simplex or a cube." );
00029
00030 public:
00031 enum { dimension = 0 };
00032 enum { basicType = defaultType };
00033
00034 static GeometryType type ()
00035 {
00036 return GeometryType( (GeometryType :: BasicType)basicType, dimension );
00037 }
00038 };
00039
00040 template< class BaseTopology, GeometryType :: BasicType defaultType >
00041 class DuneGeometryType< Prism< BaseTopology >, defaultType >
00042 {
00043 typedef DuneGeometryType< BaseTopology, defaultType > DuneBaseGeometryType;
00044
00045 dune_static_assert( ((int)defaultType == (int)GeometryType :: simplex)
00046 || ((int)defaultType == (int)GeometryType :: cube),
00047 "defaultType may only be a simplex or a cube." );
00048
00049 dune_static_assert( ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: simplex)
00050 || ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: cube),
00051 "Only prisms over simplices or cubes can be converted." );
00052
00053 public:
00054 enum { dimension = DuneBaseGeometryType :: dimension + 1 };
00055 enum
00056 {
00057 basicType = (dimension == 1)
00058 ? defaultType
00059 : ((dimension == 2)
00060 || ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: cube))
00061 ? GeometryType :: cube
00062 : GeometryType :: prism
00063 };
00064
00065 static GeometryType type ()
00066 {
00067 return GeometryType( (GeometryType :: BasicType)basicType, dimension );
00068 }
00069 };
00070
00071 template< class BaseTopology, GeometryType :: BasicType defaultType >
00072 class DuneGeometryType< Pyramid< BaseTopology >, defaultType >
00073 {
00074 typedef DuneGeometryType< BaseTopology, defaultType > DuneBaseGeometryType;
00075
00076 dune_static_assert( ((int)defaultType == (int)GeometryType :: simplex)
00077 || ((int)defaultType == (int)GeometryType :: cube),
00078 "defaultType may only be a simplex or a cube." );
00079
00080 dune_static_assert( ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: simplex)
00081 || ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: cube),
00082 "Only pyramids over simplices or cubes can be converted." );
00083
00084 public:
00085 enum { dimension = DuneBaseGeometryType :: dimension + 1 };
00086 enum
00087 {
00088 basicType = (dimension == 1)
00089 ? defaultType
00090 : ((dimension == 2)
00091 || ((int)DuneBaseGeometryType :: basicType == (int)GeometryType :: simplex))
00092 ? GeometryType :: simplex
00093 : GeometryType :: pyramid
00094 };
00095
00096 static GeometryType type ()
00097 {
00098 return GeometryType( (GeometryType :: BasicType)basicType, dimension );
00099 }
00100 };
00101
00102
00103
00104
00105
00106
00107 template< unsigned int dim, GeometryType :: BasicType defaultType >
00108 struct DuneGeometryTypeProvider
00109 {
00110 enum { dimension = dim };
00111 enum { numTopologies = (1 << dimension) };
00112
00113 private:
00114 template< int i >
00115 struct Builder;
00116
00117 GeometryType types_[ numTopologies ];
00118
00119 DuneGeometryTypeProvider ()
00120 {
00121 ForLoop< Builder, 0, (1 << dim)-1 > :: apply( types_ );
00122 }
00123
00124 static const DuneGeometryTypeProvider &instance ()
00125 {
00126 static DuneGeometryTypeProvider inst;
00127 return inst;
00128 }
00129
00130 public:
00131 static const GeometryType &type ( unsigned int topologyId )
00132 {
00133 assert( topologyId < numTopologies );
00134 return instance().types_[ topologyId ];
00135 }
00136 };
00137
00138
00139 template< unsigned int dim, GeometryType :: BasicType defaultType >
00140 template< int i >
00141 struct DuneGeometryTypeProvider< dim, defaultType > :: Builder
00142 {
00143 typedef typename GenericGeometry :: Topology< i, dimension > :: type Topology;
00144 typedef GenericGeometry :: DuneGeometryType< Topology, defaultType >
00145 DuneGeometryType;
00146
00147 static void apply ( GeometryType (&types)[ numTopologies ] )
00148 {
00149 types[ i ] = DuneGeometryType :: type();
00150 }
00151 };
00152
00153
00154
00155
00156
00157
00158
00159 template< class Topology >
00160 struct MapNumbering;
00161
00162
00163 struct MapNumberingIdentical
00164 {
00165 template< unsigned int codim >
00166 static unsigned int dune2generic ( unsigned int i )
00167 {
00168 return i;
00169 }
00170
00171 template< unsigned int codim >
00172 static unsigned int generic2dune ( unsigned int i )
00173 {
00174 return i;
00175 }
00176 };
00177
00178
00179 template<>
00180 struct MapNumbering< Point >
00181 : public MapNumberingIdentical
00182 {};
00183
00184
00185 template<>
00186 struct MapNumbering< Prism< Point > >
00187 : public MapNumberingIdentical
00188 {};
00189
00190 template<>
00191 struct MapNumbering< Pyramid< Point > >
00192 : public MapNumberingIdentical
00193 {};
00194
00195
00196 struct MapNumberingTriangle
00197 {
00198 template< unsigned int codim >
00199 static unsigned int dune2generic ( unsigned int i )
00200 {
00201 return (codim == 1 ? 2 - i : i);
00202 }
00203
00204 template< unsigned int codim >
00205 static unsigned int generic2dune ( unsigned int i )
00206 {
00207 return dune2generic< codim >( i );
00208 }
00209 };
00210
00211 template<>
00212 struct MapNumbering< Pyramid< Pyramid< Point > > >
00213 : public MapNumberingTriangle
00214 {};
00215
00216 template<>
00217 struct MapNumbering< Pyramid< Prism< Point > > >
00218 : public MapNumberingTriangle
00219 {};
00220
00221
00222
00223 template<>
00224 struct MapNumbering< Prism< Pyramid< Point > > >
00225 : public MapNumberingIdentical
00226 {};
00227
00228 template<>
00229 struct MapNumbering< Prism< Prism< Point > > >
00230 : public MapNumberingIdentical
00231 {};
00232
00233
00234 struct MapNumberingTetrahedron
00235 {
00236 template< unsigned int codim >
00237 static unsigned int dune2generic ( unsigned int i )
00238 {
00239 static unsigned int edge[ 6 ] = { 0, 2, 1, 3, 4, 5 };
00240 return (codim == 1 ? 3 - i : (codim == 2 ? edge[ i ] : i));
00241 }
00242
00243 template< unsigned int codim >
00244 static unsigned int generic2dune ( unsigned int i )
00245 {
00246 return dune2generic< codim >( i );
00247 }
00248 };
00249
00250 template<>
00251 struct MapNumbering< Pyramid< Pyramid< Pyramid< Point > > > >
00252 : public MapNumberingTetrahedron
00253 {};
00254
00255 template<>
00256 struct MapNumbering< Pyramid< Pyramid< Prism< Point > > > >
00257 : public MapNumberingTetrahedron
00258 {};
00259
00260
00261 struct MapNumberingCube
00262 {
00263 template< unsigned int codim >
00264 static unsigned int dune2generic ( unsigned int i )
00265 {
00266 static unsigned int edge[ 12 ] = { 0, 1, 2, 3, 4, 5, 8, 9, 6, 7, 10, 11 };
00267 return (codim == 2 ? edge[ i ] : i);
00268 }
00269
00270 template< unsigned int codim >
00271 static unsigned int generic2dune ( unsigned int i )
00272 {
00273 return dune2generic< codim >( i );
00274 }
00275 };
00276
00277 template<>
00278 struct MapNumbering< Prism< Prism< Pyramid< Point > > > >
00279 : public MapNumberingCube
00280 {};
00281
00282 template<>
00283 struct MapNumbering< Prism< Prism< Prism< Point > > > >
00284 : public MapNumberingCube
00285 {};
00286
00287
00288 struct MapNumberingPyramid
00289 {
00290 template< unsigned int codim >
00291 static unsigned int dune2generic ( unsigned int i )
00292 {
00293 static unsigned int vertex[ 5 ] = { 0, 1, 3, 2, 4 };
00294 static unsigned int edge[ 8 ] = { 2, 1, 3, 0, 4, 5, 7, 6 };
00295 static unsigned int face[ 5 ] = { 0, 3, 2, 4, 1 };
00296
00297 if( codim == 3 )
00298 return vertex[ i ];
00299 else if( codim == 2 )
00300 return edge[ i ];
00301 else if( codim == 1 )
00302 return face[ i ];
00303 else
00304 return i;
00305 }
00306
00307 template< unsigned int codim >
00308 static unsigned int generic2dune ( unsigned int i )
00309 {
00310 static unsigned int vertex[ 5 ] = { 0, 1, 3, 2, 4 };
00311 static unsigned int edge[ 8 ] = { 3, 1, 0, 2, 4, 5, 7, 6 };
00312 static unsigned int face[ 5 ] = { 0, 4, 2, 1, 3 };
00313
00314 if( codim == 3 )
00315 return vertex[ i ];
00316 else if( codim == 2 )
00317 return edge[ i ];
00318 else if( codim == 1 )
00319 return face[ i ];
00320 else
00321 return i;
00322 }
00323 };
00324
00325 template<>
00326 struct MapNumbering< Pyramid< Prism< Pyramid< Point > > > >
00327 : public MapNumberingPyramid
00328 {};
00329
00330 template<>
00331 struct MapNumbering< Pyramid< Prism< Prism< Point > > > >
00332 : public MapNumberingPyramid
00333 {};
00334
00335
00336 struct MapNumberingPrism
00337 {
00338 template< unsigned int codim >
00339 static unsigned int dune2generic ( unsigned int i )
00340 {
00341 static unsigned int edge[ 9 ] = { 3, 5, 4, 0, 1, 2, 6, 8, 7 };
00342 static unsigned int face[ 5 ] = { 3, 0, 2, 1, 4 };
00343
00344 if( codim == 2 )
00345 return edge[ i ];
00346 else if( codim == 1 )
00347 return face[ i ];
00348 else
00349 return i;
00350 }
00351
00352 template< unsigned int codim >
00353 static unsigned int generic2dune ( unsigned int i )
00354 {
00355 static unsigned int edge[ 9 ] = { 3, 4, 5, 0, 2, 1, 6, 8, 7 };
00356 static unsigned int face[ 5 ] = { 1, 3, 2, 0, 4 };
00357
00358 if( codim == 2 )
00359 return edge[ i ];
00360 else if( codim == 1 )
00361 return face[ i ];
00362 else
00363 return i;
00364 }
00365 };
00366
00367 template<>
00368 struct MapNumbering< Prism< Pyramid< Pyramid< Point > > > >
00369 : public MapNumberingPrism
00370 {};
00371
00372 template<>
00373 struct MapNumbering< Prism< Pyramid< Prism< Point > > > >
00374 : public MapNumberingPrism
00375 {};
00376
00377
00378
00379
00380
00381
00382 template< unsigned int dim >
00383 class MapNumberingProvider
00384 {
00385 enum { dimension = dim };
00386 enum { numTopologies = (1 << dimension) };
00387
00388 private:
00389 template< int i >
00390 struct Builder;
00391
00392 typedef std :: vector< unsigned int > Map;
00393
00394 Map dune2generic_[ numTopologies ][ dimension+1 ];
00395 Map generic2dune_[ numTopologies ][ dimension+1 ];
00396
00397 MapNumberingProvider ()
00398 {
00399 ForLoop< Builder, 0, (1 << dim)-1 > :: apply( dune2generic_, generic2dune_ );
00400 }
00401
00402 static const MapNumberingProvider &instance ()
00403 {
00404 static MapNumberingProvider inst;
00405 return inst;
00406 }
00407
00408 public:
00409 template< unsigned int codim >
00410 static unsigned int
00411 dune2generic ( unsigned int topologyId, unsigned int i )
00412 {
00413 assert( topologyId < numTopologies );
00414 return instance().dune2generic_[ topologyId ][ codim ][ i ];
00415 }
00416
00417 template< unsigned int codim >
00418 static unsigned int
00419 generic2dune ( unsigned int topologyId, unsigned int i )
00420 {
00421 assert( topologyId < numTopologies );
00422 return instance().generic2dune_[ topologyId ][ codim ][ i ];
00423 }
00424 };
00425
00426
00427 template< unsigned int dim >
00428 template< int i >
00429 struct MapNumberingProvider< dim > :: Builder
00430 {
00431 typedef typename GenericGeometry :: Topology< i, dimension > :: type Topology;
00432 typedef GenericGeometry :: MapNumbering< Topology > MapNumbering;
00433
00434 template< int codim >
00435 struct Codim;
00436
00437 static void apply ( Map (&dune2generic)[ numTopologies ][ dimension+1 ],
00438 Map (&generic2dune)[ numTopologies ][ dimension+1 ] )
00439 {
00440 ForLoop< Codim, 0, dimension > :: apply( dune2generic[ i ], generic2dune[ i ] );
00441 }
00442 };
00443
00444 template< unsigned int dim >
00445 template< int i >
00446 template< int codim >
00447 struct MapNumberingProvider< dim > :: Builder< i > :: Codim
00448 {
00449 static void apply ( Map (&dune2generic)[ dimension+1 ],
00450 Map (&generic2dune)[ dimension+1 ] )
00451 {
00452 const unsigned int size = Size< Topology, codim > :: value;
00453
00454 Map &d2g = dune2generic[ codim ];
00455 d2g.resize( size );
00456 for( unsigned int j = 0; j < size; ++j )
00457 d2g[ j ] = MapNumbering::template dune2generic< codim >( j );
00458
00459 Map &g2d = generic2dune[ codim ];
00460 g2d.resize( size );
00461 for( unsigned int j = 0; j < size; ++j )
00462 g2d[ j ] = MapNumbering::template generic2dune< codim >( j );
00463 }
00464 };
00465
00466
00467
00468
00469
00470
00471 template< GeometryType :: BasicType type, unsigned int dim >
00472 struct Convert;
00473
00474 template< unsigned int dim >
00475 struct Convert< GeometryType :: simplex, dim >
00476 {
00477 typedef Pyramid
00478 < typename Convert< GeometryType :: simplex, dim-1 > :: type >
00479 type;
00480
00481 template< unsigned int codim >
00482 static unsigned int map ( unsigned int i )
00483 {
00484 return MapNumbering<type>::template dune2generic<codim>(i);
00485 }
00486 };
00487
00488 template<>
00489 struct Convert< GeometryType :: simplex, 0 >
00490 {
00491 typedef Point type;
00492
00493 template< unsigned int codim >
00494 static unsigned int map ( unsigned int i )
00495 {
00496 return MapNumbering<type>::template dune2generic<codim>(i);
00497 }
00498 };
00499
00500 template< unsigned int dim >
00501 struct Convert< GeometryType :: cube, dim >
00502 {
00503 typedef Prism< typename Convert< GeometryType :: cube, dim-1 > :: type >
00504 type;
00505
00506 template< unsigned int codim >
00507 static unsigned int map ( unsigned int i )
00508 {
00509 return MapNumbering<type>::template dune2generic<codim>(i);
00510 }
00511 };
00512
00513 template<>
00514 struct Convert< GeometryType :: cube, 0 >
00515 {
00516 typedef Point type;
00517
00518 template< unsigned int codim >
00519 static unsigned int map ( unsigned int i )
00520 {
00521 return MapNumbering<type>::template dune2generic<codim>(i);
00522 }
00523 };
00524
00525 template< unsigned int dim >
00526 struct Convert< GeometryType :: prism, dim >
00527 {
00528 typedef Prism
00529 < typename Convert< GeometryType :: simplex, dim-1 > :: type >
00530 type;
00531
00532 template< unsigned int codim >
00533 static unsigned int map ( unsigned int i )
00534 {
00535 return MapNumbering<type>::template dune2generic<codim>(i);
00536 }
00537
00538 private:
00539
00540 };
00541
00542 template< unsigned int dim >
00543 struct Convert< GeometryType :: pyramid, dim >
00544 {
00545 typedef Pyramid
00546 < typename Convert< GeometryType :: cube, dim-1 > :: type >
00547 type;
00548
00549
00550
00551 template< unsigned int codim >
00552 static unsigned int map ( unsigned int i )
00553 {
00554 return MapNumbering<type>::template dune2generic<codim>(i);
00555 }
00556
00557 private:
00558
00559 };
00560
00561
00562
00563
00564
00565
00566
00567 inline unsigned int topologyId ( const GeometryType &type )
00568 {
00569 const unsigned int dim = type.dim();
00570
00571 switch( type.basicType() )
00572 {
00573 case GeometryType::simplex:
00574 return 0;
00575
00576 case GeometryType::cube:
00577 return (1 << dim) - 1;
00578
00579 case GeometryType::pyramid:
00580 return (1 << (dim-1)) - 1;
00581
00582 case GeometryType::prism:
00583 return 1 << (dim-1);
00584
00585 default:
00586 DUNE_THROW( RangeError,
00587 "Invalid basic geometry type: " << type.basicType() << "." );
00588 }
00589
00590 }
00591
00592 }
00593
00594 }
00595
00596 #endif