4 #ifndef DUNE_ALBERTA_GRIDFACTORY_HH
5 #define DUNE_ALBERTA_GRIDFACTORY_HH
16 #include <dune/common/array.hh>
18 #include <dune/geometry/referenceelements.hh>
48 template<
int dim,
int dimworld >
69 typedef FieldMatrix< ctype, dimensionworld, dimensionworld >
WorldMatrix;
84 static const int numVertices
85 = Alberta::NumSubEntities< dimension, dimension >::value;
93 typedef array< unsigned int, dimension > FaceId;
94 typedef std::map< FaceId, size_t > BoundaryMap;
96 class ProjectionFactory;
100 static const bool supportsBoundaryIds =
true;
102 static const bool supportPeriodicity = MacroData::supportPeriodicity;
119 macroData_.insertVertex( pos );
128 const std::vector< unsigned int > &vertices )
131 DUNE_THROW(
AlbertaError,
"Inserting element of wrong dimension: " << type.dim() );
132 if( !type.isSimplex() )
133 DUNE_THROW(
AlbertaError,
"Alberta supports only simplices." );
135 if( vertices.size() != (size_t)numVertices )
136 DUNE_THROW(
AlbertaError,
"Wrong number of vertices passed: " << vertices.size() <<
"." );
138 int array[ numVertices ];
139 for(
int i = 0; i < numVertices; ++i )
140 array[ i ] = vertices[ numberingMap_.alberta2dune(
dimension, i ) ];
141 macroData_.insertElement( array );
152 virtual void insertBoundary (
int element,
int face,
int id )
154 if( (
id <= 0) || (
id > 127) )
155 DUNE_THROW(
AlbertaError,
"Invalid boundary id: " <<
id <<
"." );
156 macroData_.boundaryId( element, numberingMap_.dune2alberta( 1, face ) ) =
id;
169 const std::vector< unsigned int > &vertices,
173 DUNE_THROW(
AlbertaError,
"Inserting boundary face of wrong dimension: " << type.dim() );
174 if( !type.isSimplex() )
175 DUNE_THROW(
AlbertaError,
"Alberta supports only simplices." );
178 if( vertices.size() != faceId.size() )
179 DUNE_THROW(
AlbertaError,
"Wrong number of face vertices passed: " << vertices.size() <<
"." );
180 for(
size_t i = 0; i < faceId.size(); ++i )
181 faceId[ i ] = vertices[ i ];
182 std::sort( faceId.begin(), faceId.end() );
184 typedef std::pair< typename BoundaryMap::iterator, bool > InsertResult;
185 const InsertResult result = boundaryMap_.insert( std::make_pair( faceId, boundaryProjections_.size() ) );
187 DUNE_THROW(
GridError,
"Only one boundary projection can be attached to a face." );
200 if( globalProjection_ )
201 DUNE_THROW(
GridError,
"Only one global boundary projection can be attached to a grid." );
213 typedef typename GenericGeometry::SimplexTopology<
dimension-1 >::type Topology;
214 insertBoundaryProjection(
GeometryType( Topology() ), vertices, 0 );
224 const shared_ptr< BoundarySegment > &boundarySegment )
229 if( !boundarySegment )
230 DUNE_THROW(
GridError,
"Trying to insert null as a boundary segment." );
231 if( (
int)vertices.size() != refSimplex.size(
dimension-1 ) )
232 DUNE_THROW(
GridError,
"Wrong number of face vertices passed: " << vertices.size() <<
"." );
234 std::vector< WorldVector > coords( refSimplex.size(
dimension-1 ) );
238 for(
int j = 0; j < dimensionworld; ++j )
239 coords[ i ][ j ] = x[ j ];
240 if( ((*boundarySegment)( refSimplex.position( i, dimension-1 ) ) - coords[ i ]).two_norm() > 1e-6 )
241 DUNE_THROW(
GridError,
"Boundary segment does not interpolate the corners." );
246 insertBoundaryProjection( gt, vertices, prj );
262 void insertFaceTransformation (
const WorldMatrix &matrix,
const WorldVector &shift );
272 void markLongestEdge ()
274 macroData_.markLongestEdge();
291 macroData_.finalize();
292 if( macroData_.elementCount() == 0 )
293 DUNE_THROW(
GridError,
"Cannot create empty AlbertaGrid." );
296 assert( macroData_.checkNeighbors() );
297 macroData_.checkCycles();
298 ProjectionFactory projectionFactory( *
this );
299 return new Grid( macroData_, projectionFactory );
306 static void destroyGrid (
Grid *grid )
319 template< GrapeIOFileFormatType type >
320 bool write (
const std::string &filename )
322 dune_static_assert( type !=
pgm,
"AlbertaGridFactory: writing pgm format is not supported." );
323 macroData_.finalize();
326 assert( macroData_.checkNeighbors() );
327 return macroData_.write( filename, (type ==
xdr) );
338 virtual bool write (
const std::string &filename )
340 return write< ascii >( filename );
346 return insertionIndex( Grid::getRealImplementation( entity ).elementInfo() );
352 const int elIndex =
insertionIndex( Grid::getRealImplementation( entity ).elementInfo() );
353 const typename MacroData::ElementId &elementId = macroData_.element( elIndex );
354 return elementId[ Grid::getRealImplementation( entity ).subEntity() ];
360 const Grid &grid = Grid::getRealImplementation( intersection ).grid();
361 const ElementInfo &elementInfo = Grid::getRealImplementation( intersection ).elementInfo();
362 const int face = grid.
generic2alberta( 1, intersection.indexInInside() );
373 unsigned int insertionIndex (
const ElementInfo &elementInfo )
const;
374 unsigned int insertionIndex (
const ElementInfo &elementInfo,
const int face )
const;
376 FaceId faceId (
const ElementInfo &elementInfo,
const int face )
const;
378 MacroData macroData_;
379 NumberingMap numberingMap_;
380 DuneProjectionPtr globalProjection_;
381 BoundaryMap boundaryMap_;
382 std::vector< DuneProjectionPtr > boundaryProjections_;
386 template<
int dim,
int dimworld >
389 macroData_.release();
393 template<
int dim,
int dimworld >
399 for(
int i = 0; i < dimworld; ++i )
400 for(
int j = 0; j < dimworld; ++j )
402 const ctype delta = (i == j ?
ctype( 1 ) : ctype( 0 ));
403 const ctype epsilon = (8*dimworld)*std::numeric_limits< ctype >::epsilon();
405 if(
std::abs( matrix[ i ] * matrix[ j ] - delta ) > epsilon )
408 "Matrix of face transformation is not orthogonal." );
414 for(
int i = 0; i < dimworld; ++i )
415 for(
int j = 0; j < dimworld; ++j )
416 M[ i ][ j ] = matrix[ i ][ j ];
420 for(
int i = 0; i < dimworld; ++i )
424 macroData_.insertWallTrafo( M, t );
428 template<
int dim,
int dimworld >
431 ::insertionIndex (
const ElementInfo &elementInfo )
const
433 const MacroElement ¯oElement = elementInfo.macroElement();
434 const unsigned int index = macroElement.index;
437 const typename MacroData::ElementId &elementId = macroData_.element( index );
438 for(
int i = 0; i <= dimension; ++i )
442 for(
int j = 0; j < dimensionworld; ++j )
444 if( x[ j ] != y[ j ] )
445 DUNE_THROW(
GridError,
"Vertex in macro element does not coincide with same vertex in macro data structure." );
448 #endif // #ifndef NDEBUG
454 template<
int dim,
int dimworld >
456 GridFactory< AlbertaGrid< dim, dimworld > >
457 ::insertionIndex (
const ElementInfo &elementInfo,
const int face )
const
459 typedef typename BoundaryMap::const_iterator Iterator;
460 const Iterator it = boundaryMap_.find( faceId( elementInfo, face ) );
461 if( it != boundaryMap_.end() )
468 template<
int dim,
int dimworld >
469 inline typename GridFactory< AlbertaGrid< dim, dimworld > >::FaceId
470 GridFactory< AlbertaGrid< dim, dimworld > >
471 ::faceId (
const ElementInfo &elementInfo,
const int face )
const
473 const unsigned int index = insertionIndex( elementInfo );
474 const typename MacroData::ElementId &elementId = macroData_.element( index );
477 for(
size_t i = 0; i < faceId.size(); ++i )
479 const int k = Alberta::MapVertices< dimension, 1 >::apply( face, i );
480 faceId[ i ] = elementId[ k ];
482 std::sort( faceId.begin(), faceId.end() );
491 template<
int dim,
int dimworld >
495 typedef ProjectionFactory This;
507 : gridFactory_( gridFactory )
510 bool hasProjection (
const ElementInfo &elementInfo,
const int face )
const
512 if( gridFactory().globalProjection_ )
515 const unsigned int index = gridFactory().insertionIndex( elementInfo, face );
517 return bool( gridFactory().boundaryProjections_[ index ] );
524 return bool( gridFactory().globalProjection_ );
529 const unsigned int index = gridFactory().insertionIndex( elementInfo, face );
532 const DuneProjectionPtr &projection = gridFactory().boundaryProjections_[ index ];
537 assert( gridFactory().globalProjection_ );
538 return Projection( gridFactory().globalProjection_ );
543 assert( gridFactory().globalProjection_ );
544 return Projection( gridFactory().globalProjection_ );
558 #endif // #if HAVE_ALBERTA
560 #endif // #ifndef DUNE_ALBERTA_GRIDFACTORY_HH