dune-localfunctions
2.1.1
|
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