libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
| Public 成员函数 | Public 属性 | Protected 成员函数 | 静态 Protected 成员函数 | Protected 属性 | Private 类型 | Private 成员函数 | Private 属性 | 所有成员列表
libMesh::DenseMatrix< T > 模板类 参考

定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。 更多...

#include <dof_map.h>

类 libMesh::DenseMatrix< T > 继承关系图:
[图例]

struct  UseBlasLapack
 用于确定是否使用blas_lapack的辅助结构。 更多...
 

Public 成员函数

 DenseMatrix (const unsigned int new_m=0, const unsigned int new_n=0)
 构造函数。创建一个维度为 m x n 的密集矩阵。 更多...
 
template<typename T2 >
 DenseMatrix (unsigned int nrow, unsigned int ncol, std::initializer_list< T2 > init_list)
 构造函数。根据行数、列数和初始化列表创建矩阵。 更多...
 
 DenseMatrix (DenseMatrix &&)=default
 移动构造函数。移动构造函数使用默认实现,因为该类不管理任何内存。 更多...
 
 DenseMatrix (const DenseMatrix &)=default
 复制构造函数。复制构造函数使用默认实现,因为该类不管理任何内存。 更多...
 
DenseMatrixoperator= (const DenseMatrix &)=default
 复制赋值运算符。复制赋值运算符使用默认实现,因为该类不管理任何内存。 更多...
 
DenseMatrixoperator= (DenseMatrix &&)=default
 移动赋值运算符。移动赋值运算符使用默认实现,因为该类不管理任何内存。 更多...
 
virtual ~DenseMatrix ()=default
 析构函数。析构函数使用默认实现,因为该类不管理任何内存。 更多...
 
virtual void zero () overridefinal
 将矩阵的所有元素设置为0,并重置任何可能先前设置的分解标志。 这允许例如计算新的LU分解,同时重用相同的存储空间。 更多...
 
DenseMatrix sub_matrix (unsigned int row_id, unsigned int row_size, unsigned int col_id, unsigned int col_size) const
 获取具有最小行和列索引以及子矩阵大小的子矩阵。 更多...
 
operator() (const unsigned int i, const unsigned int j) const
 获取矩阵的 (i,j) 元素。 更多...
 
T & operator() (const unsigned int i, const unsigned int j)
 获取矩阵的 (i,j) 元素的可写引用。 更多...
 
virtual T el (const unsigned int i, const unsigned int j) const overridefinal
 获取矩阵的 (i,j) 元素。 更多...
 
virtual T & el (const unsigned int i, const unsigned int j) overridefinal
 获取矩阵的 (i,j) 元素的可写引用。 更多...
 
virtual void left_multiply (const DenseMatrixBase< T > &M2) overridefinal
 左乘以矩阵 M2。 更多...
 
template<typename T2 >
void left_multiply (const DenseMatrixBase< T2 > &M2)
 左乘以不同类型的矩阵 M2。 更多...
 
virtual void right_multiply (const DenseMatrixBase< T > &M2) overridefinal
 右乘以矩阵 M2。 更多...
 
template<typename T2 >
void right_multiply (const DenseMatrixBase< T2 > &M2)
 右乘以不同类型的矩阵 M2。 更多...
 
void vector_mult (DenseVector< T > &dest, const DenseVector< T > &arg) const
 执行矩阵-向量乘法,dest := (*this) * arg。 更多...
 
template<typename T2 >
void vector_mult (DenseVector< typename CompareTypes< T, T2 >::supertype > &dest, const DenseVector< T2 > &arg) const
 执行矩阵-向量乘法,dest := (*this) * arg ,支持不同类型的矩阵和向量。 更多...
 
void vector_mult_transpose (DenseVector< T > &dest, const DenseVector< T > &arg) const
 执行矩阵-向量乘法,dest := (*this)^T * arg。 更多...
 
template<typename T2 >
void vector_mult_transpose (DenseVector< typename CompareTypes< T, T2 >::supertype > &dest, const DenseVector< T2 > &arg) const
 执行矩阵-向量乘法,dest := (*this)^T * arg,支持不同类型的矩阵和向量。 更多...
 
void vector_mult_add (DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
 执行缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg. 更多...
 
template<typename T2 , typename T3 >
void vector_mult_add (DenseVector< typename CompareTypes< T, typename CompareTypes< T2, T3 >::supertype >::supertype > &dest, const T2 factor, const DenseVector< T3 > &arg) const
 执行混合类型的缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg. 更多...
 
void get_principal_submatrix (unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
 sub_m x sub_n 的主子矩阵放入 dest 中。 更多...
 
void get_principal_submatrix (unsigned int sub_m, DenseMatrix< T > &dest) const
 sub_m x sub_m 的主子矩阵放入 dest 中。 更多...
 
void outer_product (const DenseVector< T > &a, const DenseVector< T > &b)
 计算两个向量的外积并将结果存储在 (*this) 中。 更多...
 
template<typename T2 >
DenseMatrix< T > & operator= (const DenseMatrix< T2 > &other_matrix)
 从另一种矩阵类型复制矩阵。 更多...
 
void swap (DenseMatrix< T > &other_matrix)
 STL 风格的交换方法,交换值和分解方法。 更多...
 
void resize (const unsigned int new_m, const unsigned int new_n)
 调整矩阵的大小,并调用 zero() 方法。 更多...
 
void scale (const T factor)
 将矩阵的每个元素乘以 factor。 更多...
 
void scale_column (const unsigned int col, const T factor)
 将矩阵的第 col 列的每个元素乘以 factor。 更多...
 
DenseMatrix< T > & operator*= (const T factor)
 将矩阵的每个元素乘以 factor。 更多...
 
template<typename T2 , typename T3 >
boostcopy::enable_if_c
< ScalarTraits< T2 >::value,
void >::type 
add (const T2 factor, const DenseMatrix< T3 > &mat)
 factor 倍的矩阵 mat 添加到此矩阵。 更多...
 
bool operator== (const DenseMatrix< T > &mat) const
 检查矩阵是否与另一个矩阵 mat 完全相等。 更多...
 
bool operator!= (const DenseMatrix< T > &mat) const
 检查矩阵是否与另一个矩阵 mat 完全不相等。 更多...
 
DenseMatrix< T > & operator+= (const DenseMatrix< T > &mat)
 将矩阵 mat 添加到此矩阵。 更多...
 
DenseMatrix< T > & operator-= (const DenseMatrix< T > &mat)
 从此矩阵中减去矩阵 mat。 更多...
 
auto min () const -> decltype(libmesh_real(T(0)))
 返回矩阵的最小元素或复数情况下的最小实部。 更多...
 
auto max () const -> decltype(libmesh_real(T(0)))
 返回矩阵的最大元素或复数情况下的最大实部。 更多...
 
auto l1_norm () const -> decltype(std::abs(T(0)))
 返回矩阵的 l1-范数,即最大列和 更多...
 
auto linfty_norm () const -> decltype(std::abs(T(0)))
 返回矩阵的 linfty-范数,即最大行和 更多...
 
void left_multiply_transpose (const DenseMatrix< T > &A)
 用矩阵 A 的转置左乘。 更多...
 
template<typename T2 >
void left_multiply_transpose (const DenseMatrix< T2 > &A)
 用包含不同数值类型的矩阵 A 的转置左乘。 更多...
 
void right_multiply_transpose (const DenseMatrix< T > &A)
 用矩阵 A 的转置右乘。 更多...
 
template<typename T2 >
void right_multiply_transpose (const DenseMatrix< T2 > &A)
 用包含不同数值类型的矩阵 A 的转置右乘。 更多...
 
transpose (const unsigned int i, const unsigned int j) const
 返回转置矩阵的 (i, j) 元素。 更多...
 
void get_transpose (DenseMatrix< T > &dest) const
 将转置矩阵存储在 dest 中。 更多...
 
std::vector< T > & get_values ()
 返回对应于存储向量的引用的底层数据存储矢量。 更多...
 
const std::vector< T > & get_values () const
 返回底层数据存储矢量的常量引用。 更多...
 
void condense (const unsigned int i, const unsigned int j, const T val, DenseVector< T > &rhs)
 将矩阵的 (i,j) 元素凝聚出来,强制其取值为 val。 更多...
 
void lu_solve (const DenseVector< T > &b, DenseVector< T > &x)
 解方程组 $ Ax=b $ 给定输入向量 b。 更多...
 
template<typename T2 >
void cholesky_solve (const DenseVector< T2 > &b, DenseVector< T2 > &x)
 对于对称正定矩阵(SPD),进行Cholesky分解。 分解为 A = L L^T,比标准LU分解大约快两倍。 因此,如果事先知道矩阵是SPD,则可以使用此方法。如果矩阵不是SPD,则会生成错误。 Cholesky分解的一个优点是它不需要主元交换以确保稳定性。 更多...
 
void svd (DenseVector< Real > &sigma)
 计算矩阵的奇异值分解(SVD)。 在退出时,sigma包含所有奇异值(按降序排列)。 更多...
 
void svd (DenseVector< Real > &sigma, DenseMatrix< Number > &U, DenseMatrix< Number > &VT)
 计算矩阵的“简化”奇异值分解。 在退出时,sigma包含所有奇异值(按降序排列), U包含左奇异向量,VT包含右奇异向量的转置。 在简化的SVD中,U有min(m,n)列,VT有min(m,n)行。(在“完整”SVD中,U和VT将是方形的。) 更多...
 
void svd_solve (const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond=std::numeric_limits< Real >::epsilon()) const
 以最小二乘意义解方程组 $ Ax=rhs $$ A $ 可能是非方阵和/或秩亏的。 可以通过更改“rcond”参数来控制哪些奇异值被视为零。 对于满足S(i) <= rcond*S(1)的奇异值S(i),在解的目的上被视为零。 传递负数的rcond将强制使用“机器精度”值。 更多...
 
void evd (DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag)
 计算一般矩阵的特征值(实部和虚部)。 更多...
 
void evd_left (DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL)
 计算一般矩阵 $ A $ 的特征值(实部和虚部)和左特征向量。 更多...
 
void evd_right (DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VR)
 计算一般矩阵 $ A $ 的特征值(实部和虚部)和右特征向量。 更多...
 
void evd_left_and_right (DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VL, DenseMatrix< T > &VR)
 计算一般矩阵的特征值(实部和虚部),以及左右特征向量。 更多...
 
det ()
 返回矩阵的行列式。 更多...
 
unsigned int m () const
 返回矩阵的行维度。 更多...
 
unsigned int n () const
 返回矩阵的列维度。 更多...
 
void print (std::ostream &os=libMesh::out) const
 漂亮地打印矩阵,默认为 libMesh::out。 更多...
 
void print_scientific (std::ostream &os, unsigned precision=8) const
 以科学计数法格式打印矩阵。 更多...
 
template<typename T2 , typename T3 >
boostcopy::enable_if_c
< ScalarTraits< T2 >::value,
void >::type 
add (const T2 factor, const DenseMatrixBase< T3 > &mat)
 factor 添加到矩阵的每个元素。 这应该仅在 T += T2 * T3 是有效的 C++,且 T2 是标量的情况下工作。返回类型是 void。 更多...
 
DenseVector< T > diagonal () const
 返回矩阵的对角线。 更多...
 

Public 属性

bool use_blas_lapack
 计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。 更多...
 

Protected 成员函数

void condense (const unsigned int i, const unsigned int j, const T val, DenseVectorBase< T > &rhs)
 将矩阵的 (i,j) 条目压缩出来,强制它取值为 val。这对于在数值模拟中应用边界条件很有用。 保留矩阵的对称性。 更多...
 

静态 Protected 成员函数

static void multiply (DenseMatrixBase< T > &M1, const DenseMatrixBase< T > &M2, const DenseMatrixBase< T > &M3)
 辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n) 更多...
 

Protected 属性

unsigned int _m
 行维度。 更多...
 
unsigned int _n
 列维度。 更多...
 

Private 类型

enum  DecompositionType { LU =0, CHOLESKY =1, LU_BLAS_LAPACK, NONE }
 _cholesky_back_substitute 的分解方案会改变矩阵A的条目。因此,在调用A.lu_solve()后再次调用A.cholesky_solve()是错误的, 因为结果可能不符合任何预期结果。这个typedef跟踪在此矩阵上执行了哪种分解。 更多...
 
enum  _BLAS_Multiply_Flag { LEFT_MULTIPLY = 0, RIGHT_MULTIPLY, LEFT_MULTIPLY_TRANSPOSE, RIGHT_MULTIPLY_TRANSPOSE }
 用于确定_multiply_blas函数行为的枚举。 更多...
 
typedef PetscBLASInt pivot_index_t
 用于存储枢轴索引的数组。可能被当前活动的任何因式分解使用, 类的客户端不应出于任何原因依赖它。 更多...
 
typedef int pivot_index_t
 

Private 成员函数

void _lu_decompose ()
 形成矩阵的LU分解。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。 更多...
 
void _lu_back_substitute (const DenseVector< T > &b, DenseVector< T > &x) const
 通过回代步骤解方程Ax=b。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。 更多...
 
void _cholesky_decompose ()
 将对称正定矩阵分解为两个下三角矩阵的乘积,即A = LL^T。 更多...
 
template<typename T2 >
void _cholesky_back_substitute (const DenseVector< T2 > &b, DenseVector< T2 > &x) const
 根据矩阵A的Cholesky分解解方程Ax=b,得到未知值x和rhs b。 更多...
 
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_transpose()和 left_multiply_transpose()例程。 [ 在dense_matrix_blas_lapack.C中实现 ] 更多...
 
void _lu_decompose_lapack ()
 使用Lapack例程“getrf”计算矩阵的LU分解。此例程只能由lu_solve()函数的“use_blas_lapack”分支使用。 调用此函数后,矩阵将被其因式分解版本替换,并且DecompositionType将设置为LU_BLAS_LAPACK。 [ 在dense_matrix_blas_lapack.C中实现 ] 更多...
 
void _svd_lapack (DenseVector< Real > &sigma)
 使用Lapack例程“getsvd”计算矩阵的奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ] 更多...
 
void _svd_lapack (DenseVector< Real > &sigma, DenseMatrix< Number > &U, DenseMatrix< Number > &VT)
 使用Lapack例程“getsvd”计算矩阵的“缩减”奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ] 更多...
 
void _svd_solve_lapack (const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond) const
 由svd_solve(rhs)调用。 更多...
 
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中实现 ] 更多...
 
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 _lu_back_substitute_lapack (const DenseVector< T > &b, DenseVector< T > &x)
 与_lu_decompose_lapack()相对应的伴随函数。不要直接使用,通过公共lu_solve()接口调用。 由于我们只是调用LAPACK例程,该函数在逻辑上是const的,因为它不修改矩阵, 但由于它比const_cast更少的麻烦,所以直接声明函数为非const。 [ 在dense_matrix_blas_lapack.C中实现 ] 更多...
 
void _matvec_blas (T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
 使用BLAS GEMV函数(通过PETSc)计算 更多...
 
template<typename T2 >
void _left_multiply_transpose (const DenseMatrix< T2 > &A)
 由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。 更多...
 
template<typename T2 >
void _right_multiply_transpose (const DenseMatrix< T2 > &A)
 由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。 更多...
 

Private 属性

std::vector< T > _val
 实际的数据值,存储为1D数组。 更多...
 
DecompositionType _decomposition_type
 此标志跟踪在矩阵上执行的分解类型。 更多...
 
std::vector< pivot_index_t_pivots
 

详细描述

template<typename T>
class libMesh::DenseMatrix< T >

定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。

作者
Benjamin S. Kirk
日期
2002 用于有限元组装和数值计算的密集矩阵对象。

在文件 dof_map.h65 行定义.

成员类型定义说明

template<typename T>
typedef PetscBLASInt libMesh::DenseMatrix< T >::pivot_index_t
private

用于存储枢轴索引的数组。可能被当前活动的任何因式分解使用, 类的客户端不应出于任何原因依赖它。

在文件 dense_matrix.h849 行定义.

template<typename T>
typedef int libMesh::DenseMatrix< T >::pivot_index_t
private

在文件 dense_matrix.h851 行定义.

成员枚举类型说明

template<typename T>
enum libMesh::DenseMatrix::_BLAS_Multiply_Flag
private

用于确定_multiply_blas函数行为的枚举。

枚举值
LEFT_MULTIPLY 
RIGHT_MULTIPLY 
LEFT_MULTIPLY_TRANSPOSE 
RIGHT_MULTIPLY_TRANSPOSE 

在文件 dense_matrix.h756 行定义.

template<typename T>
enum libMesh::DenseMatrix::DecompositionType
private

_cholesky_back_substitute 的分解方案会改变矩阵A的条目。因此,在调用A.lu_solve()后再次调用A.cholesky_solve()是错误的, 因为结果可能不符合任何预期结果。这个typedef跟踪在此矩阵上执行了哪种分解。

枚举值
LU 
CHOLESKY 
LU_BLAS_LAPACK 
NONE 

在文件 dense_matrix.h746 行定义.

构造及析构函数说明

template<typename T >
libMesh::DenseMatrix< T >::DenseMatrix ( const unsigned int  new_m = 0,
const unsigned int  new_n = 0 
)
inline

构造函数。创建一个维度为 m x n 的密集矩阵。

参数
new_m矩阵的行数。
new_n矩阵的列数。

在文件 dense_matrix.h954 行定义.

参考 libMesh::DenseMatrix< T >::resize().

955  :
956  DenseMatrixBase<T>(new_m,new_n),
958  _val(),
960 {
961  this->resize(new_m,new_n);
962 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
template<typename T2 >
libMesh::DenseMatrix< T >::DenseMatrix ( unsigned int  nrow,
unsigned int  ncol,
std::initializer_list< T2 >  init_list 
)

构造函数。根据行数、列数和初始化列表创建矩阵。

参数
new_m矩阵的行数。
new_n矩阵的列数。
init_list包含行主元素值的初始化列表,其长度必须为 nrow * ncol。

在文件 dense_matrix.h966 行定义.

968  :
969  DenseMatrixBase<T>(nrow, ncol),
971  _val(init_list.begin(), init_list.end()),
973 {
974  // 确保传递的数据量与矩阵大小一致。
975  libmesh_assert_equal_to(nrow * ncol, init_list.size());
976 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T>
libMesh::DenseMatrix< T >::DenseMatrix ( DenseMatrix< T > &&  )
default

移动构造函数。移动构造函数使用默认实现,因为该类不管理任何内存。

template<typename T>
libMesh::DenseMatrix< T >::DenseMatrix ( const DenseMatrix< T > &  )
default

复制构造函数。复制构造函数使用默认实现,因为该类不管理任何内存。

template<typename T>
virtual libMesh::DenseMatrix< T >::~DenseMatrix ( )
virtualdefault

析构函数。析构函数使用默认实现,因为该类不管理任何内存。

成员函数说明

template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::_cholesky_back_substitute ( const DenseVector< T2 > &  b,
DenseVector< T2 > &  x 
) const
private

根据矩阵A的Cholesky分解解方程Ax=b,得到未知值x和rhs b。

使用 Cholesky 分解的回代步骤,求解 Ly=b 和 L^T x = y。

注解
当A是实值,b和x是复值时,可以使用此方法。
模板参数
T2解方程时使用的数据类型。
参数
b右侧向量。
x存储解的向量。
模板参数
T2输入向量 b 和解向量 x 的数据类型。
参数
b输入向量 b。
x存储解的目标向量 x。

在文件 dense_matrix_impl.h885 行定义.

参考 libMesh::DenseVector< T >::resize().

887 {
888  // 确保矩阵是方阵
889  libmesh_assert_equal_to(this->m(), this->n());
890 
891  // 行和列的数量的简写。
892  const unsigned int n_rows = this->m();
893  const unsigned int n_cols = this->n();
894 
895  // 方便引用 *this
896  const DenseMatrix<T> &A = *this;
897 
898  // 计算 Ax = b 的解。
899  x.resize(n_rows);
900 
901  // 解 Ly=b
902  for (unsigned int i = 0; i < n_cols; ++i)
903  {
904  T2 temp = b(i);
905 
906  for (unsigned int k = 0; k < i; ++k)
907  temp -= A(i, k) * x(k);
908 
909  x(i) = temp / A(i, i);
910  }
911 
912  // 解 L^T x = y
913  for (unsigned int i = 0; i < n_cols; ++i)
914  {
915  const unsigned int ib = (n_cols - 1) - i;
916 
917  for (unsigned int k = (ib + 1); k < n_cols; ++k)
918  x(ib) -= A(k, ib) * x(k);
919 
920  x(ib) /= A(ib, ib);
921  }
922 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrix< T >::_cholesky_decompose ( )
private

将对称正定矩阵分解为两个下三角矩阵的乘积,即A = LL^T。

使用 Cholesky 分解的实际分解过程。

注解
如果矩阵不是SPD,则此程序会生成错误。

该算法基于 Numerical Recipes in C 书中的 Cholesky 分解。

在文件 dense_matrix_impl.h835 行定义.

参考 std::sqrt().

836 {
837  // 如果调用了此函数,则矩阵不应该有任何先前的分解。
838  libmesh_assert_equal_to(this->_decomposition_type, NONE);
839 
840  // 为了确保是方阵,检查行和列的数量是否相同
841  const unsigned int n_rows = this->m();
842  const unsigned int n_cols = this->n();
843 
844  // 仅为了确保是方阵
845  libmesh_assert_equal_to(n_rows, n_cols);
846 
847  // 方便引用 *this
848  DenseMatrix<T> &A = *this;
849 
850  for (unsigned int i = 0; i < n_rows; ++i)
851  {
852  for (unsigned int j = i; j < n_cols; ++j)
853  {
854  for (unsigned int k = 0; k < i; ++k)
855  A(i, j) -= A(i, k) * A(j, k);
856 
857  if (i == j)
858  {
859 #ifndef LIBMESH_USE_COMPLEX_NUMBERS
860  libmesh_error_msg_if(A(i, j) <= 0.0,
861  "Error! Can only use Cholesky decomposition with symmetric positive definite matrices.");
862 #endif
863 
864  A(i, i) = std::sqrt(A(i, j));
865  }
866  else
867  A(j, i) = A(i, j) / A(i, i);
868  }
869  }
870 
871  // 设置 CHOLESKY 分解标志
873 }
unsigned int n() const
返回矩阵的列维度。
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的平方根。
Definition: type_vector.h:88
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_evd_lapack ( DenseVector< T > &  lambda_real,
DenseVector< T > &  lambda_imag,
DenseMatrix< T > *  VL = nullptr,
DenseMatrix< T > *  VR = nullptr 
)
private

使用Lapack例程“DGEEV”计算矩阵的特征值。如果VR和/或VL不为nullptr, 则此函数还计算并返回右和/或左特征向量的矩阵。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
lambda_real存储实部特征值的向量。
lambda_imag存储虚部特征值的向量。
VL存储左特征向量的矩阵。
VR存储右特征向量的矩阵。

在文件 dense_matrix_blas_lapack.C695 行定义.

参考 libMesh::DenseVector< T >::get_values(), libMesh::DenseMatrix< T >::get_values(), libMesh::pPS(), libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseMatrix< T >::resize().

699 {
700  // This algorithm only works for square matrices, so verify this up front.
701  libmesh_error_msg_if(this->m() != this->n(), "Can only compute eigen-decompositions for square matrices.");
702 
703  // If the user requests left or right eigenvectors, we have to make
704  // sure and pass the transpose of this matrix to Lapack, otherwise
705  // it will compute the inverse transpose of what we are
706  // after... since we know the matrix is square, we can just swap
707  // entries in place. If the user does not request eigenvectors, we
708  // can skip this extra step, since the eigenvalues for A and A^T are
709  // the same.
710  if (VL || VR)
711  {
712  for (auto i : make_range(this->_m))
713  for (auto j : make_range(i))
714  std::swap((*this)(i,j), (*this)(j,i));
715  }
716 
717  // The calling sequence for dgeev is:
718  // DGEEV (character JOBVL,
719  // character JOBVR,
720  // integer N,
721  // double precision, dimension( lda, * ) A,
722  // integer LDA,
723  // double precision, dimension( * ) WR,
724  // double precision, dimension( * ) WI,
725  // double precision, dimension( ldvl, * ) VL,
726  // integer LDVL,
727  // double precision, dimension( ldvr, * ) VR,
728  // integer LDVR,
729  // double precision, dimension( * ) WORK,
730  // integer LWORK,
731  // integer INFO)
732 
733  // JOBVL (input)
734  // = 'N': left eigenvectors of A are not computed;
735  // = 'V': left eigenvectors of A are computed.
736  char JOBVL = VL ? 'V' : 'N';
737 
738  // JOBVR (input)
739  // = 'N': right eigenvectors of A are not computed;
740  // = 'V': right eigenvectors of A are computed.
741  char JOBVR = VR ? 'V' : 'N';
742 
743  // N (input)
744  // The number of rows/cols of the matrix A. N >= 0.
745  PetscBLASInt N = this->m();
746 
747  // A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
748  // On entry, the N-by-N matrix A.
749  // On exit, A has been overwritten.
750 
751  // LDA (input)
752  // The leading dimension of the array A. LDA >= max(1,N).
753  PetscBLASInt LDA = N;
754 
755  // WR (output) double precision array, dimension (N)
756  // WI (output) double precision array, dimension (N)
757  // WR and WI contain the real and imaginary parts,
758  // respectively, of the computed eigenvalues. Complex
759  // conjugate pairs of eigenvalues appear consecutively
760  // with the eigenvalue having the positive imaginary part
761  // first.
762  lambda_real.resize(N);
763  lambda_imag.resize(N);
764 
765  // VL (output) double precision array, dimension (LDVL,N)
766  // If JOBVL = 'V', the left eigenvectors u(j) are stored one
767  // after another in the columns of VL, in the same order
768  // as their eigenvalues.
769  // If JOBVL = 'N', VL is not referenced.
770  // If the j-th eigenvalue is real, then u(j) = VL(:,j),
771  // the j-th column of VL.
772  // If the j-th and (j+1)-st eigenvalues form a complex
773  // conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and
774  // u(j+1) = VL(:,j) - i*VL(:,j+1).
775  // Will be set below if needed.
776 
777  // LDVL (input)
778  // The leading dimension of the array VL. LDVL >= 1; if
779  // JOBVL = 'V', LDVL >= N.
780  PetscBLASInt LDVL = VL ? N : 1;
781 
782  // VR (output) DOUBLE PRECISION array, dimension (LDVR,N)
783  // If JOBVR = 'V', the right eigenvectors v(j) are stored one
784  // after another in the columns of VR, in the same order
785  // as their eigenvalues.
786  // If JOBVR = 'N', VR is not referenced.
787  // If the j-th eigenvalue is real, then v(j) = VR(:,j),
788  // the j-th column of VR.
789  // If the j-th and (j+1)-st eigenvalues form a complex
790  // conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and
791  // v(j+1) = VR(:,j) - i*VR(:,j+1).
792  // Will be set below if needed.
793 
794  // LDVR (input)
795  // The leading dimension of the array VR. LDVR >= 1; if
796  // JOBVR = 'V', LDVR >= N.
797  PetscBLASInt LDVR = VR ? N : 1;
798 
799  // WORK (workspace/output) double precision array, dimension (MAX(1,LWORK))
800  // On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
801  //
802  // LWORK (input)
803  // The dimension of the array WORK. LWORK >= max(1,3*N), and
804  // if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N. For good
805  // performance, LWORK must generally be larger.
806  //
807  // If LWORK = -1, then a workspace query is assumed; the routine
808  // only calculates the optimal size of the WORK array, returns
809  // this value as the first entry of the WORK array, and no error
810  // message related to LWORK is issued by XERBLA.
811  PetscBLASInt LWORK = (VR || VL) ? 4*N : 3*N;
812  std::vector<T> WORK(LWORK);
813 
814  // INFO (output)
815  // = 0: successful exit
816  // < 0: if INFO = -i, the i-th argument had an illegal value.
817  // > 0: if INFO = i, the QR algorithm failed to compute all the
818  // eigenvalues, and no eigenvectors or condition numbers
819  // have been computed; elements 1:ILO-1 and i+1:N of WR
820  // and WI contain eigenvalues which have converged.
821  PetscBLASInt INFO = 0;
822 
823  // Get references to raw data
824  std::vector<T> & lambda_real_val = lambda_real.get_values();
825  std::vector<T> & lambda_imag_val = lambda_imag.get_values();
826 
827  // Set up eigenvector storage if necessary.
828  T * VR_ptr = nullptr;
829  if (VR)
830  {
831  VR->resize(N, N);
832  VR_ptr = VR->get_values().data();
833  }
834 
835  T * VL_ptr = nullptr;
836  if (VL)
837  {
838  VL->resize(N, N);
839  VL_ptr = VL->get_values().data();
840  }
841 
842  // Ready to call the Lapack routine through PETSc's interface
843  LAPACKgeev_(&JOBVL,
844  &JOBVR,
845  &N,
846  pPS(_val.data()),
847  &LDA,
848  pPS(lambda_real_val.data()),
849  pPS(lambda_imag_val.data()),
850  pPS(VL_ptr),
851  &LDVL,
852  pPS(VR_ptr),
853  &LDVR,
854  pPS(WORK.data()),
855  &LWORK,
856  &INFO);
857 
858  // Check return value for errors
859  libmesh_error_msg_if(INFO != 0, "INFO=" << INFO << ", Error during Lapack eigenvalue calculation!");
860 
861  // If the user requested either right or left eigenvectors, LAPACK
862  // has now computed the transpose of the desired matrix, i.e. V^T
863  // instead of V. We could leave this up to user code to handle, but
864  // rather than risking getting very unexpected results, we'll just
865  // transpose it in place before handing it back.
866  if (VR)
867  {
868  for (auto i : make_range(N))
869  for (auto j : make_range(i))
870  std::swap((*VR)(i,j), (*VR)(j,i));
871  }
872 
873  if (VL)
874  {
875  for (auto i : make_range(N))
876  for (auto j : make_range(i))
877  std::swap((*VL)(i,j), (*VL)(j,i));
878  }
879 }
unsigned int n() const
返回矩阵的列维度。
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::_left_multiply_transpose ( const DenseMatrix< T2 > &  A)
private

由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。

执行左乘转置矩阵的实际操作。

模板参数
T2矩阵元素的新数据类型。
参数
A另一个矩阵。

如果正在执行 (A^T)*A,将执行一种优化方法;否则,将执行通用的左乘转置操作。

参数
A要左乘的转置矩阵。

在文件 dense_matrix_impl.h125 行定义.

参考 libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::DenseMatrix< T >::transpose().

126 {
127  // 检查是否正在执行 (A^T)*A
128  if (this == &A)
129  {
130  // 复制 *this 的副本
131  DenseMatrix<T> B(*this);
132 
133  // 简单但低效的方式
134  // 返回 this->left_multiply_transpose(B);
135 
136  // 更有效,但代码更多的方式
137  // 如果 A 是 mxn,则结果将是大小为 n x n 的方阵。
138  const unsigned int n_rows = A.m();
139  const unsigned int n_cols = A.n();
140 
141  // 调整 *this 的大小并将所有条目清零。
142  this->resize(n_cols, n_cols);
143 
144  // 计算下三角部分
145  for (unsigned int i = 0; i < n_cols; ++i)
146  for (unsigned int j = 0; j <= i; ++j)
147  for (unsigned int k = 0; k < n_rows; ++k) // 内积在 n_rows 上
148  (*this)(i, j) += B(k, i) * B(k, j);
149 
150  // 将下三角部分复制到上三角部分
151  for (unsigned int i = 0; i < n_cols; ++i)
152  for (unsigned int j = i + 1; j < n_cols; ++j)
153  (*this)(i, j) = (*this)(j, i);
154  }
155  else
156  {
157  DenseMatrix<T> B(*this);
158 
159  this->resize(A.n(), B.n());
160 
161  libmesh_assert_equal_to(A.m(), B.m());
162  libmesh_assert_equal_to(this->m(), A.n());
163  libmesh_assert_equal_to(this->n(), B.n());
164 
165  const unsigned int m_s = A.n();
166  const unsigned int p_s = A.m();
167  const unsigned int n_s = this->n();
168 
169  // 以这种方式执行是因为
170  // 很大的机会(至少对于约束矩阵而言)
171  // A.transpose(i,k) = 0。
172  for (unsigned int i = 0; i < m_s; i++)
173  for (unsigned int k = 0; k < p_s; k++)
174  if (A.transpose(i, k) != 0.)
175  for (unsigned int j = 0; j < n_s; j++)
176  (*this)(i, j) += A.transpose(i, k) * B(k, j);
177  }
178 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
template<typename T >
void libMesh::DenseMatrix< T >::_lu_back_substitute ( const DenseVector< T > &  b,
DenseVector< T > &  x 
) const
private

通过回代步骤解方程Ax=b。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。

使用 LU 分解的反向代入解线性系统。

参数
b输入向量 b。
x存储结果的目标向量 x。

在文件 dense_matrix_impl.h656 行定义.

参考 libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

657 {
658  const unsigned int n_cols = this->n();
659 
660  libmesh_assert_equal_to(this->m(), n_cols);
661  libmesh_assert_equal_to(this->m(), b.size());
662 
663  x.resize(n_cols);
664 
665  // 方便引用 *this
666  const DenseMatrix<T> & A = *this;
667 
668  // 临时向量存储。使用这个向量而不是修改 RHS。
669  DenseVector<T> z = b;
670 
671  // 下三角 "从上到下" 解法步骤,考虑了主元素
672  for (unsigned int i = 0; i < n_cols; ++i)
673  {
674  // 交换
675  if (_pivots[i] != static_cast<pivot_index_t>(i))
676  std::swap(z(i), z(_pivots[i]));
677 
678  x(i) = z(i);
679 
680  for (unsigned int j = 0; j < i; ++j)
681  x(i) -= A(i, j) * x(j);
682 
683  x(i) /= A(i, i);
684  }
685 
686  // 上三角 "从下到上" 解法步骤
687  const unsigned int last_row = n_cols - 1;
688 
689  for (int i = last_row; i >= 0; --i)
690  {
691  for (int j = i + 1; j < static_cast<int>(n_cols); ++j)
692  x(i) -= A(i, j) * x(j);
693  }
694 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
std::vector< pivot_index_t > _pivots
Definition: dense_matrix.h:853
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_lu_back_substitute_lapack ( const DenseVector< T > &  b,
DenseVector< T > &  x 
)
private

与_lu_decompose_lapack()相对应的伴随函数。不要直接使用,通过公共lu_solve()接口调用。 由于我们只是调用LAPACK例程,该函数在逻辑上是const的,因为它不修改矩阵, 但由于它比const_cast更少的麻烦,所以直接声明函数为非const。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
b右侧向量。
x存储解的向量。

在文件 dense_matrix_blas_lapack.C901 行定义.

参考 libMesh::DenseVector< T >::get_values() , 以及 libMesh::pPS().

903 {
904  // The calling sequence for getrs is:
905  // dgetrs(TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO)
906 
907  // trans (input)
908  // 'n' for no transpose, 't' for transpose
909  char TRANS[] = "t";
910 
911  // N (input)
912  // The order of the matrix A. N >= 0.
913  PetscBLASInt N = this->m();
914 
915 
916  // NRHS (input)
917  // The number of right hand sides, i.e., the number of columns
918  // of the matrix B. NRHS >= 0.
919  PetscBLASInt NRHS = 1;
920 
921  // A (input) double precision array, dimension (LDA,N)
922  // The factors L and U from the factorization A = P*L*U
923  // as computed by dgetrf.
924 
925  // LDA (input)
926  // The leading dimension of the array A. LDA >= max(1,N).
927  PetscBLASInt LDA = N;
928 
929  // ipiv (input) int array, dimension (N)
930  // The pivot indices from DGETRF; for 1<=i<=N, row i of the
931  // matrix was interchanged with row IPIV(i).
932  // Here, we pass _pivots.data() which was computed in _lu_decompose_lapack
933 
934  // B (input/output) double precision array, dimension (LDB,NRHS)
935  // On entry, the right hand side matrix B.
936  // On exit, the solution matrix X.
937  // Here, we pass a copy of the rhs vector's data array in x, so that the
938  // passed right-hand side b is unmodified. I don't see a way around this
939  // copy if we want to maintain an unmodified rhs in LibMesh.
940  x = b;
941  std::vector<T> & x_vec = x.get_values();
942 
943  // We can avoid the copy if we don't care about overwriting the RHS: just
944  // pass b to the Lapack routine and then swap with x before exiting
945  // std::vector<T> & x_vec = b.get_values();
946 
947  // LDB (input)
948  // The leading dimension of the array B. LDB >= max(1,N).
949  PetscBLASInt LDB = N;
950 
951  // INFO (output)
952  // = 0: successful exit
953  // < 0: if INFO = -i, the i-th argument had an illegal value
954  PetscBLASInt INFO = 0;
955 
956  // Finally, ready to call the Lapack getrs function
957  LAPACKgetrs_(TRANS, &N, &NRHS, pPS(_val.data()), &LDA,
958  _pivots.data(), pPS(x_vec.data()), &LDB, &INFO);
959 
960  // Check return value for errors
961  libmesh_error_msg_if(INFO != 0, "INFO=" << INFO << ", Error during Lapack LU solve!");
962 
963  // Don't do this if you already made a copy of b above
964  // Swap b and x. The solution will then be in x, and whatever was originally
965  // in x, maybe garbage, maybe nothing, will be in b.
966  // FIXME: Rewrite the LU and Cholesky solves to just take one input, and overwrite
967  // the input. This *should* make user code simpler, as they don't have to create
968  // an extra vector just to pass it in to the solve function!
969  // b.swap(x);
970 }
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
std::vector< pivot_index_t > _pivots
Definition: dense_matrix.h:853
template<typename T >
void libMesh::DenseMatrix< T >::_lu_decompose ( )
private

形成矩阵的LU分解。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。

使用 LU 分解的实际分解过程。

在文件 dense_matrix_impl.h700 行定义.

参考 std::abs(), libMesh::DenseMatrix< T >::resize() , 以及 libMesh::zero.

701 {
702  // 如果调用了此函数,则矩阵不应该有任何先前的分解。
703  libmesh_assert_equal_to(this->_decomposition_type, NONE);
704 
705  // 获取矩阵大小并确保其是方阵
706  const unsigned int n_rows = this->m();
707 
708  // 方便引用 *this
709  DenseMatrix<T> & A = *this;
710 
711  _pivots.resize(n_rows);
712 
713  for (unsigned int i = 0; i < n_rows; ++i)
714  {
715  // 通过向下搜索第 i 列找到主元素所在的行
716  _pivots[i] = i;
717 
718  // std::abs(complex) 必须返回一个实数!
719  auto the_max = std::abs(A(i, i));
720  for (unsigned int j = i + 1; j < n_rows; ++j)
721  {
722  auto candidate_max = std::abs(A(j, i));
723  if (the_max < candidate_max)
724  {
725  the_max = candidate_max;
726  _pivots[i] = j;
727  }
728  }
729 
730  // 如果最大值在不同的行中找到,则交换行
731  // 这里交换整个行,在高斯消元中,只交换 A(i,j) 和 A(p(i),j) 的子行,对于 j>i
732  if (_pivots[i] != static_cast<pivot_index_t>(i))
733  {
734  for (unsigned int j = 0; j < n_rows; ++j)
735  std::swap(A(i, j), A(_pivots[i], j));
736  }
737 
738  // 如果找到的最大绝对值条目为零,则矩阵是奇异的
739  libmesh_error_msg_if(A(i, i) == libMesh::zero, "Matrix A is singular!");
740 
741  // 将第 i 行的上三角条目缩放为对角线条目
742  // 注意:不要缩放对角线条目本身!
743  const T diag_inv = 1. / A(i, i);
744  for (unsigned int j = i + 1; j < n_rows; ++j)
745  A(i, j) *= diag_inv;
746 
747  // 通过减去(对角线已缩放的)第 i 行的上三角部分,更新剩余子矩阵 A[i+1:m][i+1:m]
748  // 通过每行的第 i 列条目进行缩放。在行操作方面,这是:
749  // 对于每个 r > i
750  // SubRow(r) = SubRow(r) - A(r,i)*SubRow(i)
751  //
752  // 如果我们也缩放了第 i 列,就像在高斯消元中一样,这将“零”第 i 列的条目。
753  for (unsigned int row = i + 1; row < n_rows; ++row)
754  for (unsigned int col = i + 1; col < n_rows; ++col)
755  A(row, col) -= A(row, i) * A(i, col);
756  } // end i 循环
757 
758  // 设置 LU 分解标志
759  this->_decomposition_type = LU;
760 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
const Number zero
.
Definition: libmesh.h:248
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
unsigned int m() const
返回矩阵的行维度。
std::vector< pivot_index_t > _pivots
Definition: dense_matrix.h:853
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_lu_decompose_lapack ( )
private

使用Lapack例程“getrf”计算矩阵的LU分解。此例程只能由lu_solve()函数的“use_blas_lapack”分支使用。 调用此函数后,矩阵将被其因式分解版本替换,并且DecompositionType将设置为LU_BLAS_LAPACK。 [ 在dense_matrix_blas_lapack.C中实现 ]

在文件 dense_matrix_blas_lapack.C210 行定义.

参考 libMesh::pPS().

211 {
212  // If this function was called, there better not be any
213  // previous decomposition of the matrix.
214  libmesh_assert_equal_to (this->_decomposition_type, NONE);
215 
216  // The calling sequence for dgetrf is:
217  // dgetrf(M, N, A, lda, ipiv, info)
218 
219  // M (input)
220  // The number of rows of the matrix A. M >= 0.
221  // In C/C++, pass the number of *cols* of A
222  PetscBLASInt M = this->n();
223 
224  // N (input)
225  // The number of columns of the matrix A. N >= 0.
226  // In C/C++, pass the number of *rows* of A
227  PetscBLASInt N = this->m();
228 
229  // A (input/output) double precision array, dimension (LDA,N)
230  // On entry, the M-by-N matrix to be factored.
231  // On exit, the factors L and U from the factorization
232  // A = P*L*U; the unit diagonal elements of L are not stored.
233 
234  // LDA (input)
235  // The leading dimension of the array A. LDA >= max(1,M).
236  PetscBLASInt LDA = M;
237 
238  // ipiv (output) integer array, dimension (min(m,n))
239  // The pivot indices; for 1 <= i <= min(m,n), row i of the
240  // matrix was interchanged with row IPIV(i).
241  // Here, we pass _pivots.data(), a private class member used to store pivots
242  this->_pivots.resize( std::min(M,N) );
243 
244  // info (output)
245  // = 0: successful exit
246  // < 0: if INFO = -i, the i-th argument had an illegal value
247  // > 0: if INFO = i, U(i,i) is exactly zero. The factorization
248  // has been completed, but the factor U is exactly
249  // singular, and division by zero will occur if it is used
250  // to solve a system of equations.
251  PetscBLASInt INFO = 0;
252 
253  // Ready to call the actual factorization routine through PETSc's interface
254  LAPACKgetrf_(&M, &N, pPS(this->_val.data()), &LDA, _pivots.data(),
255  &INFO);
256 
257  // Check return value for errors
258  libmesh_error_msg_if(INFO != 0, "INFO=" << INFO << ", Error during Lapack LU factorization!");
259 
260  // Set the flag for LU decomposition
262 }
unsigned int n() const
返回矩阵的列维度。
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
std::vector< pivot_index_t > _pivots
Definition: dense_matrix.h:853
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_matvec_blas ( alpha,
beta,
DenseVector< T > &  dest,
const DenseVector< T > &  arg,
bool  trans = false 
) const
private

使用BLAS GEMV函数(通过PETSc)计算

dest := alpha*A*arg + beta*dest

其中alpha和beta是标量,A是此矩阵,arg和dest是适当大小的输入向量。 如果trans为true,则计算转置matvec。默认情况下,trans==false。

[ 在dense_matrix_blas_lapack.C 中实现 ]

参数
alpha标量alpha。
beta标量beta。
dest存储结果的向量。
arg输入向量。
trans如果为true,则计算转置matvec。

在文件 dense_matrix_blas_lapack.C990 行定义.

参考 libMesh::DenseVector< T >::get_values(), libMesh::DenseMatrix< T >::get_values(), libMesh::pPS() , 以及 libMesh::DenseVector< T >::size().

995 {
996  // Ensure that dest and arg sizes are compatible
997  if (!trans)
998  {
999  // dest ~ A * arg
1000  // (mx1) (mxn) * (nx1)
1001  libmesh_error_msg_if((dest.size() != this->m()) || (arg.size() != this->n()),
1002  "Improper input argument sizes!");
1003  }
1004 
1005  else // trans == true
1006  {
1007  // Ensure that dest and arg are proper size
1008  // dest ~ A^T * arg
1009  // (nx1) (nxm) * (mx1)
1010  libmesh_error_msg_if((dest.size() != this->n()) || (arg.size() != this->m()),
1011  "Improper input argument sizes!");
1012  }
1013 
1014  // Calling sequence for dgemv:
1015  //
1016  // dgemv(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY)
1017 
1018  // TRANS (input)
1019  // 't' for transpose, 'n' for non-transpose multiply
1020  // We store everything in row-major order, so pass the transpose flag for
1021  // non-transposed matvecs and the 'n' flag for transposed matvecs
1022  char TRANS[] = "t";
1023  if (trans)
1024  TRANS[0] = 'n';
1025 
1026  // M (input)
1027  // On entry, M specifies the number of rows of the matrix A.
1028  // In C/C++, pass the number of *cols* of A
1029  PetscBLASInt M = this->n();
1030 
1031  // N (input)
1032  // On entry, N specifies the number of columns of the matrix A.
1033  // In C/C++, pass the number of *rows* of A
1034  PetscBLASInt N = this->m();
1035 
1036  // ALPHA (input)
1037  // The scalar constant passed to this function
1038 
1039  // A (input) double precision array of DIMENSION ( LDA, n ).
1040  // Before entry, the leading m by n part of the array A must
1041  // contain the matrix of coefficients.
1042  // The matrix, *this. Note that _matvec_blas is called from
1043  // a const function, vector_mult(), and so we have made this function const
1044  // as well. Since BLAS knows nothing about const, we have to cast it away
1045  // now.
1046  DenseMatrix<T> & a_ref = const_cast<DenseMatrix<T> &> ( *this );
1047  std::vector<T> & a = a_ref.get_values();
1048 
1049  // LDA (input)
1050  // On entry, LDA specifies the first dimension of A as declared
1051  // in the calling (sub) program. LDA must be at least
1052  // max( 1, m ).
1053  PetscBLASInt LDA = M;
1054 
1055  // X (input) double precision array of DIMENSION at least
1056  // ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n'
1057  // and at least
1058  // ( 1 + ( m - 1 )*abs( INCX ) ) otherwise.
1059  // Before entry, the incremented array X must contain the
1060  // vector x.
1061  // Here, we must cast away the const-ness of "arg" since BLAS knows
1062  // nothing about const
1063  DenseVector<T> & x_ref = const_cast<DenseVector<T> &> ( arg );
1064  std::vector<T> & x = x_ref.get_values();
1065 
1066  // INCX (input)
1067  // On entry, INCX specifies the increment for the elements of
1068  // X. INCX must not be zero.
1069  PetscBLASInt INCX = 1;
1070 
1071  // BETA (input)
1072  // On entry, BETA specifies the scalar beta. When BETA is
1073  // supplied as zero then Y need not be set on input.
1074  // The second scalar constant passed to this function
1075 
1076  // Y (input) double precision array of DIMENSION at least
1077  // ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n'
1078  // and at least
1079  // ( 1 + ( n - 1 )*abs( INCY ) ) otherwise.
1080  // Before entry with BETA non-zero, the incremented array Y
1081  // must contain the vector y. On exit, Y is overwritten by the
1082  // updated vector y.
1083  // The input vector "dest"
1084  std::vector<T> & y = dest.get_values();
1085 
1086  // INCY (input)
1087  // On entry, INCY specifies the increment for the elements of
1088  // Y. INCY must not be zero.
1089  PetscBLASInt INCY = 1;
1090 
1091  // Finally, ready to call the BLAS function
1092  BLASgemv_(TRANS, &M, &N, pPS(&alpha), pPS(a.data()), &LDA,
1093  pPS(x.data()), &INCX, pPS(&beta), pPS(y.data()), &INCY);
1094 }
unsigned int n() const
返回矩阵的列维度。
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_multiply_blas ( const DenseMatrixBase< T > &  other,
_BLAS_Multiply_Flag  flag 
)
private

_multiply_blas函数使用BLAS gemm函数计算A <- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_transpose()和 left_multiply_transpose()例程。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
other另一个矩阵。
flag用于指定操作类型的标志。

在文件 dense_matrix_blas_lapack.C37 行定义.

参考 libMesh::DenseMatrix< T >::get_values(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::pPS().

39 {
40  int result_size = 0;
41 
42  // For each case, determine the size of the final result make sure
43  // that the inner dimensions match
44  switch (flag)
45  {
46  case LEFT_MULTIPLY:
47  {
48  result_size = other.m() * this->n();
49  if (other.n() == this->m())
50  break;
51  }
52  libmesh_fallthrough();
53  case RIGHT_MULTIPLY:
54  {
55  result_size = other.n() * this->m();
56  if (other.m() == this->n())
57  break;
58  }
59  libmesh_fallthrough();
61  {
62  result_size = other.n() * this->n();
63  if (other.m() == this->m())
64  break;
65  }
66  libmesh_fallthrough();
68  {
69  result_size = other.m() * this->m();
70  if (other.n() == this->n())
71  break;
72  }
73  libmesh_fallthrough();
74  default:
75  libmesh_error_msg("Unknown flag selected or matrices are incompatible for multiplication.");
76  }
77 
78  // For this to work, the passed arg. must actually be a DenseMatrix<T>
79  const DenseMatrix<T> * const_that = cast_ptr<const DenseMatrix<T> *>(&other);
80 
81  // Also, although 'that' is logically const in this BLAS routine,
82  // the PETSc BLAS interface does not specify that any of the inputs are
83  // const. To use it, I must cast away const-ness.
84  DenseMatrix<T> * that = const_cast<DenseMatrix<T> *> (const_that);
85 
86  // Initialize A, B pointers for LEFT_MULTIPLY* cases
87  DenseMatrix<T> * A = this;
88  DenseMatrix<T> * B = that;
89 
90  // For RIGHT_MULTIPLY* cases, swap the meaning of A and B.
91  // Here is a full table of combinations we can pass to BLASgemm, and what the answer is when finished:
92  // pass A B -> (Fortran) -> A^T B^T -> (C++) -> (A^T B^T)^T -> (identity) -> B A "lt multiply"
93  // pass B A -> (Fortran) -> B^T A^T -> (C++) -> (B^T A^T)^T -> (identity) -> A B "rt multiply"
94  // pass A B^T -> (Fortran) -> A^T B -> (C++) -> (A^T B)^T -> (identity) -> B^T A "lt multiply t"
95  // pass B^T A -> (Fortran) -> B A^T -> (C++) -> (B A^T)^T -> (identity) -> A B^T "rt multiply t"
96  if (flag==RIGHT_MULTIPLY || flag==RIGHT_MULTIPLY_TRANSPOSE)
97  std::swap(A,B);
98 
99  // transa, transb values to pass to blas
100  char
101  transa[] = "n",
102  transb[] = "n";
103 
104  // Integer values to pass to BLAS:
105  //
106  // M
107  // In Fortran, the number of rows of op(A),
108  // In the BLAS documentation, typically known as 'M'.
109  //
110  // In C/C++, we set:
111  // M = n_cols(A) if (transa='n')
112  // n_rows(A) if (transa='t')
113  PetscBLASInt M = static_cast<PetscBLASInt>( A->n() );
114 
115  // N
116  // In Fortran, the number of cols of op(B), and also the number of cols of C.
117  // In the BLAS documentation, typically known as 'N'.
118  //
119  // In C/C++, we set:
120  // N = n_rows(B) if (transb='n')
121  // n_cols(B) if (transb='t')
122  PetscBLASInt N = static_cast<PetscBLASInt>( B->m() );
123 
124  // K
125  // In Fortran, the number of cols of op(A), and also
126  // the number of rows of op(B). In the BLAS documentation,
127  // typically known as 'K'.
128  //
129  // In C/C++, we set:
130  // K = n_rows(A) if (transa='n')
131  // n_cols(A) if (transa='t')
132  PetscBLASInt K = static_cast<PetscBLASInt>( A->m() );
133 
134  // LDA (leading dimension of A). In our cases,
135  // LDA is always the number of columns of A.
136  PetscBLASInt LDA = static_cast<PetscBLASInt>( A->n() );
137 
138  // LDB (leading dimension of B). In our cases,
139  // LDB is always the number of columns of B.
140  PetscBLASInt LDB = static_cast<PetscBLASInt>( B->n() );
141 
142  if (flag == LEFT_MULTIPLY_TRANSPOSE)
143  {
144  transb[0] = 't';
145  N = static_cast<PetscBLASInt>( B->n() );
146  }
147 
148  else if (flag == RIGHT_MULTIPLY_TRANSPOSE)
149  {
150  transa[0] = 't';
151  std::swap(M,K);
152  }
153 
154  // LDC (leading dimension of C). LDC is the
155  // number of columns in the solution matrix.
156  PetscBLASInt LDC = M;
157 
158  // Scalar values to pass to BLAS
159  //
160  // scalar multiplying the whole product AB
161  T alpha = 1.;
162 
163  // scalar multiplying C, which is the original matrix.
164  T beta = 0.;
165 
166  // Storage for the result
167  std::vector<T> result (result_size);
168 
169  // Finally ready to call the BLAS
170  BLASgemm_(transa, transb, &M, &N, &K, pPS(&alpha),
171  pPS(A->get_values().data()), &LDA,
172  pPS(B->get_values().data()), &LDB, pPS(&beta),
173  pPS(result.data()), &LDC);
174 
175  // Update the relevant dimension for this matrix.
176  switch (flag)
177  {
178  case LEFT_MULTIPLY: { this->_m = other.m(); break; }
179  case RIGHT_MULTIPLY: { this->_n = other.n(); break; }
180  case LEFT_MULTIPLY_TRANSPOSE: { this->_m = other.n(); break; }
181  case RIGHT_MULTIPLY_TRANSPOSE: { this->_n = other.m(); break; }
182  default:
183  libmesh_error_msg("Unknown flag selected.");
184  }
185 
186  // Swap my data vector with the result
187  this->_val.swap(result);
188 }
unsigned int n() const
返回矩阵的列维度。
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::_right_multiply_transpose ( const DenseMatrix< T2 > &  B)
private

由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。

执行右乘转置矩阵的实际操作。

模板参数
T2矩阵元素的新数据类型。
参数
A另一个矩阵。

如果正在执行 B*(B^T),将执行一种优化方法;否则,将执行通用的右乘转置操作。

参数
B要右乘的转置矩阵。

在文件 dense_matrix_impl.h261 行定义.

参考 libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::DenseMatrix< T >::transpose().

262 {
263  // 检查是否正在执行 B*(B^T)
264  if (this == &B)
265  {
266  // 复制 *this 的副本
267  DenseMatrix<T> A(*this);
268 
269  // 简单但低效的方式
270  // 返回 this->right_multiply_transpose(A);
271 
272  // 更有效,但代码更多的方式
273  // 如果 B 是 mxn,则结果将是大小为 m x m 的方阵。
274  const unsigned int n_rows = B.m();
275  const unsigned int n_cols = B.n();
276 
277  // 调整 *this 的大小并将所有条目清零。
278  this->resize(n_rows, n_rows);
279 
280  // 计算下三角部分
281  for (unsigned int i = 0; i < n_rows; ++i)
282  for (unsigned int j = 0; j <= i; ++j)
283  for (unsigned int k = 0; k < n_cols; ++k) // 内积在 n_cols 上
284  (*this)(i, j) += A(i, k) * A(j, k);
285 
286  // 将下三角部分复制到上三角部分
287  for (unsigned int i = 0; i < n_rows; ++i)
288  for (unsigned int j = i + 1; j < n_rows; ++j)
289  (*this)(i, j) = (*this)(j, i);
290  }
291  else
292  {
293  DenseMatrix<T> A(*this);
294 
295  this->resize(A.m(), B.m());
296 
297  libmesh_assert_equal_to(A.n(), B.n());
298  libmesh_assert_equal_to(this->m(), A.m());
299  libmesh_assert_equal_to(this->n(), B.m());
300 
301  const unsigned int m_s = A.m();
302  const unsigned int p_s = A.n();
303  const unsigned int n_s = this->n();
304 
305  // 以这种方式执行是因为
306  // 很多情况下(至少对于约束矩阵而言)B.transpose(k,j) = 0
307  for (unsigned int j = 0; j < n_s; j++)
308  for (unsigned int k = 0; k < p_s; k++)
309  if (B.transpose(k, j) != 0.)
310  for (unsigned int i = 0; i < m_s; i++)
311  (*this)(i, j) += A(i, k) * B.transpose(k, j);
312  }
313 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_svd_helper ( char  JOBU,
char  JOBVT,
std::vector< Real > &  sigma_val,
std::vector< Number > &  U_val,
std::vector< Number > &  VT_val 
)
private

实际执行SVD的辅助函数。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
JOBU用于控制计算左奇异向量的选项。
JOBVT用于控制计算右奇异向量的选项。
sigma_val存储奇异值的向量。
U_val存储左奇异向量的向量。
VT_val存储右奇异向量的向量。

在文件 dense_matrix_blas_lapack.C384 行定义.

参考 libMesh::pPS().

389 {
390 
391  // M (input)
392  // The number of rows of the matrix A. M >= 0.
393  // In C/C++, pass the number of *cols* of A
394  PetscBLASInt M = this->n();
395 
396  // N (input)
397  // The number of columns of the matrix A. N >= 0.
398  // In C/C++, pass the number of *rows* of A
399  PetscBLASInt N = this->m();
400 
401  PetscBLASInt min_MN = (M < N) ? M : N;
402  PetscBLASInt max_MN = (M > N) ? M : N;
403 
404  // A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
405  // On entry, the M-by-N matrix A.
406  // On exit,
407  // if JOBU = 'O', A is overwritten with the first min(m,n)
408  // columns of U (the left singular vectors,
409  // stored columnwise);
410  // if JOBVT = 'O', A is overwritten with the first min(m,n)
411  // rows of V**T (the right singular vectors,
412  // stored rowwise);
413  // if JOBU != 'O' and JOBVT != 'O', the contents of A are destroyed.
414 
415  // LDA (input)
416  // The leading dimension of the array A. LDA >= max(1,M).
417  PetscBLASInt LDA = M;
418 
419  // S (output) DOUBLE PRECISION array, dimension (min(M,N))
420  // The singular values of A, sorted so that S(i) >= S(i+1).
421  sigma_val.resize( min_MN );
422 
423  // LDU (input)
424  // The leading dimension of the array U. LDU >= 1; if
425  // JOBU = 'S' or 'A', LDU >= M.
426  PetscBLASInt LDU = M;
427 
428  // U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
429  // (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
430  // If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
431  // if JOBU = 'S', U contains the first min(m,n) columns of U
432  // (the left singular vectors, stored columnwise);
433  // if JOBU = 'N' or 'O', U is not referenced.
434  if (JOBU == 'S')
435  U_val.resize( LDU*min_MN );
436  else
437  U_val.resize( LDU*M );
438 
439  // LDVT (input)
440  // The leading dimension of the array VT. LDVT >= 1; if
441  // JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
442  PetscBLASInt LDVT = N;
443  if (JOBVT == 'S')
444  LDVT = min_MN;
445 
446  // VT (output) DOUBLE PRECISION array, dimension (LDVT,N)
447  // If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
448  // V**T;
449  // if JOBVT = 'S', VT contains the first min(m,n) rows of
450  // V**T (the right singular vectors, stored rowwise);
451  // if JOBVT = 'N' or 'O', VT is not referenced.
452  VT_val.resize( LDVT*N );
453 
454  // LWORK (input)
455  // The dimension of the array WORK.
456  // LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).
457  // For good performance, LWORK should generally be larger.
458  //
459  // If LWORK = -1, then a workspace query is assumed; the routine
460  // only calculates the optimal size of the WORK array, returns
461  // this value as the first entry of the WORK array, and no error
462  // message related to LWORK is issued by XERBLA.
463  PetscBLASInt larger = (3*min_MN+max_MN > 5*min_MN) ? 3*min_MN+max_MN : 5*min_MN;
464  PetscBLASInt LWORK = (larger > 1) ? larger : 1;
465 
466 
467  // WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
468  // On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
469  // if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
470  // superdiagonal elements of an upper bidiagonal matrix B
471  // whose diagonal is in S (not necessarily sorted). B
472  // satisfies A = U * B * VT, so it has the same singular values
473  // as A, and singular vectors related by U and VT.
474  std::vector<Number> WORK( LWORK );
475 
476  // INFO (output)
477  // = 0: successful exit.
478  // < 0: if INFO = -i, the i-th argument had an illegal value.
479  // > 0: if DBDSQR did not converge, INFO specifies how many
480  // superdiagonals of an intermediate bidiagonal form B
481  // did not converge to zero. See the description of WORK
482  // above for details.
483  PetscBLASInt INFO = 0;
484 
485  // Ready to call the actual factorization routine through PETSc's interface.
486 #ifdef LIBMESH_USE_REAL_NUMBERS
487  // Note that the call to LAPACKgesvd_ may modify _val
488  LAPACKgesvd_(&JOBU, &JOBVT, &M, &N, pPS(_val.data()), &LDA,
489  pPS(sigma_val.data()), pPS(U_val.data()), &LDU,
490  pPS(VT_val.data()), &LDVT, pPS(WORK.data()), &LWORK,
491  &INFO);
492 #else
493  // When we have LIBMESH_USE_COMPLEX_NUMBERS then we must pass an array of Complex
494  // numbers to LAPACKgesvd_, but _val may contain Reals so we copy to Number below to
495  // handle both the real-valued and complex-valued cases.
496  std::vector<Number> val_copy(_val.size());
497  for (auto i : make_range(_val.size()))
498  val_copy[i] = _val[i];
499 
500  std::vector<Real> RWORK(5 * min_MN);
501  LAPACKgesvd_(&JOBU, &JOBVT, &M, &N, val_copy.data(), &LDA, sigma_val.data(), U_val.data(),
502  &LDU, VT_val.data(), &LDVT, WORK.data(), &LWORK, RWORK.data(), &INFO);
503 #endif
504 
505  // Check return value for errors
506  libmesh_error_msg_if(INFO != 0, "INFO=" << INFO << ", Error during Lapack SVD calculation!");
507 }
unsigned int n() const
返回矩阵的列维度。
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
unsigned int m() const
返回矩阵的行维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_svd_lapack ( DenseVector< Real > &  sigma)
private

使用Lapack例程“getsvd”计算矩阵的奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
sigma存储奇异值的向量。

在文件 dense_matrix_blas_lapack.C277 行定义.

参考 libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

278 {
279  // The calling sequence for dgetrf is:
280  // DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO )
281 
282  // JOBU (input)
283  // Specifies options for computing all or part of the matrix U:
284  // = 'A': all M columns of U are returned in array U:
285  // = 'S': the first min(m,n) columns of U (the left singular
286  // vectors) are returned in the array U;
287  // = 'O': the first min(m,n) columns of U (the left singular
288  // vectors) are overwritten on the array A;
289  // = 'N': no columns of U (no left singular vectors) are
290  // computed.
291  char JOBU = 'N';
292 
293  // JOBVT (input)
294  // Specifies options for computing all or part of the matrix
295  // V**T:
296  // = 'A': all N rows of V**T are returned in the array VT;
297  // = 'S': the first min(m,n) rows of V**T (the right singular
298  // vectors) are returned in the array VT;
299  // = 'O': the first min(m,n) rows of V**T (the right singular
300  // vectors) are overwritten on the array A;
301  // = 'N': no rows of V**T (no right singular vectors) are
302  // computed.
303  char JOBVT = 'N';
304 
305  std::vector<Real> sigma_val;
306  std::vector<Number> U_val;
307  std::vector<Number> VT_val;
308 
309  _svd_helper(JOBU, JOBVT, sigma_val, U_val, VT_val);
310 
311  // Copy the singular values into sigma, ignore U_val and VT_val
312  sigma.resize(cast_int<unsigned int>(sigma_val.size()));
313  for (auto i : make_range(sigma.size()))
314  sigma(i) = sigma_val[i];
315 }
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中实现 ]
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_svd_lapack ( DenseVector< Real > &  sigma,
DenseMatrix< Number > &  U,
DenseMatrix< Number > &  VT 
)
private

使用Lapack例程“getsvd”计算矩阵的“缩减”奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ]

参数
sigma存储奇异值的向量。
U存储左奇异向量的矩阵。
VT存储右奇异向量的矩阵的转置。

在文件 dense_matrix_blas_lapack.C318 行定义.

参考 libMesh::DenseMatrix< T >::get_values(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize() , 以及 libMesh::DenseVector< T >::size().

321 {
322  // The calling sequence for dgetrf is:
323  // DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO )
324 
325  // JOBU (input)
326  // Specifies options for computing all or part of the matrix U:
327  // = 'A': all M columns of U are returned in array U:
328  // = 'S': the first min(m,n) columns of U (the left singular
329  // vectors) are returned in the array U;
330  // = 'O': the first min(m,n) columns of U (the left singular
331  // vectors) are overwritten on the array A;
332  // = 'N': no columns of U (no left singular vectors) are
333  // computed.
334  char JOBU = 'S';
335 
336  // JOBVT (input)
337  // Specifies options for computing all or part of the matrix
338  // V**T:
339  // = 'A': all N rows of V**T are returned in the array VT;
340  // = 'S': the first min(m,n) rows of V**T (the right singular
341  // vectors) are returned in the array VT;
342  // = 'O': the first min(m,n) rows of V**T (the right singular
343  // vectors) are overwritten on the array A;
344  // = 'N': no rows of V**T (no right singular vectors) are
345  // computed.
346  char JOBVT = 'S';
347 
348  // Note: Lapack is going to compute the singular values of A^T. If
349  // A=U * S * V^T, then A^T = V * S * U^T, which means that the
350  // values returned in the "U_val" array actually correspond to the
351  // entries of the V matrix, and the values returned in the VT_val
352  // array actually correspond to the entries of U^T. Therefore, we
353  // pass VT in the place of U and U in the place of VT below!
354  std::vector<Real> sigma_val;
355  int M = this->n();
356  int N = this->m();
357  int min_MN = (M < N) ? M : N;
358 
359  // Size user-provided storage appropriately. Inside svd_helper:
360  // U_val is sized to (M x min_MN)
361  // VT_val is sized to (min_MN x N)
362  // So, we set up U to have the shape of "VT_val^T", and VT to
363  // have the shape of "U_val^T".
364  //
365  // Finally, since the results are stored in column-major order by
366  // Lapack, but we actually want the transpose of what Lapack
367  // returns, this means (conveniently) that we don't even have to
368  // copy anything after the call to _svd_helper, it should already be
369  // in the correct order!
370  U.resize(N, min_MN);
371  VT.resize(min_MN, M);
372 
373  _svd_helper(JOBU, JOBVT, sigma_val, VT.get_values(), U.get_values());
374 
375  // Copy the singular values into sigma.
376  sigma.resize(cast_int<unsigned int>(sigma_val.size()));
377  for (auto i : make_range(sigma.size()))
378  sigma(i) = sigma_val[i];
379 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
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中实现 ]
template<typename T >
template LIBMESH_EXPORT void libMesh::DenseMatrix< T >::_svd_solve_lapack ( const DenseVector< T > &  rhs,
DenseVector< T > &  x,
Real  rcond 
) const
private

由svd_solve(rhs)调用。

参数
rhs右侧向量。
x存储解的向量。
rcond控制哪些奇异值被视为零的参数。

在文件 dense_matrix_blas_lapack.C529 行定义.

参考 libMesh::DenseVector< T >::get_values(), libMesh::DenseMatrix< T >::get_values(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::pPS(), libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

532 {
533  // Since BLAS is expecting column-major storage, we first need to
534  // make a transposed copy of *this, then pass it to the gelss
535  // routine instead of the original. This extra copy is kind of a
536  // bummer, it might be better if we could use the full SVD to
537  // compute the least-squares solution instead... Note that it isn't
538  // completely terrible either, since A_trans gets overwritten by
539  // Lapack, and we usually would end up making a copy of A outside
540  // the function call anyway.
541  DenseMatrix<T> A_trans;
542  this->get_transpose(A_trans);
543 
544  // M
545  // The number of rows of the input matrix. M >= 0.
546  // This is actually the number of *columns* of A_trans.
547  PetscBLASInt M = A_trans.n();
548 
549  // N
550  // The number of columns of the matrix A. N >= 0.
551  // This is actually the number of *rows* of A_trans.
552  PetscBLASInt N = A_trans.m();
553 
554  // We'll use the min and max of (M,N) several times below.
555  PetscBLASInt max_MN = std::max(M,N);
556  PetscBLASInt min_MN = std::min(M,N);
557 
558  // NRHS
559  // The number of right hand sides, i.e., the number of columns
560  // of the matrices B and X. NRHS >= 0.
561  // This could later be generalized to solve for multiple right-hand
562  // sides...
563  PetscBLASInt NRHS = 1;
564 
565  // A is double precision array, dimension (LDA,N)
566  // On entry, the M-by-N matrix A.
567  // On exit, the first min(m,n) rows of A are overwritten with
568  // its right singular vectors, stored rowwise.
569  //
570  // The data vector that will be passed to Lapack.
571  std::vector<T> & A_trans_vals = A_trans.get_values();
572 
573  // LDA
574  // The leading dimension of the array A. LDA >= max(1,M).
575  PetscBLASInt LDA = M;
576 
577  // B is double precision array, dimension (LDB,NRHS)
578  // On entry, the M-by-NRHS right hand side matrix B.
579  // On exit, B is overwritten by the N-by-NRHS solution
580  // matrix X. If m >= n and RANK = n, the residual
581  // sum-of-squares for the solution in the i-th column is given
582  // by the sum of squares of elements n+1:m in that column.
583  //
584  // Since we don't want the user's rhs vector to be overwritten by
585  // the solution, we copy the rhs values into the solution vector "x"
586  // now. x needs to be long enough to hold both the (Nx1) solution
587  // vector or the (Mx1) rhs, so size it to the max of those.
588  x.resize(max_MN);
589  for (auto i : make_range(rhs.size()))
590  x(i) = rhs(i);
591 
592  // Make the syntax below simpler by grabbing a reference to this array.
593  std::vector<T> & B = x.get_values();
594 
595  // LDB
596  // The leading dimension of the array B. LDB >= max(1,max(M,N)).
597  PetscBLASInt LDB = x.size();
598 
599  // S is double precision array, dimension (min(M,N))
600  // The singular values of A in decreasing order.
601  // The condition number of A in the 2-norm = S(1)/S(min(m,n)).
602  std::vector<T> S(min_MN);
603 
604  // RCOND
605  // Used to determine the effective rank of A. Singular values
606  // S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine
607  // precision is used instead.
608  PetscScalar RCOND = rcond;
609 
610  // RANK
611  // The effective rank of A, i.e., the number of singular values
612  // which are greater than RCOND*S(1).
613  PetscBLASInt RANK = 0;
614 
615  // LWORK
616  // The dimension of the array WORK. LWORK >= 1, and also:
617  // LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )
618  // For good performance, LWORK should generally be larger.
619  //
620  // If LWORK = -1, then a workspace query is assumed; the routine
621  // only calculates the optimal size of the WORK array, returns
622  // this value as the first entry of the WORK array, and no error
623  // message related to LWORK is issued by XERBLA.
624  //
625  // The factor of 3/2 is arbitrary and is used to satisfy the "should
626  // generally be larger" clause.
627  PetscBLASInt LWORK = (3*min_MN + std::max(2*min_MN, std::max(max_MN, NRHS))) * 3/2;
628 
629  // WORK is double precision array, dimension (MAX(1,LWORK))
630  // On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
631  std::vector<T> WORK(LWORK);
632 
633  // INFO
634  // = 0: successful exit
635  // < 0: if INFO = -i, the i-th argument had an illegal value.
636  // > 0: the algorithm for computing the SVD failed to converge;
637  // if INFO = i, i off-diagonal elements of an intermediate
638  // bidiagonal form did not converge to zero.
639  PetscBLASInt INFO = 0;
640 
641  // LAPACKgelss_(const PetscBLASInt *, // M
642  // const PetscBLASInt *, // N
643  // const PetscBLASInt *, // NRHS
644  // PetscScalar *, // A
645  // const PetscBLASInt *, // LDA
646  // PetscScalar *, // B
647  // const PetscBLASInt *, // LDB
648  // PetscReal *, // S(out) = singular values of A in increasing order
649  // const PetscReal *, // RCOND = tolerance for singular values
650  // PetscBLASInt *, // RANK(out) = number of "non-zero" singular values
651  // PetscScalar *, // WORK
652  // const PetscBLASInt *, // LWORK
653  // PetscBLASInt *); // INFO
654  LAPACKgelss_(&M, &N, &NRHS, pPS(A_trans_vals.data()), &LDA,
655  pPS(B.data()), &LDB, pPS(S.data()), &RCOND, &RANK,
656  pPS(WORK.data()), &LWORK, &INFO);
657 
658  // Check for errors in the Lapack call
659  libmesh_error_msg_if(INFO < 0, "Error, argument " << -INFO << " to LAPACKgelss_ had an illegal value.");
660  libmesh_error_msg_if(INFO > 0, "The algorithm for computing the SVD failed to converge!");
661 
662  // Debugging: print singular values and information about condition number:
663  // libMesh::err << "RCOND=" << RCOND << std::endl;
664  // libMesh::err << "Singular values: " << std::endl;
665  // for (auto i : index_range(S))
666  // libMesh::err << S[i] << std::endl;
667  // libMesh::err << "The condition number of A is approximately: " << S[0]/S.back() << std::endl;
668 
669  // Lapack has already written the solution into B, but it will be
670  // the wrong size for non-square problems, so we need to resize it
671  // correctly. The size of the solution vector should be the number
672  // of columns of the original A matrix. Unfortunately, resizing a
673  // DenseVector currently also zeros it out (unlike a std::vector) so
674  // we'll resize the underlying storage directly (the size is not
675  // stored independently elsewhere).
676  x.get_values().resize(this->n());
677 }
unsigned int n() const
返回矩阵的列维度。
void get_transpose(DenseMatrix< T > &dest) const
将转置矩阵存储在 dest 中。
PetscScalar * pPS(T *ptr)
Definition: petsc_macro.h:172
template<typename T >
template<typename T2 , typename T3 >
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type libMesh::DenseMatrixBase< T >::add ( const T2  factor,
const DenseMatrixBase< T3 > &  mat 
)
inlineinherited

factor 添加到矩阵的每个元素。 这应该仅在 T += T2 * T3 是有效的 C++,且 T2 是标量的情况下工作。返回类型是 void。

参数
factor要添加的标量因子。
mat乘法的右操作数矩阵。

在文件 dense_matrix_base.h217 行定义.

参考 libMesh::DenseMatrixBase< T >::el(), libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

219 {
220  libmesh_assert_equal_to (this->m(), mat.m());
221  libmesh_assert_equal_to (this->n(), mat.n());
222 
223  for (auto j : make_range(this->n()))
224  for (auto i : make_range(this->m()))
225  this->el(i,j) += factor*mat.el(i,j);
226 }
unsigned int n() const
返回矩阵的列维度。
virtual T el(const unsigned int i, const unsigned int j) const =0
返回矩阵的 (i,j) 元素。 由于内部数据表示可能不同,必须重新定义此函数。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template<typename T2 , typename T3 >
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type libMesh::DenseMatrix< T >::add ( const T2  factor,
const DenseMatrix< T3 > &  mat 
)
inline

factor 倍的矩阵 mat 添加到此矩阵。

参数
factor缩放因子。
mat要添加的矩阵。

在文件 dense_matrix.h1135 行定义.

1137 {
1138  libmesh_assert_equal_to (this->m(), mat.m());
1139  libmesh_assert_equal_to (this->n(), mat.n());
1140 
1141  for (auto i : make_range(this->m()))
1142  for (auto j : make_range(this->n()))
1143  (*this)(i,j) += factor * mat(i,j);
1144 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::cholesky_solve ( const DenseVector< T2 > &  b,
DenseVector< T2 > &  x 
)

对于对称正定矩阵(SPD),进行Cholesky分解。 分解为 A = L L^T,比标准LU分解大约快两倍。 因此,如果事先知道矩阵是SPD,则可以使用此方法。如果矩阵不是SPD,则会生成错误。 Cholesky分解的一个优点是它不需要主元交换以确保稳定性。

使用 Cholesky 分解解线性系统。

注意:一旦调用cholesky_solve(),就不能通过对operator(i,j)的调用修改矩阵的条目, 并在没有先调用zero()或resize()的情况下再次调用cholesky_solve(),否则代码将跳过计算矩阵的分解, 直接进行回代步骤。这是出于效率考虑而故意这样做的,以便相同的分解可用于多个右侧。但这也可能导致一些问题,所以要小心!

注解
此方法也可用于A为实值,而x和b为复值的情况。
模板参数
T2解向量x和右侧向量b的元素类型。
参数
b输入向量b。
x解向量x。

Cholesky 分解首先通过 cholesky_decompose 对矩阵进行分解, 然后使用 cholesky_back_substitute 找到解 x。

模板参数
T2输入向量 b 的数据类型。
参数
b输入向量 b。
x存储结果的目标向量 x。

在文件 dense_matrix_impl.h804 行定义.

805 {
806  // 检查是否已进行先前的分解
807  switch (this->_decomposition_type)
808  {
809  case NONE:
810  {
811  this->_cholesky_decompose();
812  break;
813  }
814 
815  case CHOLESKY:
816  {
817  // 已经分解,只需调用 back_substitute。
818  break;
819  }
820 
821  default:
822  libmesh_error_msg("Error! This matrix already has a different decomposition...");
823  }
824 
825  // 执行回代
826  this->_cholesky_back_substitute(b, x);
827 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
根据矩阵A的Cholesky分解解方程Ax=b,得到未知值x和rhs b。
void _cholesky_decompose()
将对称正定矩阵分解为两个下三角矩阵的乘积,即A = LL^T。
template<typename T >
void libMesh::DenseMatrixBase< T >::condense ( const unsigned int  iv,
const unsigned int  jv,
const T  val,
DenseVectorBase< T > &  rhs 
)
protectedinherited

将矩阵的 (i,j) 条目压缩出来,强制它取值为 val。这对于在数值模拟中应用边界条件很有用。 保留矩阵的对称性。

将矩阵列约减为已知值。

参数
i要压缩的行索引。
j要压缩的列索引。
val压缩出的值。
rhs与压缩操作相关联的右侧向量。
模板参数
T矩阵元素类型。
参数
iv列索引。
jv列索引。
val已知值。
rhs包含右侧向量的 DenseVectorBase 对象。

在文件 dense_matrix_base_impl.h94 行定义.

参考 libMesh::DenseVectorBase< T >::el() , 以及 libMesh::DenseVectorBase< T >::size().

参考自 libMesh::DenseMatrix< T >::condense().

98 {
99  libmesh_assert_equal_to(this->_m, rhs.size());
100  libmesh_assert_equal_to(iv, jv);
101 
102  // 将已知值移入 RHS,并将列置零
103  for (auto i : make_range(this->m()))
104  {
105  rhs.el(i) -= this->el(i, jv) * val;
106  this->el(i, jv) = 0.;
107  }
108 
109  // 将行置零
110  for (auto j : make_range(this->n()))
111  this->el(iv, j) = 0.;
112 
113  this->el(iv, jv) = 1.;
114  rhs.el(iv) = val;
115 }
unsigned int n() const
返回矩阵的列维度。
virtual T el(const unsigned int i, const unsigned int j) const =0
返回矩阵的 (i,j) 元素。 由于内部数据表示可能不同,必须重新定义此函数。
unsigned int m() const
返回矩阵的行维度。
unsigned int _m
行维度。
template<typename T>
void libMesh::DenseMatrix< T >::condense ( const unsigned int  i,
const unsigned int  j,
const T  val,
DenseVector< T > &  rhs 
)
inline

将矩阵的 (i,j) 元素凝聚出来,强制其取值为 val。

这在数值模拟中用于应用边界条件。保留矩阵的对称性。

参数
i矩阵行索引。
j矩阵列索引。
val设定的值。
rhs右侧向量。

在文件 dense_matrix.h507 行定义.

参考 libMesh::DenseMatrixBase< T >::condense().

511  { DenseMatrixBase<T>::condense (i, j, val, rhs); }
void condense(const unsigned int i, const unsigned int j, const T val, DenseVectorBase< T > &rhs)
将矩阵的 (i,j) 条目压缩出来,强制它取值为 val。这对于在数值模拟中应用边界条件很有用。 保留矩阵的对称性。
template<typename T>
T libMesh::DenseMatrix< T >::det ( )

返回矩阵的行列式。

注解
通过计算LU分解,然后取对角线项的乘积实现。因此,这是一个 修改矩阵条目的非const方法。
返回
矩阵的行列式。
template<typename T >
DenseVector< T > libMesh::DenseMatrixBase< T >::diagonal ( ) const
inherited

返回矩阵的对角线。

返回稠密矩阵的对角线。

返回
矩阵对角线的 DenseVector。
模板参数
T矩阵元素类型。
返回
返回包含对角线元素的 DenseVector 对象。

在文件 dense_matrix_base_impl.h43 行定义.

参考自 libMesh::DiagonalMatrix< T >::add_matrix().

44 {
45  DenseVector<T> ret(_m);
46  for (decltype(_m) i = 0; i < _m; ++i)
47  ret(i) = el(i, i);
48  return ret;
49 }
virtual T el(const unsigned int i, const unsigned int j) const =0
返回矩阵的 (i,j) 元素。 由于内部数据表示可能不同,必须重新定义此函数。
unsigned int _m
行维度。
template<typename T>
virtual T libMesh::DenseMatrix< T >::el ( const unsigned int  i,
const unsigned int  j 
) const
inlinefinaloverridevirtual

获取矩阵的 (i,j) 元素。

参数
i元素的行索引。
j元素的列索引。
返回
矩阵的 (i,j) 元素。

实现了 libMesh::DenseMatrixBase< T >.

在文件 dense_matrix.h160 行定义.

162  { return (*this)(i,j); }
template<typename T>
virtual T& libMesh::DenseMatrix< T >::el ( const unsigned int  i,
const unsigned int  j 
)
inlinefinaloverridevirtual

获取矩阵的 (i,j) 元素的可写引用。

参数
i元素的行索引。
j元素的列索引。
返回
矩阵的 (i,j) 元素的可写引用。

实现了 libMesh::DenseMatrixBase< T >.

在文件 dense_matrix.h171 行定义.

173  { return (*this)(i,j); }
template<typename T>
void libMesh::DenseMatrix< T >::evd ( DenseVector< T > &  lambda_real,
DenseVector< T > &  lambda_imag 
)

计算一般矩阵的特征值(实部和虚部)。

警告:此函数会覆盖*this的内容!

实现需要由PETSc包装的LAPACKgeev_函数。

参数
lambda_real存储实部特征值的向量。
lambda_imag存储虚部特征值的向量。
template<typename T>
void libMesh::DenseMatrix< T >::evd_left ( DenseVector< T > &  lambda_real,
DenseVector< T > &  lambda_imag,
DenseMatrix< T > &  VL 
)

计算一般矩阵 $ A $ 的特征值(实部和虚部)和左特征向量。

警告:此函数会覆盖*this的内容!

矩阵 $ A $ 的左特征向量 $ u_j $ 满足: $ u_j^H A = lambda_j u_j^H $,其中 $ u_j^H $ 表示 $ u_j $ 的共轭转置。

如果第j和(j+1)个特征值形成复共轭对,则VL的第j和(j+1)列“共享”它们的实值存储,方式如下: u_j = VL(:,j) + i*VL(:,j+1) 和 u_{j+1} = VL(:,j) - i*VL(:,j+1)。

实现需要由PETSc提供的LAPACKgeev_例程。

参数
lambda_real存储实部特征值的向量。
lambda_imag存储虚部特征值的向量。
VL存储左特征向量的矩阵。
template<typename T>
void libMesh::DenseMatrix< T >::evd_left_and_right ( DenseVector< T > &  lambda_real,
DenseVector< T > &  lambda_imag,
DenseMatrix< T > &  VL,
DenseMatrix< T > &  VR 
)

计算一般矩阵的特征值(实部和虚部),以及左右特征向量。

警告:此函数会覆盖*this的内容!

有关更多信息,请参见evd_left()evd_right() 函数的文档。 实现需要由PETSc提供的LAPACKgeev_例程。

参数
lambda_real存储实部特征值的向量。
lambda_imag存储虚部特征值的向量。
VL存储左特征向量的矩阵。
VR存储右特征向量的矩阵。
template<typename T>
void libMesh::DenseMatrix< T >::evd_right ( DenseVector< T > &  lambda_real,
DenseVector< T > &  lambda_imag,
DenseMatrix< T > &  VR 
)

计算一般矩阵 $ A $ 的特征值(实部和虚部)和右特征向量。

警告:此函数会覆盖*this的内容!

矩阵 $ A $ 的右特征向量 $ v_j $ 满足: $ A v_j = lambda_j v_j $,其中 $ lambda_j $ 是其相应的特征值。

注解
如果第j和(j+1)个特征值形成复共轭对,则VR的第j和(j+1)列“共享”它们的实值存储,方式如下: v_j = VR(:,j) + i*VR(:,j+1) 和 v_{j+1} = VR(:,j) - i*VR(:,j+1)。

实现需要由PETSc提供的LAPACKgeev_例程。

参数
lambda_real存储实部特征值的向量。
lambda_imag存储虚部特征值的向量。
VR存储右特征向量的矩阵。
template<typename T >
void libMesh::DenseMatrix< T >::get_principal_submatrix ( unsigned int  sub_m,
unsigned int  sub_n,
DenseMatrix< T > &  dest 
) const

sub_m x sub_n 的主子矩阵放入 dest 中。

获取主对角线子矩阵。

参数
sub_m子矩阵的行数。
sub_n子矩阵的列数。
dest存储结果的矩阵。
sub_m子矩阵的行数。
sub_n子矩阵的列数。
dest存储结果的目标矩阵。

在文件 dense_matrix_impl.h529 行定义.

参考 libMesh::DenseMatrix< T >::resize().

532 {
533  libmesh_assert((sub_m <= this->m()) && (sub_n <= this->n()));
534 
535  dest.resize(sub_m, sub_n);
536  for (unsigned int i = 0; i < sub_m; i++)
537  for (unsigned int j = 0; j < sub_n; j++)
538  dest(i, j) = (*this)(i, j);
539 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrix< T >::get_principal_submatrix ( unsigned int  sub_m,
DenseMatrix< T > &  dest 
) const

sub_m x sub_m 的主子矩阵放入 dest 中。

获取主对角线子矩阵。

参数
sub_m子矩阵的行数和列数。
dest存储结果的矩阵。
sub_m子矩阵的行数和列数。
dest存储结果的目标矩阵。

在文件 dense_matrix_impl.h567 行定义.

568 {
569  get_principal_submatrix(sub_m, sub_m, dest);
570 }
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
将 sub_m x sub_n 的主子矩阵放入 dest 中。
template<typename T >
void libMesh::DenseMatrix< T >::get_transpose ( DenseMatrix< T > &  dest) const

将转置矩阵存储在 dest 中。

获取矩阵的转置。

参数
dest存储结果的矩阵。
dest存储结果的目标矩阵。

在文件 dense_matrix_impl.h578 行定义.

参考 libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::DenseMatrix< T >::resize().

579 {
580  dest.resize(this->n(), this->m());
581 
582  for (auto i : make_range(dest.m()))
583  for (auto j : make_range(dest.n()))
584  dest(i, j) = (*this)(j, i);
585 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T>
std::vector<T>& libMesh::DenseMatrix< T >::get_values ( )
inline

返回对应于存储向量的引用的底层数据存储矢量。

警告:在使用时应谨慎(即不应更改向量的大小等),但用于与期望简单数组的低级BLAS例程进行交互很有用。

返回
对底层数据存储矢量的引用。

在文件 dense_matrix.h488 行定义.

参考 libMesh::DenseMatrix< T >::_val.

参考自 libMesh::DenseMatrix< T >::_evd_lapack(), libMesh::DenseMatrix< T >::_matvec_blas(), libMesh::DenseMatrix< T >::_multiply_blas(), libMesh::DenseMatrix< T >::_svd_lapack(), libMesh::DenseMatrix< T >::_svd_solve_lapack(), libMesh::PetscMatrix< T >::add_block_matrix(), libMesh::EpetraMatrix< T >::add_matrix() , 以及 libMesh::PetscMatrix< T >::add_matrix().

488 { return _val; }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T>
const std::vector<T>& libMesh::DenseMatrix< T >::get_values ( ) const
inline

返回底层数据存储矢量的常量引用。

返回
对底层数据存储矢量的常量引用。

在文件 dense_matrix.h495 行定义.

参考 libMesh::DenseMatrix< T >::_val.

495 { return _val; }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
auto libMesh::DenseMatrix< T >::l1_norm ( ) const -> decltype(std::abs(T(0)))
inline

返回矩阵的 l1-范数,即最大列和

这是与向量的 l1-范数兼容的自然矩阵范数,即 $ |Mv|_1 \leq |M|_1 |v|_1 $

返回
矩阵的 l1-范数。

在文件 dense_matrix.h1242 行定义.

参考 std::abs().

1243 {
1244  libmesh_assert (this->_m);
1245  libmesh_assert (this->_n);
1246 
1247  auto columnsum = std::abs(T(0));
1248  for (unsigned int i=0; i!=this->_m; i++)
1249  {
1250  columnsum += std::abs((*this)(i,0));
1251  }
1252  auto my_max = columnsum;
1253  for (unsigned int j=1; j!=this->_n; j++)
1254  {
1255  columnsum = 0.;
1256  for (unsigned int i=0; i!=this->_m; i++)
1257  {
1258  columnsum += std::abs((*this)(i,j));
1259  }
1260  my_max = (my_max > columnsum? my_max : columnsum);
1261  }
1262  return my_max;
1263 }
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
unsigned int _n
列维度。
unsigned int _m
行维度。
template<typename T >
void libMesh::DenseMatrix< T >::left_multiply ( const DenseMatrixBase< T > &  M2)
finaloverridevirtual

左乘以矩阵 M2。

左乘另一个矩阵(M2 * (*this))。

参数
M2另一个矩阵。
M2与之左乘的矩阵。

实现了 libMesh::DenseMatrixBase< T >.

在文件 dense_matrix_impl.h51 行定义.

参考 libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

52 {
53  if (this->use_blas_lapack)
54  this->_multiply_blas(M2, LEFT_MULTIPLY);
55  else
56  {
57  // M3 是 *this 调整大小之前的副本
58  DenseMatrix<T> M3(*this);
59 
60  // 调整 *this 的大小以适应结果
61  this->resize(M2.m(), M3.n());
62 
63  // 在基类中调用乘法函数
64  this->multiply(*this, M2, M3);
65  }
66 }
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
_multiply_blas函数使用BLAS gemm函数计算A &lt;- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_...
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
static void multiply(DenseMatrixBase< T > &M1, const DenseMatrixBase< T > &M2, const DenseMatrixBase< T > &M3)
辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n)
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::left_multiply ( const DenseMatrixBase< T2 > &  M2)

左乘以不同类型的矩阵 M2。

左乘另一个矩阵(M2 * (*this))。

模板参数
T2矩阵 M2 的元素类型。
参数
M2另一个矩阵。
M2与之左乘的矩阵。

在文件 dense_matrix_impl.h76 行定义.

参考 libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

77 {
78  // M3 是 *this 调整大小之前的副本
79  DenseMatrix<T> M3(*this);
80 
81  // 调整 *this 的大小以适应结果
82  this->resize(M2.m(), M3.n());
83 
84  // 在基类中调用乘法函数
85  this->multiply(*this, M2, M3);
86 }
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
static void multiply(DenseMatrixBase< T > &M1, const DenseMatrixBase< T > &M2, const DenseMatrixBase< T > &M3)
辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n)
template<typename T >
void libMesh::DenseMatrix< T >::left_multiply_transpose ( const DenseMatrix< T > &  A)

用矩阵 A 的转置左乘。

左乘转置矩阵。

参数
A要与左乘的矩阵。

如果启用了 BLAS/LAPACK,它将使用优化的 BLAS 例程;否则,它将执行 _left_multiply_transpose 函数。

参数
A要左乘的转置矩阵。

在文件 dense_matrix_impl.h96 行定义.

参考自 libMesh::DofMap::constrain_element_matrix(), libMesh::DofMap::constrain_element_matrix_and_vector(), libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual() , 以及 libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector().

97 {
98  if (this->use_blas_lapack)
100  else
101  this->_left_multiply_transpose(A);
102 }
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
_multiply_blas函数使用BLAS gemm函数计算A &lt;- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_...
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::left_multiply_transpose ( const DenseMatrix< T2 > &  A)

用包含不同数值类型的矩阵 A 的转置左乘。

左乘转置矩阵。

参数
T2矩阵元素的其他数值类型。
A要与左乘的矩阵。
A要左乘的转置矩阵。

在文件 dense_matrix_impl.h111 行定义.

112 {
113  this->_left_multiply_transpose(A);
114 }
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。
template<typename T >
auto libMesh::DenseMatrix< T >::linfty_norm ( ) const -> decltype(std::abs(T(0)))
inline

返回矩阵的 linfty-范数,即最大行和

这是与向量的 linfty-范数兼容的自然矩阵范数,即 $ |Mv|_\infty \leq |M|_\infty |v|_\infty $

返回
矩阵的 linfty-范数。

在文件 dense_matrix.h1269 行定义.

参考 std::abs().

1270 {
1271  libmesh_assert (this->_m);
1272  libmesh_assert (this->_n);
1273 
1274  auto rowsum = std::abs(T(0));
1275  for (unsigned int j=0; j!=this->_n; j++)
1276  {
1277  rowsum += std::abs((*this)(0,j));
1278  }
1279  auto my_max = rowsum;
1280  for (unsigned int i=1; i!=this->_m; i++)
1281  {
1282  rowsum = 0.;
1283  for (unsigned int j=0; j!=this->_n; j++)
1284  {
1285  rowsum += std::abs((*this)(i,j));
1286  }
1287  my_max = (my_max > rowsum? my_max : rowsum);
1288  }
1289  return my_max;
1290 }
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
unsigned int _n
列维度。
unsigned int _m
行维度。
template<typename T >
void libMesh::DenseMatrix< T >::lu_solve ( const DenseVector< T > &  b,
DenseVector< T > &  x 
)

解方程组 $ Ax=b $ 给定输入向量 b。

使用 LU 分解解线性系统。

默认情况下执行部分主元消去以保持算法对舍入误差的影响稳定。

注意:一旦调用 lu_solve(),就不能通过对 operator(i, j) 的调用修改矩阵的条目, 也不能在没有先调用 zero()resize() 的情况下再次调用 lu_solve(), 否则代码将跳过计算矩阵的分解而直接进入回代步骤。 这是出于效率考虑而故意这样做的,以便相同的LU分解可以用于多个右侧。 但这也可能导致一些问题,所以要小心!

参数
b输入向量 b。
x解向量 x。
b输入向量 b。
x存储结果的目标向量 x。 使用 LU 分解解线性系统。

在进行 LU 求解之前,确保矩阵是方阵。通常情况下,可以计算非方阵的 LU 分解,但是:

  • 过定定系统(m>n)只有在足够的方程线性相关时才有解。
  • 欠定定系统(m<n)通常有无穷多个解。

不希望在这里处理这两种不明确的情况

参数
b输入向量 b。
x存储结果的目标向量 x。

在文件 dense_matrix_impl.h607 行定义.

608 {
609  // 确保矩阵是方阵
610  libmesh_assert_equal_to(this->m(), this->n());
611 
612  switch (this->_decomposition_type)
613  {
614  case NONE:
615  {
616  if (this->use_blas_lapack)
617  this->_lu_decompose_lapack();
618  else
619  this->_lu_decompose();
620  break;
621  }
622 
623  case LU_BLAS_LAPACK:
624  {
625  // 已经分解,只需调用 back_substitute。
626  if (this->use_blas_lapack)
627  break;
628  }
629  libmesh_fallthrough();
630 
631  case LU:
632  {
633  // 已经分解,只需调用 back_substitute。
634  if (!(this->use_blas_lapack))
635  break;
636  }
637  libmesh_fallthrough();
638 
639  default:
640  libmesh_error_msg("Error! This matrix already has a different decomposition...");
641  }
642 
643  if (this->use_blas_lapack)
644  this->_lu_back_substitute_lapack(b, x);
645  else
646  this->_lu_back_substitute(b, x);
647 }
void _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
通过回代步骤解方程Ax=b。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
unsigned int n() const
返回矩阵的列维度。
void _lu_decompose_lapack()
使用Lapack例程“getrf”计算矩阵的LU分解。此例程只能由lu_solve()函数的“use_blas_lapack”分支使用。 调用此函数后,矩阵将被其因式分解版本替换,并且Decomposi...
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
unsigned int m() const
返回矩阵的行维度。
void _lu_back_substitute_lapack(const DenseVector< T > &b, DenseVector< T > &x)
与_lu_decompose_lapack()相对应的伴随函数。不要直接使用,通过公共lu_solve()接口调用。 由于我们只是调用LAPACK例程,该函数在逻辑上是const的,因为它不修改矩阵, ...
void _lu_decompose()
形成矩阵的LU分解。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
template<typename T>
unsigned int libMesh::DenseMatrixBase< T >::m ( ) const
inlineinherited

返回矩阵的行维度。

返回
矩阵的行维度。

在文件 dense_matrix_base.h115 行定义.

参考 libMesh::DenseMatrixBase< T >::_m.

参考自 libMesh::DenseMatrix< T >::_left_multiply_transpose(), libMesh::DenseMatrix< T >::_multiply_blas(), libMesh::DenseMatrix< T >::_right_multiply_transpose(), libMesh::DenseMatrix< T >::_svd_solve_lapack(), libMesh::DenseMatrixBase< T >::add(), libMesh::SparseMatrix< T >::add_block_matrix(), libMesh::PetscMatrix< T >::add_block_matrix(), libMesh::EigenSparseMatrix< T >::add_matrix(), libMesh::DiagonalMatrix< T >::add_matrix(), libMesh::LaspackMatrix< T >::add_matrix(), libMesh::EpetraMatrix< T >::add_matrix(), libMesh::PetscMatrix< T >::add_matrix(), libMesh::DofMap::build_constraint_matrix(), libMesh::DofMap::build_constraint_matrix_and_vector(), libMesh::DofMap::constrain_element_dyad_matrix(), libMesh::DofMap::constrain_element_matrix(), libMesh::DofMap::constrain_element_matrix_and_vector(), libMesh::DofMap::constrain_element_vector(), libMesh::DofMap::extract_local_vector(), libMesh::DenseMatrix< T >::get_transpose(), libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual(), libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector(), libMesh::DofMap::heterogeneously_constrain_element_residual(), libMesh::DofMap::heterogeneously_constrain_element_vector(), libMesh::DenseMatrix< T >::left_multiply(), libMesh::DofMap::max_constraint_error(), libMesh::DenseMatrixBase< T >::multiply(), libMesh::DenseMatrix< T >::right_multiply() , 以及 MetaPhysicL::RawType< libMesh::DenseMatrix< T > >::value().

115 { return _m; }
unsigned int _m
行维度。
template<typename T >
auto libMesh::DenseMatrix< T >::max ( ) const -> decltype(libmesh_real(T(0)))
inline

返回矩阵的最大元素或复数情况下的最大实部。

返回
矩阵的最大元素或复数情况下的最大实部。

在文件 dense_matrix.h1221 行定义.

参考 libMesh::libmesh_real().

1222 {
1223  libmesh_assert (this->_m);
1224  libmesh_assert (this->_n);
1225  auto my_max = libmesh_real((*this)(0,0));
1226 
1227  for (unsigned int i=0; i!=this->_m; i++)
1228  {
1229  for (unsigned int j=0; j!=this->_n; j++)
1230  {
1231  auto current = libmesh_real((*this)(i,j));
1232  my_max = (my_max > current? my_max : current);
1233  }
1234  }
1235  return my_max;
1236 }
T libmesh_real(T a)
unsigned int _n
列维度。
unsigned int _m
行维度。
template<typename T >
auto libMesh::DenseMatrix< T >::min ( ) const -> decltype(libmesh_real(T(0)))
inline

返回矩阵的最小元素或复数情况下的最小实部。

返回
矩阵的最小元素或复数情况下的最小实部。

在文件 dense_matrix.h1200 行定义.

参考 libMesh::libmesh_real().

1201 {
1202  libmesh_assert (this->_m);
1203  libmesh_assert (this->_n);
1204  auto my_min = libmesh_real((*this)(0,0));
1205 
1206  for (unsigned int i=0; i!=this->_m; i++)
1207  {
1208  for (unsigned int j=0; j!=this->_n; j++)
1209  {
1210  auto current = libmesh_real((*this)(i,j));
1211  my_min = (my_min < current? my_min : current);
1212  }
1213  }
1214  return my_min;
1215 }
T libmesh_real(T a)
unsigned int _n
列维度。
unsigned int _m
行维度。
template<typename T >
void libMesh::DenseMatrixBase< T >::multiply ( DenseMatrixBase< T > &  M1,
const DenseMatrixBase< T > &  M2,
const DenseMatrixBase< T > &  M3 
)
staticprotectedinherited

辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n)

将两个矩阵相乘。

参数
M1乘法的结果矩阵。
M2乘法的左操作数矩阵。
M3乘法的右操作数矩阵。
模板参数
T矩阵元素类型。
参数
M1存储结果的矩阵。
M2第一个矩阵。
M3第二个矩阵。

在文件 dense_matrix_base_impl.h61 行定义.

参考 libMesh::DenseMatrixBase< T >::el(), libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

64 {
65  // 断言确保我们传递了正确维度的矩阵
66  libmesh_assert_equal_to(M1.m(), M2.m());
67  libmesh_assert_equal_to(M1.n(), M3.n());
68  libmesh_assert_equal_to(M2.n(), M3.m());
69 
70  const unsigned int m_s = M2.m();
71  const unsigned int p_s = M2.n();
72  const unsigned int n_s = M1.n();
73 
74  // 通过这种方式执行是因为有很大的机会(至少对于约束矩阵来说)
75  // 在右乘时 M3(k,j) = 0.
76  for (unsigned int k = 0; k < p_s; k++)
77  for (unsigned int j = 0; j < n_s; j++)
78  if (M3.el(k, j) != 0.)
79  for (unsigned int i = 0; i < m_s; i++)
80  M1.el(i, j) += M2.el(i, k) * M3.el(k, j);
81 }
template<typename T>
unsigned int libMesh::DenseMatrixBase< T >::n ( ) const
inlineinherited

返回矩阵的列维度。

返回
矩阵的列维度。

在文件 dense_matrix_base.h122 行定义.

参考 libMesh::DenseMatrixBase< T >::_n.

参考自 libMesh::DenseMatrix< T >::_left_multiply_transpose(), libMesh::DenseMatrix< T >::_multiply_blas(), libMesh::DenseMatrix< T >::_right_multiply_transpose(), libMesh::DenseMatrix< T >::_svd_solve_lapack(), libMesh::DenseMatrixBase< T >::add(), libMesh::SparseMatrix< T >::add_block_matrix(), libMesh::PetscMatrix< T >::add_block_matrix(), libMesh::EigenSparseMatrix< T >::add_matrix(), libMesh::DiagonalMatrix< T >::add_matrix(), libMesh::LaspackMatrix< T >::add_matrix(), libMesh::EpetraMatrix< T >::add_matrix(), libMesh::PetscMatrix< T >::add_matrix(), libMesh::DofMap::build_constraint_matrix(), libMesh::DofMap::build_constraint_matrix_and_vector(), libMesh::DofMap::constrain_element_dyad_matrix(), libMesh::DofMap::constrain_element_matrix(), libMesh::DofMap::constrain_element_matrix_and_vector(), libMesh::DofMap::constrain_element_residual(), libMesh::DofMap::constrain_element_vector(), libMesh::DofMap::extract_local_vector(), libMesh::DenseMatrix< T >::get_transpose(), libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual(), libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector(), libMesh::DofMap::heterogeneously_constrain_element_residual(), libMesh::DofMap::heterogeneously_constrain_element_vector(), libMesh::DenseMatrix< T >::left_multiply(), libMesh::DofMap::max_constraint_error(), libMesh::DenseMatrixBase< T >::multiply(), libMesh::DenseMatrix< T >::right_multiply() , 以及 MetaPhysicL::RawType< libMesh::DenseMatrix< T > >::value().

122 { return _n; }
unsigned int _n
列维度。
template<typename T >
bool libMesh::DenseMatrix< T >::operator!= ( const DenseMatrix< T > &  mat) const
inline

检查矩阵是否与另一个矩阵 mat 完全不相等。

参数
mat要比较的矩阵。
返回
如果 mat 与当前矩阵完全不相等,则为 true,否则为 false。

在文件 dense_matrix.h1163 行定义.

1164 {
1165  for (auto i : index_range(_val))
1166  if (_val[i] != mat._val[i])
1167  return true;
1168 
1169  return false;
1170 }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
T libMesh::DenseMatrix< T >::operator() ( const unsigned int  i,
const unsigned int  j 
) const
inline

获取矩阵的 (i,j) 元素。

参数
i元素的行索引。
j元素的列索引。
返回
矩阵的 (i,j) 元素。

在文件 dense_matrix.h1070 行定义.

1072 {
1073  libmesh_assert_less (i*j, _val.size());
1074  libmesh_assert_less (i, this->_m);
1075  libmesh_assert_less (j, this->_n);
1076 
1077 
1078  // return _val[(i) + (this->_m)*(j)]; // col-major
1079  return _val[(i)*(this->_n) + (j)]; // row-major
1080 }
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
T & libMesh::DenseMatrix< T >::operator() ( const unsigned int  i,
const unsigned int  j 
)
inline

获取矩阵的 (i,j) 元素的可写引用。

参数
i元素的行索引。
j元素的列索引。
返回
矩阵的 (i,j) 元素的可写引用。

在文件 dense_matrix.h1086 行定义.

1088 {
1089  libmesh_assert_less (i*j, _val.size());
1090  libmesh_assert_less (i, this->_m);
1091  libmesh_assert_less (j, this->_n);
1092 
1093  //return _val[(i) + (this->_m)*(j)]; // col-major
1094  return _val[(i)*(this->_n) + (j)]; // row-major
1095 }
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
DenseMatrix< T > & libMesh::DenseMatrix< T >::operator*= ( const T  factor)
inline

将矩阵的每个元素乘以 factor。

返回
对 *this 的引用。

在文件 dense_matrix.h1122 行定义.

1123 {
1124  this->scale(factor);
1125  return *this;
1126 }
void scale(const T factor)
将矩阵的每个元素乘以 factor。
template<typename T >
DenseMatrix< T > & libMesh::DenseMatrix< T >::operator+= ( const DenseMatrix< T > &  mat)
inline

将矩阵 mat 添加到此矩阵。

返回
对 *this 的引用。

在文件 dense_matrix.h1176 行定义.

1177 {
1178  for (auto i : index_range(_val))
1179  _val[i] += mat._val[i];
1180 
1181  return *this;
1182 }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
DenseMatrix< T > & libMesh::DenseMatrix< T >::operator-= ( const DenseMatrix< T > &  mat)
inline

从此矩阵中减去矩阵 mat。

返回
对 *this 的引用。

在文件 dense_matrix.h1188 行定义.

1189 {
1190  for (auto i : index_range(_val))
1191  _val[i] -= mat._val[i];
1192 
1193  return *this;
1194 }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T>
DenseMatrix& libMesh::DenseMatrix< T >::operator= ( const DenseMatrix< T > &  )
default

复制赋值运算符。复制赋值运算符使用默认实现,因为该类不管理任何内存。

template<typename T>
DenseMatrix& libMesh::DenseMatrix< T >::operator= ( DenseMatrix< T > &&  )
default

移动赋值运算符。移动赋值运算符使用默认实现,因为该类不管理任何内存。

template<typename T >
template<typename T2 >
DenseMatrix< T > & libMesh::DenseMatrix< T >::operator= ( const DenseMatrix< T2 > &  other_matrix)
inline

从另一种矩阵类型复制矩阵。

将类型为 T2 的矩阵复制到当前矩阵。这对于将实矩阵复制到复矩阵以进行后续操作很有用。

参数
other_matrix要复制的矩阵。
返回
对 *this 的引用。

在文件 dense_matrix.h997 行定义.

998 {
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);
1004 
1005  return *this;
1006 }
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
template<typename T >
bool libMesh::DenseMatrix< T >::operator== ( const DenseMatrix< T > &  mat) const
inline

检查矩阵是否与另一个矩阵 mat 完全相等。

参数
mat要比较的矩阵。
返回
如果 mat 与当前矩阵完全相等,则为 true,否则为 false。

在文件 dense_matrix.h1150 行定义.

1151 {
1152  for (auto i : index_range(_val))
1153  if (_val[i] != mat._val[i])
1154  return false;
1155 
1156  return true;
1157 }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
void libMesh::DenseMatrix< T >::outer_product ( const DenseVector< T > &  a,
const DenseVector< T > &  b 
)

计算两个向量的外积并将结果存储在 (*this) 中。

外积操作。

对于两个实值向量 $\mathbf{a}$$\mathbf{b}$ 的外积是

\[ (\mathbf{a}\mathbf{b}^T)_{i,j} = \mathbf{a}_i \mathbf{b}_j . \]

对于两个复值向量 $\mathbf{a}$$\mathbf{b}$ 的外积是

\[ (\mathbf{a}\mathbf{b}^H)_{i,j} = \mathbf{a}_i \mathbf{b}^*_j , \]

其中 $H$ 表示向量的共轭转置, $*$ 表示复共轭。

参数
a与行相关的向量。
b与列相关的向量。
a输入向量 a。
b输入向量 b。

在文件 dense_matrix_impl.h548 行定义.

参考 libMesh::libmesh_conj() , 以及 libMesh::DenseVector< T >::size().

550 {
551  const unsigned int m = a.size();
552  const unsigned int n = b.size();
553 
554  this->resize(m, n);
555  for (unsigned int i = 0; i < m; ++i)
556  for (unsigned int j = 0; j < n; ++j)
557  (*this)(i, j) = a(i) * libmesh_conj(b(j));
558 }
unsigned int n() const
返回矩阵的列维度。
T libmesh_conj(T a)
unsigned int m() const
返回矩阵的行维度。
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
template<typename T >
void libMesh::DenseMatrixBase< T >::print ( std::ostream &  os = libMesh::out) const
inherited

漂亮地打印矩阵,默认为 libMesh::out。

以普通格式打印矩阵。

参数
os输出流,默认为 libMesh::out。
模板参数
T矩阵元素类型。
参数
os输出流。

在文件 dense_matrix_base_impl.h155 行定义.

156 {
157  for (auto i : make_range(this->m()))
158  {
159  for (auto j : make_range(this->n()))
160  os << std::setw(8)
161  << this->el(i, j) << " ";
162 
163  os << std::endl;
164  }
165 
166  return;
167 }
unsigned int n() const
返回矩阵的列维度。
virtual T el(const unsigned int i, const unsigned int j) const =0
返回矩阵的 (i,j) 元素。 由于内部数据表示可能不同,必须重新定义此函数。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrixBase< T >::print_scientific ( std::ostream &  os,
unsigned  precision = 8 
) const
inherited

以科学计数法格式打印矩阵。

参数
os输出流。
precision打印的精度。
模板参数
T矩阵元素类型。
参数
os输出流。
precision打印的精度。

在文件 dense_matrix_base_impl.h126 行定义.

127 {
128  // 保存初始格式标志
129  std::ios_base::fmtflags os_flags = os.flags();
130 
131  // 打印矩阵元素
132  for (auto i : make_range(this->m()))
133  {
134  for (auto j : make_range(this->n()))
135  os << std::setw(15)
136  << std::scientific
137  << std::setprecision(precision)
138  << this->el(i, j) << " ";
139 
140  os << std::endl;
141  }
142 
143  // 恢复原始格式标志
144  os.flags(os_flags);
145 }
unsigned int n() const
返回矩阵的列维度。
virtual T el(const unsigned int i, const unsigned int j) const =0
返回矩阵的 (i,j) 元素。 由于内部数据表示可能不同,必须重新定义此函数。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrix< T >::resize ( const unsigned int  new_m,
const unsigned int  new_n 
)
inline

调整矩阵的大小,并调用 zero() 方法。

不会释放内存,但可能会分配更多内存。注意:当矩阵被 zero() 时,任何分解(LU、Cholesky 等)也将被清除, 强制在下一次调用例如 lu_solve() 时重新计算。

参数
new_m新的行数。
new_n新的列数。

在文件 dense_matrix.h1012 行定义.

参考 libMesh::zero.

参考自 libMesh::DenseMatrix< T >::_evd_lapack(), libMesh::DenseMatrix< T >::_lu_decompose(), libMesh::DenseMatrix< T >::_svd_lapack(), libMesh::DofMap::build_constraint_matrix(), libMesh::DofMap::build_constraint_matrix_and_vector(), libMesh::DenseMatrix< T >::DenseMatrix(), libMesh::DenseMatrix< T >::get_principal_submatrix() , 以及 libMesh::DenseMatrix< T >::get_transpose().

1014 {
1015  _val.resize(new_m*new_n);
1016 
1017  this->_m = new_m;
1018  this->_n = new_n;
1019 
1020  // zero and set decomposition_type to NONE
1021  this->zero();
1022 }
virtual void zero() overridefinal
将矩阵的所有元素设置为0,并重置任何可能先前设置的分解标志。 这允许例如计算新的LU分解,同时重用相同的存储空间。
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
void libMesh::DenseMatrix< T >::right_multiply ( const DenseMatrixBase< T > &  M3)
finaloverridevirtual

右乘以矩阵 M2。

右乘另一个矩阵((*this) * M3)。

参数
M2另一个矩阵。

如果启用了 BLAS/LAPACK,它将使用优化的 BLAS 例程;否则,它将执行基类中的乘法函数。

参数
M3与之右乘的矩阵。

实现了 libMesh::DenseMatrixBase< T >.

在文件 dense_matrix_impl.h188 行定义.

参考 libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

参考自 libMesh::DofMap::build_constraint_matrix(), libMesh::DofMap::build_constraint_matrix_and_vector(), libMesh::DofMap::constrain_element_matrix(), libMesh::DofMap::constrain_element_matrix_and_vector(), libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual() , 以及 libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector().

189 {
190  if (this->use_blas_lapack)
191  this->_multiply_blas(M3, RIGHT_MULTIPLY);
192  else
193  {
194  // M2 是 *this 调整大小之前的副本
195  DenseMatrix<T> M2(*this);
196 
197  // 调整 *this 的大小以适应结果
198  this->resize(M2.m(), M3.n());
199 
200  this->multiply(*this, M2, M3);
201  }
202 }
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
_multiply_blas函数使用BLAS gemm函数计算A &lt;- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_...
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
static void multiply(DenseMatrixBase< T > &M1, const DenseMatrixBase< T > &M2, const DenseMatrixBase< T > &M3)
辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n)
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::right_multiply ( const DenseMatrixBase< T2 > &  M3)

右乘以不同类型的矩阵 M2。

右乘另一个矩阵((*this) * M3)。

模板参数
T2矩阵 M2 的元素类型。
参数
M2另一个矩阵。

如果启用了 BLAS/LAPACK,它将使用优化的 BLAS 例程;否则,它将执行基类中的乘法函数。

参数
M3与之右乘的矩阵。

在文件 dense_matrix_impl.h213 行定义.

参考 libMesh::DenseMatrixBase< T >::m() , 以及 libMesh::DenseMatrixBase< T >::n().

214 {
215  // M2 是 *this 调整大小之前的副本
216  DenseMatrix<T> M2(*this);
217 
218  // 调整 *this 的大小以适应结果
219  this->resize(M2.m(), M3.n());
220 
221  this->multiply(*this, M2, M3);
222 }
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
static void multiply(DenseMatrixBase< T > &M1, const DenseMatrixBase< T > &M2, const DenseMatrixBase< T > &M3)
辅助函数 - 执行计算 M1 = M2 * M3 其中: M1 = (m x n) M2 = (m x p) M3 = (p x n)
template<typename T >
void libMesh::DenseMatrix< T >::right_multiply_transpose ( const DenseMatrix< T > &  B)

用矩阵 A 的转置右乘。

右乘转置矩阵。

参数
A要与右乘的矩阵。

如果启用了 BLAS/LAPACK,它将使用优化的 BLAS 例程;否则,它将执行 _right_multiply_transpose 函数。

参数
B要右乘的转置矩阵。

在文件 dense_matrix_impl.h232 行定义.

233 {
234  if (this->use_blas_lapack)
236  else
237  this->_right_multiply_transpose(B);
238 }
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
void _multiply_blas(const DenseMatrixBase< T > &other, _BLAS_Multiply_Flag flag)
_multiply_blas函数使用BLAS gemm函数计算A &lt;- op(A) * op(B)。 用于right_multiply()、left_multiply()、right_multiply_...
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::right_multiply_transpose ( const DenseMatrix< T2 > &  B)

用包含不同数值类型的矩阵 A 的转置右乘。

右乘转置矩阵。

参数
T2矩阵元素的其他数值类型。
A要与右乘的矩阵。
B要右乘的转置矩阵。

在文件 dense_matrix_impl.h247 行定义.

248 {
249  this->_right_multiply_transpose(B);
250 }
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。
template<typename T >
void libMesh::DenseMatrix< T >::scale ( const T  factor)
inline

将矩阵的每个元素乘以 factor。

参数
factor乘法因子。

在文件 dense_matrix.h1103 行定义.

1104 {
1105  for (auto & v : _val)
1106  v *= factor;
1107 }
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
template<typename T >
void libMesh::DenseMatrix< T >::scale_column ( const unsigned int  col,
const T  factor 
)
inline

将矩阵的第 col 列的每个元素乘以 factor。

参数
col列索引。
factor乘法因子。

在文件 dense_matrix.h1112 行定义.

1113 {
1114  for (auto i : make_range(this->m()))
1115  (*this)(i, col) *= factor;
1116 }
unsigned int m() const
返回矩阵的行维度。
template<typename T >
DenseMatrix< T > libMesh::DenseMatrix< T >::sub_matrix ( unsigned int  row_id,
unsigned int  row_size,
unsigned int  col_id,
unsigned int  col_size 
) const
inline

获取具有最小行和列索引以及子矩阵大小的子矩阵。

参数
row_id子矩阵的起始行索引。
row_size子矩阵的行数。
col_id子矩阵的起始列索引。
col_size子矩阵的列数。
返回
具有指定大小和位置的子矩阵。

在文件 dense_matrix.h1039 行定义.

1041 {
1042  libmesh_assert_less (row_id + row_size - 1, this->_m);
1043  libmesh_assert_less (col_id + col_size - 1, this->_n);
1044 
1045  DenseMatrix<T> sub;
1046  sub._m = row_size;
1047  sub._n = col_size;
1048  sub._val.resize(row_size * col_size);
1049 
1050  unsigned int end_col = this->_n - col_size - col_id;
1051  unsigned int p = row_id * this->_n;
1052  unsigned int q = 0;
1053  for (unsigned int i=0; i<row_size; i++)
1054  {
1055  // 跳到开头的列
1056  p += col_id;
1057  for (unsigned int j=0; j<col_size; j++)
1058  sub._val[q++] = _val[p++];
1059  // 跳过剩余的列
1060  p += end_col;
1061  }
1062 
1063  return sub;
1064 }
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
unsigned int _m
行维度。
template<typename T >
void libMesh::DenseMatrix< T >::svd ( DenseVector< Real > &  sigma)

计算矩阵的奇异值分解(SVD)。 在退出时,sigma包含所有奇异值(按降序排列)。

使用 LAPACK svd 实现的奇异值分解。

实现使用PETSc对BLAS/LAPACK的接口。如果不可用,此函数会引发错误。

参数
sigma存储奇异值的向量。
sigma存储奇异值的目标向量。

在文件 dense_matrix_impl.h768 行定义.

769 {
770  // 使用 LAPACK svd 实现
771  _svd_lapack(sigma);
772 }
void _svd_lapack(DenseVector< Real > &sigma)
使用Lapack例程“getsvd”计算矩阵的奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ]
template<typename T >
void libMesh::DenseMatrix< T >::svd ( DenseVector< Real > &  sigma,
DenseMatrix< Number > &  U,
DenseMatrix< Number > &  VT 
)

计算矩阵的“简化”奇异值分解。 在退出时,sigma包含所有奇异值(按降序排列), U包含左奇异向量,VT包含右奇异向量的转置。 在简化的SVD中,U有min(m,n)列,VT有min(m,n)行。(在“完整”SVD中,U和VT将是方形的。)

使用 LAPACK svd 实现的奇异值分解。

实现使用PETSc对BLAS/LAPACK的接口。如果不可用,此函数会引发错误。

参数
sigma存储奇异值的向量。
U存储左奇异向量的矩阵。
VT存储右奇异向量的转置的矩阵。
sigma存储奇异值的目标向量。
U存储左奇异向量的目标矩阵。
VT存储右奇异向量的目标矩阵。

在文件 dense_matrix_impl.h782 行定义.

785 {
786  // 使用 LAPACK svd 实现
787  _svd_lapack(sigma, U, VT);
788 }
void _svd_lapack(DenseVector< Real > &sigma)
使用Lapack例程“getsvd”计算矩阵的奇异值分解。 [ 在dense_matrix_blas_lapack.C中实现 ]
template<typename T>
void libMesh::DenseMatrix< T >::svd_solve ( const DenseVector< T > &  rhs,
DenseVector< T > &  x,
Real  rcond = std::numeric_limits< Real >::epsilon() 
) const

以最小二乘意义解方程组 $ Ax=rhs $$ A $ 可能是非方阵和/或秩亏的。 可以通过更改“rcond”参数来控制哪些奇异值被视为零。 对于满足S(i) <= rcond*S(1)的奇异值S(i),在解的目的上被视为零。 传递负数的rcond将强制使用“机器精度”值。

由于各种实现细节,此函数被标记为const,我们不需要修改A的内容来计算SVD(内部会进行复制)。

需要PETSc >= 3.1,因为这是提供LAPACKgelss_包装器的第一个版本。

参数
rhs右侧向量rhs。
x解向量x。
rcond控制奇异值被视为零的阈值。
template<typename T >
void libMesh::DenseMatrix< T >::swap ( DenseMatrix< T > &  other_matrix)
inline

STL 风格的交换方法,交换值和分解方法。

参数
other_matrix要交换值的矩阵。

在文件 dense_matrix.h982 行定义.

983 {
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;
990 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
unsigned int _n
列维度。
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709
DecompositionType
_cholesky_back_substitute 的分解方案会改变矩阵A的条目。因此,在调用A.lu_solve()后再次调用A.cholesky_solve()是错误的, 因为结果可能不符合任何预期...
Definition: dense_matrix.h:746
unsigned int _m
行维度。
template<typename T >
T libMesh::DenseMatrix< T >::transpose ( const unsigned int  i,
const unsigned int  j 
) const
inline

返回转置矩阵的 (i, j) 元素。

参数
i行索引。
j列索引。
返回
转置矩阵的 (i, j) 元素。

在文件 dense_matrix.h1296 行定义.

参考自 libMesh::DenseMatrix< T >::_left_multiply_transpose() , 以及 libMesh::DenseMatrix< T >::_right_multiply_transpose().

1298 {
1299  // Implement in terms of operator()
1300  return (*this)(j,i);
1301 }
template<typename T >
void libMesh::DenseMatrix< T >::vector_mult ( DenseVector< T > &  dest,
const DenseVector< T > &  arg 
) const

执行矩阵-向量乘法,dest := (*this) * arg。

矩阵与向量的乘法。

参数
dest存储结果的向量。
arg输入向量。

确保输入大小兼容。调整并清除 dest。 注意:DenseVector::resize() 也会将向量清零。

参数
dest存储结果的目标向量。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h326 行定义.

参考 libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

参考自 libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector() , 以及 libMesh::DofMap::heterogeneously_constrain_element_vector().

327 {
328  // 确保输入大小兼容
329  libmesh_assert_equal_to(this->n(), arg.size());
330 
331  // 调整并清除 dest
332  // 注意:DenseVector::resize() 也会将向量清零
333  dest.resize(this->m());
334 
335  // 如果矩阵为空,直接返回
336  if (this->m() == 0 || this->n() == 0)
337  return;
338 
339  if (this->use_blas_lapack)
340  this->_matvec_blas(1., 0., dest, arg);
341  else
342  {
343  const unsigned int n_rows = this->m();
344  const unsigned int n_cols = this->n();
345 
346  for (unsigned int i = 0; i < n_rows; i++)
347  for (unsigned int j = 0; j < n_cols; j++)
348  dest(i) += (*this)(i, j) * arg(j);
349  }
350 }
void _matvec_blas(T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
使用BLAS GEMV函数(通过PETSc)计算
unsigned int n() const
返回矩阵的列维度。
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::vector_mult ( DenseVector< typename CompareTypes< T, T2 >::supertype > &  dest,
const DenseVector< T2 > &  arg 
) const

执行矩阵-向量乘法,dest := (*this) * arg ,支持不同类型的矩阵和向量。

重载的 vector_mult 函数,支持不同数据类型的向量。

模板参数
T2输入向量 arg 的元素类型。
参数
dest存储结果的向量。
arg输入向量。
dest存储结果的目标向量。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h360 行定义.

参考 libMesh::DenseVector< T >::size().

362 {
363  // 确保输入大小兼容
364  libmesh_assert_equal_to(this->n(), arg.size());
365 
366  // 调整并清除 dest
367  // 注意:DenseVector::resize() 也会将向量清零
368  dest.resize(this->m());
369 
370  // 如果矩阵为空,直接返回
371  if (this->m() == 0 || this->n() == 0)
372  return;
373 
374  const unsigned int n_rows = this->m();
375  const unsigned int n_cols = this->n();
376 
377  for (unsigned int i = 0; i < n_rows; i++)
378  for (unsigned int j = 0; j < n_cols; j++)
379  dest(i) += (*this)(i, j) * arg(j);
380 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrix< T >::vector_mult_add ( DenseVector< T > &  dest,
const T  factor,
const DenseVector< T > &  arg 
) const

执行缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg.

矩阵与向量相加。

参数
dest结果向量,存储缩放后的矩阵乘以向量的和。
factor缩放因子。
arg乘法的右侧向量。

如果矩阵为空,直接返回。根据是否启用 BLAS/LAPACK 执行不同的操作。

参数
dest存储结果的目标向量。
factor与乘积相加的因子。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h473 行定义.

参考 libMesh::DenseVector< T >::add(), libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

参考自 libMesh::DofMap::build_constraint_matrix_and_vector().

476 {
477  // 如果矩阵为空,直接返回
478  if (this->m() == 0)
479  {
480  dest.resize(0);
481  return;
482  }
483 
484  if (this->use_blas_lapack)
485  this->_matvec_blas(factor, 1., dest, arg);
486  else
487  {
488  DenseVector<T> temp(arg.size());
489  this->vector_mult(temp, arg);
490  dest.add(factor, temp);
491  }
492 }
void _matvec_blas(T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
使用BLAS GEMV函数(通过PETSc)计算
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
unsigned int m() const
返回矩阵的行维度。
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
template<typename T >
template<typename T2 , typename T3 >
void libMesh::DenseMatrix< T >::vector_mult_add ( DenseVector< typename CompareTypes< T, typename CompareTypes< T2, T3 >::supertype >::supertype > &  dest,
const T2  factor,
const DenseVector< T3 > &  arg 
) const

执行混合类型的缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg.

重载的 vector_mult_add 函数,支持不同数据类型的向量。

参数
dest结果向量,存储缩放后的矩阵乘以向量的和。
factor缩放因子。
arg乘法的右侧向量。

如果矩阵为空,直接返回。根据是否启用 BLAS/LAPACK 执行不同的操作。

参数
dest存储结果的目标向量。
factor与乘积相加的因子。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h505 行定义.

参考 libMesh::DenseVector< T >::size().

508 {
509  // 如果矩阵为空,直接返回
510  if (this->m() == 0)
511  {
512  dest.resize(0);
513  return;
514  }
515 
516  DenseVector<typename CompareTypes<T, T3>::supertype> temp(arg.size());
517  this->vector_mult(temp, arg);
518  dest.add(factor, temp);
519 }
unsigned int m() const
返回矩阵的行维度。
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
template<typename T >
void libMesh::DenseMatrix< T >::vector_mult_transpose ( DenseVector< T > &  dest,
const DenseVector< T > &  arg 
) const

执行矩阵-向量乘法,dest := (*this)^T * arg。

矩阵转置与向量的乘法。

参数
dest存储结果的向量。
arg输入向量。

确保输入大小兼容。调整并清除 dest。 注意:DenseVector::resize() 也会将向量清零。

参数
dest存储结果的目标向量。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h392 行定义.

参考 libMesh::DenseVector< T >::resize() , 以及 libMesh::DenseVector< T >::size().

参考自 libMesh::DofMap::constrain_element_dyad_matrix(), libMesh::DofMap::constrain_element_matrix_and_vector(), libMesh::DofMap::constrain_element_residual(), libMesh::DofMap::constrain_element_vector(), libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual(), libMesh::DofMap::heterogeneously_constrain_element_matrix_and_vector(), libMesh::DofMap::heterogeneously_constrain_element_residual() , 以及 libMesh::DofMap::heterogeneously_constrain_element_vector().

394 {
395  // 确保输入大小兼容
396  libmesh_assert_equal_to(this->m(), arg.size());
397 
398  // 调整并清除 dest
399  // 注意:DenseVector::resize() 也会将向量清零
400  dest.resize(this->n());
401 
402  // 如果矩阵为空,直接返回
403  if (this->m() == 0)
404  return;
405 
406  if (this->use_blas_lapack)
407  {
408  this->_matvec_blas(1., 0., dest, arg, /*trans=*/true);
409  }
410  else
411  {
412  const unsigned int n_rows = this->m();
413  const unsigned int n_cols = this->n();
414 
415  // WORKS
416  // for (unsigned int j=0; j<n_cols; j++)
417  // for (unsigned int i=0; i<n_rows; i++)
418  // dest(j) += (*this)(i,j)*arg(i);
419 
420  // ALSO WORKS, (i,j) just swapped
421  for (unsigned int i = 0; i < n_cols; i++)
422  for (unsigned int j = 0; j < n_rows; j++)
423  dest(i) += (*this)(j, i) * arg(j);
424  }
425 }
void _matvec_blas(T alpha, T beta, DenseVector< T > &dest, const DenseVector< T > &arg, bool trans=false) const
使用BLAS GEMV函数(通过PETSc)计算
unsigned int n() const
返回矩阵的列维度。
bool use_blas_lapack
计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。
Definition: dense_matrix.h:694
unsigned int m() const
返回矩阵的行维度。
template<typename T >
template<typename T2 >
void libMesh::DenseMatrix< T >::vector_mult_transpose ( DenseVector< typename CompareTypes< T, T2 >::supertype > &  dest,
const DenseVector< T2 > &  arg 
) const

执行矩阵-向量乘法,dest := (*this)^T * arg,支持不同类型的矩阵和向量。

重载的 vector_mult_transpose 函数,支持不同数据类型的向量。

模板参数
T2输入向量 arg 的元素类型。
参数
dest存储结果的向量。
arg输入向量。
dest存储结果的目标向量。
arg与之相乘的输入向量。

在文件 dense_matrix_impl.h435 行定义.

参考 libMesh::DenseVector< T >::size().

437 {
438  // 确保输入大小兼容
439  libmesh_assert_equal_to(this->m(), arg.size());
440 
441  // 调整并清除 dest
442  // 注意:DenseVector::resize() 也会将向量清零
443  dest.resize(this->n());
444 
445  // 如果矩阵为空,直接返回
446  if (this->m() == 0)
447  return;
448 
449  const unsigned int n_rows = this->m();
450  const unsigned int n_cols = this->n();
451 
452  // WORKS
453  // for (unsigned int j=0; j<n_cols; j++)
454  // for (unsigned int i=0; i<n_rows; i++)
455  // dest(j) += (*this)(i,j)*arg(i);
456 
457  // ALSO WORKS, (i,j) just swapped
458  for (unsigned int i = 0; i < n_cols; i++)
459  for (unsigned int j = 0; j < n_rows; j++)
460  dest(i) += (*this)(j, i) * arg(j);
461 }
unsigned int n() const
返回矩阵的列维度。
unsigned int m() const
返回矩阵的行维度。
template<typename T >
void libMesh::DenseMatrix< T >::zero ( )
inlinefinaloverridevirtual

将矩阵的所有元素设置为0,并重置任何可能先前设置的分解标志。 这允许例如计算新的LU分解,同时重用相同的存储空间。

实现了 libMesh::DenseMatrixBase< T >.

在文件 dense_matrix.h1028 行定义.

1029 {
1031 
1032  std::fill (_val.begin(), _val.end(), static_cast<T>(0));
1033 }
DecompositionType _decomposition_type
此标志跟踪在矩阵上执行的分解类型。
Definition: dense_matrix.h:751
std::vector< T > _val
实际的数据值,存储为1D数组。
Definition: dense_matrix.h:709

类成员变量说明

template<typename T>
DecompositionType libMesh::DenseMatrix< T >::_decomposition_type
private

此标志跟踪在矩阵上执行的分解类型。

在文件 dense_matrix.h751 行定义.

template<typename T>
unsigned int libMesh::DenseMatrixBase< T >::_m
protectedinherited

行维度。

在文件 dense_matrix_base.h204 行定义.

参考自 libMesh::DenseMatrixBase< T >::m().

template<typename T>
unsigned int libMesh::DenseMatrixBase< T >::_n
protectedinherited

列维度。

在文件 dense_matrix_base.h209 行定义.

参考自 libMesh::DenseMatrixBase< T >::n().

template<typename T>
std::vector<pivot_index_t> libMesh::DenseMatrix< T >::_pivots
private

在文件 dense_matrix.h853 行定义.

template<typename T>
std::vector<T> libMesh::DenseMatrix< T >::_val
private

实际的数据值,存储为1D数组。

在文件 dense_matrix.h709 行定义.

参考自 libMesh::DenseMatrix< T >::get_values().

template<typename T>
bool libMesh::DenseMatrix< T >::use_blas_lapack

计算密矩阵的逆(假设可逆性), 首先计算LU分解,然后执行多次回代步骤。 遵循在Web上提供的Numerical Recipes in C中的算法。

该程序被注释掉,因为它实际上不是一种内存或计算上高效的实现。 而且,通常不需要实际的逆矩阵,可以使用lu_solve()之类的东西代替。 在运行时选择性地启用/禁用BLAS支持的选项。 这主要用于测试目的

在文件 dense_matrix.h694 行定义.


该类的文档由以下文件生成: