从几个较小的稀疏矩阵构建大型稀疏矩阵
Build large sparse matrix from several smaller sparse matrices
我正在使用 Eigen 库来解决 FEM 问题,在该问题中,我使用几个相似的稀疏矩阵来计算不同种类的导数。要构建稀疏矩阵来求解系统,我想使用逗号初始值设定项,但稀疏矩阵 (https://eigen.tuxfamily.org/dox/group__TutorialSparse.html and ) 不支持它。在那个答案中,Henri Menke 确实建议使用 Eigen 不受支持的 Kronecker 产品,但我认为这在这里行不通。
使用 NxM 网格,我计算了几个导数矩阵(稀疏矩阵),Dx2, Dxz,
和 Dz2
,维度为 N*M x N*M。我的求解器矩阵如下,(K
只是常数,0
只是填充物——零矩阵,N*M x N*M)
K3*Dx2 + K1*Dz2 K2*Dxz 0 0 0
K2*Dxz K3*Dz2 + K1*Dx2 0 0 0
0 0 K1*(Dx2+Dz2) 0 0
0 0 0 K3*Dx2 + K1*Dz2 K2*Dxz
0 0 0 K2*Dxz K3*Dz2 + K1*Dx2
截至目前,我通过使用逗号初始值设定项将稀疏转换为密集,然后通过 .sparseView() 转换回稀疏来构建它。唯一的问题是,如果网格比 16x16 大得多,我会得到一个 std::bad_alloc 错误(这是合理预期的,因为它创建了一个巨大的矩阵:5*N*M x 5*N*M) ,我需要一个至少 100x100 的网格(并且不会总是像当前显示的那样多 0
矩阵,尽管它仍然是一个稀疏矩阵)。
构建这个矩阵的最佳方法是什么?我曾想过尝试使用 Triplets 来实现,类似于此()。
编辑: 我认为使用三元组不会那么容易(尽管我目前正在尝试),因为我编辑了每个 D_ _ 矩阵中的几个值边界条件...除非有办法在给定行号和列号的 std::vector 中找到三元组?
更新:Triplet和Kronecker乘积法都是可行的,但是我运行遇到了几个问题:
使用 Kronecker 产品,我在编译时遇到以下错误(大约一百次左右):
.../eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h:225:97: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<int, std::complex<double>, Eigen::internal::scalar_product_op<int, std::complex<double> > >’
使用 Triplet 方法,我定义了一些运算符和一个函数来 'shift' 矩阵到正确的位置(基本上是 Kronecker 产品所做的)。我只需要弄清楚索引越界问题。
问题出在我在 Kronecker 乘积中使用的矩阵是 SparseMatrix<int>
和 SparseMatrix<complex<double>>
类型。 int
和 complex<double>
没有运算符重载,因此通过创建兼容类型的两个矩阵,代码可以按预期编译和运行。
我正在使用 Eigen 库来解决 FEM 问题,在该问题中,我使用几个相似的稀疏矩阵来计算不同种类的导数。要构建稀疏矩阵来求解系统,我想使用逗号初始值设定项,但稀疏矩阵 (https://eigen.tuxfamily.org/dox/group__TutorialSparse.html and
使用 NxM 网格,我计算了几个导数矩阵(稀疏矩阵),Dx2, Dxz,
和 Dz2
,维度为 N*M x N*M。我的求解器矩阵如下,(K
只是常数,0
只是填充物——零矩阵,N*M x N*M)
K3*Dx2 + K1*Dz2 K2*Dxz 0 0 0
K2*Dxz K3*Dz2 + K1*Dx2 0 0 0
0 0 K1*(Dx2+Dz2) 0 0
0 0 0 K3*Dx2 + K1*Dz2 K2*Dxz
0 0 0 K2*Dxz K3*Dz2 + K1*Dx2
截至目前,我通过使用逗号初始值设定项将稀疏转换为密集,然后通过 .sparseView() 转换回稀疏来构建它。唯一的问题是,如果网格比 16x16 大得多,我会得到一个 std::bad_alloc 错误(这是合理预期的,因为它创建了一个巨大的矩阵:5*N*M x 5*N*M) ,我需要一个至少 100x100 的网格(并且不会总是像当前显示的那样多 0
矩阵,尽管它仍然是一个稀疏矩阵)。
构建这个矩阵的最佳方法是什么?我曾想过尝试使用 Triplets 来实现,类似于此(
编辑: 我认为使用三元组不会那么容易(尽管我目前正在尝试),因为我编辑了每个 D_ _ 矩阵中的几个值边界条件...除非有办法在给定行号和列号的 std::vector 中找到三元组?
更新:Triplet和Kronecker乘积法都是可行的,但是我运行遇到了几个问题:
使用 Kronecker 产品,我在编译时遇到以下错误(大约一百次左右):
.../eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h:225:97: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<int, std::complex<double>, Eigen::internal::scalar_product_op<int, std::complex<double> > >’
使用 Triplet 方法,我定义了一些运算符和一个函数来 'shift' 矩阵到正确的位置(基本上是 Kronecker 产品所做的)。我只需要弄清楚索引越界问题。
问题出在我在 Kronecker 乘积中使用的矩阵是 SparseMatrix<int>
和 SparseMatrix<complex<double>>
类型。 int
和 complex<double>
没有运算符重载,因此通过创建兼容类型的两个矩阵,代码可以按预期编译和运行。