coordcache.hh
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 template< int dim >
00017 class CoordCache
00018 {
00019 typedef DofVectorPointer< GlobalVector > CoordVectorPointer;
00020 typedef Alberta::DofAccess< dim, dim > DofAccess;
00021
00022 class LocalCaching;
00023 struct Interpolation;
00024
00025 public:
00026 static const int dimension = dim;
00027
00028 typedef Alberta::ElementInfo< dimension > ElementInfo;
00029 typedef Alberta::MeshPointer< dimension > MeshPointer;
00030 typedef HierarchyDofNumbering< dimension > DofNumbering;
00031
00032 private:
00033 CoordVectorPointer coords_;
00034 DofAccess dofAccess_;
00035
00036 public:
00037 GlobalVector &operator() ( const Element *element, int vertex ) const
00038 {
00039 assert( !(!coords_) );
00040 GlobalVector *array = (GlobalVector *)coords_;
00041 return array[ dofAccess_( element, vertex ) ];
00042 }
00043
00044 GlobalVector &operator() ( const ElementInfo &elementInfo, int vertex ) const
00045 {
00046 return (*this)( elementInfo.el(), vertex );
00047 }
00048
00049 void create ( const DofNumbering &dofNumbering )
00050 {
00051 MeshPointer mesh = dofNumbering.mesh();
00052 const DofSpace *dofSpace = dofNumbering.dofSpace( dimension );
00053
00054 coords_.create( dofSpace, "Coordinate Cache" );
00055 LocalCaching localCaching( coords_ );
00056 mesh.hierarchicTraverse( localCaching, FillFlags< dimension >::coords );
00057 coords_.template setupInterpolation< Interpolation >();
00058
00059
00060 dofAccess_ = DofAccess( dofSpace );
00061 }
00062
00063 void release ()
00064 {
00065 coords_.release();
00066 }
00067 };
00068
00069
00070
00071
00072
00073
00074 template< int dim >
00075 class CoordCache< dim >::LocalCaching
00076 {
00077 CoordVectorPointer coords_;
00078 DofAccess dofAccess_;
00079
00080 public:
00081 explicit LocalCaching ( const CoordVectorPointer &coords )
00082 : coords_( coords ),
00083 dofAccess_( coords.dofSpace() )
00084 {}
00085
00086 void operator() ( const ElementInfo &elementInfo ) const
00087 {
00088 GlobalVector *array = (GlobalVector *)coords_;
00089 for( int i = 0; i < DofAccess::numSubEntities; ++i )
00090 {
00091 const GlobalVector &x = elementInfo.coordinate( i );
00092 GlobalVector &y = array[ dofAccess_( elementInfo.el(), i ) ];
00093 for( int i = 0; i < dimWorld; ++i )
00094 y[ i ] = x[ i ];
00095 }
00096 }
00097 };
00098
00099
00100
00101
00102
00103
00104 template< int dim >
00105 struct CoordCache< dim >::Interpolation
00106 {
00107 static const int dimension = dim;
00108
00109 typedef Alberta::Patch< dimension > Patch;
00110
00111 static void
00112 interpolateVector ( const CoordVectorPointer &dofVector, const Patch &patch )
00113 {
00114 DofAccess dofAccess( dofVector.dofSpace() );
00115 GlobalVector *array = (GlobalVector *)dofVector;
00116
00117
00118 const Element *element = patch[ 0 ];
00119 const GlobalVector &coord0 = array[ dofAccess( element, 0 ) ];
00120 const GlobalVector &coord1 = array[ dofAccess( element, 1 ) ];
00121
00122
00123 assert( element->child[ 0 ] != NULL );
00124 GlobalVector &newCoord = array[ dofAccess( element->child[ 0 ], dimension ) ];
00125
00126
00127 for( int j = 0; j < dimWorld; ++j )
00128 newCoord[ j ] = 0.5 * (coord0[ j ] + coord1[ j ]);
00129 }
00130 };
00131
00132 }
00133
00134 }
00135
00136 #endif // #if HAVE_ALBERTA
00137
00138 #endif