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
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
00092 Base::resize(size,size);
00093 S.resize(size,size);
00094 d.resize(size);
00095
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
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
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