$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_DENSE_MATRIX_H 00021 #define LIBMESH_DENSE_MATRIX_H 00022 00023 // Local Includes 00024 #include "libmesh/libmesh_common.h" 00025 #include "libmesh/dense_matrix_base.h" 00026 00027 // C++ includes 00028 #include <vector> 00029 #include <algorithm> 00030 00031 namespace libMesh 00032 { 00033 00034 // Forward Declarations 00035 template <typename T> class DenseVector; 00036 00037 00038 00047 // ------------------------------------------------------------ 00048 // Dense Matrix class definition 00049 template<typename T> 00050 class DenseMatrix : public DenseMatrixBase<T> 00051 { 00052 public: 00053 00057 DenseMatrix(const unsigned int new_m=0, 00058 const unsigned int new_n=0); 00059 00063 //DenseMatrix (const DenseMatrix<T>& other_matrix); 00064 00068 virtual ~DenseMatrix() {} 00069 00070 00074 virtual void zero(); 00075 00079 T operator() (const unsigned int i, 00080 const unsigned int j) const; 00081 00085 T & operator() (const unsigned int i, 00086 const unsigned int j); 00087 00091 virtual T el(const unsigned int i, 00092 const unsigned int j) const { return (*this)(i,j); } 00093 00097 virtual T & el(const unsigned int i, 00098 const unsigned int j) { return (*this)(i,j); } 00099 00103 virtual void left_multiply (const DenseMatrixBase<T>& M2); 00104 00108 template <typename T2> 00109 void left_multiply (const DenseMatrixBase<T2>& M2); 00110 00114 virtual void right_multiply (const DenseMatrixBase<T>& M2); 00115 00119 template <typename T2> 00120 void right_multiply (const DenseMatrixBase<T2>& M2); 00121 00126 void vector_mult (DenseVector<T>& dest, 00127 const DenseVector<T>& arg) const; 00128 00134 template <typename T2> 00135 void vector_mult (DenseVector<typename CompareTypes<T,T2>::supertype>& dest, 00136 const DenseVector<T2>& arg) const; 00137 00142 void vector_mult_transpose (DenseVector<T>& dest, 00143 const DenseVector<T>& arg) const; 00144 00150 template <typename T2> 00151 void vector_mult_transpose (DenseVector<typename CompareTypes<T,T2>::supertype>& dest, 00152 const DenseVector<T2>& arg) const; 00153 00158 void vector_mult_add (DenseVector<T>& dest, 00159 const T factor, 00160 const DenseVector<T>& arg) const; 00161 00167 template <typename T2, typename T3> 00168 void vector_mult_add (DenseVector<typename CompareTypes<T, typename CompareTypes<T2,T3>::supertype>::supertype>& dest, 00169 const T2 factor, 00170 const DenseVector<T3>& arg) const; 00171 00175 void get_principal_submatrix (unsigned int sub_m, unsigned int sub_n, DenseMatrix<T>& dest) const; 00176 00180 void get_principal_submatrix (unsigned int sub_m, DenseMatrix<T>& dest) const; 00181 00185 DenseMatrix<T>& operator = (const DenseMatrix<T>& other_matrix); 00186 00194 template <typename T2> 00195 DenseMatrix<T>& operator = (const DenseMatrix<T2>& other_matrix); 00196 00200 void swap(DenseMatrix<T>& other_matrix); 00201 00206 void resize(const unsigned int new_m, 00207 const unsigned int new_n); 00208 00212 void scale (const T factor); 00213 00214 00218 void scale_column (const unsigned int col, const T factor); 00219 00223 DenseMatrix<T>& operator *= (const T factor); 00224 00228 template<typename T2, typename T3> 00229 typename boostcopy::enable_if_c< 00230 ScalarTraits<T2>::value, void >::type add (const T2 factor, 00231 const DenseMatrix<T3>& mat); 00232 00236 bool operator== (const DenseMatrix<T> &mat) const; 00237 00241 bool operator!= (const DenseMatrix<T> &mat) const; 00242 00246 DenseMatrix<T>& operator+= (const DenseMatrix<T> &mat); 00247 00251 DenseMatrix<T>& operator-= (const DenseMatrix<T> &mat); 00252 00258 Real min () const; 00259 00265 Real max () const; 00266 00277 Real l1_norm () const; 00278 00290 Real linfty_norm () const; 00291 00295 void left_multiply_transpose (const DenseMatrix<T>& A); 00296 00301 template <typename T2> 00302 void left_multiply_transpose (const DenseMatrix<T2>& A); 00303 00304 00308 void right_multiply_transpose (const DenseMatrix<T>& A); 00309 00314 template <typename T2> 00315 void right_multiply_transpose (const DenseMatrix<T2>& A); 00316 00320 T transpose (const unsigned int i, 00321 const unsigned int j) const; 00322 00326 void get_transpose(DenseMatrix<T>& dest) const; 00327 00333 std::vector<T>& get_values() { return _val; } 00334 00338 const std::vector<T>& get_values() const { return _val; } 00339 00346 void condense(const unsigned int i, 00347 const unsigned int j, 00348 const T val, 00349 DenseVector<T>& rhs) 00350 { DenseMatrixBase<T>::condense (i, j, val, rhs); } 00351 00357 void lu_solve (const DenseVector<T>& b, 00358 DenseVector<T>& x); 00359 00360 00361 00371 template <typename T2> 00372 void cholesky_solve(const DenseVector<T2>& b, 00373 DenseVector<T2>& x); 00374 00375 00384 void svd(DenseVector<T>& sigma); 00385 00386 00398 void svd(DenseVector<T>& sigma, DenseMatrix<T>& U, DenseMatrix<T>& VT); 00399 00400 00407 void evd(DenseVector<T>& lambda_real, DenseVector<T>& lambda_imag); 00408 00409 00415 T det(); 00416 00425 // void inverse(); 00426 00432 bool use_blas_lapack; 00433 00434 private: 00435 00439 std::vector<T> _val; 00440 00446 void _lu_decompose (); 00447 00453 void _lu_back_substitute (const DenseVector<T>& b, 00454 DenseVector<T>& x) const; 00455 00462 void _cholesky_decompose(); 00463 00470 template <typename T2> 00471 void _cholesky_back_substitute(const DenseVector<T2>& b, 00472 DenseVector<T2>& x) const; 00473 00481 enum DecompositionType {LU=0, CHOLESKY=1, LU_BLAS_LAPACK, NONE}; 00482 00487 DecompositionType _decomposition_type; 00488 00493 enum _BLAS_Multiply_Flag { 00494 LEFT_MULTIPLY = 0, 00495 RIGHT_MULTIPLY, 00496 LEFT_MULTIPLY_TRANSPOSE, 00497 RIGHT_MULTIPLY_TRANSPOSE 00498 }; 00499 00507 void _multiply_blas(const DenseMatrixBase<T>& other, 00508 _BLAS_Multiply_Flag flag); 00509 00519 void _lu_decompose_lapack(); 00520 00526 void _svd_lapack(DenseVector<T>& sigma); 00527 00533 void _svd_lapack(DenseVector<T>& sigma, 00534 DenseMatrix<T>& U, 00535 DenseMatrix<T>& VT); 00536 00541 void _svd_helper (char JOBU, 00542 char JOBVT, 00543 std::vector<T>& sigma_val, 00544 std::vector<T>& U_val, 00545 std::vector<T>& VT_val); 00546 00552 void _evd_lapack(DenseVector<T>& lambda_real, DenseVector<T>& lambda_imag); 00553 00559 std::vector<int> _pivots; 00560 00570 void _lu_back_substitute_lapack (const DenseVector<T>& b, 00571 DenseVector<T>& x); 00572 00585 void _matvec_blas(T alpha, T beta, 00586 DenseVector<T>& dest, 00587 const DenseVector<T>& arg, 00588 bool trans=false) const; 00589 }; 00590 00591 00592 00593 00594 00595 // ------------------------------------------------------------ 00599 namespace DenseMatrices 00600 { 00601 00606 typedef DenseMatrix<Real> RealDenseMatrix; 00607 00617 typedef DenseMatrix<Complex> ComplexDenseMatrix; 00618 00619 } 00620 00621 00622 00623 using namespace DenseMatrices; 00624 00625 00626 00627 00628 00629 // ------------------------------------------------------------ 00630 // Dense Matrix member functions 00631 template<typename T> 00632 inline 00633 DenseMatrix<T>::DenseMatrix(const unsigned int new_m, 00634 const unsigned int new_n) 00635 : DenseMatrixBase<T>(new_m,new_n), 00636 #if defined(LIBMESH_HAVE_PETSC) && defined(LIBMESH_USE_REAL_NUMBERS) && defined(LIBMESH_DEFAULT_DOUBLE_PRECISION) 00637 use_blas_lapack(true), 00638 #else 00639 use_blas_lapack(false), 00640 #endif 00641 _val(), 00642 _decomposition_type(NONE), 00643 _pivots() 00644 { 00645 this->resize(new_m,new_n); 00646 } 00647 00648 00649 00650 // FIXME[JWP]: This copy ctor has not been maintained along with 00651 // the rest of the class... 00652 // Can we just use the compiler-generated copy ctor here? 00653 // template<typename T> 00654 // inline 00655 // DenseMatrix<T>::DenseMatrix (const DenseMatrix<T>& other_matrix) 00656 // : DenseMatrixBase<T>(other_matrix._m, other_matrix._n) 00657 // { 00658 // _val = other_matrix._val; 00659 // } 00660 00661 00662 00663 template<typename T> 00664 inline 00665 void DenseMatrix<T>::swap(DenseMatrix<T>& other_matrix) 00666 { 00667 std::swap(this->_m, other_matrix._m); 00668 std::swap(this->_n, other_matrix._n); 00669 _val.swap(other_matrix._val); 00670 DecompositionType _temp = _decomposition_type; 00671 _decomposition_type = other_matrix._decomposition_type; 00672 other_matrix._decomposition_type = _temp; 00673 } 00674 00675 00676 template <typename T> 00677 template <typename T2> 00678 inline 00679 DenseMatrix<T>& 00680 DenseMatrix<T>::operator=(const DenseMatrix<T2>& mat) 00681 { 00682 unsigned int mat_m = mat.m(), mat_n = mat.n(); 00683 this->resize(mat_m, mat_n); 00684 for (unsigned int i=0; i<mat_m; i++) 00685 for (unsigned int j=0; j<mat_n; j++) 00686 (*this)(i,j) = mat(i,j); 00687 00688 return *this; 00689 } 00690 00691 00692 00693 template<typename T> 00694 inline 00695 void DenseMatrix<T>::resize(const unsigned int new_m, 00696 const unsigned int new_n) 00697 { 00698 _val.resize(new_m*new_n); 00699 00700 this->_m = new_m; 00701 this->_n = new_n; 00702 00703 // zero and set decomposition_type to NONE 00704 this->zero(); 00705 } 00706 00707 00708 00709 template<typename T> 00710 inline 00711 void DenseMatrix<T>::zero() 00712 { 00713 _decomposition_type = NONE; 00714 00715 std::fill (_val.begin(), _val.end(), static_cast<T>(0)); 00716 } 00717 00718 00719 00720 template<typename T> 00721 inline 00722 DenseMatrix<T>& DenseMatrix<T>::operator = (const DenseMatrix<T>& other_matrix) 00723 { 00724 this->_m = other_matrix._m; 00725 this->_n = other_matrix._n; 00726 00727 _val = other_matrix._val; 00728 _decomposition_type = other_matrix._decomposition_type; 00729 00730 return *this; 00731 } 00732 00733 00734 00735 template<typename T> 00736 inline 00737 T DenseMatrix<T>::operator () (const unsigned int i, 00738 const unsigned int j) const 00739 { 00740 libmesh_assert_less (i*j, _val.size()); 00741 libmesh_assert_less (i, this->_m); 00742 libmesh_assert_less (j, this->_n); 00743 00744 00745 // return _val[(i) + (this->_m)*(j)]; // col-major 00746 return _val[(i)*(this->_n) + (j)]; // row-major 00747 } 00748 00749 00750 00751 template<typename T> 00752 inline 00753 T & DenseMatrix<T>::operator () (const unsigned int i, 00754 const unsigned int j) 00755 { 00756 libmesh_assert_less (i*j, _val.size()); 00757 libmesh_assert_less (i, this->_m); 00758 libmesh_assert_less (j, this->_n); 00759 00760 //return _val[(i) + (this->_m)*(j)]; // col-major 00761 return _val[(i)*(this->_n) + (j)]; // row-major 00762 } 00763 00764 00765 00766 00767 00768 template<typename T> 00769 inline 00770 void DenseMatrix<T>::scale (const T factor) 00771 { 00772 for (unsigned int i=0; i<_val.size(); i++) 00773 _val[i] *= factor; 00774 } 00775 00776 00777 template<typename T> 00778 inline 00779 void DenseMatrix<T>::scale_column (const unsigned int col, const T factor) 00780 { 00781 for (unsigned int i=0; i<this->m(); i++) 00782 (*this)(i, col) *= factor; 00783 } 00784 00785 00786 00787 template<typename T> 00788 inline 00789 DenseMatrix<T>& DenseMatrix<T>::operator *= (const T factor) 00790 { 00791 this->scale(factor); 00792 return *this; 00793 } 00794 00795 00796 00797 template<typename T> 00798 template<typename T2, typename T3> 00799 inline 00800 typename boostcopy::enable_if_c< 00801 ScalarTraits<T2>::value, void >::type 00802 DenseMatrix<T>::add (const T2 factor, 00803 const DenseMatrix<T3>& mat) 00804 { 00805 libmesh_assert_equal_to (this->m(), mat.m()); 00806 libmesh_assert_equal_to (this->n(), mat.n()); 00807 00808 for (unsigned int i=0; i<this->m(); i++) 00809 for (unsigned int j=0; j<this->n(); j++) 00810 (*this)(i,j) += factor * mat(i,j); 00811 } 00812 00813 00814 00815 template<typename T> 00816 inline 00817 bool DenseMatrix<T>::operator == (const DenseMatrix<T> &mat) const 00818 { 00819 for (unsigned int i=0; i<_val.size(); i++) 00820 if (_val[i] != mat._val[i]) 00821 return false; 00822 00823 return true; 00824 } 00825 00826 00827 00828 template<typename T> 00829 inline 00830 bool DenseMatrix<T>::operator != (const DenseMatrix<T> &mat) const 00831 { 00832 for (unsigned int i=0; i<_val.size(); i++) 00833 if (_val[i] != mat._val[i]) 00834 return true; 00835 00836 return false; 00837 } 00838 00839 00840 00841 template<typename T> 00842 inline 00843 DenseMatrix<T>& DenseMatrix<T>::operator += (const DenseMatrix<T> &mat) 00844 { 00845 for (unsigned int i=0; i<_val.size(); i++) 00846 _val[i] += mat._val[i]; 00847 00848 return *this; 00849 } 00850 00851 00852 00853 template<typename T> 00854 inline 00855 DenseMatrix<T>& DenseMatrix<T>::operator -= (const DenseMatrix<T> &mat) 00856 { 00857 for (unsigned int i=0; i<_val.size(); i++) 00858 _val[i] -= mat._val[i]; 00859 00860 return *this; 00861 } 00862 00863 00864 00865 template<typename T> 00866 inline 00867 Real DenseMatrix<T>::min () const 00868 { 00869 libmesh_assert (this->_m); 00870 libmesh_assert (this->_n); 00871 Real my_min = libmesh_real((*this)(0,0)); 00872 00873 for (unsigned int i=0; i!=this->_m; i++) 00874 { 00875 for (unsigned int j=0; j!=this->_n; j++) 00876 { 00877 Real current = libmesh_real((*this)(i,j)); 00878 my_min = (my_min < current? my_min : current); 00879 } 00880 } 00881 return my_min; 00882 } 00883 00884 00885 00886 template<typename T> 00887 inline 00888 Real DenseMatrix<T>::max () const 00889 { 00890 libmesh_assert (this->_m); 00891 libmesh_assert (this->_n); 00892 Real my_max = libmesh_real((*this)(0,0)); 00893 00894 for (unsigned int i=0; i!=this->_m; i++) 00895 { 00896 for (unsigned int j=0; j!=this->_n; j++) 00897 { 00898 Real current = libmesh_real((*this)(i,j)); 00899 my_max = (my_max > current? my_max : current); 00900 } 00901 } 00902 return my_max; 00903 } 00904 00905 00906 00907 template<typename T> 00908 inline 00909 Real DenseMatrix<T>::l1_norm () const 00910 { 00911 libmesh_assert (this->_m); 00912 libmesh_assert (this->_n); 00913 00914 Real columnsum = 0.; 00915 for (unsigned int i=0; i!=this->_m; i++) 00916 { 00917 columnsum += std::abs((*this)(i,0)); 00918 } 00919 Real my_max = columnsum; 00920 for (unsigned int j=1; j!=this->_n; j++) 00921 { 00922 columnsum = 0.; 00923 for (unsigned int i=0; i!=this->_m; i++) 00924 { 00925 columnsum += std::abs((*this)(i,j)); 00926 } 00927 my_max = (my_max > columnsum? my_max : columnsum); 00928 } 00929 return my_max; 00930 } 00931 00932 00933 00934 template<typename T> 00935 inline 00936 Real DenseMatrix<T>::linfty_norm () const 00937 { 00938 libmesh_assert (this->_m); 00939 libmesh_assert (this->_n); 00940 00941 Real rowsum = 0.; 00942 for (unsigned int j=0; j!=this->_n; j++) 00943 { 00944 rowsum += std::abs((*this)(0,j)); 00945 } 00946 Real my_max = rowsum; 00947 for (unsigned int i=1; i!=this->_m; i++) 00948 { 00949 rowsum = 0.; 00950 for (unsigned int j=0; j!=this->_n; j++) 00951 { 00952 rowsum += std::abs((*this)(i,j)); 00953 } 00954 my_max = (my_max > rowsum? my_max : rowsum); 00955 } 00956 return my_max; 00957 } 00958 00959 00960 00961 template<typename T> 00962 inline 00963 T DenseMatrix<T>::transpose (const unsigned int i, 00964 const unsigned int j) const 00965 { 00966 // Implement in terms of operator() 00967 return (*this)(j,i); 00968 } 00969 00970 00971 00972 00973 00974 // template<typename T> 00975 // inline 00976 // void DenseMatrix<T>::condense(const unsigned int iv, 00977 // const unsigned int jv, 00978 // const T val, 00979 // DenseVector<T>& rhs) 00980 // { 00981 // libmesh_assert_equal_to (this->_m, rhs.size()); 00982 // libmesh_assert_equal_to (iv, jv); 00983 00984 00985 // // move the known value into the RHS 00986 // // and zero the column 00987 // for (unsigned int i=0; i<this->m(); i++) 00988 // { 00989 // rhs(i) -= ((*this)(i,jv))*val; 00990 // (*this)(i,jv) = 0.; 00991 // } 00992 00993 // // zero the row 00994 // for (unsigned int j=0; j<this->n(); j++) 00995 // (*this)(iv,j) = 0.; 00996 00997 // (*this)(iv,jv) = 1.; 00998 // rhs(iv) = val; 00999 01000 // } 01001 01002 01003 01004 01005 } // namespace libMesh 01006 01007 01008 01009 01010 #endif // LIBMESH_DENSE_MATRIX_H