jacobi.f 6.8 KB

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