dune-localfunctions  2.1.1
equidistantpoints.hh
Go to the documentation of this file.
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