Poisson Jacobi
数学模型#
二维Poisson方程可以被表述为: $$-\nabla^2 u(x,y)=f(x,y),(x,y)\in \Omega$$
展开成坐标形式: $$-\left(\frac{\partial^2 u}{\partial x^2}+\frac{\partial^2 u}{\partial y^2}\right)=f(x,y)$$
通常使用的是Dirichlet边界条件。
网格离散#
在规则网格上使用二阶差分
$$\frac{\partial^2 u}{\partial x^2}\approx \frac{u_{i,j+1}-2u_{i,j}+u_{i,j-1}}{h_x^2} $$
以及
$$\frac{\partial^2 u}{\partial y^2}\approx \frac{u_{i+1,j}-2u_{i,j}+u_{i+1,j}}{h_y^2} $$
带入poisson方程,有
$$-\left(\frac{u_{i,j+1}-2u_{i,j}+u_{i,j-1}}{h_x^2}+\frac{u_{i+1,j}-2u_{i,j}+u_{i+1,j}}{h_y^2}\right)=f_{i,j}$$
对于$u_{i,j}$项进行收集
$$\left(\frac{2}{h_x^2}+\frac{2}{h_y^2}\right)u_{i,j}-\frac{u_{i,j+1}+u_{i,j-1}}{h_x^2}-\frac{u_{i+1,j}+u_{i-1,j}}{h_y^2}=f_{i,j}$$
可以构成一个线性系统 $Au=b$
使用Jacobi迭代求解问题#
(bug)
cpp Code#
void PoissonJacobi::solve(Field& x, const Field& b) {
auto& u = x.data();
const auto& rhs = b.data();
int ny = u.rows();
int nx = u.cols();
Eigen::MatrixXd u_new = u;
double hx2 = 1.0;
double hy2 = 1.0;
double inv = 1.0 / (2.0 / hx2 + 2.0 / hy2);
for (int it = 0; it < max_iter_; ++it) {
double err = 0.0;
for (int i = 1; i < ny - 1; ++i)
for (int j = 1; j < nx - 1; ++j) {
double val =
(u(i+1,j) + u(i-1,j)) / hy2 +
(u(i,j+1) + u(i,j-1)) / hx2 -
rhs(i,j);
u_new(i,j) = inv * val;
err += std::abs(u_new(i,j) - u(i,j));
}
u.swap(u_new);
if (err < tol_) break;
}
}