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