dune-localfunctions  2.1.1
basisevaluator.hh
Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=8 sw=2 sts=2:
00003 
00004 #ifndef DUNE_BASISEVALUATOR_HH
00005 #define DUNE_BASISEVALUATOR_HH
00006 
00007 #include <vector>
00008 
00009 #include <dune/common/fmatrix.hh>
00010 #include <dune/common/fvector.hh>
00011 #include <dune/common/typetraits.hh>
00012 
00013 #include <dune/grid/genericgeometry/topologytypes.hh>
00014 
00015 #include <dune/localfunctions/utility/field.hh>
00016 
00017 #include <dune/localfunctions/utility/multiindex.hh>
00018 
00019 #include <dune/localfunctions/utility/tensor.hh>
00020 
00021 namespace Dune
00022 {
00023   /*******************************************
00024    * Should be removed as soon as the Tensor
00025    * classes have been revisited. See remarks
00026    * in tensor.hh (also hold true here).
00027    *******************************************/
00028  
00029 
00030   template <class B>
00031   struct MonomialEvaluator
00032   {
00033     typedef B Basis;
00034     typedef typename Basis::Field Field;
00035     typedef typename Basis::DomainVector DomainVector;
00036     static const int dimension = Basis::dimension;
00037     static const int dimRange = Basis::dimRange;
00038 
00039     typedef std::vector<Field> Container;
00040 
00041     template< class Deriv >
00042     struct BaseIterator;
00043 
00044     template <unsigned int deriv>
00045     struct Iterator 
00046     {
00047       typedef BaseIterator<Derivatives<Field,dimension,dimRange,deriv,derivative> > All;
00048       typedef BaseIterator<Derivatives<Field,dimension,1,0,value> > Integrate;
00049     };
00050 
00051     unsigned int size() const 
00052     {
00053       return size_;
00054     }
00055 
00056     protected:
00057     MonomialEvaluator(const Basis &basis,unsigned int order,unsigned int size) 
00058     : basis_(basis),
00059       order_(order),
00060       size_(size),
00061       container_(0)
00062     {
00063     }
00064     template <int deriv>
00065     void resize() 
00066     {
00067       const int totalSize = Derivatives<Field,dimension,dimRange,deriv,derivative>::size*size_;
00068       container_.resize(totalSize);
00069     }
00070     MonomialEvaluator(const MonomialEvaluator&);
00071     const Basis &basis_;
00072     unsigned int order_,size_;
00073     Container container_;
00074   };
00075 
00076 
00077   template< class B >
00078   template< class Deriv >
00079   struct MonomialEvaluator< B >::BaseIterator
00080   {
00081     typedef Deriv Derivatives;
00082     typedef typename Deriv::Field Field;
00083     static const unsigned int blockSize = Deriv::size;
00084     typedef Dune::FieldVector<Field,blockSize> Block;
00085     static const DerivativeLayout layout = Deriv::layout;
00086     static const unsigned int dimDomain = Deriv::dimDomain;
00087     static const unsigned int dimRange = Deriv::dimRange;
00088 
00089     typedef std::vector<Field> Container;
00090     typedef typename Container::iterator CIter;
00091 
00092     explicit BaseIterator ( Container &container ) 
00093     : pos_( container.begin() ),
00094       end_( container.end() )
00095     {}
00096 
00097     const Deriv &operator*() const 
00098     {
00099       assert(!done());
00100       return reinterpret_cast<const Deriv&>(*pos_);
00101     }
00102 
00103     const Deriv *operator->() const 
00104     {
00105       return &(operator*());
00106     }
00107 
00108     bool done () const
00109     {
00110       return pos_ == end_;
00111     }
00112 
00113     BaseIterator &operator++ () 
00114     {
00115       pos_ += blockSize;
00116       return *this;
00117     }
00118 
00119     BaseIterator &operator+= ( unsigned int skip )
00120     {
00121       pos_ += skip*blockSize;
00122       return *this;
00123     }
00124 
00125   private:
00126     CIter pos_;
00127     const CIter end_;
00128   };
00129 
00130   template< class B >
00131   struct StandardEvaluator
00132   : public MonomialEvaluator< B >
00133   {
00134     typedef B Basis;
00135     typedef typename Basis::Field Field;
00136     typedef typename Basis::DomainVector DomainVector;
00137     typedef std::vector<Field> Container;
00138     static const int dimension = Basis::dimension;
00139     static const int dimRange = Basis::dimRange;
00140     typedef MonomialEvaluator<B> Base;
00141 
00142     template <unsigned int deriv>
00143     struct Iterator : public Base::template Iterator<deriv>
00144     {
00145     };
00146 
00147     StandardEvaluator(const Basis &basis) 
00148     : Base(basis,basis.order(),basis.size())
00149     {
00150     }
00151     template <unsigned int deriv,class DVector>
00152     typename Iterator<deriv>::All evaluate(const DVector &x) 
00153     {
00154       Base::template resize<deriv>();
00155       basis_.template evaluate<deriv>(x,&(container_[0]));
00156       return typename Iterator<deriv>::All(container_);
00157     }
00158     typename Iterator<0>::Integrate integrate() 
00159     {
00160       Base::template resize<0>();
00161       basis_.integrate(&(container_[0]));
00162       return typename Iterator<0>::Integrate(container_);
00163     }
00164 
00165   protected:
00166     StandardEvaluator ( const Basis &basis, unsigned int size )
00167     : Base( basis, basis.order(), size )
00168     {}
00169 
00170   private:
00171     StandardEvaluator(const StandardEvaluator&);
00172     using Base::basis_;
00173     using Base::container_;
00174   };
00175 
00176 #if 0 // OLD OLD
00177   template< class B, class Fill >
00178   struct VecEvaluator
00179   : public StandardEvaluator< B >
00180   {
00181     typedef B Basis;
00182     typedef typename Basis::Field Field;
00183     static const int dimension = Basis::dimension;
00184     static const int dimRange = Basis::dimRange*Fill::dimRange;
00185     typedef typename Basis::DomainVector DomainVector;
00186     typedef std::vector<Field> Container;
00187     typedef StandardEvaluator<B> Base;
00188 
00189     template <unsigned int deriv>
00190     struct Iterator 
00191     {
00192       typedef typename Base::template BaseIterator<Derivatives<Field,dimension,dimRange,deriv,Fill::layout> > All;
00193     };
00194 
00195     VecEvaluator ( const Basis &basis, const Fill &fill )
00196     : Base( basis, basis.size() ),
00197       fill_( fill ),
00198       size_( basis.size()*dimRange )
00199     {
00200     }
00201     template <unsigned int deriv>
00202     typename Iterator<deriv>::All evaluate(const DomainVector &x) 
00203     {
00204       resize< deriv >();
00205       fill_.template apply<deriv>( x,Base::template evaluate<deriv>(x), vecContainer_ );
00206       std::vector<Derivatives<Field,dimension,dimRange,deriv,Fill::layout> >& derivContainer =
00207          reinterpret_cast<std::vector<Derivatives<Field,dimension,dimRange,deriv,Fill::layout> >&>(vecContainer_);
00208       return typename Iterator<deriv>::All(derivContainer);
00209     }
00210     template <unsigned int deriv,class DVector>
00211     typename Iterator<deriv>::All evaluate(const DVector &x) 
00212     {
00213       resize< deriv >();
00214       fill_.template apply<deriv>( x,Base::template evaluate<deriv>(x), vecContainer_ );
00215       std::vector<Derivatives<Field,dimension,dimRange,deriv,Fill::layout> >& derivContainer =
00216          reinterpret_cast<std::vector<Derivatives<Field,dimension,dimRange,deriv,Fill::layout> >&>(vecContainer_);
00217       return typename Iterator<deriv>::All(derivContainer);
00218     }
00219     unsigned int size() const
00220     {
00221       return size_;
00222     }
00223 
00224   protected:
00225     VecEvaluator ( const Basis &basis, const Fill &fill, unsigned int size )
00226     : Base( basis, basis.size() ),
00227       fill_( fill ),
00228       size_( size )
00229     {
00230       resize< 2 >();
00231     }
00232 
00233     template <int deriv>
00234     void resize() 
00235     {
00236       const int totalSize = Derivatives<Field,dimension,dimRange,deriv,derivative>::size*size_;
00237       vecContainer_.resize(totalSize);
00238     }
00239 
00240     VecEvaluator(const VecEvaluator&);
00241 
00242     Container vecContainer_;
00243     const Fill &fill_;
00244     unsigned int size_;
00245   };
00246 
00247   template <int dimR,DerivativeLayout layout>
00248   struct DiagonalFill;
00249 
00250   template <int dimR>
00251   struct DiagonalFill<dimR,derivative>
00252   {
00253     static const DerivativeLayout layout = derivative;
00254     static const int dimRange = dimR;
00255     template <int deriv, class Domain, class Iter,class Field>
00256     void apply(const Domain &x,
00257                Iter iter,std::vector<Field> &vecContainer) const
00258     {
00259       typedef std::vector<Field> Container;
00260       typename Container::iterator vecIter = vecContainer.begin();
00261       for ( ; !iter.done(); ++iter)
00262       {
00263         const typename Iter::Block &block = iter->block();
00264         for (int r1=0;r1<dimR;++r1) 
00265         {
00266           unsigned int b = 0;
00267           apply<Field>(r1,x,block,b,vecIter);
00268         }
00269       }
00270     }
00271     template <class Field, class Domain, class Block,class VecIter>
00272     void apply(int r1, const Domain &x,
00273                const Block &block,unsigned int &b, 
00274                VecIter &vecIter) const
00275     {
00276       unsigned int bStart = b;
00277       unsigned int bEnd = b+Block::size;
00278       apply<Field>(r1,x,block,bStart,bEnd,vecIter);
00279       b=bEnd;
00280     }
00281     template <class Field, class Domain, class Block,class VecIter>
00282     void apply(int r1, const Domain &x,const Block &block,
00283                unsigned int bStart, unsigned int bEnd,
00284                VecIter &vecIter) const
00285     {
00286       for (int r2=0;r2<dimR;++r2) 
00287       {
00288         for (unsigned int bb=bStart;bb<bEnd;++bb)
00289         {
00290           *vecIter = (r1==r2?block[bb]:Field(0));
00291           ++vecIter;
00292         }
00293       }
00294     }
00295   };
00296   template <int dimR>
00297   struct DiagonalFill<dimR,value>
00298   {
00299     static const DerivativeLayout layout = value;
00300     static const int dimRange = dimR;
00301     template <int deriv, class Domain, class Iter,class Field>
00302     void apply(const Domain &x,
00303                Iter iter,std::vector<Field> &vecContainer) const
00304     {
00305       typedef std::vector<Field> Container;
00306       typename Container::iterator vecIter = vecContainer.begin();
00307       for ( ; !iter.done(); ++iter)
00308       {
00309         const typename Iter::Block &block = iter->block();
00310         for (int r1=0;r1<dimR;++r1) 
00311         {
00312           unsigned int b = 0;
00313           apply<Field>(integral_constant<int,deriv>(),r1,x,block,b,vecIter);
00314         }
00315       }
00316     }
00317     template <class Field, class Domain, class Block,class VecIter,int deriv>
00318     void apply(const integral_constat<int,deriv>&, int r1, const Domain &x,
00319                const Block &block,unsigned int &b, 
00320                VecIter &vecIter) const
00321     {
00322       apply<Field>(integral_constant<int,deriv-1>(),r1,x,block,b,vecIter);
00323       unsigned int bStart = b;
00324       unsigned int bEnd = b+LFETensor<Field,Domain::dimension,deriv>::size;
00325       apply<Field>(r1,x,block,bStart,bEnd,vecIter);
00326       b=bEnd;
00327     }
00328     template <class Field, class Domain, class Block,class VecIter>
00329     void apply(const integral_constant<int,0>&, int r1, const Domain &x,
00330                const Block &block,unsigned int &b, 
00331                VecIter &vecIter) const
00332     {
00333       apply<Field>(r1,x,block,b,b+1,vecIter);
00334       ++b;
00335     }
00336     template <class Field, class Domain, class Block,class VecIter>
00337     void apply(int r1, const Domain &x,const Block &block,
00338                unsigned int bStart, unsigned int bEnd,
00339                VecIter &vecIter) const
00340     {
00341       for (int r2=0;r2<dimR;++r2) 
00342       {
00343         for (unsigned int bb=bStart;bb<bEnd;++bb)
00344         {
00345           *vecIter = (r1==r2?block[bb]:Field(0));
00346           ++vecIter;
00347         }
00348       }
00349     }
00350   };
00351 
00352   template <class B,int dimR,DerivativeLayout layout>
00353   struct VectorialEvaluator 
00354   : public VecEvaluator<B,DiagonalFill<dimR,layout> >
00355   {
00356     typedef DiagonalFill<dimR,layout> Fill;
00357     typedef VecEvaluator< B,Fill > Base;
00358     VectorialEvaluator(const B &basis)
00359     : Base(basis,fill_,basis.size()*dimR)
00360     {
00361     }
00362     private:
00363     Fill fill_;
00364   };
00365 #endif // OLD OLD
00366 
00367 }
00368 
00369 #endif