Skip to content

Commit 12adcd9

Browse files
committed
增加了稀疏矩阵的迭代求解功能,并对稀疏矩阵和稠密矩阵进行了封装
1 parent 636ee97 commit 12adcd9

File tree

7 files changed

+285
-66
lines changed

7 files changed

+285
-66
lines changed

MatrixCoeff.cpp

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,67 @@
11
#include "MatrixCoeff.h"
2+
#include "MatrixWrapper.h"
23

3-
// a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u}
4-
void MatrixCoeff::initMatrix(const Mesh* mesh, const Boundary& boundary, const Source& source)
4+
// a_p T_p = a_L T_L + a_R T_R + ... + S_{u}
5+
void MatrixCoeff::initDenseMatrix()
56
{
6-
int N = mesh->get_N();
7+
init(&dense_matrix_wrapper);
8+
9+
b_m = Su;
10+
}
11+
12+
void MatrixCoeff::initSparseMatrix()
13+
{
14+
SparseMatrix<double> A_m = sparse_matrix_wrapper.getMatrix();
15+
16+
// 每列预留5个元素的空间,用于插入
17+
// ref. http://eigen.tuxfamily.org/dox/group__TutorialSparse.html - Filling a sparse matrix
18+
A_m.reserve(VectorXi::Constant(N, 5));
19+
20+
init(&sparse_matrix_wrapper);
21+
22+
A_m.makeCompressed(); // optional
23+
24+
b_m = Su;
25+
}
726

27+
void MatrixCoeff::init(MatrixInterface* matrix)
28+
{
829
for(int i = 0; i < N; i++)
930
{
1031
int i_l = mesh->left_of(i);
1132
int i_r = mesh->right_of(i);
1233
int i_t = mesh->top_of(i);
1334
int i_b = mesh->bottom_of(i);
1435

15-
A_m(i, i) = aP[i];
36+
matrix->setNum(i, i, aP[i]);
1637

1738
if(!mesh->is_at_left_boundary(i))
1839
{
19-
A_m(i, i_l) = -aL[i];
40+
matrix->setNum(i, i_l, -aL[i]);
2041
}
2142
if(!mesh->is_at_right_boundary(i))
2243
{
23-
A_m(i, i_r) = -aR[i];
44+
matrix->setNum(i, i_r, -aR[i]);
2445
}
2546
if(!mesh->is_at_bottom_boundary(i))
2647
{
27-
A_m(i, i_b) = -aB[i];
48+
matrix->setNum(i, i_b, -aB[i]);
2849
}
2950
if(!mesh->is_at_top_boundary(i))
3051
{
31-
A_m(i, i_t) = -aT[i];
52+
matrix->setNum(i, i_t, -aT[i]);
3253
}
3354
}
34-
35-
b_m = Su;
36-
37-
cout << "A_m: " << endl << A_m << endl;
38-
cout << endl;
39-
40-
cout << "b_m: " << endl << b_m << endl;
41-
cout << endl;
4255
}
4356

44-
MatrixCoeff& MatrixCoeff::addConvectionTerm(const Mesh* mesh, const Boundary& boundary, const Source& source)
57+
MatrixCoeff& MatrixCoeff::addConvectionTerm()
4558
{
46-
double T_l = boundary.T_left;
47-
double T_r = boundary.T_right;
48-
double T_b = boundary.T_bottom;
49-
double T_t = boundary.T_top;
59+
double T_l = boundary->T_left;
60+
double T_r = boundary->T_right;
61+
double T_b = boundary->T_bottom;
62+
double T_t = boundary->T_top;
5063

51-
double q_w = boundary.q_w;
64+
double q_w = boundary->q_w;
5265

5366
double Ax = mesh->get_Ax();
5467
double Ay = mesh->get_Ay();
@@ -59,8 +72,6 @@ MatrixCoeff& MatrixCoeff::addConvectionTerm(const Mesh* mesh, const Boundary& bo
5972
const VectorXd& F_b = mesh->get_F_b();
6073
const VectorXd& F_t = mesh->get_F_t();
6174

62-
int N = mesh->get_N();
63-
6475
aL += F_l.cwiseMax(VectorXd::Zero(N));
6576
aR += (-F_r).cwiseMax(VectorXd::Zero(N));
6677
aB += F_b.cwiseMax(VectorXd::Zero(N));
@@ -99,13 +110,13 @@ MatrixCoeff& MatrixCoeff::addConvectionTerm(const Mesh* mesh, const Boundary& bo
99110
return *this;
100111
}
101112

102-
MatrixCoeff& MatrixCoeff::addDiffusionTerm(const Mesh* mesh, const Boundary& boundary, const Source& source)
113+
MatrixCoeff& MatrixCoeff::addDiffusionTerm()
103114
{
104-
double T_l = boundary.T_left;
105-
double T_r = boundary.T_right;
106-
double T_b = boundary.T_bottom;
107-
double T_t = boundary.T_top;
108-
double q_w = boundary.q_w;
115+
double T_l = boundary->T_left;
116+
double T_r = boundary->T_right;
117+
double T_b = boundary->T_bottom;
118+
double T_t = boundary->T_top;
119+
double q_w = boundary->q_w;
109120

110121
double Ax = mesh->get_Ax();
111122
double Ay = mesh->get_Ay();
@@ -116,8 +127,6 @@ MatrixCoeff& MatrixCoeff::addDiffusionTerm(const Mesh* mesh, const Boundary& bou
116127
const VectorXd& DA_B = mesh->get_DA_B();
117128
const VectorXd& DA_T = mesh->get_DA_T();
118129

119-
int N = mesh->get_N();
120-
121130
aL += DA_L;
122131
aR += DA_R;
123132
aB += DA_B;
@@ -157,9 +166,9 @@ MatrixCoeff& MatrixCoeff::addDiffusionTerm(const Mesh* mesh, const Boundary& bou
157166
return *this;
158167
}
159168

160-
MatrixCoeff& MatrixCoeff::addSourceTerm(const Mesh* mesh, const Boundary& boundary, const Source& source)
169+
MatrixCoeff& MatrixCoeff::addSourceTerm()
161170
{
162-
double S_bar = source.S_bar;
171+
double S_bar = source->S_bar;
163172

164173
const VectorXd& V = mesh->get_V();
165174

@@ -168,4 +177,44 @@ MatrixCoeff& MatrixCoeff::addSourceTerm(const Mesh* mesh, const Boundary& bounda
168177
Su += S_bar * V;
169178

170179
return *this;
180+
}
181+
182+
void MatrixCoeff::DebugSolve()
183+
{
184+
initDenseMatrix();
185+
186+
MatrixXd& A_m = dense_matrix_wrapper.getMatrix();
187+
188+
// 求解矩阵
189+
x = A_m.fullPivLu().solve(b_m);
190+
191+
// 输出结果
192+
cout << "A_m: " << endl << A_m << endl;
193+
cout << endl;
194+
195+
cout << "b_m: " << endl << b_m << endl;
196+
cout << endl;
197+
198+
cout << "Solution: " << endl << x << endl;
199+
}
200+
201+
void MatrixCoeff::Solve()
202+
{
203+
initSparseMatrix();
204+
205+
SparseMatrix<double>& A_m = sparse_matrix_wrapper.getMatrix();
206+
207+
// ref. http://eigen.tuxfamily.org/dox/classEigen_1_1BiCGSTAB.html
208+
// ref. http://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html#TutorialSparseSolverConcept
209+
// ref. http://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
210+
211+
// BiCGSTAB<SparseMatrix<double>, Eigen::IdentityPreconditioner> solver;
212+
BiCGSTAB<SparseMatrix<double>, Eigen::IncompleteLUT<double>> solver;
213+
solver.compute(A_m);
214+
x = solver.solve(b_m);
215+
216+
std::cout << "#iterations: " << solver.iterations() << std::endl;
217+
std::cout << "estimated error: " << solver.error() << std::endl;
218+
219+
std::cout << "x: " << std::endl << x << std::endl;
171220
}

MatrixCoeff.h

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,43 @@
22
#define __MATRIX_COEFF__
33

44
#include <iostream>
5+
#include <Eigen/Sparse>
6+
#include <Eigen/IterativeLinearSolvers>
57
#include "Inputs.h"
68
#include "Mesh.h"
9+
#include "MatrixWrapper.h"
710

11+
using Eigen::SparseMatrix;
12+
using Eigen::BiCGSTAB;
813
using namespace std;
914

1015
// N: 网格数
1116
class MatrixCoeff
1217
{
1318
private:
19+
const Mesh* mesh;
20+
const Boundary* boundary;
21+
const Source* source;
22+
// 网格数量
23+
int N;
24+
1425
VectorXd aL, aR, aB, aT, aP, Sp, Su;
1526

16-
MatrixXd A_m;
1727
VectorXd b_m;
1828
VectorXd x;
1929

30+
/**
31+
* MatrixXd和SparseMatrix的封装类,封装后的Wrapper类共同继承接口MatrixInterface,
32+
* 并实现接口函数MatrixInterface::setNum,这个函数用来往矩阵中插入元素
33+
*/
34+
DenseMatrixWrapper dense_matrix_wrapper;
35+
SparseMatrixWrapper sparse_matrix_wrapper;
36+
2037
public:
21-
MatrixCoeff(const Mesh* mesh, const Boundary& boundary, const Source& source)
38+
MatrixCoeff(const Mesh* mesh, const Boundary* boundary, const Source* source)
39+
: mesh(mesh), boundary(boundary), source(source), N(mesh->get_N()),
40+
dense_matrix_wrapper(N, N), sparse_matrix_wrapper(N, N)
2241
{
23-
int N = mesh->get_N();
24-
2542
aL = VectorXd::Zero(N);
2643
aR = VectorXd::Zero(N);
2744
aB = VectorXd::Zero(N);
@@ -31,21 +48,30 @@ class MatrixCoeff
3148
Sp = VectorXd::Zero(N);
3249
Su = VectorXd::Zero(N);
3350

34-
A_m = MatrixXd::Zero(N, N);
3551
b_m = VectorXd::Zero(N);
3652
x = VectorXd::Zero(N);
3753
}
3854

39-
MatrixXd& get_A_m() { return A_m; }
4055
VectorXd& get_b_m() { return b_m; }
4156
VectorXd& get_x() { return x; }
4257

43-
MatrixCoeff& addConvectionTerm(const Mesh* mesh, const Boundary& boundary, const Source& source);
44-
MatrixCoeff& addDiffusionTerm(const Mesh* mesh, const Boundary& boundary, const Source& source);
45-
MatrixCoeff& addSourceTerm(const Mesh* mesh, const Boundary& boundary, const Source& source);
46-
47-
// Matrix系数初始化
48-
void initMatrix(const Mesh* mesh, const Boundary& boundary, const Source& source);
58+
// MatrixXd系数初始化
59+
void initDenseMatrix();
60+
61+
// SparseMatrix系数初始化
62+
void initSparseMatrix();
63+
64+
void init(MatrixInterface* matrix);
65+
66+
MatrixCoeff& addConvectionTerm();
67+
MatrixCoeff& addDiffusionTerm();
68+
MatrixCoeff& addSourceTerm();
69+
70+
// 系数矩阵存在非稀疏矩阵MatrixXd中,方便打印输出
71+
void DebugSolve();
72+
73+
// 系数矩阵存在稀疏矩阵SparseMatrix中,用于迭代求解
74+
void Solve();
4975
};
5076

5177
#endif

MatrixInterface.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "MatrixInterface.h"
2+
3+
// 纯虚析构函数必须保留一个类外实现,因为子类在析构的时候会调用父类的析构函数,如果不定义会编译报错
4+
MatrixInterface::~MatrixInterface()
5+
{
6+
7+
}

MatrixInterface.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef __MATRIX_INTERFACE__
2+
#define __MATRIX_INTERFACE__
3+
4+
class MatrixInterface
5+
{
6+
public:
7+
virtual void setNum(int row, int col, double value) = 0;
8+
virtual ~MatrixInterface() = 0;
9+
};
10+
11+
#endif

MatrixWrapper.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef __MATRIX_WRAPPER__
2+
#define __MATRIX_WRAPPER__
3+
4+
#include <iostream>
5+
#include <Eigen/Sparse>
6+
#include "MatrixInterface.h"
7+
8+
using Eigen::MatrixXd;
9+
using Eigen::SparseMatrix;
10+
11+
class DenseMatrixWrapper : public MatrixInterface
12+
{
13+
private:
14+
MatrixXd m_dense_matrix;
15+
public:
16+
DenseMatrixWrapper(int row, int col) : m_dense_matrix(row, col) { }
17+
18+
void setNum(int row, int col, double value)
19+
{
20+
m_dense_matrix(row, col) = value;
21+
}
22+
23+
MatrixXd& getMatrix()
24+
{
25+
return m_dense_matrix;
26+
}
27+
};
28+
29+
class SparseMatrixWrapper : public MatrixInterface
30+
{
31+
private:
32+
SparseMatrix<double> m_sparse_matrix;
33+
public:
34+
SparseMatrixWrapper(int row, int col) : m_sparse_matrix(row, col) { }
35+
36+
void setNum(int row, int col, double value)
37+
{
38+
// ref. http://eigen.tuxfamily.org/dox/group__TutorialSparse.html - Filling a sparse matrix
39+
m_sparse_matrix.insert(row, col) = value; // alternative: A.coeffRef(i,j) += v_ij;
40+
}
41+
42+
SparseMatrix<double>& getMatrix()
43+
{
44+
return m_sparse_matrix;
45+
}
46+
};
47+
48+
#endif

0 commit comments

Comments
 (0)