orthonormalcompute.hh

Go to the documentation of this file.
00001 #ifndef DUNE_ORTHONORMALCOMPUTE_HH
00002 #define DUNE_ORTHONORMALCOMPUTE_HH
00003 
00004 #include <cassert>
00005 #include <iostream>
00006 #include <fstream>
00007 #include <iomanip>
00008 #include <map>
00009 
00010 #include <dune/common/fmatrix.hh>
00011 
00012 #include <dune/localfunctions/utility/field.hh>
00013 #include <dune/localfunctions/utility/lfematrix.hh>
00014 
00015 #include <dune/grid/genericgeometry/topologytypes.hh>
00016 
00017 #include <dune/localfunctions/utility/monomialbasis.hh>
00018 #include <dune/localfunctions/utility/multiindex.hh>
00019 
00020 namespace ONBCompute
00021 {
00022 
00023   template <class scalar_t>
00024   scalar_t factorial(int start,int end) {
00025     scalar_t ret(1);
00026     for (int j=start;j<=end;j++)
00027       ret*=j;
00028     return ret;
00029   }
00030   template <class Topology> 
00031   struct Integral;
00032   template <class Base> 
00033   struct Integral<Dune::GenericGeometry::Pyramid<Base> > {
00034     enum {d = Base::dimension+1};
00035     template <int dim,class scalar_t>
00036     static int compute(const Dune::MultiIndex<dim, scalar_t>& alpha,
00037                           scalar_t& p,scalar_t& q) {
00038       int i = alpha.z(d-1);
00039       int ord = Integral<Base>::compute(alpha,p,q);
00040       p *= factorial<scalar_t>(1,i);
00041       q *= factorial<scalar_t>(d+ord,d+ord+i);
00042       return ord+i;
00043     }
00044   };
00045   template <class Base> 
00046   struct Integral<Dune::GenericGeometry::Prism<Base> > {
00047     enum {d = Base::dimension+1};
00048     template <int dim,class scalar_t>
00049     static int compute(const Dune::MultiIndex<dim,scalar_t>& alpha,
00050                         scalar_t& p,scalar_t& q) {
00051       int i = alpha.z(d-1);
00052       int ord = Integral<Base>::compute(alpha,p,q);
00053       Integral<Base>::compute(alpha,p,q);
00054       p *= 1.;
00055       q *= (i+1.);
00056       return ord+i;
00057     }
00058   };
00059   template <> 
00060   struct Integral<Dune::GenericGeometry::Point> {
00061     template <int dim,class scalar_t>
00062     static int compute(const Dune::MultiIndex<dim,scalar_t>& alpha,
00063                         scalar_t& p,scalar_t& q) {
00064       p = 1.;
00065       q = 1.;
00066       return 0;
00067     }
00068   };
00069   template <class Topology, class scalar_t>
00070   struct ONBMatrix : Dune::LFEMatrix<scalar_t>
00071   {
00072     typedef Dune::LFEMatrix<scalar_t> Base;
00073 
00074     typedef std::vector< scalar_t > vec_t;
00075     typedef Dune::LFEMatrix< scalar_t > mat_t;
00076     static const unsigned int dim=Topology::dimension;
00077 
00078     explicit ONBMatrix( const unsigned int order )
00079     {
00080       // get all multiindecies for monomial basis
00081       typedef Dune::MultiIndex<dim,scalar_t> MI;
00082       typedef Dune::StandardMonomialBasis< dim, MI  > Basis;
00083       Basis basis( order );
00084       const unsigned int size = basis.size( );
00085       std::vector< Dune::FieldVector< MI,1> > y( size );
00086       Dune::FieldVector< MI, dim > x;
00087       for (unsigned int i=0;i<dim;++i) {
00088         x[i].set(i);
00089       }
00090       basis.evaluate( x, y );
00091       // set bounds of data 
00092       Base::resize(size,size);
00093       S.resize(size,size);
00094       d.resize(size);
00095       // Aufstellen der Matrix fuer die Bilinearform xSy: S_ij = int_A x^(i+j)
00096       scalar_t p,q;
00097       for( unsigned int i=0;i<size;++i )
00098       {
00099         for( unsigned int j=0;j<size;j++ )
00100         { 
00101           Integral<Topology>::compute(y[i]*y[j],p,q);
00102           S(i,j) = p;
00103           S(i,j) /= q;
00104         }
00105       }
00106       gramSchmidt();
00107     }
00108     template <class Vector>
00109     void row( const unsigned int row, Vector &vec ) const
00110     {
00111       // transposed matrix is required
00112       assert(row<Base::cols());
00113       for (unsigned int i=0;i<Base::rows();++i)
00114         Dune::field_cast(Base::operator()(i,row), vec[i]);
00115     }
00116     bool test() {
00117       bool ret = true;
00118       const unsigned int N = Base::rows();
00119       // Nun schauen wir noch, ob wirklich C^T S C = E gilt
00120       scalar_t prod;
00121       for (unsigned int i=0;i<N;++i) {
00122         for (unsigned int j=0;j<N;j++) {
00123           prod = 0;
00124           for (unsigned int k=0;k<N;k++) {
00125             for (unsigned int l=0;l<N;l++) {
00126               prod += Base::operator()(l,i)*S(l,k)*Base::operator()(k,j);
00127             }
00128           }
00129           assert((i==j)?1: fabs( Dune::field_cast<double>(prod) )<1e-10); 
00130         }
00131       } 
00132       return ret;
00133     }
00134   private:
00135     void sprod(int col1,int col2, scalar_t& ret) 
00136     {
00137       ret = 0;
00138       for (int k=0;k<=col1;k++) {
00139         for (int l=0;l<=col2;l++) {
00140           ret += Base::operator()(l,col2)*this->S(l,k)*Base::operator()(k,col1);
00141         }
00142       }
00143     }
00144     void vmul(unsigned int col, unsigned int rowEnd, scalar_t &ret)
00145     {
00146       for (unsigned int i=0;i<=rowEnd;++i)
00147         Base::operator()(i,col) *= ret;
00148     }
00149     void vsub(unsigned int coldest, unsigned int colsrc, 
00150               unsigned int rowEnd, scalar_t &ret)
00151     {
00152       for (unsigned int i=0;i<=rowEnd;++i)
00153         Base::operator()(i,coldest) -= ret*Base::operator()(i,colsrc);
00154     }
00155     void gramSchmidt() 
00156     {
00157       const unsigned int N = Base::rows();
00158       scalar_t s;
00159       for (unsigned int i=0;i<N;++i)
00160         for (unsigned int j=0;j<N;++j)
00161           Base::operator()(i,j) = (i==j)?1:0;
00162       sprod(0,0,s);
00163       s = 1./sqrt(s);
00164       vmul(0,0,s);
00165       for (unsigned int i=0;i<N-1;i++) {
00166         for (unsigned int k=0;k<=i;++k) {
00167           sprod(i+1,k,s);
00168           vsub(i+1,k,i+1,s);
00169         }
00170         sprod(i+1,i+1,s);
00171         s = 1./sqrt(s);
00172         vmul(i+1,i+1,s);
00173       }
00174     }
00175 
00176     vec_t d;
00177     mat_t S;
00178   };
00179 
00180 }
00181 #endif 
Generated on Sat Apr 24 11:15:34 2010 for dune-localfunctions by  doxygen 1.6.3