dune-grid  2.1.1
coordcache.hh
Go to the documentation of this file.
00001 #ifndef DUNE_ALBERTA_COORDCACHE_HH
00002 #define DUNE_ALBERTA_COORDCACHE_HH
00003 
00004 #include <dune/grid/albertagrid/meshpointer.hh>
00005 #include <dune/grid/albertagrid/dofadmin.hh>
00006 #include <dune/grid/albertagrid/dofvector.hh>
00007 
00008 #if HAVE_ALBERTA
00009 
00010 namespace Dune
00011 {
00012 
00013   namespace Alberta
00014   {
00015 
00016     // CoordCache
00017     // ----------
00018 
00019     template< int dim >
00020     class CoordCache
00021     {
00022       typedef DofVectorPointer< GlobalVector > CoordVectorPointer;
00023       typedef Alberta::DofAccess< dim, dim > DofAccess;
00024 
00025       class LocalCaching;
00026       struct Interpolation;
00027 
00028     public:
00029       static const int dimension = dim;
00030 
00031       typedef Alberta::ElementInfo< dimension > ElementInfo;
00032       typedef Alberta::MeshPointer< dimension > MeshPointer;
00033       typedef HierarchyDofNumbering< dimension > DofNumbering;
00034 
00035       GlobalVector &operator() ( const Element *element, int vertex ) const
00036       {
00037         assert( !(!coords_) );
00038         GlobalVector *array = (GlobalVector *)coords_;
00039         return array[ dofAccess_( element, vertex ) ];
00040       }
00041 
00042       GlobalVector &operator() ( const ElementInfo &elementInfo, int vertex ) const
00043       {
00044         return (*this)( elementInfo.el(), vertex );
00045       }
00046 
00047       void create ( const DofNumbering &dofNumbering )
00048       {
00049         MeshPointer mesh = dofNumbering.mesh();
00050         const DofSpace *dofSpace = dofNumbering.dofSpace( dimension );
00051         
00052         coords_.create( dofSpace, "Coordinate Cache" );
00053         LocalCaching localCaching( coords_ );
00054         mesh.hierarchicTraverse( localCaching, FillFlags< dimension >::coords );
00055         coords_.template setupInterpolation< Interpolation >();
00056 
00057         dofAccess_ = DofAccess( dofSpace );
00058       }
00059 
00060       void release ()
00061       {
00062         coords_.release();
00063       }
00064 
00065     private:
00066       CoordVectorPointer coords_;
00067       DofAccess dofAccess_;
00068     };
00069 
00070 
00071 
00072     // CoordCache::LocalCaching
00073     // ------------------------
00074 
00075     template< int dim >
00076     class CoordCache< dim >::LocalCaching
00077     {
00078       CoordVectorPointer coords_;
00079       DofAccess dofAccess_;
00080 
00081     public:
00082       explicit LocalCaching ( const CoordVectorPointer &coords )
00083       : coords_( coords ),
00084         dofAccess_( coords.dofSpace() )
00085       {}
00086 
00087       void operator() ( const ElementInfo &elementInfo ) const
00088       {
00089         GlobalVector *array = (GlobalVector *)coords_;
00090         for( int i = 0; i < DofAccess::numSubEntities; ++i )
00091         {
00092           const GlobalVector &x = elementInfo.coordinate( i );
00093           GlobalVector &y = array[ dofAccess_( elementInfo.el(), i ) ];
00094           for( int i = 0; i < dimWorld; ++i )
00095             y[ i ] = x[ i ];
00096         }
00097       }
00098     };
00099 
00100 
00101 
00102     // CoordCache::Interpolation
00103     // -------------------------
00104 
00105     template< int dim >
00106     struct CoordCache< dim >::Interpolation
00107     {
00108       static const int dimension = dim;
00109 
00110       typedef Alberta::Patch< dimension > Patch;
00111 
00112       static void
00113       interpolateVector ( const CoordVectorPointer &dofVector, const Patch &patch )
00114       {
00115         DofAccess dofAccess( dofVector.dofSpace() );
00116         GlobalVector *array = (GlobalVector *)dofVector;
00117 
00118         const Element *element = patch[ 0 ];
00119 
00120         // new vertex is always the last one
00121         assert( element->child[ 0 ] != NULL );
00122         GlobalVector &newCoord = array[ dofAccess( element->child[ 0 ], dimension ) ];
00123 
00124         if( element->new_coord != NULL )
00125         {
00126           for( int j = 0; j < dimWorld; ++j )
00127             newCoord[ j ] = element->new_coord[ j ];
00128         }
00129         else
00130         {
00131           // new coordinate is the average of of old ones on the same edge
00132           // refinement edge is always between vertices 0 and 1
00133           const GlobalVector &coord0 = array[ dofAccess( element, 0 ) ];
00134           const GlobalVector &coord1 = array[ dofAccess( element, 1 ) ];
00135           for( int j = 0; j < dimWorld; ++j )
00136             newCoord[ j ] = 0.5 * (coord0[ j ] + coord1[ j ]);
00137         }
00138       }
00139     };
00140 
00141   }
00142 
00143 }
00144 
00145 #endif // #if HAVE_ALBERTA
00146 
00147 #endif // #ifndef DUNE_ALBERTA_COORDCACHE_HH