dune-grid  2.1.1
alu3dgridfactory.hh
Go to the documentation of this file.
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_ALU3DGRID_FACTORY_HH
00005 #define DUNE_ALU3DGRID_FACTORY_HH
00006 
00007 #include <map>
00008 #include <vector>
00009 
00010 #ifdef ENABLE_ALUGRID
00011 
00012 #include <dune/common/array.hh>
00013 #include <dune/common/mpihelper.hh>
00014 
00015 #include <dune/grid/common/genericreferenceelements.hh>
00016 #include <dune/grid/common/gridfactory.hh>
00017 #include <dune/grid/common/boundaryprojection.hh>
00018 
00019 #include <dune/grid/alugrid/common/transformation.hh>
00020 #include <dune/grid/alugrid/3d/alugrid.hh>
00021 
00022 namespace Dune
00023 {
00024 
00026   template< class ALUGrid >
00027   class ALU3dGridFactory
00028   : public GridFactoryInterface< ALUGrid >
00029   {
00030     typedef ALU3dGridFactory< ALUGrid > ThisType;
00031     typedef GridFactoryInterface< ALUGrid > BaseType;
00032 
00033   public:
00034     typedef ALUGrid Grid;
00035 
00036     typedef typename Grid::ctype ctype;
00037 
00038     static const ALU3dGridElementType elementType = Grid::elementType;
00039 
00040     static const unsigned int dimension = Grid::dimension;
00041     static const unsigned int dimensionworld = Grid::dimensionworld;
00042 
00043     typedef typename Grid::MPICommunicatorType MPICommunicatorType;
00044 
00046     typedef DuneBoundaryProjection< 3 >  DuneBoundaryProjectionType;
00047 
00048     template< int codim >
00049     struct Codim
00050     {
00051       typedef typename Grid::template Codim< codim >::Entity Entity;
00052     };
00053 
00054     typedef ALUGridTransformation< ctype, dimensionworld > Transformation;
00055 
00057     typedef typename Transformation::WorldVector WorldVector;
00059     typedef typename Transformation::WorldMatrix WorldMatrix;
00060 
00061   private:
00062     dune_static_assert( (elementType == tetra || elementType == hexa),
00063                         "ALU3dGridFactory supports only grids containing "
00064                         "tetrahedrons or hexahedrons exclusively." );
00065 
00066     typedef Dune::BoundarySegmentWrapper< dimension, dimensionworld > BoundarySegmentWrapperType;
00067 
00068     static const unsigned int numCorners = EntityCount< elementType >::numVertices;
00069     static const unsigned int numFaces = EntityCount< elementType >::numFaces;
00070     static const unsigned int numFaceCorners = EntityCount< elementType >::numVerticesPerFace;
00071     
00072     typedef ElementTopologyMapping< elementType > ElementTopologyMappingType;
00073     typedef FaceTopologyMapping< elementType > FaceTopologyMappingType;
00074 
00075     typedef FieldVector< ctype, dimensionworld > VertexType;
00076     typedef std::vector< unsigned int > ElementType;
00077     typedef array< unsigned int, numFaceCorners > FaceType;
00078 
00079     struct FaceLess;
00080 
00081     typedef std::vector< VertexType > VertexVector;
00082     typedef std::vector< ElementType > ElementVector;
00083     typedef std::vector< std::pair< FaceType, int > > BoundaryIdVector;
00084     typedef std::vector< std::pair< FaceType, FaceType > > PeriodicBoundaryVector;
00085     typedef std::pair< unsigned int, int > SubEntity;
00086     typedef std::map< FaceType, SubEntity, FaceLess > FaceMap;
00087 
00088     typedef std::map< FaceType, const DuneBoundaryProjectionType* > BoundaryProjectionMap;
00089     typedef std::vector< const DuneBoundaryProjectionType* > BoundaryProjectionVector;
00090 
00091     typedef std::vector< Transformation > FaceTransformationVector;
00092 
00093     // copy vertex numbers and store smalled #dimension ones 
00094     void copyAndSort ( const std::vector< unsigned int > &vertices, FaceType &faceId ) const
00095     {
00096       std::vector<unsigned int> tmp( vertices );
00097       std::sort( tmp.begin(), tmp.end() );
00098 
00099       // copy only the first dimension vertices (enough for key)
00100       for( size_t i = 0; i < faceId.size(); ++i ) faceId[ i ] = tmp[ i ];
00101     }
00102 
00103   private:
00104     // return grid object 
00105     virtual Grid* createGridObj( BoundaryProjectionVector* bndProjections, const std::string& name ) const
00106     {
00107       return ( allowGridGeneration_ ) ?
00108               new Grid( communicator_, globalProjection_, bndProjections , name, realGrid_ ) :
00109               new Grid( communicator_ );
00110     }
00111 
00112   public:
00114     explicit ALU3dGridFactory ( const MPICommunicatorType &communicator = Grid::defaultCommunicator(),
00115                                 bool removeGeneratedFile = true );
00116 
00118     explicit ALU3dGridFactory ( const std::string &filename, 
00119                                 const MPICommunicatorType &communicator = Grid::defaultCommunicator() );
00120 
00122     explicit ALU3dGridFactory ( const bool verbose, const MPICommunicatorType &communicator );
00123 
00125     virtual ~ALU3dGridFactory ();
00126 
00131     virtual void insertVertex ( const VertexType &pos );
00132 
00141     virtual void
00142     insertElement ( const GeometryType &geometry,
00143                     const std::vector< unsigned int > &vertices );
00144 
00155     virtual void
00156     insertBoundary ( const GeometryType &geometry,
00157                      const std::vector< unsigned int > &faceVertices,
00158                      const int id );
00159 
00166     virtual void insertBoundary ( const int element, const int face, const int id );
00167 
00176     virtual void
00177     insertBoundaryProjection ( const GeometryType &type,
00178                                const std::vector< unsigned int > &vertices,
00179                                const DuneBoundaryProjectionType *projection );
00180 
00185     virtual void
00186     insertBoundarySegment ( const std::vector< unsigned int >& vertices ) ;
00187 
00193     virtual void
00194     insertBoundarySegment ( const std::vector< unsigned int >& vertices,
00195                             const shared_ptr<BoundarySegment<3,3> >& boundarySegment ) ;
00196 
00201     virtual void insertBoundaryProjection ( const DuneBoundaryProjectionType& bndProjection );
00202 
00212     void insertFaceTransformation ( const WorldMatrix &matrix, const WorldVector &shift );
00213 
00218     Grid *createGrid ();
00219 
00220     Grid *createGrid ( const bool addMissingBoundaries, const std::string dgfName = "" );
00221 
00222     Grid *createGrid ( const bool addMissingBoundaries, bool temporary, const std::string dgfName = "" );
00223 
00224     virtual unsigned int
00225     insertionIndex ( const typename Codim< 0 >::Entity &entity ) const
00226     {
00227       return Grid::getRealImplementation( entity ).getIndex();
00228     }
00229     virtual unsigned int
00230     insertionIndex ( const typename Codim< dimension >::Entity &entity ) const
00231     {
00232       return Grid::getRealImplementation( entity ).getIndex();
00233     }
00234     virtual unsigned int
00235     insertionIndex ( const typename Grid::LeafIntersection &intersection ) const
00236     {
00237       return intersection.boundarySegmentIndex();
00238     }
00239     virtual bool
00240     wasInserted ( const typename Grid::LeafIntersection &intersection ) const
00241     {
00242       return intersection.boundary() &&
00243         ( insertionIndex(intersection) < numFacesInserted_ );
00244     }
00245 
00246   private:
00247     void assertGeometryType( const GeometryType &geometry );
00248     static void generateFace ( const ElementType &element, const int f, FaceType &face );
00249     void generateFace ( const SubEntity &subEntity, FaceType &face ) const;
00250     void correctElementOrientation ();
00251     bool identifyFaces ( const Transformation &transformation, const FaceType &key1, const FaceType &key2 );
00252     void searchPeriodicNeighbor ( FaceMap &faceMap, const typename FaceMap::iterator &pos );
00253     void reinsertBoundary ( const FaceMap &faceMap, const typename FaceMap::const_iterator &pos, const int id );
00254     void recreateBoundaryIds ( const int defaultId = 1 );
00255 
00256     int rank_;
00257 
00258     VertexVector vertices_;
00259     ElementVector elements_;
00260     BoundaryIdVector boundaryIds_;
00261     PeriodicBoundaryVector periodicBoundaries_;
00262     const DuneBoundaryProjectionType* globalProjection_ ; 
00263     BoundaryProjectionMap boundaryProjections_;
00264     FaceTransformationVector faceTransformations_;
00265     unsigned int numFacesInserted_;
00266     bool realGrid_;
00267     const bool allowGridGeneration_;
00268 
00269     MPICommunicatorType communicator_;
00270   };
00271 
00272 
00273 
00274   template< class ALUGrid >
00275   struct ALU3dGridFactory< ALUGrid >::FaceLess
00276   : public std::binary_function< FaceType, FaceType, bool >
00277   {
00278     bool operator() ( const FaceType &a, const FaceType &b ) const
00279     {
00280       for( unsigned int i = 0; i < numFaceCorners; ++i )
00281       {
00282         if( a[ i ] != b[ i ] )
00283           return (a[ i ] < b[ i ]);
00284       }
00285       return false;
00286     }
00287   };
00288 
00289 
00290   template< class ALUGrid >
00291   inline void ALU3dGridFactory< ALUGrid >
00292     ::assertGeometryType( const GeometryType &geometry )
00293   {
00294     if( elementType == tetra )
00295     {
00296       if( !geometry.isSimplex() )
00297         DUNE_THROW( GridError, "Only simplex geometries can be inserted into "
00298                                "ALUSimplexGrid< 3, 3 >." );
00299     }
00300     else
00301     {
00302       if( !geometry.isCube() )
00303         DUNE_THROW( GridError, "Only cube geometries can be inserted into "
00304                                "ALUCubeGrid< 3, 3 >." );
00305     }
00306   }
00307   
00308 
00312   template<>
00313   class GridFactory< ALUSimplexGrid< 3, 3 > >
00314   : public ALU3dGridFactory< ALUSimplexGrid< 3, 3 > >
00315   {
00316     typedef GridFactory< ALUSimplexGrid< 3, 3 > > ThisType;
00317     typedef ALU3dGridFactory< ALUSimplexGrid< 3, 3 > > BaseType;
00318 
00319   public:
00320     typedef BaseType::Grid Grid;
00321 
00322     typedef BaseType::MPICommunicatorType MPICommunicatorType;
00323 
00325     explicit GridFactory ( const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00326     : BaseType( communicator )
00327     {}
00328 
00330     GridFactory ( const std::string &filename, 
00331                   const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00332     : BaseType( filename, communicator )
00333     {}
00334 
00335   protected:  
00336     template< class, class, int > friend class ALULocalGeometryStorage;
00338     GridFactory ( const bool realGrid, 
00339                   const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00340     : BaseType( realGrid, communicator )
00341     {}
00342   };
00343 
00344 
00345 
00349   template<>
00350   class GridFactory< ALUCubeGrid< 3, 3 > >
00351   : public ALU3dGridFactory< ALUCubeGrid< 3, 3 > >
00352   {
00353     typedef GridFactory< ALUCubeGrid< 3, 3 > > ThisType;
00354     typedef ALU3dGridFactory< ALUCubeGrid< 3, 3 > > BaseType;
00355 
00356   public:
00357     typedef BaseType::Grid Grid;
00358 
00359     typedef BaseType::MPICommunicatorType MPICommunicatorType;
00360 
00362     explicit GridFactory ( const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00363     : BaseType( communicator )
00364     {}
00365     
00367     GridFactory ( const std::string &filename, 
00368                   const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00369     : BaseType( filename, communicator )
00370     {}
00371 
00372   protected:  
00373     template< class, class, int > friend class ALULocalGeometryStorage;
00375     GridFactory ( const bool realGrid, 
00376                   const MPICommunicatorType &communicator = Grid::defaultCommunicator() )
00377     : BaseType( realGrid, communicator )
00378     {}
00379   };
00380 
00381 
00382 
00383   // Implementation of ALU3dGridFactory
00384   // ----------------------------------
00385 
00386   template< class ALUGrid >
00387   inline 
00388   ALU3dGridFactory< ALUGrid >
00389     :: ALU3dGridFactory ( const MPICommunicatorType &communicator,
00390                           bool removeGeneratedFile )
00391   : rank_( ALU3dGridCommunications< elementType, MPICommunicatorType >::getRank( communicator ) ),
00392     globalProjection_ ( 0 ),
00393     numFacesInserted_ ( 0 ),
00394     realGrid_( true ),
00395     allowGridGeneration_( rank_ == 0 ),
00396     communicator_( communicator )
00397   {}
00398 
00399   template< class ALUGrid >
00400   inline 
00401   ALU3dGridFactory< ALUGrid >
00402     :: ALU3dGridFactory ( const std::string &filename,
00403                           const MPICommunicatorType &communicator )
00404   : rank_( ALU3dGridCommunications< elementType, MPICommunicatorType >::getRank( communicator ) ),
00405     globalProjection_ ( 0 ),
00406     numFacesInserted_ ( 0 ),
00407     realGrid_( true ),
00408     allowGridGeneration_( rank_ == 0 ),
00409     communicator_( communicator )
00410   {}
00411 
00412   template< class ALUGrid >
00413   inline 
00414   ALU3dGridFactory< ALUGrid >
00415     :: ALU3dGridFactory ( const bool realGrid, 
00416                           const MPICommunicatorType &communicator )
00417   : rank_( ALU3dGridCommunications< elementType, MPICommunicatorType >::getRank( communicator ) ),
00418     globalProjection_ ( 0 ),
00419     numFacesInserted_ ( 0 ),
00420     realGrid_( realGrid ),
00421     allowGridGeneration_( true ),
00422     communicator_( communicator )
00423   {}
00424 
00425   template< class ALUGrid >
00426   inline void ALU3dGridFactory< ALUGrid > ::
00427   insertBoundarySegment ( const std::vector< unsigned int >& vertices )
00428   {
00429     FaceType faceId;
00430     copyAndSort( vertices, faceId );
00431 
00432     if( vertices.size() != numFaceCorners )
00433       DUNE_THROW( GridError, "Wrong number of face vertices passed: " << vertices.size() << "." );
00434 
00435     if( boundaryProjections_.find( faceId ) != boundaryProjections_.end() )
00436       DUNE_THROW( GridError, "Only one boundary projection can be attached to a face." );
00437     //  DUNE_THROW( NotImplemented, "insertBoundarySegment with a single argument" );
00438 
00439     boundaryProjections_[ faceId ] = 0;
00440 
00441     std::pair< FaceType, int > boundaryId;
00442     for( unsigned int i = 0; i < numFaceCorners; ++i )
00443     {
00444       const unsigned int j = FaceTopologyMappingType::dune2aluVertex( i );
00445       boundaryId.first[ j ] = vertices[ i ];
00446     }
00447     boundaryId.second = 1;
00448     boundaryIds_.push_back( boundaryId );
00449   }
00450 
00451   template< class ALUGrid >
00452   inline void ALU3dGridFactory< ALUGrid > ::
00453   insertBoundarySegment ( const std::vector< unsigned int >& vertices,
00454                           const shared_ptr<BoundarySegment<3,3> >& boundarySegment )
00455   {
00456     FaceType faceId;
00457     copyAndSort( vertices, faceId );
00458 
00459     if( vertices.size() != numFaceCorners )
00460       DUNE_THROW( GridError, "Wrong number of face vertices passed: " << vertices.size() << "." );
00461 
00462     if( boundaryProjections_.find( faceId ) != boundaryProjections_.end() )
00463       DUNE_THROW( GridError, "Only one boundary projection can be attached to a face." );
00464 
00465     const size_t numVx = vertices.size();
00466     GeometryType type;
00467     if( numVx == 3 )
00468       type.makeSimplex( dimension-1 );
00469     else  
00470       type.makeCube( dimension-1 );
00471 
00472     // we need double here because of the structure of BoundarySegment
00473     // and BoundarySegmentWrapper which have double as coordinate type
00474     typedef FieldVector< double, dimensionworld > CoordType;
00475     std::vector< CoordType > coords( numVx );
00476     for( size_t i = 0; i < numVx; ++i )
00477     {
00478       // if this assertions is thrown vertices were not inserted at first 
00479       assert( vertices_.size() > vertices[ i ] );
00480 
00481       // get global coordinate and copy it 
00482       const VertexType &x = vertices_[ vertices[ i ] ];
00483       for( unsigned int j = 0; j < dimensionworld; ++j )
00484         coords[ i ][ j ] = x[ j ];
00485     }
00486 
00487     BoundarySegmentWrapperType* prj
00488       = new BoundarySegmentWrapperType( type, coords, boundarySegment );
00489     boundaryProjections_[ faceId ] = prj;
00490 #ifndef NDEBUG 
00491     // consistency check 
00492     for( size_t i = 0; i < numVx; ++i )
00493     {
00494       CoordType global = (*prj)( coords [ i ] );
00495       if( (global - coords[ i ]).two_norm() > 1e-6 )
00496         DUNE_THROW(GridError,"BoundarySegment does not map face vertices to face vertices.");
00497     }
00498 #endif
00499 
00500     std::pair< FaceType, int > boundaryId;
00501     for( unsigned int i = 0; i < numFaceCorners; ++i )
00502     {
00503       const unsigned int j = FaceTopologyMappingType::dune2aluVertex( i );
00504       boundaryId.first[ j ] = vertices[ i ];
00505     }
00506     boundaryId.second = 1;
00507     boundaryIds_.push_back( boundaryId );
00508   }
00509 
00510 
00511   template< class ALUGrid >
00512   inline void ALU3dGridFactory< ALUGrid >
00513     ::generateFace ( const SubEntity &subEntity, FaceType &face ) const
00514   {
00515     generateFace( elements_[ subEntity.first ], subEntity.second, face );
00516   }
00517 
00518 } // end namespace Dune
00519 
00520 #endif // #ifdef ENABLE_ALUGRID
00521 
00522 #if COMPILE_ALUGRID_INLINE
00523   #include "alu3dgridfactory.cc"
00524 #endif
00525 #endif