[英]define and filling a sparse matrix using Eigen Library in C++
I am trying to build a spars Matrix using a Eigen or Armadillo library in C++ to solve a system of linear equations Ax=b.我正在尝试使用 C++ 中的 Eigen 或 Armadillo 库构建一个晶石矩阵来求解线性方程组 Ax=b。 A is the coefficient matrix with a dimension of n*n, and B is a vector of right hand side with a dimension of n the Spars Matrix A is like this, see the figure A为系数矩阵,维度为n*n,B为右手边向量,维度为n。Spars矩阵A是这样的,见图
I had a look though the Eigen document but I have a problem with defining and filling the Spars Matrix in C++.我查看了 Eigen 文档,但在用 C++ 定义和填充 Spars 矩阵时遇到了问题。
could you please give me an example code to define the spars matrix and how to fill the values into the matrix using Eigen library in c++?你能给我一个示例代码来定义spars矩阵以及如何使用C++中的Eigen库将值填充到矩阵中吗?
consider for example a simple spars matrix A:例如考虑一个简单的spars矩阵A:
1 2 0 0 1 2 0 0
0 3 0 0 0 3 0 0
0 0 4 5 0 0 4 5
0 0 6 7 0 0 6 7
int main()
{
SparseMatrix<double> A;
// fill the A matrix ????
VectorXd b, x;
SparseCholesky<SparseMatrix<double> > solver;
solver.compute(A);
x = solver.solve(b);
return 0;
}
The sparse matrix could be filled with the values mentioned in the post by using the .coeffRef()
member function, as shown in this routine:稀疏矩阵可以使用.coeffRef()
成员函数填充帖子中提到的值,如下例所示:
SparseMatrix<double> fillMatrix() {
int N = 4;
int M = 4;
SparseMatrix<double> m1(N,M);
m1.reserve(VectorXi::Constant(M, 4)); // 4: estimated number of non-zero enties per column
m1.coeffRef(0,0) = 1;
m1.coeffRef(0,1) = 2.;
m1.coeffRef(1,1) = 3.;
m1.coeffRef(2,2) = 4.;
m1.coeffRef(2,3) = 5.;
m1.coeffRef(3,2) = 6.;
m1.coeffRef(3,3) = 7.;
m1.makeCompressed();
return m1;
}
However, the SparseCholesky
module ( SimplicialCholesky<SparseMatrix<double> >
) won't work in this case because the matrix is not Hermitian.但是, SparseCholesky
模块 ( SimplicialCholesky<SparseMatrix<double> >
) 在这种情况下不起作用,因为矩阵不是 Hermitian。 The system could be solved with a LU or BiCGStab solver.该系统可以用 LU 或 BiCGStab 求解器求解。 Also note that sizes of x
and b
need to be defined: VectorXd b(A.rows()), x(A.cols());
另请注意,需要定义x
和b
的大小: VectorXd b(A.rows()), x(A.cols());
In case of larger sparse matrices you may also want to look at the .reserve()
function in order to allocate memory before filling the elements.对于较大的稀疏矩阵,您可能还需要查看.reserve()
函数,以便在填充元素之前分配内存。 The .reserve()
function can be used to provide an estimate of the number of non-zero entries per column (or row, depending on the storage order. The default is comumn-major). .reserve()
函数可用于估计每列(或每行,取决于存储顺序。默认为 comumn-major)的非零条目数。 In the example above that estimate is 4, but it does not make sense in such a small matrix.在上面的示例中,估计值为 4,但在如此小的矩阵中没有意义。 The documentation states that it is preferable to overestimate the number of non-zeros per column .该文档指出,最好高估每列的非零数。
Since this question also asks about Armadillo , here is the corresponding Armadillo-based code.由于这个问题还涉及Armadillo ,因此这里是相应的基于 Armadillo 的代码。 Best to use Armadillo version 9.100+ or later, and link with SuperLU.最好使用 Armadillo 9.100+ 或更高版本,并与 SuperLU 链接。
#include <armadillo>
using namespace arma;
int main()
{
sp_mat A(4,4); // don't need to explicitly reserve the number of non-zeros
// fill with direct element access
A(0,0) = 1.0;
A(0,1) = 2.0;
A(1,1) = 3.0;
A(2,2) = 4.0;
A(2,3) = 5.0;
A(3,2) = 6.0;
A(3,3) = 7.0; // etc
// or load the sparse matrix from a text file with the data stored in coord format
sp_mat AA;
AA.load("my_sparse_matrix.txt", coord_ascii)
vec b; // ... fill b here ...
vec x = spsolve(A,b); // solve sparse system
return 0;
}
See also the documentation for SpMat , element access , .load() , spsolve() .另请参阅SpMat 、 element access 、 .load( ) 、 spsolve()的文档。
The coord file format is simple.坐标文件格式很简单。 It stores non-zeros values.它存储非零值。 Each line contains:每行包含:
row col value
The row and column counts start at zero.行数和列数从零开始。 Example:例子:
0 0 1.0
0 1 2.0
1 1 3.0
2 2 4.0
2 3 5.0
3 2 6.0
3 3 7.0
1000 2000 9.0
Values not explicitly listed are assumed to be zero.未明确列出的值假定为零。
#include <vector>
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/Core>
#include <cstdlib>
using namespace Eigen;
using namespace std;
int main()
{
//one_d_diffusion();
double L = 5; // Length
const int N = 120; // No of cells
double L_cell = L / N;
double k = 100; // Thermal Conductivity
double T_A = 100.;
double T_B = 200.;
double S = 1000.;
Vector<double, N> d, D, A, aL, aR, aP, S_u, S_p;
vector<double> xp;
xp.push_back((0 + L_cell) / 2.0);
double xm = xp[0];
for (int i = 0; i < N - 1; i++)
{
xm = xm + L_cell;
xp.push_back(xm);
}
for (int i = 0; i < N; i++)
{
A(i) = .1;
d(i) = L_cell;
D(i) = k / d(i);
}
aL(0) = 0;
aR(0) = D(0) * A(0);
S_p(0) = -2 * D(0) * A(0);
aP(0) = aL(0) + aR(0) - S_p(0);
S_u(0) = 2 * D(0) * A(0) * T_A + S * L_cell * A(0);
for (int i = 1; i < N - 1; i++)
{
aL(i) = D(i) * A(i);
aR(i) = D(i) * A(i);
S_p(i) = 0;
aP(i) = aL(i) + aR(i) - S_p(i);
S_u(i) = S * A(i) * L_cell;
}
aL(N - 1) = D(N - 1) * A(N - 1);
aR(N - 1) = 0;
S_p(N - 1) = -2 * D(N - 1) * A(N - 1);
aP(N - 1) = aL(N - 1) + aR(N - 1) - S_p(N - 1);
S_u(N - 1) = 2 * D(N - 1) * A(N - 1) * T_B + S * L_cell * A(N - 1);
typedef Eigen::Triplet<double> T;
std::vector<T> tripletList;
tripletList.reserve(N * 3);
Matrix<double, N, 3> v; /// v is declared here
v << (-1) * aL, aP, (-1)* aR;
for (int i = 0, j = 0; i < N && j < N; i++, j++)
{
tripletList.push_back(T(i, j, v(i, 1)));
if (i + 1 < N && j + 1 < N)
{
tripletList.push_back(T(i + 1, j, v(i + 1, 0)));
tripletList.push_back(T(i, j + 1, v(i, 2)));
}
}
SparseMatrix<double> coeff(N, N);
coeff.setFromTriplets(tripletList.begin(), tripletList.end());
SimplicialLDLT<SparseMatrix<double> > solver;
solver.compute(coeff);
if (solver.info() != Success) {
cout << "decomposition failed" << endl;
return;
}
Vector<double, N> temparature;
temparature = solver.solve(S_u);
if (solver.info() != Success)
{
cout << "Solving failed" << endl;
return;
}
vector<double> Te = {}, x = {};
Te.push_back(T_A);
x.push_back(0);
for (int i = 0; i < N; i++)
{
Te.push_back(temparature(i));
x.push_back(xp[i]);
}
Te.push_back(T_B);
x.push_back(L);
for (int i = 0; i < N + 2; i++)
{
cout << x[i] << " " << Te[i] << endl;
}
return 0;
} }
Here is a full code of a numerical problem.这是一个数值问题的完整代码。 Look at the matrix v .查看矩阵v 。 It has all the nonzero elements.它具有所有非零元素。 In the next loop I made a series of tripletlist.push_back(.....) with their indexes and values.在下一个循环中,我制作了一系列Tripletlist.push_back(.....)及其索引和值。 The values will hold the position of Sparse Matrix at their accompanied indexes.这些值将在其伴随的索引处保持稀疏矩阵的位置。 Now declare a Sparse Matrix with a size and use the function setFromTroplets(....) and you will have your Sparse Matrix.现在声明一个具有大小的稀疏矩阵并使用函数setFromTroplets(....) ,你将拥有你的稀疏矩阵。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.