xref: /openbsd-src/gnu/gcc/libgomp/testsuite/libgomp.fortran/jacobi.f (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert* { dg-do run }
2*404b540aSrobert
3*404b540aSrobert      program main
4*404b540aSrobert************************************************************
5*404b540aSrobert* program to solve a finite difference
6*404b540aSrobert* discretization of Helmholtz equation :
7*404b540aSrobert* (d2/dx2)u + (d2/dy2)u - alpha u = f
8*404b540aSrobert* using Jacobi iterative method.
9*404b540aSrobert*
10*404b540aSrobert* Modified: Sanjiv Shah,       Kuck and Associates, Inc. (KAI), 1998
11*404b540aSrobert* Author:   Joseph Robicheaux, Kuck and Associates, Inc. (KAI), 1998
12*404b540aSrobert*
13*404b540aSrobert* Directives are used in this code to achieve paralleism.
14*404b540aSrobert* All do loops are parallized with default 'static' scheduling.
15*404b540aSrobert*
16*404b540aSrobert* Input :  n - grid dimension in x direction
17*404b540aSrobert*          m - grid dimension in y direction
18*404b540aSrobert*          alpha - Helmholtz constant (always greater than 0.0)
19*404b540aSrobert*          tol   - error tolerance for iterative solver
20*404b540aSrobert*          relax - Successice over relaxation parameter
21*404b540aSrobert*          mits  - Maximum iterations for iterative solver
22*404b540aSrobert*
23*404b540aSrobert* On output
24*404b540aSrobert*       : u(n,m) - Dependent variable (solutions)
25*404b540aSrobert*       : f(n,m) - Right hand side function
26*404b540aSrobert*************************************************************
27*404b540aSrobert      implicit none
28*404b540aSrobert
29*404b540aSrobert      integer n,m,mits,mtemp
30*404b540aSrobert      include "omp_lib.h"
31*404b540aSrobert      double precision tol,relax,alpha
32*404b540aSrobert
33*404b540aSrobert      common /idat/ n,m,mits,mtemp
34*404b540aSrobert      common /fdat/tol,alpha,relax
35*404b540aSrobert*
36*404b540aSrobert* Read info
37*404b540aSrobert*
38*404b540aSrobert      write(*,*) "Input n,m - grid dimension in x,y direction "
39*404b540aSrobert      n = 64
40*404b540aSrobert      m = 64
41*404b540aSrobert*     read(5,*) n,m
42*404b540aSrobert      write(*,*) n, m
43*404b540aSrobert      write(*,*) "Input alpha - Helmholts constant "
44*404b540aSrobert      alpha = 0.5
45*404b540aSrobert*     read(5,*) alpha
46*404b540aSrobert      write(*,*) alpha
47*404b540aSrobert      write(*,*) "Input relax - Successive over-relaxation parameter"
48*404b540aSrobert      relax = 0.9
49*404b540aSrobert*     read(5,*) relax
50*404b540aSrobert      write(*,*) relax
51*404b540aSrobert      write(*,*) "Input tol - error tolerance for iterative solver"
52*404b540aSrobert      tol = 1.0E-12
53*404b540aSrobert*     read(5,*) tol
54*404b540aSrobert      write(*,*) tol
55*404b540aSrobert      write(*,*) "Input mits - Maximum iterations for solver"
56*404b540aSrobert      mits = 100
57*404b540aSrobert*     read(5,*) mits
58*404b540aSrobert      write(*,*) mits
59*404b540aSrobert
60*404b540aSrobert      call omp_set_num_threads (2)
61*404b540aSrobert
62*404b540aSrobert*
63*404b540aSrobert* Calls a driver routine
64*404b540aSrobert*
65*404b540aSrobert      call driver ()
66*404b540aSrobert
67*404b540aSrobert      stop
68*404b540aSrobert      end
69*404b540aSrobert
70*404b540aSrobert      subroutine driver ( )
71*404b540aSrobert*************************************************************
72*404b540aSrobert* Subroutine driver ()
73*404b540aSrobert* This is where the arrays are allocated and initialzed.
74*404b540aSrobert*
75*404b540aSrobert* Working varaibles/arrays
76*404b540aSrobert*     dx  - grid spacing in x direction
77*404b540aSrobert*     dy  - grid spacing in y direction
78*404b540aSrobert*************************************************************
79*404b540aSrobert      implicit none
80*404b540aSrobert
81*404b540aSrobert      integer n,m,mits,mtemp
82*404b540aSrobert      double precision tol,relax,alpha
83*404b540aSrobert
84*404b540aSrobert      common /idat/ n,m,mits,mtemp
85*404b540aSrobert      common /fdat/tol,alpha,relax
86*404b540aSrobert
87*404b540aSrobert      double precision u(n,m),f(n,m),dx,dy
88*404b540aSrobert
89*404b540aSrobert* Initialize data
90*404b540aSrobert
91*404b540aSrobert      call initialize (n,m,alpha,dx,dy,u,f)
92*404b540aSrobert
93*404b540aSrobert* Solve Helmholtz equation
94*404b540aSrobert
95*404b540aSrobert      call jacobi (n,m,dx,dy,alpha,relax,u,f,tol,mits)
96*404b540aSrobert
97*404b540aSrobert* Check error between exact solution
98*404b540aSrobert
99*404b540aSrobert      call  error_check (n,m,alpha,dx,dy,u,f)
100*404b540aSrobert
101*404b540aSrobert      return
102*404b540aSrobert      end
103*404b540aSrobert
104*404b540aSrobert      subroutine initialize (n,m,alpha,dx,dy,u,f)
105*404b540aSrobert******************************************************
106*404b540aSrobert* Initializes data
107*404b540aSrobert* Assumes exact solution is u(x,y) = (1-x^2)*(1-y^2)
108*404b540aSrobert*
109*404b540aSrobert******************************************************
110*404b540aSrobert      implicit none
111*404b540aSrobert
112*404b540aSrobert      integer n,m
113*404b540aSrobert      double precision u(n,m),f(n,m),dx,dy,alpha
114*404b540aSrobert
115*404b540aSrobert      integer i,j, xx,yy
116*404b540aSrobert      double precision PI
117*404b540aSrobert      parameter (PI=3.1415926)
118*404b540aSrobert
119*404b540aSrobert      dx = 2.0 / (n-1)
120*404b540aSrobert      dy = 2.0 / (m-1)
121*404b540aSrobert
122*404b540aSrobert* Initilize initial condition and RHS
123*404b540aSrobert
124*404b540aSrobert!$omp parallel do private(xx,yy)
125*404b540aSrobert      do j = 1,m
126*404b540aSrobert         do i = 1,n
127*404b540aSrobert            xx = -1.0 + dx * dble(i-1)        ! -1 < x < 1
128*404b540aSrobert            yy = -1.0 + dy * dble(j-1)        ! -1 < y < 1
129*404b540aSrobert            u(i,j) = 0.0
130*404b540aSrobert            f(i,j) = -alpha *(1.0-xx*xx)*(1.0-yy*yy)
131*404b540aSrobert     &           - 2.0*(1.0-xx*xx)-2.0*(1.0-yy*yy)
132*404b540aSrobert         enddo
133*404b540aSrobert      enddo
134*404b540aSrobert!$omp end parallel do
135*404b540aSrobert
136*404b540aSrobert      return
137*404b540aSrobert      end
138*404b540aSrobert
139*404b540aSrobert      subroutine jacobi (n,m,dx,dy,alpha,omega,u,f,tol,maxit)
140*404b540aSrobert******************************************************************
141*404b540aSrobert* Subroutine HelmholtzJ
142*404b540aSrobert* Solves poisson equation on rectangular grid assuming :
143*404b540aSrobert* (1) Uniform discretization in each direction, and
144*404b540aSrobert* (2) Dirichlect boundary conditions
145*404b540aSrobert*
146*404b540aSrobert* Jacobi method is used in this routine
147*404b540aSrobert*
148*404b540aSrobert* Input : n,m   Number of grid points in the X/Y directions
149*404b540aSrobert*         dx,dy Grid spacing in the X/Y directions
150*404b540aSrobert*         alpha Helmholtz eqn. coefficient
151*404b540aSrobert*         omega Relaxation factor
152*404b540aSrobert*         f(n,m) Right hand side function
153*404b540aSrobert*         u(n,m) Dependent variable/Solution
154*404b540aSrobert*         tol    Tolerance for iterative solver
155*404b540aSrobert*         maxit  Maximum number of iterations
156*404b540aSrobert*
157*404b540aSrobert* Output : u(n,m) - Solution
158*404b540aSrobert*****************************************************************
159*404b540aSrobert      implicit none
160*404b540aSrobert      integer n,m,maxit
161*404b540aSrobert      double precision dx,dy,f(n,m),u(n,m),alpha, tol,omega
162*404b540aSrobert*
163*404b540aSrobert* Local variables
164*404b540aSrobert*
165*404b540aSrobert      integer i,j,k,k_local
166*404b540aSrobert      double precision error,resid,rsum,ax,ay,b
167*404b540aSrobert      double precision error_local, uold(n,m)
168*404b540aSrobert
169*404b540aSrobert      real ta,tb,tc,td,te,ta1,ta2,tb1,tb2,tc1,tc2,td1,td2
170*404b540aSrobert      real te1,te2
171*404b540aSrobert      real second
172*404b540aSrobert      external second
173*404b540aSrobert*
174*404b540aSrobert* Initialize coefficients
175*404b540aSrobert      ax = 1.0/(dx*dx) ! X-direction coef
176*404b540aSrobert      ay = 1.0/(dy*dy) ! Y-direction coef
177*404b540aSrobert      b  = -2.0/(dx*dx)-2.0/(dy*dy) - alpha ! Central coeff
178*404b540aSrobert
179*404b540aSrobert      error = 10.0 * tol
180*404b540aSrobert      k = 1
181*404b540aSrobert
182*404b540aSrobert      do while (k.le.maxit .and. error.gt. tol)
183*404b540aSrobert
184*404b540aSrobert         error = 0.0
185*404b540aSrobert
186*404b540aSrobert* Copy new solution into old
187*404b540aSrobert!$omp parallel
188*404b540aSrobert
189*404b540aSrobert!$omp do
190*404b540aSrobert         do j=1,m
191*404b540aSrobert            do i=1,n
192*404b540aSrobert               uold(i,j) = u(i,j)
193*404b540aSrobert            enddo
194*404b540aSrobert         enddo
195*404b540aSrobert
196*404b540aSrobert* Compute stencil, residual, & update
197*404b540aSrobert
198*404b540aSrobert!$omp do private(resid) reduction(+:error)
199*404b540aSrobert         do j = 2,m-1
200*404b540aSrobert            do i = 2,n-1
201*404b540aSrobert*     Evaluate residual
202*404b540aSrobert               resid = (ax*(uold(i-1,j) + uold(i+1,j))
203*404b540aSrobert     &                + ay*(uold(i,j-1) + uold(i,j+1))
204*404b540aSrobert     &                 + b * uold(i,j) - f(i,j))/b
205*404b540aSrobert* Update solution
206*404b540aSrobert               u(i,j) = uold(i,j) - omega * resid
207*404b540aSrobert* Accumulate residual error
208*404b540aSrobert               error = error + resid*resid
209*404b540aSrobert            end do
210*404b540aSrobert         enddo
211*404b540aSrobert!$omp enddo nowait
212*404b540aSrobert
213*404b540aSrobert!$omp end parallel
214*404b540aSrobert
215*404b540aSrobert* Error check
216*404b540aSrobert
217*404b540aSrobert         k = k + 1
218*404b540aSrobert
219*404b540aSrobert         error = sqrt(error)/dble(n*m)
220*404b540aSrobert*
221*404b540aSrobert      enddo                     ! End iteration loop
222*404b540aSrobert*
223*404b540aSrobert      print *, 'Total Number of Iterations ', k
224*404b540aSrobert      print *, 'Residual                   ', error
225*404b540aSrobert
226*404b540aSrobert      return
227*404b540aSrobert      end
228*404b540aSrobert
229*404b540aSrobert      subroutine error_check (n,m,alpha,dx,dy,u,f)
230*404b540aSrobert      implicit none
231*404b540aSrobert************************************************************
232*404b540aSrobert* Checks error between numerical and exact solution
233*404b540aSrobert*
234*404b540aSrobert************************************************************
235*404b540aSrobert
236*404b540aSrobert      integer n,m
237*404b540aSrobert      double precision u(n,m),f(n,m),dx,dy,alpha
238*404b540aSrobert
239*404b540aSrobert      integer i,j
240*404b540aSrobert      double precision xx,yy,temp,error
241*404b540aSrobert
242*404b540aSrobert      dx = 2.0 / (n-1)
243*404b540aSrobert      dy = 2.0 / (m-1)
244*404b540aSrobert      error = 0.0
245*404b540aSrobert
246*404b540aSrobert!$omp parallel do private(xx,yy,temp) reduction(+:error)
247*404b540aSrobert      do j = 1,m
248*404b540aSrobert         do i = 1,n
249*404b540aSrobert            xx = -1.0d0 + dx * dble(i-1)
250*404b540aSrobert            yy = -1.0d0 + dy * dble(j-1)
251*404b540aSrobert            temp  = u(i,j) - (1.0-xx*xx)*(1.0-yy*yy)
252*404b540aSrobert            error = error + temp*temp
253*404b540aSrobert         enddo
254*404b540aSrobert      enddo
255*404b540aSrobert
256*404b540aSrobert      error = sqrt(error)/dble(n*m)
257*404b540aSrobert
258*404b540aSrobert      print *, 'Solution Error : ',error
259*404b540aSrobert
260*404b540aSrobert      return
261*404b540aSrobert      end
262