20 #ifndef LIBMESH_DENSE_MATRIX_H
21 #define LIBMESH_DENSE_MATRIX_H
24 #include "libmesh/libmesh_common.h"
25 #include "libmesh/dense_matrix_base.h"
26 #include "libmesh/int_range.h"
29 #if (LIBMESH_HAVE_PETSC)
30 # include "libmesh/petsc_macro.h"
32 # define LIBMESH_SAW_I
35 #include "libmesh/ignore_warnings.h"
36 # include <petscsys.h>
37 #include "libmesh/restore_warnings.h"
39 # ifndef LIBMESH_SAW_I
40 # undef I // Avoid complex.h contamination
47 #include <initializer_list>
49 #ifdef LIBMESH_HAVE_METAPHYSICL
50 #include "metaphysicl/dualnumber_decl.h"
51 #include "metaphysicl/raw_type.h"
58 template <
typename T>
class DenseVector;
70 class DenseMatrix :
public DenseMatrixBase<T>
81 const unsigned int new_n=0);
90 template <
typename T2>
93 std::initializer_list<T2> init_list);
120 virtual void zero() override final;
132 unsigned int col_id,
unsigned int col_size) const;
141 T operator() (const
unsigned int i,
142 const
unsigned int j) const;
151 T & operator() (const
unsigned int i,
152 const
unsigned int j);
160 virtual T
el(const
unsigned int i,
161 const
unsigned int j) const override final
162 {
return (*
this)(i,j); }
171 virtual T &
el(
const unsigned int i,
172 const unsigned int j)
override final
173 {
return (*
this)(i,j); }
188 template <
typename T2>
204 template <
typename T2>
223 template <
typename T2>
243 template <
typename T2>
266 template <
typename T2,
typename T3>
314 template <
typename T2>
333 void resize(
const unsigned int new_m,
334 const unsigned int new_n);
341 void scale (
const T factor);
349 void scale_column (
const unsigned int col,
const T factor);
364 template<
typename T2,
typename T3>
365 typename boostcopy::enable_if_c<
366 ScalarTraits<T2>::value,
void >::type
add (
const T2 factor,
420 auto
l1_norm () const -> decltype(std::
abs(T(0)));
444 template <typename T2>
461 template <typename T2>
472 const
unsigned int j) const;
508 const unsigned int j,
546 template <
typename T2>
593 Real rcond=std::numeric_limits<Real>::epsilon())
const;
738 template <
typename T2>
825 std::vector<Real> & sigma_val,
826 std::vector<Number> & U_val,
827 std::vector<Number> & VT_val);
848 #if (LIBMESH_HAVE_PETSC && LIBMESH_USE_REAL_NUMBERS)
886 bool trans=
false)
const;
894 template <
typename T2>
903 template <
typename T2>
915 namespace DenseMatrices
934 using namespace DenseMatrices;
939 #if defined(LIBMESH_HAVE_PETSC) && \
940 defined(LIBMESH_USE_REAL_NUMBERS) && \
941 defined(LIBMESH_DEFAULT_DOUBLE_PRECISION)
945 static const bool value =
true;
955 const unsigned int new_n) :
959 _decomposition_type(NONE)
961 this->
resize(new_m,new_n);
964 template <
typename T>
965 template <
typename T2>
968 std::initializer_list<T2> init_list) :
971 _val(init_list.begin(), init_list.end()),
972 _decomposition_type(NONE)
975 libmesh_assert_equal_to(nrow * ncol, init_list.size());
984 std::swap(this->_m, other_matrix._m);
985 std::swap(this->_n, other_matrix._n);
986 _val.swap(other_matrix._val);
988 _decomposition_type = other_matrix._decomposition_type;
989 other_matrix._decomposition_type = _temp;
993 template <
typename T>
994 template <
typename T2>
999 unsigned int mat_m = mat.m(), mat_n = mat.n();
1000 this->resize(mat_m, mat_n);
1001 for (
unsigned int i=0; i<mat_m; i++)
1002 for (
unsigned int j=0; j<mat_n; j++)
1003 (*
this)(i,j) = mat(i,j);
1010 template<
typename T>
1013 const unsigned int new_n)
1015 _val.resize(new_m*new_n);
1026 template<
typename T>
1030 _decomposition_type = NONE;
1032 std::fill (_val.begin(), _val.end(),
static_cast<T
>(0));
1037 template<
typename T>
1040 unsigned int col_id,
unsigned int col_size)
const
1042 libmesh_assert_less (row_id + row_size - 1, this->_m);
1043 libmesh_assert_less (col_id + col_size - 1, this->_n);
1048 sub._val.resize(row_size * col_size);
1050 unsigned int end_col = this->_n - col_size - col_id;
1051 unsigned int p = row_id * this->_n;
1053 for (
unsigned int i=0; i<row_size; i++)
1057 for (
unsigned int j=0; j<col_size; j++)
1058 sub._val[q++] = _val[p++];
1068 template<
typename T>
1071 const unsigned int j)
const
1073 libmesh_assert_less (i*j, _val.size());
1074 libmesh_assert_less (i, this->_m);
1075 libmesh_assert_less (j, this->_n);
1079 return _val[(i)*(this->_n) + (j)];
1084 template<
typename T>
1087 const unsigned int j)
1089 libmesh_assert_less (i*j, _val.size());
1090 libmesh_assert_less (i, this->_m);
1091 libmesh_assert_less (j, this->_n);
1094 return _val[(i)*(this->_n) + (j)];
1101 template<
typename T>
1105 for (
auto & v : _val)
1110 template<
typename T>
1114 for (
auto i : make_range(this->m()))
1115 (*this)(i, col) *= factor;
1120 template<
typename T>
1124 this->scale(factor);
1130 template<
typename T>
1131 template<
typename T2,
typename T3>
1133 typename boostcopy::enable_if_c<
1134 ScalarTraits<T2>::value,
void >::type
1138 libmesh_assert_equal_to (this->m(), mat.m());
1139 libmesh_assert_equal_to (this->n(), mat.n());
1141 for (
auto i : make_range(this->m()))
1142 for (
auto j : make_range(this->n()))
1143 (*
this)(i,j) += factor * mat(i,j);
1148 template<
typename T>
1152 for (
auto i : index_range(_val))
1153 if (_val[i] != mat._val[i])
1161 template<
typename T>
1165 for (
auto i : index_range(_val))
1166 if (_val[i] != mat._val[i])
1174 template<
typename T>
1178 for (
auto i : index_range(_val))
1179 _val[i] += mat._val[i];
1186 template<
typename T>
1190 for (
auto i : index_range(_val))
1191 _val[i] -= mat._val[i];
1198 template<
typename T>
1202 libmesh_assert (this->_m);
1203 libmesh_assert (this->_n);
1206 for (
unsigned int i=0; i!=this->_m; i++)
1208 for (
unsigned int j=0; j!=this->_n; j++)
1211 my_min = (my_min < current? my_min : current);
1219 template<
typename T>
1223 libmesh_assert (this->_m);
1224 libmesh_assert (this->_n);
1227 for (
unsigned int i=0; i!=this->_m; i++)
1229 for (
unsigned int j=0; j!=this->_n; j++)
1232 my_max = (my_max > current? my_max : current);
1240 template<
typename T>
1244 libmesh_assert (this->_m);
1245 libmesh_assert (this->_n);
1248 for (
unsigned int i=0; i!=this->_m; i++)
1250 columnsum +=
std::abs((*
this)(i,0));
1252 auto my_max = columnsum;
1253 for (
unsigned int j=1; j!=this->_n; j++)
1256 for (
unsigned int i=0; i!=this->_m; i++)
1258 columnsum +=
std::abs((*
this)(i,j));
1260 my_max = (my_max > columnsum? my_max : columnsum);
1267 template<
typename T>
1271 libmesh_assert (this->_m);
1272 libmesh_assert (this->_n);
1275 for (
unsigned int j=0; j!=this->_n; j++)
1279 auto my_max = rowsum;
1280 for (
unsigned int i=1; i!=this->_m; i++)
1283 for (
unsigned int j=0; j!=this->_n; j++)
1287 my_max = (my_max > rowsum? my_max : rowsum);
1294 template<
typename T>
1297 const unsigned int j)
const
1300 return (*
this)(j,i);
1340 #ifdef LIBMESH_HAVE_METAPHYSICL
1341 namespace MetaPhysicL
1343 template <
typename T>
1344 struct RawType<libMesh::DenseMatrix<T>>
1350 const auto m = in.
m(), n = in.
n();
1352 for (
unsigned int i = 0; i < m; ++i)
1353 for (
unsigned int j = 0; j < n; ++j)
1354 ret(i,j) = raw_value(in(i,j));
1363 #endif // LIBMESH_DENSE_MATRIX_H
bool operator!=(const DenseMatrix< T > &mat) const
检查矩阵是否与另一个矩阵 mat 完全不相等。
void _matvec_blas(T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
使用BLAS GEMV函数(通过PETSc)计算
void _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
通过回代步骤解方程Ax=b。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
void swap(DenseMatrix< T > &other_matrix)
STL 风格的交换方法,交换值和分解方法。
void condense(const unsigned int i, const unsigned int j, const T val, DenseVector< T > &rhs)
将矩阵的 (i,j) 元素凝聚出来,强制其取值为 val。
unsigned int n() const
返回矩阵的列维度。
DenseMatrix< Complex > ComplexDenseMatrix
此typedef可能是仅包含实数的矩阵,也可能是真正的复数矩阵, 具体取决于 libmesh_common.h 中如何定义 Number。 此外,要注意对于实数数据,DenseMatrix<T> 可能比...
void _lu_decompose_lapack()
使用Lapack例程“getrf”计算矩阵的LU分解。此例程只能由lu_solve()函数的“use_blas_lapack”分支使用。 调用此函数后,矩阵将被其因式分解版本替换,并且Decomposi...
void svd_solve(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond=std::numeric_limits< Real >::epsilon()) const
以最小二乘意义解方程组 。 可能是非方阵和/或秩亏的。 可以通过更改“rcond”参数来控制哪些奇异值被视为零。 对于满足S(i) <= rcond*S(1)的奇异值S(i),在解的目的上被视为零。 ...
virtual void zero() overridefinal
将矩阵的所有元素设置为0,并重置任何可能先前设置的分解标志。 这允许例如计算新的LU分解,同时重用相同的存储空间。
auto max() const -> decltype(libmesh_real(T(0)))
返回矩阵的最大元素或复数情况下的最大实部。
_BLAS_Multiply_Flag
用于确定_multiply_blas函数行为的枚举。
const std::vector< T > & get_values() const
返回底层数据存储矢量的常量引用。
DenseMatrix< T > & operator+=(const DenseMatrix< T > &mat)
将矩阵 mat 添加到此矩阵。
virtual void left_multiply(const DenseMatrixBase< T > &M2) overridefinal
左乘以矩阵 M2。
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
bool operator==(const DenseMatrix< T > &mat) const
检查矩阵是否与另一个矩阵 mat 完全相等。
void evd_left(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL)
计算一般矩阵 的特征值(实部和虚部)和左特征向量。
virtual ~DenseMatrix()=default
析构函数。析构函数使用默认实现,因为该类不管理任何内存。
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
根据矩阵A的Cholesky分解解方程Ax=b,得到未知值x和rhs b。
void evd_left_and_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL, DenseMatrix< T > &VR)
计算一般矩阵的特征值(实部和虚部),以及左右特征向量。
auto l1_norm() const -> decltype(std::abs(T(0)))
返回矩阵的 l1-范数,即最大列和
void get_transpose(DenseMatrix< T > &dest) const
将转置矩阵存储在 dest 中。
DenseMatrix< T > & operator-=(const DenseMatrix< T > &mat)
从此矩阵中减去矩阵 mat。
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
_multiply_blas函数使用BLAS gemm函数计算A <- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_...
DenseMatrix(const unsigned int new_m=0, const unsigned int new_n=0)
构造函数。创建一个维度为 m x n 的密集矩阵。
void outer_product(const DenseVector< T > &a, const DenseVector< T > &b)
计算两个向量的外积并将结果存储在 (*this) 中。
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
void scale_column(const unsigned int col, const T factor)
将矩阵的第 col 列的每个元素乘以 factor。
DenseMatrix & operator=(const DenseMatrix &)=default
复制赋值运算符。复制赋值运算符使用默认实现,因为该类不管理任何内存。
unsigned int m() const
返回矩阵的行维度。
void _lu_back_substitute_lapack(const DenseVector< T > &b, DenseVector< T > &x)
与_lu_decompose_lapack()相对应的伴随函数。不要直接使用,通过公共lu_solve()接口调用。 由于我们只是调用LAPACK例程,该函数在逻辑上是const的,因为它不修改矩阵, ...
void svd(DenseVector< Real > &sigma)
计算矩阵的奇异值分解(SVD)。 在退出时,sigma包含所有奇异值(按降序排列)。
auto linfty_norm() const -> decltype(std::abs(T(0)))
返回矩阵的 linfty-范数,即最大行和
void _lu_decompose()
形成矩阵的LU分解。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
执行缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg.
T transpose(const unsigned int i, const unsigned int j) const
返回转置矩阵的 (i, j) 元素。
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseMatrix< T3 > &mat)
将 factor 倍的矩阵 mat 添加到此矩阵。
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
将 sub_m x sub_n 的主子矩阵放入 dest 中。
DenseMatrix< Real > RealDenseMatrix
仅包含实数的密集矩阵的方便定义。
void evd_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VR)
计算一般矩阵 的特征值(实部和虚部)和右特征向量。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
void _cholesky_decompose()
将对称正定矩阵分解为两个下三角矩阵的乘积,即A = LL^T。
void _svd_lapack(DenseVector< Real > &sigma)
使用Lapack例程“getsvd”计算矩阵的奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ]
std::vector< T > & get_values()
返回对应于存储向量的引用的底层数据存储矢量。
T operator()(const unsigned int i, const unsigned int j) const
获取矩阵的 (i,j) 元素。
void right_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置右乘。
void scale(const T factor)
将矩阵的每个元素乘以 factor。
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
解方程组 给定输入向量 b。
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void _evd_lapack(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > *VL=nullptr, DenseMatrix< T > *VR=nullptr)
使用Lapack例程“DGEEV”计算矩阵的特征值。如果VR和/或VL不为nullptr, 则此函数还计算并返回右和/或左特征向量的矩阵。 [ 在dense_matrix_blas_lapack.C中实现 ]
void evd(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag)
计算一般矩阵的特征值(实部和虚部)。
void left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。
用于确定是否使用blas_lapack的辅助结构。
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
auto min() const -> decltype(libmesh_real(T(0)))
返回矩阵的最小元素或复数情况下的最小实部。
DenseMatrix sub_matrix(unsigned int row_id, unsigned int row_size, unsigned int col_id, unsigned int col_size) const
获取具有最小行和列索引以及子矩阵大小的子矩阵。
std::vector< T > _val
实际的数据值,存储为1D数组。
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
对于对称正定矩阵(SPD),进行Cholesky分解。 分解为 A = L L^T,比标准LU分解大约快两倍。 因此,如果事先知道矩阵是SPD,则可以使用此方法。如果矩阵不是SPD,则会生成错误。 Ch...
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
void _svd_solve_lapack(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond) const
由svd_solve(rhs)调用。
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。
DenseMatrix< T > & operator*=(const T factor)
将矩阵的每个元素乘以 factor。
为有限元类型的计算定义了一个抽象的稠密矩阵基类。例如 DenseSubMatrices 可以从这个类派生出来。
virtual T & el(const unsigned int i, const unsigned int j) overridefinal
获取矩阵的 (i,j) 元素的可写引用。
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
void _svd_helper(char JOBU, char JOBVT, std::vector< Real > &sigma_val, std::vector< Number > &U_val, std::vector< Number > &VT_val)
实际执行SVD的辅助函数。 [ 在dense_matrix_blas_lapack.C中实现 ]
DecompositionType
_cholesky_back_substitute 的分解方案会改变矩阵A的条目。因此,在调用A.lu_solve()后再次调用A.cholesky_solve()是错误的, 因为结果可能不符合任何预期...
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
std::vector< pivot_index_t > _pivots
PetscBLASInt pivot_index_t
用于存储枢轴索引的数组。可能被当前活动的任何因式分解使用, 类的客户端不应出于任何原因依赖它。
void condense(const unsigned int i, const unsigned int j, const T val, DenseVectorBase< T > &rhs)
将矩阵的 (i,j) 条目压缩出来,强制它取值为 val。这对于在数值模拟中应用边界条件很有用。 保留矩阵的对称性。
virtual T el(const unsigned int i, const unsigned int j) const overridefinal
获取矩阵的 (i,j) 元素。