4 #ifndef DUNE_DENSEMATRIX_HH
5 #define DUNE_DENSEMATRIX_HH
23 template<
typename M>
class DenseMatrix;
42 static typename V::size_type
size(
const V & v) {
return v.size(); }
45 template<
class K,
int N>
48 typedef FieldVector<K,N> V;
49 static typename V::size_type
size(
const V & v) {
return N; }
68 template<
typename M,
typename T>
71 DUNE_THROW(
NotImplemented,
"You need to specialise the method istl_assign_to_fmatrix(DenseMatrix<M>& f, const T& t) "
72 <<
"(with M being " << className<M>() <<
") "
73 <<
"for T == " << className<T>() <<
"!");
79 struct DenseMatrixAssigner
81 template<
typename M,
typename T>
82 static void assign(DenseMatrix<M>& fm,
const T&
t)
91 struct DenseMatrixAssigner<true>
93 template<
typename M,
typename T>
94 static void assign(DenseMatrix<M>& fm,
const T&
t)
96 fm =
static_cast<const typename DenseMatVecTraits<M>::value_type
>(
t);
114 template<
typename MAT>
120 MAT & asImp() {
return static_cast<MAT&
>(*this); }
121 const MAT & asImp()
const {
return static_cast<const MAT&
>(*this); }
161 return asImp().mat_access(i);
166 return asImp().mat_access(i);
257 DenseMatrixAssigner<Conversion<T,field_type>::exists>::assign(*
this, t);
263 template <
class Other>
272 template <
class Other>
297 template <
class Other>
301 (*
this)[ i ].
axpy( k, y[ i ] );
306 template <
class Other>
310 if ((*
this)[i]!=y[i])
315 template <
class Other>
325 template<
class X,
class Y>
326 void mv (
const X& x, Y& y)
const
328 #ifdef DUNE_FMatrix_WITH_CHECKING
336 y[i] += (*
this)[i][j] * x[j];
341 template<
class X,
class Y >
342 void mtv (
const X &x, Y &y )
const
344 #ifdef DUNE_FMatrix_WITH_CHECKING
358 y[ i ] += (*
this)[ j ][ i ] * x[ j ];
363 template<
class X,
class Y>
364 void umv (
const X& x, Y& y)
const
366 #ifdef DUNE_FMatrix_WITH_CHECKING
368 DUNE_THROW(
FMatrixError,
"y += A x -- index out of range (sizes: x: " << x.N() <<
", y: " << y.N() <<
", A: " << this->
N() <<
" x " << this->
M() <<
")" << std::endl);
370 DUNE_THROW(
FMatrixError,
"y += A x -- index out of range (sizes: x: " << x.N() <<
", y: " << y.N() <<
", A: " << this->
N() <<
" x " << this->
M() <<
")" << std::endl);
374 y[i] += (*
this)[i][j] * x[j];
378 template<
class X,
class Y>
379 void umtv (
const X& x, Y& y)
const
381 #ifdef DUNE_FMatrix_WITH_CHECKING
388 y[j] += (*
this)[i][j]*x[i];
392 template<
class X,
class Y>
393 void umhv (
const X& x, Y& y)
const
395 #ifdef DUNE_FMatrix_WITH_CHECKING
406 template<
class X,
class Y>
407 void mmv (
const X& x, Y& y)
const
409 #ifdef DUNE_FMatrix_WITH_CHECKING
415 y[i] -= (*
this)[i][j] * x[j];
419 template<
class X,
class Y>
420 void mmtv (
const X& x, Y& y)
const
422 #ifdef DUNE_FMatrix_WITH_CHECKING
429 y[j] -= (*
this)[i][j]*x[i];
433 template<
class X,
class Y>
434 void mmhv (
const X& x, Y& y)
const
436 #ifdef DUNE_FMatrix_WITH_CHECKING
447 template<
class X,
class Y>
450 #ifdef DUNE_FMatrix_WITH_CHECKING
456 y[i] += alpha * (*
this)[i][j] * x[j];
460 template<
class X,
class Y>
463 #ifdef DUNE_FMatrix_WITH_CHECKING
470 y[j] += alpha*(*
this)[i][j]*x[i];
474 template<
class X,
class Y>
477 #ifdef DUNE_FMatrix_WITH_CHECKING
493 for (
size_type i=0; i<
rows(); ++i) sum += (*
this)[i].two_norm2();
494 return fvmeta::sqrt(sum);
501 for (
size_type i=0; i<
rows(); ++i) sum += (*
this)[i].two_norm2();
509 for (
size_type i=0; i<
rows(); ++i) max = std::max(max,(*
this)[i].one_norm());
517 for (
size_type i=0; i<
rows(); ++i) max = std::max(max,(*
this)[i].one_norm_real());
528 void solve (V& x,
const V& b)
const;
540 template<
typename M2>
550 (*
this)[i][j] += M[i][k]*C[k][j];
557 template<
typename M2>
567 (*
this)[i][j] += C[i][k]*M[k][j];
583 C[i][j] += M[i][k]*(*
this)[k][j];
591 FieldMatrix<K,rows,l> rightmultiplyany (
const FieldMatrix<K,cols,l>& M)
const
593 FieldMatrix<K,rows,l> C;
599 C[i][j] += (*
this)[i][k]*M[k][j];
623 return asImp().mat_rows();
629 return asImp().mat_cols();
637 #ifdef DUNE_FMatrix_WITH_CHECKING
649 ElimPivot(std::vector<size_type> & pivot);
651 void swap(
int i,
int j);
654 void operator()(
const T&,
int k,
int i)
657 std::vector<size_type> & pivot_;
665 void swap(
int i,
int j);
667 void operator()(
const typename V::field_type& factor,
int k,
int i);
677 void swap(
int i,
int j)
680 void operator()(
const field_type&,
int k,
int i)
688 void luDecomposition(DenseMatrix<MAT>& A, Func func)
const;
692 template<
typename MAT>
693 DenseMatrix<MAT>::ElimPivot::ElimPivot(std::vector<size_type> & pivot)
696 typedef typename std::vector<size_type>::size_type size_type;
697 for(size_type i=0; i < pivot_.size(); ++i) pivot_[i]=i;
700 template<
typename MAT>
701 void DenseMatrix<MAT>::ElimPivot::swap(
int i,
int j)
706 template<
typename MAT>
708 DenseMatrix<MAT>::Elim<V>::Elim(V& rhs)
712 template<
typename MAT>
714 void DenseMatrix<MAT>::Elim<V>::swap(
int i,
int j)
716 std::swap((*rhs_)[i], (*rhs_)[j]);
719 template<
typename MAT>
721 void DenseMatrix<MAT>::
722 Elim<V>::operator()(
const typename V::field_type& factor,
int k,
int i)
724 (*rhs_)[k] -= factor*(*rhs_)[i];
726 template<
typename MAT>
727 template<
typename Func>
728 inline void DenseMatrix<MAT>::luDecomposition(DenseMatrix<MAT>& A, Func func)
const
730 typedef typename FieldTraits<value_type>::real_type
732 real_type norm = A.infinity_norm_real();
733 real_type pivthres = std::max( FMatrixPrecision< real_type >::absolute_limit(), norm * FMatrixPrecision< real_type >::pivoting_limit() );
734 real_type singthres = std::max( FMatrixPrecision< real_type >::absolute_limit(), norm * FMatrixPrecision< real_type >::singular_limit() );
737 for (size_type i=0; i<rows(); i++)
739 typename FieldTraits<value_type>::real_type pivmax=fvmeta::absreal(A[i][i]);
746 typename FieldTraits<value_type>::real_type abs(0.0);
747 for (size_type k=i+1; k<rows(); k++)
748 if ((abs=fvmeta::absreal(A[k][i]))>pivmax)
750 pivmax = abs; imax = k;
754 for (size_type j=0; j<rows(); j++)
755 std::swap(A[i][j],A[imax][j]);
761 if (pivmax<singthres)
762 DUNE_THROW(FMatrixError,
"matrix is singular");
765 for (size_type k=i+1; k<rows(); k++)
767 field_type factor = A[k][i]/A[i][i];
769 for (size_type j=i+1; j<rows(); j++)
770 A[k][j] -= factor*A[i][j];
776 template<
typename MAT>
778 inline void DenseMatrix<MAT>::solve(V& x,
const V& b)
const
782 DUNE_THROW(FMatrixError,
"Can't solve for a " << rows() <<
"x" << cols() <<
" matrix!");
786 #ifdef DUNE_FMatrix_WITH_CHECKING
787 if (fvmeta::absreal((*
this)[0][0])<FMatrixPrecision<>::absolute_limit())
788 DUNE_THROW(FMatrixError,
"matrix is singular");
790 x[0] = b[0]/(*this)[0][0];
793 else if (rows()==2) {
795 field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
796 #ifdef DUNE_FMatrix_WITH_CHECKING
797 if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
798 DUNE_THROW(FMatrixError,
"matrix is singular");
802 x[0] = detinv*((*this)[1][1]*b[0]-(*this)[0][1]*b[1]);
803 x[1] = detinv*((*this)[0][0]*b[1]-(*this)[1][0]*b[0]);
806 else if (rows()==3) {
808 field_type d = determinant();
809 #ifdef DUNE_FMatrix_WITH_CHECKING
810 if (fvmeta::absreal(d)<FMatrixPrecision<>::absolute_limit())
811 DUNE_THROW(FMatrixError,
"matrix is singular");
814 x[0] = (b[0]*(*this)[1][1]*(*this)[2][2] - b[0]*(*this)[2][1]*(*this)[1][2]
815 - b[1] *(*this)[0][1]*(*this)[2][2] + b[1]*(*this)[2][1]*(*this)[0][2]
816 + b[2] *(*this)[0][1]*(*this)[1][2] - b[2]*(*this)[1][1]*(*this)[0][2]) / d;
818 x[1] = ((*this)[0][0]*b[1]*(*this)[2][2] - (*this)[0][0]*b[2]*(*this)[1][2]
819 - (*this)[1][0] *b[0]*(*this)[2][2] + (*this)[1][0]*b[2]*(*this)[0][2]
820 + (*this)[2][0] *b[0]*(*this)[1][2] - (*this)[2][0]*b[1]*(*this)[0][2]) / d;
822 x[2] = ((*this)[0][0]*(*this)[1][1]*b[2] - (*this)[0][0]*(*this)[2][1]*b[1]
823 - (*this)[1][0] *(*this)[0][1]*b[2] + (*this)[1][0]*(*this)[2][1]*b[0]
824 + (*this)[2][0] *(*this)[0][1]*b[1] - (*this)[2][0]*(*this)[1][1]*b[0]) / d;
834 luDecomposition(A, elim);
837 for(
int i=rows()-1; i>=0; i--){
838 for (size_type j=i+1; j<rows(); j++)
839 rhs[i] -= A[i][j]*x[j];
840 x[i] = rhs[i]/A[i][i];
845 template<
typename MAT>
846 inline void DenseMatrix<MAT>::invert()
850 DUNE_THROW(FMatrixError,
"Can't invert a " << rows() <<
"x" << cols() <<
" matrix!");
854 #ifdef DUNE_FMatrix_WITH_CHECKING
855 if (fvmeta::absreal((*
this)[0][0])<FMatrixPrecision<>::absolute_limit())
856 DUNE_THROW(FMatrixError,
"matrix is singular");
858 (*this)[0][0] = 1.0/(*this)[0][0];
861 else if (rows()==2) {
863 field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
864 #ifdef DUNE_FMatrix_WITH_CHECKING
865 if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
866 DUNE_THROW(FMatrixError,
"matrix is singular");
870 field_type temp=(*this)[0][0];
871 (*this)[0][0] = (*this)[1][1]*detinv;
872 (*this)[0][1] = -(*this)[0][1]*detinv;
873 (*this)[1][0] = -(*this)[1][0]*detinv;
874 (*this)[1][1] = temp*detinv;
880 std::vector<size_type> pivot(rows());
881 luDecomposition(A, ElimPivot(pivot));
882 DenseMatrix<MAT>& L=A;
883 DenseMatrix<MAT>& U=A;
888 for(size_type i=0; i<rows(); ++i)
892 for (size_type i=0; i<rows(); i++)
893 for (size_type j=0; j<i; j++)
894 for (size_type k=0; k<rows(); k++)
895 (*
this)[i][k] -= L[i][j]*(*this)[j][k];
898 for (size_type i=rows(); i>0;){
900 for (size_type k=0; k<rows(); k++){
901 for (size_type j=i+1; j<rows(); j++)
902 (*
this)[i][k] -= U[i][j]*(*this)[j][k];
903 (*this)[i][k] /= U[i][i];
907 for(size_type i=rows(); i>0; ){
910 for(size_type j=0; j<rows(); ++j)
911 std::swap((*
this)[j][pivot[i]], (*this)[j][i]);
917 template<
typename MAT>
918 inline typename DenseMatrix<MAT>::field_type
919 DenseMatrix<MAT>::determinant()
const
923 DUNE_THROW(FMatrixError,
"There is no determinant for a " << rows() <<
"x" << cols() <<
" matrix!");
926 return (*
this)[0][0];
929 return (*
this)[0][0]*(*this)[1][1] - (*this)[0][1]*(*this)[1][0];
933 field_type t4 = (*this)[0][0] * (*this)[1][1];
934 field_type t6 = (*this)[0][0] * (*this)[1][2];
935 field_type t8 = (*this)[0][1] * (*this)[1][0];
936 field_type t10 = (*this)[0][2] * (*this)[1][0];
937 field_type t12 = (*this)[0][1] * (*this)[2][0];
938 field_type t14 = (*this)[0][2] * (*this)[2][0];
940 return (t4*(*
this)[2][2]-t6*(*
this)[2][1]-t8*(*
this)[2][2]+
941 t10*(*
this)[2][1]+t12*(*
this)[1][2]-t14*(*
this)[1][1]);
949 luDecomposition(A, ElimDet(det));
951 catch (FMatrixError&)
955 for (size_type i = 0; i < rows(); ++i)
962 namespace DenseMatrixHelp {
965 template <
typename K>
968 inverse[0][0] = 1.0/matrix[0][0];
973 template <
typename K>
981 template <
typename K>
985 field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
986 field_type det_1 = 1.0/det;
987 inverse[0][0] = matrix[1][1] * det_1;
988 inverse[0][1] = - matrix[0][1] * det_1;
989 inverse[1][0] = - matrix[1][0] * det_1;
990 inverse[1][1] = matrix[0][0] * det_1;
996 template <
typename K>
1000 field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
1001 field_type det_1 = 1.0/det;
1002 inverse[0][0] = matrix[1][1] * det_1;
1003 inverse[1][0] = - matrix[0][1] * det_1;
1004 inverse[0][1] = - matrix[1][0] * det_1;
1005 inverse[1][1] = matrix[0][0] * det_1;
1010 template <
typename K>
1014 field_type t4 = matrix[0][0] * matrix[1][1];
1015 field_type t6 = matrix[0][0] * matrix[1][2];
1016 field_type t8 = matrix[0][1] * matrix[1][0];
1017 field_type t10 = matrix[0][2] * matrix[1][0];
1018 field_type t12 = matrix[0][1] * matrix[2][0];
1019 field_type t14 = matrix[0][2] * matrix[2][0];
1021 field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
1022 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
1023 field_type t17 = 1.0/det;
1025 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
1026 inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
1027 inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
1028 inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
1029 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
1030 inverse[1][2] = -(t6-t10) * t17;
1031 inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
1032 inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
1033 inverse[2][2] = (t4-t8) * t17;
1039 template <
typename K>
1043 field_type t4 = matrix[0][0] * matrix[1][1];
1044 field_type t6 = matrix[0][0] * matrix[1][2];
1045 field_type t8 = matrix[0][1] * matrix[1][0];
1046 field_type t10 = matrix[0][2] * matrix[1][0];
1047 field_type t12 = matrix[0][1] * matrix[2][0];
1048 field_type t14 = matrix[0][2] * matrix[2][0];
1050 field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
1051 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
1052 field_type t17 = 1.0/det;
1054 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
1055 inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
1056 inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
1057 inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
1058 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
1059 inverse[2][1] = -(t6-t10) * t17;
1060 inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
1061 inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
1062 inverse[2][2] = (t4-t8) * t17;
1068 template<
class K,
int m,
int n,
int p >
1075 for( size_type i = 0; i < m; ++i )
1077 for( size_type j = 0; j < p; ++j )
1079 ret[ i ][ j ] = K( 0 );
1080 for( size_type k = 0; k < n; ++k )
1081 ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
1087 template <
typename K,
int rows,
int cols>
1092 for(size_type i=0; i<cols(); i++)
1093 for(size_type j=0; j<cols(); j++)
1096 for(size_type k=0; k<rows(); k++)
1097 ret[i][j]+=matrix[k][i]*matrix[k][j];
1103 template <
typename MAT,
typename V1,
typename V2>
1107 assert(ret.
size() == matrix.
rows());
1110 for(size_type i=0; i<matrix.
rows(); ++i)
1113 for(size_type j=0; j<matrix.
cols(); ++j)
1115 ret[i] += matrix[i][j]*x[j];
1122 template <
typename K,
int rows,
int cols>
1127 for(size_type i=0; i<cols(); ++i)
1130 for(size_type j=0; j<rows(); ++j)
1131 ret[i] += matrix[j][i]*x[j];
1136 template <
typename K,
int rows,
int cols>
1137 static inline FieldVector<K,rows>
mult(
const FieldMatrix<K,rows,cols> &matrix,
const FieldVector<K,cols> & x)
1139 FieldVector<K,rows> ret;
1145 template <
typename K,
int rows,
int cols>
1146 static inline FieldVector<K,cols>
multTransposed(
const FieldMatrix<K,rows,cols> &matrix,
const FieldVector<K,rows> & x)
1148 FieldVector<K,cols> ret;
1157 template<
typename MAT>
1158 std::ostream& operator<< (std::ostream& s, const DenseMatrix<MAT>& a)
1161 s << a[i] << std::endl;