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