1)代码
PROGRAM OPENMP_GZ
INCLUDE 'omp_lib.h'
INTEGER, PARAMETER :: N = 101
INTEGER I,J,L,MAXIT,T,S
REAL(8), ALLOCATABLE, DIMENSION(:,:):: W,X,Y
REAL(8) ERROR, EPS, T1, T2, dX, dY, C
MAXIT = 100000 !最大迭代次数
EPS = 1E-6 !收敛精度
ERROR = 1E6 !初始误差
L = 1
ALLOCATE (W(N,N),X(N,N),Y(N,N))
OPEN(1, FILE='101.msh')!从文件读取网格数据
DO J=1,N
DO I=1,N
READ(1,*) X(I,J), Y(I,J)
ENDDO
ENDDO
CLOSE(1)
W(2:N-1,2:N-1) = 0.0! 设置边界条件
DO J=1,N
W(1,J) = EXP(-1.5*(X(1,J))**2 + 2*(Y(1,J))**2)
W(N,J) = EXP(-1.5*(X(N,J))**2 + 2*(Y(N,J))**2)
ENDDO
DO I=1,N
W(I,1) = EXP(-1.5*(X(I,1))**2 + 2*(Y(I,1))**2)
W(I,N) = EXP(-1.5*(X(I,N))**2 + 2*(Y(I,N))**2)
ENDDO
T1 = OMP_GET_WTIME()
DO S=1,100000000
DO WHILE (L .LE. MAXIT .AND. ERROR .GT. EPS)
ERROR = 0.0
!$OMP PARALLEL PRIVATE(I,J,dX,dY,C) ! PARALLEL DO 指令允许指定哪些循环应由编译器并行化
!$OMP DO REDUCTION(MAX:ERROR) ! DO 循环,通过 REDUCTION 计算最大误差
DO J = 2, N-1
DO I = 2, N-1
dY = Y(I,J+1) - Y(I,J)
dX = X(I+1,J) - X(I,J)
C = W(I,J)
W(I,J) = 0.5 * (dY*(W(I-1,J) + W(I+1,J)) + dX*(W(I,J-1) + W(I,J+1)) - 0.2*dX*dY)/( dX + dY)
ERROR = MAX(ERROR, ABS(W(I,J) - C))
END DO
ENDDO
!$OMP END DO !END PARALLEL DO 指令标记在 PARALLEL DO 指令中指定的 DO 循环的结束
!$OMP END PARALLEL
L = L + 1
END DO
END DO
T2 = OMP_GET_WTIME()
PRINT *, 'computational time: ', T2-T1, 's'
PRINT *, L
OPEN(2,FILE='Res.dat') ! 输出数据到文件
DO J=1,N
DO I=1,N
WRITE(2,*) X(I,J), Y(I,J), W(I,J)
END DO
END DO
CLOSE(2)
DEALLOCATE (W,X,Y)
END PROGRAM
2)编译命令
gfortran -fopenmp -o pa.exe Gauss–Seidel_parallel.f90
3)输入数据
见附件
3)运行结果
3000-3100行的数据:
串行:
0.40000000000000002 -0.41999999999999998 0.94283719429734447
0.41999999999999998 -0.41999999999999998 0.91517049547914420
0.44000000000000000 -0.41999999999999998 0.88692669347676489
0.46000000000000002 -0.41999999999999998 0.85820552287434693
0.47999999999999998 -0.41999999999999998 0.82910918519491994
0.50000000000000000 -0.41999999999999998 0.79974214641266483
0.52000000000000002 -0.41999999999999998 0.77021094585209326
0.54000000000000004 -0.41999999999999998 0.74062401904255837
0.56000000000000005 -0.41999999999999998 0.71109153718516127
0.57999999999999996 -0.41999999999999998 0.68172526596580540
0.59999999999999998 -0.41999999999999998 0.65263844650670655
并行:
0.40000000000000002 -0.41999999999999998 0.94283837147741767
0.41999999999999998 -0.41999999999999998 0.91517164464449596
0.44000000000000000 -0.41999999999999998 0.88692781352135375
0.46000000000000002 -0.41999999999999998 0.85820661272195631
0.47999999999999998 -0.41999999999999998 0.82911024380019038
0.50000000000000000 -0.41999999999999998 0.79974317276209350
0.52000000000000002 -0.41999999999999998 0.77021193896500240
0.54000000000000004 -0.41999999999999998 0.74062497797203064
0.56000000000000005 -0.41999999999999998 0.71109246101893997
0.57999999999999996 -0.41999999999999998 0.68172615382715873
0.59999999999999998 -0.41999999999999998 0.65263929755525862
串行:
10000-10010
-1.0000000000000000 0.97999999999999998 1.5231796120207264
-0.97999999999999998 0.97999999999999998 1.6350407390271877
-0.95999999999999996 0.97999999999999998 1.7454097502627000
-0.93999999999999995 0.97999999999999998 1.8566927732738419
-0.92000000000000004 0.97999999999999998 1.9699458586500573
-0.90000000000000002 0.97999999999999998 2.0856822347163213
-0.88000000000000000 0.97999999999999998 2.2041598308409540
-0.85999999999999999 0.97999999999999998 2.3254975194154395
-0.83999999999999997 0.97999999999999998 2.4497279948182107
-0.81999999999999995 0.97999999999999998 2.5768244045233648
-0.80000000000000004 0.97999999999999998 2.7067149417711622
并行:
-1.0000000000000000 0.97999999999999998 1.5231796120207264
-0.97999999999999998 0.97999999999999998 1.6350407359076693
-0.95999999999999996 0.97999999999999998 1.7454097440298204
-0.93999999999999995 0.97999999999999998 1.8566927639368240
-0.92000000000000004 0.97999999999999998 1.9699458462211767
-0.90000000000000002 0.97999999999999998 2.0856822192108919
-0.88000000000000000 0.97999999999999998 2.2041598122773096
-0.85999999999999999 0.97999999999999998 2.3254974978149128
-0.83999999999999997 0.97999999999999998 2.4497279702051098
-0.81999999999999995 0.97999999999999998 2.5768243769249448
-0.80000000000000004 0.97999999999999998 2.7067149112175963
5)分析
数据类型是双精度的,
REAL(8), ALLOCATABLE, DIMENSION(:,:):: W,X,Y
下面的代码存在强依赖,就是W(I,J)依赖于W(I-1,J)和W(I,J-1)
W(I,J) = 0.5 * (dY*(W(I-1,J) + W(I+1,J)) + dX*(W(I,J-1) + W(I,J+1)) - 0.2*dX*dY)/(dX + dY)
尽管迭代会逐步减少误差到满足收敛要求
DO WHILE (L .LE. MAXIT .AND. ERROR .GT. EPS)
6)
确实也是可以并行,但是只是结果不一样
根据EP判断收敛,确实是可以的。