parallel jacobi for Five-point difference format
格式分析
Jacobi迭代的基本形式
$$
x_i^{k+1}=\frac{1}{a_{ii}}\left(b_i-\sum_{j\neq i}a_{ij}x_j^k\right)
$$
对于二维Laplace方程,$x,y$方向采用相同的步长,在$x,y$方向采用中心差分离散可得
$$
\frac{\partial^2u(x,y)}{\partial x^2}\big|_{(x_i,y_j)}\approx\frac{2u(x_i,y_j)-u(x_{i-1},y_j)-u(x_{i+1},y_j)}{h^2}
$$
$$
\frac{\partial^2u(x,y)}{\partial y^2}\big|_{(x_i,y_j)}\approx\frac{2u(x_i,y_j)-u(x_{i},y_{j-1})-u(x_{i},y_{j+1})}{h^2}
$$
带入二维Laplace方程即可得Laplace方程在$(x_i,y_i)$点的近似离散方程
$$
4U_{i,j}-U_{i-1,j}-U_{i+1,j}-U_{i,j-1}-U_{i,j+1}=h^2f_{i,j}
$$
伪代码格式
while (not converged) {
for (i,j)
xnew[i][j] = (x[i+1][j] + x[i-1][j] + x[i][j+1] + x[i][j-1]+h*h*f)/4;
for (i,j)
x[i][j] = xnew[i][j];
}
误差范数估计采用如下
diffnorm = 0;
for (i,j)
diffnorm += (xnew[i][j] - x[i][j]) * (xnew[i][j] - x[i][j]);
diffnorm = sqrt(diffnorm);
并行程序
为了程序便于实现,本程序未处理边界,可以globMat中处理好边界然后传递给localMat,这样程序会好很多。但是写好了不想改了,就选择了边界为0的一个例子
$$
\begin{aligned}\Delta u &=f \quad \Omega\in[0,1]\times[0,1] \\ u(x,y)&=0 \quad [x,y]\in \partial \Omega\end{aligned}
$$
这里$u=x^2(x-1)^2y^2(y-1)^2$,
$$
\begin{aligned}f&=2(x^4(6y^2-6y+1)-2x^3(6y^2-6y+1)+\\&x^2(6y^4-12y^3+12y^2-6y+1)-6x(y-1)^2y^2+(y-1)^2y^2)\end{aligned}
$$
。
/*------------------------------------------------
JACOBI PARALLEL CODE
SOLVE \nabla u=f
------------------------------------------------*/
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define N 8
#define eps 1e-9
const double pi = acos(-1.0);
const double T = 1.0;
const long long int maxIter = 1e10;
double uFun(double x,double y){
return x*x*(x-1)*(x-1)*y*y*(y-1)*(y-1);
}
int main(int argc, char* argv[]) {
double h = T / (N - 1);
int rank, size;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (N % size != 0) {
MPI_Abort(MPI_COMM_WORLD, 1);
}
MPI_Barrier(MPI_COMM_WORLD);
int rows = N / size;
double(*localMat)[N] = new double[rows + 2][N];
double(*globMat)[N] = new double[rows][N];
for (int i = 0; i < rows + 2; i++) {
for (int j = 0; j < N; j++) {
*(*(localMat + i) + j) = 0;
}
}
int iterFrist = rank == 0 ? 2 : 1;
int iterLast = rank == size - 1 ? rows - 1 : rows;
double diffLoc = 1, diffGlob = 1;
int cnt = 0;
double startTimes = MPI_Wtime();
while (diffGlob > eps && cnt < maxIter) {
if (rank < size - 1) {
MPI_Send(*(localMat + rows), N, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD);
}
if (rank > 0) {
MPI_Recv(*localMat, N, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &status);
}
if (rank > 0) {
MPI_Send(*(localMat + 1), N, MPI_DOUBLE, rank - 1, 1, MPI_COMM_WORLD);
}
if (rank < size - 1) {
MPI_Recv(*(localMat + rows + 1), N, MPI_DOUBLE, rank + 1, 1, MPI_COMM_WORLD, &status);
}
diffLoc = 0;
for (int i = iterFrist; i < iterLast + 1; i++) {
for (int j = 1; j < N - 1; j++) {
//f(x,y) ---------
double xx = h * (rank * rows + i - 1);
double yy = h * j;
double f = 2 * (pow(xx, 4) * (6 * yy * yy - 6 * yy + 1) -
2 * pow(xx, 3) * (6 * yy * yy - 6 * yy + 1) +
xx * xx *
(6 * pow(yy, 4) - 12 * pow(yy, 3) +
12 * pow(yy, 2) - 6 * yy + 1) -
6 * xx * (yy - 1) * (yy - 1) * yy * yy +
(yy - 1) * (yy - 1) * yy * yy);
//----------------
*(*(globMat + i - 1) + j) =
(localMat[i][j + 1] + localMat[i][j - 1] + localMat[i - 1][j] +
localMat[i + 1][j] - f * h * h) /
4.0;
diffLoc += (globMat[i - 1][j] - localMat[i][j]) * (globMat[i - 1][j] - localMat[i][j]);
}
}
for (int i = iterFrist; i < iterLast + 1; i++) {
for (int j = 1; j < N - 1; j++) {
*(*(localMat + i) + j) = *(*(globMat + i - 1) + j);
}
}
MPI_Allreduce(&diffLoc, &diffGlob, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
diffGlob = sqrt(diffGlob);
cnt++;
}
double endTimes = MPI_Wtime();
double Final[N][N];
MPI_Gather(*(localMat+1), N * rows, MPI_DOUBLE, Final, N * rows, MPI_DOUBLE, 0, MPI_COMM_WORLD);
delete [] localMat;
delete [] globMat;
double infMax=-1.0;
if (rank == 0) {
FILE* f = fopen("data1.txt", "w");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
fprintf(f, "%.12lf,", Final[i][j]);
infMax = fmax(infMax,fabs(Final[i][j]-uFun(i*h,j*h)));
}
fprintf(f, "\n");
}
fclose(f);
}
MPI_Barrier(MPI_COMM_WORLD);
if (rank == 0) {
fprintf(stdout, "Total time is: %lf\n %d \n %.12lf\n", endTimes - startTimes, cnt,infMax);
}
MPI_Finalize();
return 0;
}
64点差分三维图
import numpy as np
import matplotlib.pyplot as plt
filename='./data1.txt'
Z = np.genfromtxt(filename,delimiter=',',dtype=np.float)
Z=np.delete(Z,-1,axis=1)
x = np.arange(0,1,1/64)
y = np.arange(0,1,1/64)
X,Y = np.meshgrid(x,y)
fig = plt.figure('himmelblau')
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z,cmap='rainbow')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
误差分析图
0 条评论