dune-grid
2.1.1
|
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 // vi: set et ts=8 sw=2 sts=2: 00003 00004 #ifndef DUNE_ALBERTA_GRIDFACTORY_HH 00005 #define DUNE_ALBERTA_GRIDFACTORY_HH 00006 00012 #include <algorithm> 00013 #include <limits> 00014 #include <map> 00015 00016 #include <dune/common/array.hh> 00017 00018 #include <dune/grid/common/gridfactory.hh> 00019 #include <dune/grid/common/genericreferenceelements.hh> 00020 00021 #include <dune/grid/utility/grapedataioformattypes.hh> 00022 00023 #include <dune/grid/albertagrid/agrid.hh> 00024 00025 #if HAVE_ALBERTA 00026 00027 namespace Dune 00028 { 00029 00047 template< int dim, int dimworld > 00048 class GridFactory< AlbertaGrid< dim, dimworld > > 00049 : public GridFactoryInterface< AlbertaGrid< dim, dimworld > > 00050 { 00051 typedef GridFactory< AlbertaGrid< dim, dimworld > > This; 00052 00053 public: 00055 typedef AlbertaGrid< dim, dimworld > Grid; 00056 00058 typedef typename Grid::ctype ctype; 00059 00061 static const int dimension = Grid::dimension; 00063 static const int dimensionworld = Grid::dimensionworld; 00064 00066 typedef FieldVector< ctype, dimensionworld > WorldVector; 00068 typedef FieldMatrix< ctype, dimensionworld, dimensionworld > WorldMatrix; 00069 00070 typedef DuneBoundaryProjection< dimensionworld > DuneProjection; 00071 typedef Dune::shared_ptr< const DuneProjection > DuneProjectionPtr; 00072 typedef Dune::BoundarySegment< dimension, dimensionworld > BoundarySegment; 00073 00074 template< int codim > 00075 struct Codim 00076 { 00077 typedef typename Grid::template Codim< codim >::Entity Entity; 00078 }; 00079 00080 private: 00081 typedef Dune::BoundarySegmentWrapper< dimension, dimensionworld > BoundarySegmentWrapper; 00082 00083 static const int numVertices 00084 = Alberta::NumSubEntities< dimension, dimension >::value; 00085 00086 typedef Alberta::MacroElement< dimension > MacroElement; 00087 typedef Alberta::ElementInfo< dimension > ElementInfo; 00088 typedef Alberta::MacroData< dimension > MacroData; 00089 typedef Alberta::NumberingMap< dimension, Alberta::Dune2AlbertaNumbering > NumberingMap; 00090 typedef Alberta::DuneBoundaryProjection< dimension > Projection; 00091 00092 typedef array< unsigned int, dimension > FaceId; 00093 typedef std::map< FaceId, size_t > BoundaryMap; 00094 00095 class ProjectionFactory; 00096 00097 public: 00099 static const bool supportsBoundaryIds = true; 00101 static const bool supportPeriodicity = MacroData::supportPeriodicity; 00102 00104 GridFactory () 00105 : globalProjection_( (const DuneProjection *)0 ) 00106 { 00107 macroData_.create(); 00108 } 00109 00110 virtual ~GridFactory (); 00111 00116 virtual void insertVertex ( const WorldVector &pos ) 00117 { 00118 macroData_.insertVertex( pos ); 00119 } 00120 00126 virtual void insertElement ( const GeometryType &type, 00127 const std::vector< unsigned int > &vertices ) 00128 { 00129 if( (int)type.dim() != dimension ) 00130 DUNE_THROW( AlbertaError, "Inserting element of wrong dimension: " << type.dim() ); 00131 if( !type.isSimplex() ) 00132 DUNE_THROW( AlbertaError, "Alberta supports only simplices." ); 00133 00134 if( vertices.size() != (size_t)numVertices ) 00135 DUNE_THROW( AlbertaError, "Wrong number of vertices passed: " << vertices.size() << "." ); 00136 00137 int array[ numVertices ]; 00138 for( int i = 0; i < numVertices; ++i ) 00139 array[ i ] = vertices[ numberingMap_.alberta2dune( dimension, i ) ]; 00140 macroData_.insertElement( array ); 00141 } 00142 00151 virtual void insertBoundary ( int element, int face, int id ) 00152 { 00153 if( (id <= 0) || (id > 127) ) 00154 DUNE_THROW( AlbertaError, "Invalid boundary id: " << id << "." ); 00155 macroData_.boundaryId( element, numberingMap_.dune2alberta( 1, face ) ) = id; 00156 } 00157 00166 virtual void 00167 insertBoundaryProjection ( const GeometryType &type, 00168 const std::vector< unsigned int > &vertices, 00169 const DuneProjection *projection ) 00170 { 00171 if( (int)type.dim() != dimension-1 ) 00172 DUNE_THROW( AlbertaError, "Inserting boundary face of wrong dimension: " << type.dim() ); 00173 if( !type.isSimplex() ) 00174 DUNE_THROW( AlbertaError, "Alberta supports only simplices." ); 00175 00176 FaceId faceId; 00177 if( vertices.size() != faceId.size() ) 00178 DUNE_THROW( AlbertaError, "Wrong number of face vertices passed: " << vertices.size() << "." ); 00179 for( size_t i = 0; i < faceId.size(); ++i ) 00180 faceId[ i ] = vertices[ i ]; 00181 std::sort( faceId.begin(), faceId.end() ); 00182 00183 typedef std::pair< typename BoundaryMap::iterator, bool > InsertResult; 00184 const InsertResult result = boundaryMap_.insert( std::make_pair( faceId, boundaryProjections_.size() ) ); 00185 if( !result.second ) 00186 DUNE_THROW( GridError, "Only one boundary projection can be attached to a face." ); 00187 boundaryProjections_.push_back( DuneProjectionPtr( projection ) ); 00188 } 00189 00190 00197 virtual void insertBoundaryProjection ( const DuneProjection *projection ) 00198 { 00199 if( globalProjection_ ) 00200 DUNE_THROW( GridError, "Only one global boundary projection can be attached to a grid." ); 00201 globalProjection_ = DuneProjectionPtr( projection ); 00202 } 00203 00209 virtual void 00210 insertBoundarySegment ( const std::vector< unsigned int >& vertices ) 00211 { 00212 typedef typename GenericGeometry::SimplexTopology< dimension-1 >::type Topology; 00213 insertBoundaryProjection( GeometryType( Topology() ), vertices, 0 ); 00214 } 00215 00221 virtual void 00222 insertBoundarySegment ( const std::vector< unsigned int > &vertices, 00223 const shared_ptr< BoundarySegment > &boundarySegment ) 00224 { 00225 const GenericReferenceElement< ctype, dimension-1 > &refSimplex 00226 = GenericReferenceElements< ctype, dimension-1 >::simplex(); 00227 00228 if( !boundarySegment ) 00229 DUNE_THROW( GridError, "Trying to insert null as a boundary segment." ); 00230 if( (int)vertices.size() != refSimplex.size( dimension-1 ) ) 00231 DUNE_THROW( GridError, "Wrong number of face vertices passed: " << vertices.size() << "." ); 00232 00233 std::vector< WorldVector > coords( refSimplex.size( dimension-1 ) ); 00234 for( int i = 0; i < dimension; ++i ) 00235 { 00236 Alberta::GlobalVector &x = macroData_.vertex( vertices[ i ] ); 00237 for( int j = 0; j < dimensionworld; ++j ) 00238 coords[ i ][ j ] = x[ j ]; 00239 if( ((*boundarySegment)( refSimplex.position( i, dimension-1 ) ) - coords[ i ]).two_norm() > 1e-6 ) 00240 DUNE_THROW( GridError, "Boundary segment does not interpolate the corners." ); 00241 } 00242 00243 const GeometryType gt = refSimplex.type( 0, 0 ); 00244 const DuneProjection *prj = new BoundarySegmentWrapper( gt, coords, boundarySegment ); 00245 insertBoundaryProjection( gt, vertices, prj ); 00246 } 00247 00261 void insertFaceTransformation ( const WorldMatrix &matrix, const WorldVector &shift ); 00262 00271 void markLongestEdge () 00272 { 00273 macroData_.markLongestEdge(); 00274 } 00275 00288 Grid *createGrid () 00289 { 00290 macroData_.finalize(); 00291 if( macroData_.elementCount() == 0 ) 00292 DUNE_THROW( GridError, "Cannot create empty AlbertaGrid." ); 00293 if( dimension < 3 ) 00294 macroData_.setOrientation( Alberta::Real( 1 ) ); 00295 assert( macroData_.checkNeighbors() ); 00296 macroData_.checkCycles(); 00297 ProjectionFactory projectionFactory( *this ); 00298 return new Grid( macroData_, projectionFactory ); 00299 } 00300 00305 static void destroyGrid ( Grid *grid ) 00306 { 00307 delete grid; 00308 } 00309 00318 template< GrapeIOFileFormatType type > 00319 bool write ( const std::string &filename ) 00320 { 00321 dune_static_assert( type != pgm, "AlbertaGridFactory: writing pgm format is not supported." ); 00322 macroData_.finalize(); 00323 if( dimension < 3 ) 00324 macroData_.setOrientation( Alberta::Real( 1 ) ); 00325 assert( macroData_.checkNeighbors() ); 00326 return macroData_.write( filename, (type == xdr) ); 00327 } 00328 00337 virtual bool write ( const std::string &filename ) 00338 { 00339 return write< ascii >( filename ); 00340 } 00341 00342 virtual unsigned int 00343 insertionIndex ( const typename Codim< 0 >::Entity &entity ) const 00344 { 00345 return insertionIndex( Grid::getRealImplementation( entity ).elementInfo() ); 00346 } 00347 00348 virtual unsigned int 00349 insertionIndex ( const typename Codim< dimension >::Entity &entity ) const 00350 { 00351 const int elIndex = insertionIndex( Grid::getRealImplementation( entity ).elementInfo() ); 00352 const typename MacroData::ElementId &elementId = macroData_.element( elIndex ); 00353 return elementId[ Grid::getRealImplementation( entity ).subEntity() ]; 00354 } 00355 00356 virtual unsigned int 00357 insertionIndex ( const typename Grid::LeafIntersection &intersection ) const 00358 { 00359 const Grid &grid = Grid::getRealImplementation( intersection ).grid(); 00360 const ElementInfo &elementInfo = Grid::getRealImplementation( intersection ).elementInfo(); 00361 const int face = grid.generic2alberta( 1, intersection.indexInInside() ); 00362 return insertionIndex( elementInfo, face ); 00363 } 00364 00365 virtual bool 00366 wasInserted ( const typename Grid::LeafIntersection &intersection ) const 00367 { 00368 return (insertionIndex( intersection ) < std::numeric_limits< unsigned int >::max()); 00369 } 00370 00371 private: 00372 unsigned int insertionIndex ( const ElementInfo &elementInfo ) const; 00373 unsigned int insertionIndex ( const ElementInfo &elementInfo, const int face ) const; 00374 00375 FaceId faceId ( const ElementInfo &elementInfo, const int face ) const; 00376 00377 MacroData macroData_; 00378 NumberingMap numberingMap_; 00379 DuneProjectionPtr globalProjection_; 00380 BoundaryMap boundaryMap_; 00381 std::vector< DuneProjectionPtr > boundaryProjections_; 00382 }; 00383 00384 00385 template< int dim, int dimworld > 00386 GridFactory< AlbertaGrid< dim, dimworld > >::~GridFactory () 00387 { 00388 macroData_.release(); 00389 } 00390 00391 00392 template< int dim, int dimworld > 00393 inline void 00394 GridFactory< AlbertaGrid< dim, dimworld > > 00395 ::insertFaceTransformation ( const WorldMatrix &matrix, const WorldVector &shift ) 00396 { 00397 // make sure the matrix is orthogonal 00398 for( int i = 0; i < dimworld; ++i ) 00399 for( int j = 0; j < dimworld; ++j ) 00400 { 00401 const ctype delta = (i == j ? ctype( 1 ) : ctype( 0 )); 00402 const ctype epsilon = (8*dimworld)*std::numeric_limits< ctype >::epsilon(); 00403 00404 if( std::abs( matrix[ i ] * matrix[ j ] - delta ) > epsilon ) 00405 { 00406 DUNE_THROW( AlbertaError, 00407 "Matrix of face transformation is not orthogonal." ); 00408 } 00409 } 00410 00411 // copy matrix 00412 Alberta::GlobalMatrix M; 00413 for( int i = 0; i < dimworld; ++i ) 00414 for( int j = 0; j < dimworld; ++j ) 00415 M[ i ][ j ] = matrix[ i ][ j ]; 00416 00417 // copy shift 00418 Alberta::GlobalVector t; 00419 for( int i = 0; i < dimworld; ++i ) 00420 t[ i ] = shift[ i ]; 00421 00422 // insert into ALBERTA macro data 00423 macroData_.insertWallTrafo( M, t ); 00424 } 00425 00426 00427 template< int dim, int dimworld > 00428 inline unsigned int 00429 GridFactory< AlbertaGrid< dim, dimworld > > 00430 ::insertionIndex ( const ElementInfo &elementInfo ) const 00431 { 00432 const MacroElement ¯oElement = elementInfo.macroElement(); 00433 const unsigned int index = macroElement.index; 00434 00435 #ifndef NDEBUG 00436 const typename MacroData::ElementId &elementId = macroData_.element( index ); 00437 for( int i = 0; i <= dimension; ++i ) 00438 { 00439 const Alberta::GlobalVector &x = macroData_.vertex( elementId[ i ] ); 00440 const Alberta::GlobalVector &y = macroElement.coordinate( i ); 00441 for( int j = 0; j < dimensionworld; ++j ) 00442 { 00443 if( x[ j ] != y[ j ] ) 00444 DUNE_THROW( GridError, "Vertex in macro element does not coincide with same vertex in macro data structure." ); 00445 } 00446 } 00447 #endif // #ifndef NDEBUG 00448 00449 return index; 00450 } 00451 00452 00453 template< int dim, int dimworld > 00454 inline unsigned int 00455 GridFactory< AlbertaGrid< dim, dimworld > > 00456 ::insertionIndex ( const ElementInfo &elementInfo, const int face ) const 00457 { 00458 typedef typename BoundaryMap::const_iterator Iterator; 00459 const Iterator it = boundaryMap_.find( faceId( elementInfo, face ) ); 00460 if( it != boundaryMap_.end() ) 00461 return it->second; 00462 else 00463 return std::numeric_limits< unsigned int >::max(); 00464 } 00465 00466 00467 template< int dim, int dimworld > 00468 inline typename GridFactory< AlbertaGrid< dim, dimworld > >::FaceId 00469 GridFactory< AlbertaGrid< dim, dimworld > > 00470 ::faceId ( const ElementInfo &elementInfo, const int face ) const 00471 { 00472 const unsigned int index = insertionIndex( elementInfo ); 00473 const typename MacroData::ElementId &elementId = macroData_.element( index ); 00474 00475 FaceId faceId; 00476 for( size_t i = 0; i < faceId.size(); ++i ) 00477 { 00478 const int k = Alberta::MapVertices< dimension, 1 >::apply( face, i ); 00479 faceId[ i ] = elementId[ k ]; 00480 } 00481 std::sort( faceId.begin(), faceId.end() ); 00482 return faceId; 00483 } 00484 00485 00486 00487 // GridFactory::ProjectionFactory 00488 // ------------------------------ 00489 00490 template< int dim, int dimworld > 00491 class GridFactory< AlbertaGrid< dim, dimworld > >::ProjectionFactory 00492 : public Alberta::ProjectionFactory< Alberta::DuneBoundaryProjection< dim >, ProjectionFactory > 00493 { 00494 typedef ProjectionFactory This; 00495 typedef Alberta::ProjectionFactory< Alberta::DuneBoundaryProjection< dim >, ProjectionFactory > Base; 00496 00497 typedef typename Dune::GridFactory< AlbertaGrid< dim, dimworld > > Factory; 00498 00499 public: 00500 typedef typename Base::Projection Projection; 00501 typedef typename Base::ElementInfo ElementInfo; 00502 00503 typedef typename Projection::Projection DuneProjection; 00504 00505 ProjectionFactory( const GridFactory &gridFactory ) 00506 : gridFactory_( gridFactory ) 00507 {} 00508 00509 bool hasProjection ( const ElementInfo &elementInfo, const int face ) const 00510 { 00511 if( gridFactory().globalProjection_ ) 00512 return true; 00513 00514 const unsigned int index = gridFactory().insertionIndex( elementInfo, face ); 00515 if( index < std::numeric_limits< unsigned int >::max() ) 00516 return bool( gridFactory().boundaryProjections_[ index ] ); 00517 else 00518 return false; 00519 } 00520 00521 bool hasProjection ( const ElementInfo &elementInfo ) const 00522 { 00523 return bool( gridFactory().globalProjection_ ); 00524 } 00525 00526 Projection projection ( const ElementInfo &elementInfo, const int face ) const 00527 { 00528 const unsigned int index = gridFactory().insertionIndex( elementInfo, face ); 00529 if( index < std::numeric_limits< unsigned int >::max() ) 00530 { 00531 const DuneProjectionPtr &projection = gridFactory().boundaryProjections_[ index ]; 00532 if( projection ) 00533 return Projection( projection ); 00534 } 00535 00536 assert( gridFactory().globalProjection_ ); 00537 return Projection( gridFactory().globalProjection_ ); 00538 }; 00539 00540 Projection projection ( const ElementInfo &elementInfo ) const 00541 { 00542 assert( gridFactory().globalProjection_ ); 00543 return Projection( gridFactory().globalProjection_ ); 00544 }; 00545 00546 const GridFactory &gridFactory () const 00547 { 00548 return gridFactory_; 00549 } 00550 00551 private: 00552 const GridFactory &gridFactory_; 00553 }; 00554 00555 } 00556 00557 #endif // #if HAVE_ALBERTA 00558 00559 #endif // #ifndef DUNE_ALBERTA_GRIDFACTORY_HH