dune-grid  2.2beta1
dofadmin.hh
Go to the documentation of this file.
00001 #ifndef DUNE_ALBERTA_DOFADMIN_HH
00002 #define DUNE_ALBERTA_DOFADMIN_HH
00003 
00004 #include <dune/grid/albertagrid/misc.hh>
00005 #include <dune/grid/albertagrid/elementinfo.hh>
00006 
00007 #if HAVE_ALBERTA
00008 
00009 namespace Dune
00010 {
00011 
00012   namespace Alberta
00013   {
00014 
00015     // External Forward Declarations
00016     // -----------------------------
00017 
00018     template< int dim >
00019     class MeshPointer;
00020 
00021 
00022 
00023     // DofAccess
00024     // ---------
00025 
00026     template< int dim, int codim >
00027     class DofAccess
00028     {
00029       static const int codimtype = CodimType< dim, codim >::value;
00030 
00031     public:
00032       static const int numSubEntities = NumSubEntities< dim, codim >::value;
00033 
00034       static const int dimension = dim;
00035       static const int codimension = codim;
00036 
00037       typedef Alberta::ElementInfo< dimension > ElementInfo;
00038 
00039       DofAccess ()
00040       : node_( -1 )
00041       {}
00042 
00043       explicit DofAccess ( const DofSpace *dofSpace )
00044       {
00045         assert( dofSpace );
00046         node_ = dofSpace->admin->mesh->node[ codimtype ];
00047         index_ = dofSpace->admin->n0_dof[ codimtype ];
00048       }
00049 
00050       int operator() ( const Element *element, int subEntity, int i ) const
00051       {
00052         assert( element );
00053         assert( node_ != -1 );
00054         assert( subEntity < numSubEntities );
00055         return element->dof[ node_ + subEntity ][ index_ + i ];
00056       }
00057 
00058       int operator() ( const Element *element, int subEntity ) const
00059       {
00060         return (*this)( element, subEntity, 0 );
00061       }
00062 
00063       int operator() ( const ElementInfo &elementInfo, int subEntity, int i ) const
00064       {
00065         return (*this)( elementInfo.el(), subEntity, i );
00066       }
00067 
00068       int operator() ( const ElementInfo &elementInfo, int subEntity ) const
00069       {
00070         return (*this)( elementInfo.el(), subEntity );
00071       }
00072 
00073     private:
00074       int node_;
00075       int index_;
00076     };
00077 
00078 
00079 
00080     // HierarchyDofNumbering
00081     // ---------------------
00082 
00083     template< int dim >
00084     class HierarchyDofNumbering
00085     {
00086       typedef HierarchyDofNumbering< dim > This;
00087 
00088     public:
00089       static const int dimension = dim;
00090 
00091       typedef Alberta::MeshPointer< dimension > MeshPointer;
00092       typedef Alberta::ElementInfo< dimension > ElementInfo;
00093 
00094     private:
00095       static const int nNodeTypes = N_NODE_TYPES;
00096 
00097       template< int codim >
00098       struct CreateDofSpace;
00099 
00100       template< int codim >
00101       struct CacheDofSpace;
00102 
00103       typedef std::pair< int, int > Cache;
00104 
00105     public:
00106       HierarchyDofNumbering ()
00107       {}
00108 
00109     private:
00110       HierarchyDofNumbering ( const This & );
00111       This &operator= ( const This & );
00112 
00113     public:
00114       ~HierarchyDofNumbering ()
00115       {
00116         release();
00117       }
00118 
00119       int operator() ( const Element *element, int codim, unsigned int subEntity ) const
00120       {
00121         assert( !(*this) == false );
00122         assert( (codim >= 0) && (codim <= dimension) );
00123         const Cache &cache = cache_[ codim ];
00124         return element->dof[ cache.first + subEntity ][ cache.second ];
00125       }
00126 
00127       int operator() ( const ElementInfo &element, int codim, unsigned int subEntity ) const
00128       {
00129         return (*this)( element.el(), codim, subEntity );
00130       }
00131 
00132       operator bool () const
00133       {
00134         return (bool)mesh_;
00135       }
00136 
00137       const DofSpace *dofSpace ( int codim ) const
00138       {
00139         assert( *this );
00140         assert( (codim >= 0) && (codim <= dimension) );
00141         return dofSpace_[ codim ];
00142       }
00143 
00144       const DofSpace *emptyDofSpace () const
00145       {
00146         assert( *this );
00147         return emptySpace_;
00148       }
00149 
00150       const MeshPointer &mesh () const
00151       {
00152         return mesh_;
00153       }
00154 
00155       int size ( int codim ) const
00156       {
00157         return dofSpace( codim )->admin->size;
00158       }
00159 
00160       void create ( const MeshPointer &mesh );
00161 
00162       void release ()
00163       {
00164         if( *this )
00165         {
00166           for( int codim = 0; codim <= dimension; ++codim )
00167             freeDofSpace( dofSpace_[ codim ] );
00168           freeDofSpace( emptySpace_ );
00169           mesh_ = MeshPointer();
00170         }
00171       }
00172 
00173     private:
00174       static const DofSpace *createEmptyDofSpace ( const MeshPointer &mesh );
00175       static const DofSpace *createDofSpace ( const MeshPointer &mesh,
00176                                               const std::string &name,
00177                                               const int (&ndof)[ nNodeTypes ],
00178                                               const bool periodic = false );
00179       static void freeDofSpace ( const DofSpace *dofSpace );
00180 
00181       MeshPointer mesh_;
00182       const DofSpace *emptySpace_;
00183       const DofSpace *dofSpace_[ dimension+1 ];
00184       Cache cache_[ dimension+1 ];
00185     };
00186 
00187 
00188 
00189     template< int dim >
00190     inline void
00191     HierarchyDofNumbering< dim >::create ( const MeshPointer &mesh )
00192     {
00193       release();
00194 
00195       if( !mesh )
00196         return;
00197 
00198       mesh_ = mesh;
00199       ForLoop< CreateDofSpace, 0, dimension >::apply( mesh_, dofSpace_ );
00200       ForLoop< CacheDofSpace, 0, dimension >::apply( dofSpace_, cache_ );
00201 
00202       emptySpace_ = createEmptyDofSpace( mesh_ );
00203       for( int i = 0; i < nNodeTypes; ++i )
00204         assert( emptySpace_->admin->n_dof[ i ] == 0 );
00205     }
00206 
00207 
00208 
00209     template< int dim >
00210     inline const DofSpace *
00211     HierarchyDofNumbering< dim >::createEmptyDofSpace ( const MeshPointer &mesh )
00212     {
00213       int ndof[ nNodeTypes ];
00214       for( int i = 0; i < nNodeTypes; ++i )
00215         ndof[ i ] = 0;
00216       std::string name = "Empty";
00217       return createDofSpace( mesh, name, ndof );
00218     }
00219 
00220 
00221 #if DUNE_ALBERTA_VERSION >= 0x300
00222     template< int dim >
00223     inline const DofSpace *
00224     HierarchyDofNumbering< dim >::createDofSpace ( const MeshPointer &mesh,
00225                                                    const std::string &name,
00226                                                    const int (&ndof)[ nNodeTypes ],
00227                                                    const bool periodic )
00228     {
00229       const ALBERTA FLAGS flags
00230         = ADM_PRESERVE_COARSE_DOFS | (periodic ? ADM_PERIODIC : 0);
00231       return ALBERTA get_dof_space ( mesh, name.c_str(), ndof, flags );
00232     }
00233 #endif // #if DUNE_ALBERTA_VERSION >= 0x300
00234 
00235 #if DUNE_ALBERTA_VERSION == 0x200
00236     template< int dim >
00237     inline const DofSpace *
00238     HierarchyDofNumbering< dim >::createDofSpace ( const MeshPointer &mesh,
00239                                                    const std::string &name,
00240                                                    const int (&ndof)[ nNodeTypes ],
00241                                                    const bool periodic )
00242     {
00243       return ALBERTA get_fe_space( mesh, name.c_str(), ndof, NULL, 1 );
00244     }
00245 #endif // #if DUNE_ALBERTA_VERSION == 0x200
00246 
00247 
00248 #if DUNE_ALBERTA_VERSION >= 0x300
00249     template< int dim >
00250     inline void
00251     HierarchyDofNumbering< dim >::freeDofSpace ( const DofSpace *dofSpace )
00252     {
00253       ALBERTA free_fe_space( dofSpace );
00254     }
00255 #endif // #if DUNE_ALBERTA_VERSION >= 0x300
00256 
00257 #if DUNE_ALBERTA_VERSION == 0x200
00258     template< int dim >
00259     inline void
00260     HierarchyDofNumbering< dim >::freeDofSpace ( const DofSpace *dofSpace )
00261     {
00262       // the const cast is needed due to a bug in ALBERTA 2.0
00263       ALBERTA free_fe_space( const_cast< DofSpace * >( dofSpace ) );
00264     }
00265 #endif // #if DUNE_ALBERTA_VERSION == 0x200
00266 
00267 
00268 
00269     // HierarchyDofNumbering::CreateDofSpace
00270     // -------------------------------------
00271 
00272     template< int dim >
00273     template< int codim >
00274     struct HierarchyDofNumbering< dim >::CreateDofSpace
00275     {
00276       static void apply ( const MeshPointer &mesh, const DofSpace *(&dofSpace)[ dim+1 ] )
00277       {
00278         int ndof[ nNodeTypes ];
00279         for( int i = 0; i < nNodeTypes; ++i )
00280           ndof[ i ] = 0;
00281         ndof[ CodimType< dim, codim >::value ] = 1;
00282 
00283         std::string name = "Codimension ";
00284         name += (char)(codim + '0');
00285 
00286         dofSpace[ codim ] = createDofSpace( mesh, name, ndof );
00287         assert( dofSpace[ codim ] );
00288       }
00289     };
00290 
00291 
00292 
00293     // HierarchyDofNumbering::CacheDofSpace
00294     // ------------------------------------
00295 
00296     template< int dim >
00297     template< int codim >
00298     struct HierarchyDofNumbering< dim >::CacheDofSpace
00299     {
00300       static void apply ( const DofSpace *(&dofSpace)[ dim+1 ], Cache (&cache)[ dim+1 ] )
00301       {
00302         assert( dofSpace[ codim ] );
00303         const int codimtype = CodimType< dim, codim >::value;
00304         cache[ codim ].first = dofSpace[ codim ]->mesh->node[ codimtype ];
00305         cache[ codim ].second = dofSpace[ codim ]->admin->n0_dof[ codimtype ];
00306       }
00307     };
00308 
00309   } // namespace Alberta
00310 
00311 } // namespace Dune
00312 
00313 #endif // #if HAVE_ALBERTA
00314 
00315 #endif // #ifndef DUNE_ALBERTA_DOFADMIN_HH