123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- * { dg-do run }
- program main
- ************************************************************
- * program to solve a finite difference
- * discretization of Helmholtz equation :
- * (d2/dx2)u + (d2/dy2)u - alpha u = f
- * using Jacobi iterative method.
- *
- * Modified: Sanjiv Shah, Kuck and Associates, Inc. (KAI), 1998
- * Author: Joseph Robicheaux, Kuck and Associates, Inc. (KAI), 1998
- *
- * Directives are used in this code to achieve paralleism.
- * All do loops are parallized with default 'static' scheduling.
- *
- * Input : n - grid dimension in x direction
- * m - grid dimension in y direction
- * alpha - Helmholtz constant (always greater than 0.0)
- * tol - error tolerance for iterative solver
- * relax - Successice over relaxation parameter
- * mits - Maximum iterations for iterative solver
- *
- * On output
- * : u(n,m) - Dependent variable (solutions)
- * : f(n,m) - Right hand side function
- *************************************************************
- implicit none
- integer n,m,mits,mtemp
- include "omp_lib.h"
- double precision tol,relax,alpha
- common /idat/ n,m,mits,mtemp
- common /fdat/tol,alpha,relax
- *
- * Read info
- *
- write(*,*) "Input n,m - grid dimension in x,y direction "
- n = 64
- m = 64
- * read(5,*) n,m
- write(*,*) n, m
- write(*,*) "Input alpha - Helmholts constant "
- alpha = 0.5
- * read(5,*) alpha
- write(*,*) alpha
- write(*,*) "Input relax - Successive over-relaxation parameter"
- relax = 0.9
- * read(5,*) relax
- write(*,*) relax
- write(*,*) "Input tol - error tolerance for iterative solver"
- tol = 1.0E-12
- * read(5,*) tol
- write(*,*) tol
- write(*,*) "Input mits - Maximum iterations for solver"
- mits = 100
- * read(5,*) mits
- write(*,*) mits
- call omp_set_num_threads (2)
- *
- * Calls a driver routine
- *
- call driver ()
- stop
- end
- subroutine driver ( )
- *************************************************************
- * Subroutine driver ()
- * This is where the arrays are allocated and initialzed.
- *
- * Working varaibles/arrays
- * dx - grid spacing in x direction
- * dy - grid spacing in y direction
- *************************************************************
- implicit none
- integer n,m,mits,mtemp
- double precision tol,relax,alpha
- common /idat/ n,m,mits,mtemp
- common /fdat/tol,alpha,relax
- double precision u(n,m),f(n,m),dx,dy
- * Initialize data
- call initialize (n,m,alpha,dx,dy,u,f)
- * Solve Helmholtz equation
- call jacobi (n,m,dx,dy,alpha,relax,u,f,tol,mits)
- * Check error between exact solution
- call error_check (n,m,alpha,dx,dy,u,f)
- return
- end
- subroutine initialize (n,m,alpha,dx,dy,u,f)
- ******************************************************
- * Initializes data
- * Assumes exact solution is u(x,y) = (1-x^2)*(1-y^2)
- *
- ******************************************************
- implicit none
-
- integer n,m
- double precision u(n,m),f(n,m),dx,dy,alpha
-
- integer i,j, xx,yy
- double precision PI
- parameter (PI=3.1415926)
- dx = 2.0 / (n-1)
- dy = 2.0 / (m-1)
- * Initilize initial condition and RHS
- !$omp parallel do private(xx,yy)
- do j = 1,m
- do i = 1,n
- xx = -1.0 + dx * dble(i-1) ! -1 < x < 1
- yy = -1.0 + dy * dble(j-1) ! -1 < y < 1
- u(i,j) = 0.0
- f(i,j) = -alpha *(1.0-xx*xx)*(1.0-yy*yy)
- & - 2.0*(1.0-xx*xx)-2.0*(1.0-yy*yy)
- enddo
- enddo
- !$omp end parallel do
- return
- end
- subroutine jacobi (n,m,dx,dy,alpha,omega,u,f,tol,maxit)
- ******************************************************************
- * Subroutine HelmholtzJ
- * Solves poisson equation on rectangular grid assuming :
- * (1) Uniform discretization in each direction, and
- * (2) Dirichlect boundary conditions
- *
- * Jacobi method is used in this routine
- *
- * Input : n,m Number of grid points in the X/Y directions
- * dx,dy Grid spacing in the X/Y directions
- * alpha Helmholtz eqn. coefficient
- * omega Relaxation factor
- * f(n,m) Right hand side function
- * u(n,m) Dependent variable/Solution
- * tol Tolerance for iterative solver
- * maxit Maximum number of iterations
- *
- * Output : u(n,m) - Solution
- *****************************************************************
- implicit none
- integer n,m,maxit
- double precision dx,dy,f(n,m),u(n,m),alpha, tol,omega
- *
- * Local variables
- *
- integer i,j,k,k_local
- double precision error,resid,rsum,ax,ay,b
- double precision error_local, uold(n,m)
- real ta,tb,tc,td,te,ta1,ta2,tb1,tb2,tc1,tc2,td1,td2
- real te1,te2
- real second
- external second
- *
- * Initialize coefficients
- ax = 1.0/(dx*dx) ! X-direction coef
- ay = 1.0/(dy*dy) ! Y-direction coef
- b = -2.0/(dx*dx)-2.0/(dy*dy) - alpha ! Central coeff
- error = 10.0 * tol
- k = 1
- do while (k.le.maxit .and. error.gt. tol)
- error = 0.0
- * Copy new solution into old
- !$omp parallel
- !$omp do
- do j=1,m
- do i=1,n
- uold(i,j) = u(i,j)
- enddo
- enddo
- * Compute stencil, residual, & update
- !$omp do private(resid) reduction(+:error)
- do j = 2,m-1
- do i = 2,n-1
- * Evaluate residual
- resid = (ax*(uold(i-1,j) + uold(i+1,j))
- & + ay*(uold(i,j-1) + uold(i,j+1))
- & + b * uold(i,j) - f(i,j))/b
- * Update solution
- u(i,j) = uold(i,j) - omega * resid
- * Accumulate residual error
- error = error + resid*resid
- end do
- enddo
- !$omp enddo nowait
- !$omp end parallel
- * Error check
- k = k + 1
- error = sqrt(error)/dble(n*m)
- *
- enddo ! End iteration loop
- *
- print *, 'Total Number of Iterations ', k
- print *, 'Residual ', error
- return
- end
- subroutine error_check (n,m,alpha,dx,dy,u,f)
- implicit none
- ************************************************************
- * Checks error between numerical and exact solution
- *
- ************************************************************
-
- integer n,m
- double precision u(n,m),f(n,m),dx,dy,alpha
-
- integer i,j
- double precision xx,yy,temp,error
- dx = 2.0 / (n-1)
- dy = 2.0 / (m-1)
- error = 0.0
- !$omp parallel do private(xx,yy,temp) reduction(+:error)
- do j = 1,m
- do i = 1,n
- xx = -1.0d0 + dx * dble(i-1)
- yy = -1.0d0 + dy * dble(j-1)
- temp = u(i,j) - (1.0-xx*xx)*(1.0-yy*yy)
- error = error + temp*temp
- enddo
- enddo
-
- error = sqrt(error)/dble(n*m)
- print *, 'Solution Error : ',error
- return
- end
|