dune-grid  2.1.1
level.hh
Go to the documentation of this file.
00001 #ifndef DUNE_ALBERTA_LEVEL_HH
00002 #define DUNE_ALBERTA_LEVEL_HH
00003 
00004 #include <cassert>
00005 #include <cstdlib>
00006 
00007 #include <dune/grid/albertagrid/meshpointer.hh>
00008 #include <dune/grid/albertagrid/dofadmin.hh>
00009 #include <dune/grid/albertagrid/dofvector.hh>
00010 
00011 #if HAVE_ALBERTA
00012 
00013 namespace Dune
00014 {
00015 
00016   // AlbertaGridLevelProvider
00017   // ------------------------
00018 
00019   template< int dim >
00020   class AlbertaGridLevelProvider
00021   {
00022     typedef AlbertaGridLevelProvider< dim > This;
00023 
00024     typedef unsigned char Level;
00025 
00026     typedef Alberta::DofVectorPointer< Level > DofVectorPointer;
00027     typedef Alberta::DofAccess< dim, 0 > DofAccess;
00028 
00029     typedef Alberta::FillFlags< dim > FillFlags;
00030 
00031     static const Level isNewFlag = (1 << 7);
00032     static const Level levelMask = (1 << 7) - 1;
00033 
00034     struct SetLocal;
00035     struct CalcMaxLevel;
00036 
00037     template< Level flags >
00038     struct ClearFlags;
00039 
00040     struct Interpolation;
00041 
00042   public:
00043     typedef Alberta::ElementInfo< dim > ElementInfo;
00044     typedef Alberta::MeshPointer< dim > MeshPointer;
00045     typedef Alberta::HierarchyDofNumbering< dim > DofNumbering;
00046 
00047   private:
00048     DofVectorPointer level_;
00049     DofAccess dofAccess_;
00050 
00051   public:
00052     Level operator() ( const Alberta::Element *element ) const
00053     {
00054       const Level *array = (Level *)level_;
00055       return array[ dofAccess_( element, 0 ) ] & levelMask;
00056     }
00057 
00058     Level operator() ( const ElementInfo &elementInfo ) const
00059     {
00060       return (*this)( elementInfo.el() );
00061     }
00062 
00063     bool isNew ( const Alberta::Element *element ) const
00064     {
00065       const Level *array = (Level *)level_;
00066       return ((array[ dofAccess_( element, 0 ) ] & isNewFlag) != 0);
00067     }
00068 
00069     bool isNew ( const ElementInfo &elementInfo ) const
00070     {
00071       return isNew( elementInfo.el() );
00072     }
00073 
00074     Level maxLevel () const
00075     {
00076       CalcMaxLevel calcFromCache;
00077       level_.forEach( calcFromCache );
00078 #ifndef NDEBUG
00079       CalcMaxLevel calcFromGrid;
00080       mesh().leafTraverse( calcFromGrid, FillFlags::nothing );
00081       assert( calcFromCache.maxLevel() == calcFromGrid.maxLevel() );
00082 #endif
00083       return calcFromCache.maxLevel();;
00084     }
00085 
00086     MeshPointer mesh () const
00087     {
00088       return MeshPointer( level_.dofSpace()->mesh );
00089     }
00090 
00091     void markAllOld ()
00092     {
00093       ClearFlags< isNewFlag > clearIsNew;
00094       level_.forEach( clearIsNew );
00095     }
00096 
00097     void create ( const DofNumbering &dofNumbering )
00098     {
00099       const Alberta::DofSpace *const dofSpace = dofNumbering.dofSpace( 0 );
00100       dofAccess_ = DofAccess( dofSpace );
00101 
00102       level_.create( dofSpace, "Element level" );
00103       assert( !(!level_) );
00104       level_.template setupInterpolation< Interpolation >();
00105 
00106       SetLocal setLocal( level_ );
00107       mesh().hierarchicTraverse( setLocal, FillFlags::nothing );
00108     }
00109 
00110     void release ()
00111     {
00112       level_.release();
00113       dofAccess_ = DofAccess();
00114     }
00115   };
00116 
00117 
00118 
00119   // AlbertaGridLevelProvider::SetLocal
00120   // ----------------------------------
00121 
00122   template< int dim >
00123   class AlbertaGridLevelProvider< dim >::SetLocal
00124   {
00125     DofVectorPointer level_;
00126     DofAccess dofAccess_;
00127 
00128   public:
00129     explicit SetLocal ( const DofVectorPointer &level )
00130     : level_( level ),
00131       dofAccess_( level.dofSpace() )
00132     {}
00133 
00134     void operator() ( const Alberta::ElementInfo< dim > &elementInfo ) const
00135     {
00136       Level *const array = (Level *)level_;
00137       array[ dofAccess_( elementInfo, 0 ) ] = elementInfo.level();
00138     }
00139   };
00140 
00141 
00142 
00143   // AlbertaGridLevelProvider::CalcMaxLevel
00144   // --------------------------------------
00145 
00146   template< int dim >
00147   class AlbertaGridLevelProvider< dim >::CalcMaxLevel
00148   {
00149     Level maxLevel_;
00150 
00151   public:
00152     CalcMaxLevel ()
00153     : maxLevel_( 0 )
00154     {}
00155 
00156     void operator() ( const Level &dof )
00157     {
00158       maxLevel_ = std::max( maxLevel_, Level( dof & levelMask ) );
00159     }
00160 
00161     void operator() ( const Alberta::ElementInfo< dim > &elementInfo )
00162     {
00163       maxLevel_ = std::max( maxLevel_, Level( elementInfo.level() ) );
00164     }
00165 
00166     Level maxLevel () const
00167     {
00168       return maxLevel_;
00169     }
00170   };
00171 
00172 
00173 
00174   // AlbertaGridLevelProvider::ClearFlags
00175   // ------------------------------------
00176 
00177   template< int dim >
00178   template< typename AlbertaGridLevelProvider< dim >::Level flags >
00179   struct AlbertaGridLevelProvider< dim >::ClearFlags
00180   {
00181     void operator() ( Level &dof ) const
00182     {
00183       dof &= ~flags;
00184     }
00185   };
00186 
00187 
00188 
00189   // AlbertaGridLevelProvider::Interpolation
00190   // ---------------------------------------
00191 
00192   template< int dim >
00193   struct AlbertaGridLevelProvider< dim >::Interpolation
00194   {
00195     static const int dimension = dim;
00196 
00197     typedef Alberta::Patch< dimension > Patch;
00198 
00199     static void interpolateVector ( const DofVectorPointer &dofVector,
00200                                     const Patch &patch )
00201     {
00202       const DofAccess dofAccess( dofVector.dofSpace() );
00203       Level *array = (Level *)dofVector;
00204 
00205       for( int i = 0; i < patch.count(); ++i )
00206       {
00207         const Alberta::Element *const father = patch[ i ];
00208         assert( (array[ dofAccess( father, 0 ) ] & levelMask) < levelMask );
00209         const Level childLevel = (array[ dofAccess( father, 0 ) ] + 1) | isNewFlag;
00210         for( int i = 0; i < 2; ++i )
00211         {
00212           const Alberta::Element *child = father->child[ i ];
00213           array[ dofAccess( child, 0 ) ] = childLevel;
00214         }
00215       }
00216     }
00217   };
00218 
00219 }
00220 
00221 #endif // #if HAVE_ALBERTA
00222 
00223 #endif