$extrastylesheet
dense_matrix.h
Go to the documentation of this file.
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