forked from csc-training/summerschool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jacobi.F90
123 lines (86 loc) · 2.29 KB
/
jacobi.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
program jacobi
use iso_fortran_env, only : REAL64
implicit none
integer, parameter :: dp = REAL64
real(dp), parameter :: eps = 0.005
real(dp), dimension(:,:), allocatable :: u, unew, b
real(dp), allocatable, dimension(:,:) :: tmp_u
real(dp) :: norm
integer :: array_shape(2)
integer :: nx, ny, i, j, iter
real(kind=dp) :: t_start, t_end
iter = 0
t_start = wtime()
!$omp parallel shared(u, unew, b, norm, iter) private(i, j, nx, ny)
! TODO start: add necessary execution controls (single, master, barrier)
! in this parallel region
! Read b
call read_file(b)
array_shape = shape(b)
nx = array_shape(1)
ny = array_shape(2)
! Allocate space also for boundaries
allocate(u(0:nx + 1, 0:ny + 1), unew(0:nx + 1, 0:ny + 1))
! Initialize
!$omp workshare
u = 0.0
unew = 0.0
!$omp endworkshare
! Jacobi iteration
do
norm = 0.0
!$omp do reduction(+:norm)
do j = 1, ny
do i = 1, nx
unew(i, j) = 0.25 * (u(i, j - 1) + u(i, j + 1) + &
& u(i - 1, j) + u(i + 1, j) - &
& b(i, j))
norm = norm + (unew(i, j) - u(i, j))**2
end do
end do
!$omp end do
! Swap u and unew
call move_alloc(u, tmp_u)
call move_alloc(unew, u)
call move_alloc(tmp_u, unew)
if (mod(iter, 500) == 0) then
write(*,'(A, I6, A, F9.5)') 'Iteration', iter, ' norm:', norm
end if
iter = iter + 1
if (norm < eps) exit
end do
! TODO end
!$omp end parallel
t_end = wtime()
write(*,'(A, I6, A, F9.5, A, F9.5)') &
& 'Converged in', iter, ' iterations, norm', norm, &
& ' Time spent', t_end - t_start
deallocate(b, u, unew)
contains
subroutine read_file(mat)
implicit none
real(dp), allocatable, intent(inout) :: mat(:,:)
integer :: nx, ny, i
character(len=2) :: dummy
open(10, file='input.dat')
! Read the header
read(10, *) dummy, nx, ny
allocate(mat(nx, ny))
! Read the data
do i = 1, nx
read(10, *) mat(i, 1:ny)
end do
end subroutine read_file
function wtime() result(t0)
#ifdef _OPENMP
use omp_lib
#endif
implicit none
real(dp) :: t0
#ifdef _OPENMP
t0 = omp_get_wtime()
#else
call cpu_time(t0)
#endif
end function wtime
end program jacobi