dune-localfunctions
2.1.1
|
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 // Internal Forward Declarations 00019 // ----------------------------- 00020 00021 template< class F, unsigned int dim > 00022 class EquidistantPointSet; 00023 00024 // EquidistantPointSetImpl 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 // private: 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 // private: 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 // LagnragePoints 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