dune-localfunctions
2.1.1
|
00001 #ifndef DUNE_ALGLIB_MATRIX_HH 00002 #define DUNE_ALGLIB_MATRIX_HH 00003 00004 #include <cassert> 00005 #include <vector> 00006 00007 #include <dune/localfunctions/utility/field.hh> 00008 // #include <dune/localfunctions/utility/vector.hh> 00009 00010 #if HAVE_ALGLIB 00011 #include <alglib/amp.h> 00012 #include <alglib/matinv.h> 00013 #endif 00014 00015 namespace Dune 00016 { 00017 00018 template< class F, bool aligned = false > 00019 class LFEMatrix; 00020 00021 00022 template< class F, bool aligned > 00023 class LFEMatrix 00024 { 00025 typedef LFEMatrix< F, aligned > This; 00026 // typedef LFEVector< F > Row; 00027 typedef std::vector< F > Row; 00028 typedef std::vector<Row> RealMatrix; 00029 00030 public: 00031 typedef F Field; 00032 00033 operator const RealMatrix & () const 00034 { 00035 return matrix_; 00036 } 00037 00038 operator RealMatrix & () 00039 { 00040 return matrix_; 00041 } 00042 00043 template <class Vector> 00044 void row( const unsigned int row, Vector &vec ) const 00045 { 00046 assert(row<rows()); 00047 for (int i=0;i<cols();++i) 00048 field_cast(matrix_[row][i], vec[i]); 00049 } 00050 00051 const Field &operator() ( const unsigned int row, const unsigned int col ) const 00052 { 00053 assert(row<rows()); 00054 assert(col<cols()); 00055 return matrix_[ row ][ col ]; 00056 } 00057 00058 Field &operator() ( const unsigned int row, const unsigned int col ) 00059 { 00060 assert(row<rows()); 00061 assert(col<cols()); 00062 return matrix_[ row ][ col ]; 00063 } 00064 00065 unsigned int rows () const 00066 { 00067 return rows_; 00068 } 00069 00070 unsigned int cols () const 00071 { 00072 return cols_; 00073 } 00074 00075 const Field *rowPtr ( const unsigned int row ) const 00076 { 00077 assert(row<rows()); 00078 return &(matrix_[row][0]); 00079 } 00080 00081 Field *rowPtr ( const unsigned int row ) 00082 { 00083 assert(row<rows()); 00084 return &(matrix_[row][0]); 00085 } 00086 00087 void resize ( const unsigned int rows, const unsigned int cols ) 00088 { 00089 matrix_.resize(rows); 00090 for (unsigned int i=0;i<rows;++i) 00091 matrix_[i].resize(cols); 00092 rows_ = rows; 00093 cols_ = cols; 00094 } 00095 00096 bool invert () 00097 { 00098 assert( rows() == cols() ); 00099 std::vector<unsigned int> p(rows()); 00100 for (unsigned int j=0;j<rows();++j) 00101 p[j] = j; 00102 for (unsigned int j=0;j<rows();++j) 00103 { 00104 // pivot search 00105 unsigned int r = j; 00106 Field max = std::abs( (*this)(j,j) ); 00107 for (unsigned int i=j+1;i<rows();++i) 00108 { 00109 if ( std::abs( (*this)(i,j) ) > max ) 00110 { 00111 max = std::abs( (*this)(i,j) ); 00112 r = i; 00113 } 00114 } 00115 if (max == Zero<Field>()) 00116 return false; 00117 // row swap 00118 if (r > j) 00119 { 00120 for (unsigned int k=0;k<cols();++k) 00121 std::swap( (*this)(j,k), (*this)(r,k) ); 00122 std::swap( p[j], p[r] ); 00123 } 00124 // transformation 00125 Field hr = Unity<Field>()/(*this)(j,j); 00126 for (unsigned int i=0;i<rows();++i) 00127 (*this)(i,j) *= hr; 00128 (*this)(j,j) = hr; 00129 for (unsigned int k=0;k<cols();++k) 00130 { 00131 if (k==j) continue; 00132 for (unsigned int i=0;i<rows();++i) 00133 { 00134 if (i==j) continue; 00135 (*this)(i,k) -= (*this)(i,j)*(*this)(j,k); 00136 } 00137 (*this)(j,k) *= -hr; 00138 } 00139 } 00140 // column exchange 00141 Row hv(rows()); 00142 for (unsigned int i=0;i<rows();++i) 00143 { 00144 for (unsigned int k=0;k<rows();++k) 00145 hv[ p[k] ] = (*this)(i,k); 00146 for (unsigned int k=0;k<rows();++k) 00147 (*this)(i,k) = hv[k]; 00148 } 00149 return true; 00150 } 00151 00152 private: 00153 RealMatrix matrix_; 00154 unsigned int cols_,rows_; 00155 }; 00156 00157 #if HAVE_ALGLIB 00158 template< unsigned int precision, bool aligned > 00159 class LFEMatrix< amp::ampf< precision >, aligned > 00160 { 00161 public: 00162 typedef amp::ampf< precision > Field; 00163 private: 00164 typedef LFEMatrix< amp::ampf< precision >, aligned > This; 00165 typedef ap::template_2d_array< Field, aligned > RealMatrix; 00166 00167 public: 00168 operator const RealMatrix & () const 00169 { 00170 return matrix_; 00171 } 00172 00173 operator RealMatrix & () 00174 { 00175 return matrix_; 00176 } 00177 00178 template <class Vector> 00179 void row( const unsigned int row, Vector &vec ) const 00180 { 00181 assert(row<rows()); 00182 for (unsigned int i=0;i<cols();++i) 00183 field_cast(matrix_(row,i), vec[i]); 00184 } 00185 00186 const Field &operator() ( const unsigned int row, const unsigned int col ) const 00187 { 00188 assert(row<rows()); 00189 assert(col<cols()); 00190 return matrix_( row, col ); 00191 } 00192 00193 Field &operator() ( const unsigned int row, const unsigned int col ) 00194 { 00195 assert(row<rows()); 00196 assert(col<cols()); 00197 return matrix_( row, col ); 00198 } 00199 00200 unsigned int rows () const 00201 { 00202 return matrix_.gethighbound( 1 )+1; 00203 } 00204 00205 unsigned int cols () const 00206 { 00207 return matrix_.gethighbound( 2 )+1; 00208 } 00209 00210 const Field *rowPtr ( const unsigned int row ) const 00211 { 00212 assert(row<rows()); 00213 const int lastCol = matrix_.gethighbound( 2 ); 00214 ap::const_raw_vector< Field > rowVector = matrix_.getrow( row, 0, lastCol ); 00215 assert( (rowVector.GetStep() == 1) && (rowVector.GetLength() == lastCol+1) ); 00216 return rowVector.GetData(); 00217 } 00218 00219 Field *rowPtr ( const unsigned int row ) 00220 { 00221 assert(row<rows()); 00222 const int lastCol = matrix_.gethighbound( 2 ); 00223 ap::raw_vector< Field > rowVector = matrix_.getrow( row, 0, lastCol ); 00224 assert( (rowVector.GetStep() == 1) && (rowVector.GetLength() == lastCol+1) ); 00225 return rowVector.GetData(); 00226 } 00227 00228 void resize ( const unsigned int rows, const unsigned int cols ) 00229 { 00230 matrix_.setbounds( 0, rows-1, 0, cols-1 ); 00231 } 00232 00233 bool invert () 00234 { 00235 assert( rows() == cols() ); 00236 int info; 00237 matinv::matinvreport< precision > report; 00238 matinv::rmatrixinverse< precision >( matrix_, rows(), info, report ); 00239 return (info >= 0); 00240 } 00241 00242 private: 00243 RealMatrix matrix_; 00244 }; 00245 #endif 00246 00247 template< class Field, bool aligned > 00248 inline std::ostream &operator<<(std::ostream &out, const LFEMatrix<Field,aligned> &mat) 00249 { 00250 for (unsigned int r=0;r<mat.rows();++r) 00251 { 00252 out << field_cast<double>(mat(r,0)); 00253 for (unsigned int c=1;c<mat.cols();++c) 00254 { 00255 out << " , " << field_cast<double>(mat(r,c)); 00256 } 00257 out << std::endl; 00258 } 00259 return out; 00260 } 00261 } 00262 00263 #endif // #ifndef DUNE_ALGLIB_MATRIX_HH