00001 #ifndef DUNE_EQUIDISTANTPOINTS_HH
00002 #define DUNE_EQUIDISTANTPOINTS_HH
00003
00004 #include <vector>
00005
00006 #include <dune/common/fvector.hh>
00007 #include <dune/localfunctions/utility/field.hh>
00008 #include <dune/common/forloop.hh>
00009 #include <dune/grid/common/topologyfactory.hh>
00010 #include <dune/grid/genericgeometry/topologytypes.hh>
00011 #include <dune/grid/genericgeometry/subtopologies.hh>
00012
00013 #include <dune/localfunctions/lagrange/emptypoints.hh>
00014
00015 namespace Dune
00016 {
00017
00018
00019
00020
00021 template< class F, unsigned int dim >
00022 class EquidistantPointSet;
00023
00024
00025
00026
00027 template< class Topology, class F >
00028 class EquidistantPointSetImpl;
00029
00030 template< class F >
00031 class EquidistantPointSetImpl< GenericGeometry::Point, F >
00032 {
00033 typedef EquidistantPointSetImpl< GenericGeometry::Point, F > This;
00034
00035 typedef GenericGeometry::Point Topology;
00036
00037 friend class EquidistantPointSet< F, Topology::dimension >;
00038 friend class EquidistantPointSetImpl< GenericGeometry::Prism< Topology >, F >;
00039 friend class EquidistantPointSetImpl< GenericGeometry::Pyramid< Topology >, F >;
00040
00041 public:
00042 typedef F Field;
00043
00044 static const unsigned int dimension = Topology::dimension;
00045
00046 static unsigned int size ( const unsigned int order )
00047 {
00048 return 1;
00049 }
00050
00051 private:
00052 template< unsigned int codim, unsigned int dim >
00053 static unsigned int setup ( const unsigned int order,
00054 unsigned int *count,
00055 LagrangePoint< Field, dim > *points )
00056 {
00057 assert( codim == 0 );
00058 points->localKey_ = LocalKey( 0, 0, count[ 0 ]++ );
00059 points->point_ = Field( 0 );
00060 return 1;
00061 }
00062 };
00063
00064 template< class BaseTopology, class F >
00065 class EquidistantPointSetImpl< GenericGeometry::Prism< BaseTopology >, F >
00066 {
00067 typedef EquidistantPointSetImpl< GenericGeometry::Prism< BaseTopology >, F > This;
00068
00069 typedef GenericGeometry::Prism< BaseTopology > Topology;
00070
00071 friend class EquidistantPointSet< F, Topology::dimension >;
00072 friend class EquidistantPointSetImpl< GenericGeometry::Prism< Topology >, F >;
00073 friend class EquidistantPointSetImpl< GenericGeometry::Pyramid< Topology >, F >;
00074
00075 typedef EquidistantPointSetImpl< BaseTopology, F > BaseImpl;
00076
00077 public:
00078 typedef F Field;
00079
00080 static const unsigned int dimension = Topology::dimension;
00081
00082 static unsigned int size ( const unsigned int order )
00083 {
00084 return BaseImpl::size( order ) * (order+1);
00085 }
00086
00087
00088 template< unsigned int codim, unsigned int dim >
00089 static unsigned int setup ( const unsigned int order,
00090 unsigned int *count,
00091 LagrangePoint< Field, dim > *points )
00092 {
00093 unsigned int size = 0;
00094 unsigned int numBaseN = 0;
00095
00096 if( codim < dimension )
00097 {
00098 const unsigned int vcodim = (codim < dimension ? codim : dimension-1);
00099 numBaseN = GenericGeometry::Size< BaseTopology, vcodim >::value;
00100 for( unsigned int i = 1; i < order; ++i )
00101 {
00102 const unsigned int n = BaseImpl::template setup< vcodim, dim >( order, count, points );
00103 for( unsigned int j = 0; j < n; ++j )
00104 {
00105 LocalKey &key = points->localKey_;
00106 key = LocalKey( key.subEntity(), codim, key.index() );
00107 points->point_[ dimension-1 ] = Field( i ) / Field( order );
00108 ++points;
00109 }
00110 size += n;
00111 }
00112 }
00113
00114 if( codim > 0 )
00115 {
00116 const unsigned int vcodim = (codim > 0 ? codim : 1);
00117 const unsigned int numBaseM = GenericGeometry::Size< BaseTopology, vcodim-1 >::value;
00118 const unsigned int n = BaseImpl::template setup< vcodim-1, dim >( order, count+numBaseN, points );
00119 for( unsigned int j = 0; j < n; ++j )
00120 {
00121 LocalKey &key = points[ j ].localKey_;
00122 key = LocalKey( key.subEntity() + numBaseN, codim, key.index() );
00123 points[ j + n ].point_ = points[ j ].point_;
00124 points[ j + n ].point_[ dimension-1 ] = Field( 1 );
00125 points[ j + n ].localKey_ = LocalKey( key.subEntity() + numBaseM, codim, key.index() );
00126 ++count[ key.subEntity() + numBaseM ];
00127 }
00128 size += 2*n;
00129 }
00130 return size;
00131 }
00132 };
00133
00134 template< class BaseTopology, class F >
00135 class EquidistantPointSetImpl< GenericGeometry::Pyramid< BaseTopology >, F >
00136 {
00137 typedef EquidistantPointSetImpl< GenericGeometry::Pyramid< BaseTopology >, F > This;
00138
00139 typedef GenericGeometry::Pyramid< BaseTopology > Topology;
00140
00141 friend class EquidistantPointSet< F, Topology::dimension >;
00142 friend class EquidistantPointSetImpl< GenericGeometry::Prism< Topology >, F >;
00143 friend class EquidistantPointSetImpl< GenericGeometry::Pyramid< Topology >, F >;
00144
00145 typedef EquidistantPointSetImpl< BaseTopology, F > BaseImpl;
00146
00147 public:
00148 typedef F Field;
00149
00150 static const unsigned int dimension = Topology::dimension;
00151
00152 static unsigned int size ( const unsigned int order )
00153 {
00154 unsigned int size = BaseImpl::size( order );
00155 for( unsigned int i = 1; i <= order; ++i )
00156 size += BaseImpl::size( order - i );
00157 return size;
00158 }
00159
00160
00161 template< unsigned int codim, unsigned int dim >
00162 static unsigned int setup ( const unsigned int order,
00163 unsigned int *count,
00164 LagrangePoint< Field, dim > *points )
00165 {
00166 unsigned int size = 0;
00167 unsigned int numBaseM = 0;
00168
00169 if( codim > 0 )
00170 {
00171 const unsigned int vcodim = (codim > 0 ? codim : 1);
00172 numBaseM = GenericGeometry::Size< BaseTopology, vcodim-1 >::value;
00173 size = BaseImpl::template setup< vcodim-1, dim >( order, count, points );
00174 LagrangePoint< Field, dim > *const end = points + size;
00175 for( ; points != end; ++points )
00176 {
00177 LocalKey &key = points->localKey_;
00178 key = LocalKey( key.subEntity(), codim, key.index() );
00179 }
00180 }
00181
00182 if( codim < dimension )
00183 {
00184 const unsigned int vcodim = (codim < dimension ? codim : dimension-1);
00185 for( unsigned int i = order-1; i > 0; --i )
00186 {
00187 const unsigned int n = BaseImpl::template setup< vcodim, dim >( i, count+numBaseM, points );
00188 LagrangePoint< Field, dim > *const end = points + n;
00189 for( ; points != end; ++points )
00190 {
00191 LocalKey &key = points->localKey_;
00192 key = LocalKey( key.subEntity()+numBaseM, codim, key.index() );
00193 for( unsigned int j = 0; j < dimension-1; ++j )
00194 points->point_[ j ] *= Field( i ) / Field( order );
00195 points->point_[ dimension-1 ] = Field( order - i ) / Field( order );
00196 }
00197 size += n;
00198 }
00199 }
00200 else
00201 {
00202 points->localKey_ = LocalKey( numBaseM, dimension, count[ numBaseM ]++ );
00203 points->point_ = Field( 0 );
00204 points->point_[ dimension-1 ] = 1;
00205 ++size;
00206 }
00207
00208 return size;
00209 }
00210 };
00211
00212
00213
00214
00215
00216
00217 template< class F, unsigned int dim >
00218 class EquidistantPointSet : public EmptyPointSet<F,dim>
00219 {
00220 template< class T >
00221 struct Topology;
00222 typedef EmptyPointSet<F,dim> Base;
00223 public:
00224 static const unsigned int dimension = dim;
00225
00226 EquidistantPointSet( unsigned int order )
00227 : Base(order)
00228 {
00229 }
00230
00231 template< class T >
00232 bool build ( );
00233
00234 template< class T >
00235 static bool supports ( unsigned int order )
00236 {
00237 return true;
00238 }
00239 private:
00240 using Base::points_;
00241 };
00242
00243 template< class F, unsigned int dim >
00244 template< class T >
00245 struct EquidistantPointSet< F, dim >::Topology
00246 {
00247 typedef EquidistantPointSetImpl< T, F > Impl;
00248 typedef Dune::LagrangePoint< F, dim > LagrangePoint;
00249
00250 template< int pdim >
00251 struct Init
00252 {
00253 static void apply ( const unsigned int order, LagrangePoint *&p )
00254 {
00255 const unsigned int size = GenericGeometry::Size< T, dimension-pdim >::value;
00256 unsigned int count[ size ];
00257 for( unsigned int i = 0; i < size; ++i )
00258 count[ i ] = 0;
00259 p += Impl::template setup< dimension-pdim, dimension >( order, count, p );
00260 }
00261 };
00262 };
00263
00264 template< class F, unsigned int dim >
00265 template< class T >
00266 inline bool EquidistantPointSet< F, dim >::build ( )
00267 {
00268 unsigned int order = Base::order();
00269 typedef Dune::LagrangePoint< F, dimension > LagrangePoint;
00270 typedef typename Topology< T >::Impl Impl;
00271 points_.resize( Impl::size( order ) );
00272 LagrangePoint *p = &(points_[ 0 ]);
00273 ForLoop< Topology< T >::template Init, 0, dimension >::apply( order, p );
00274 return true;
00275 }
00276 }
00277
00278 #endif