1 1 Последовательное решение уравнения

  1. program diff
  2. integer xmax,ymax
  3. c Размер сетки по оси X
  4. parameter (xmax=4000)
  5. c Размер сетки по оси Y
  6. parameter (ymax=6000)
  7. real*8 f0(xmax,ymax), f1(xmax,ymax)
  8. real*8 df
  9. integer x,y,n
  10. c Задаем начальные значения
  11. call initial(f0,xmax,ymax)
  12. call initial(f1,xmax,ymax)
  13. c Задаем граничные значения
  14. call boundary(f0,xmax,ymax)
  15. call boundary(f1,xmax,ymax)
  16. c Начинаем основной итерационный цикл
  17. df=0.0
  18. n=0
  19. 1 continue
  20. c При смене итераций меняем местами массивы
  21. if ( ((n/2)*2) .EQ. n ) then
  22. c Обрабатываем f0 для каждой четной итерации
  23. call iter(f0,f1,xmax,ymax,df)
  24. else
  25. c Обрабатываем f1 для каждой нечетной итерации
  26. call iter(f1,f0,xmax,ymax,df)
  27. endif
  28. c Увеличиваем номер цикла на единицу
  29. n=n+1
  30. c Выводим на экран разницу между итерациями
  31. write(*,*) 'Diff:',df
  32. c Если разница больше заданной, то решение не найдено
  33. c и мы идем на следующий цикл
  34. if (df > 1e-2) goto 1
  35. c Печатаем количество итераций, потребовавшихся
  36. c для нахождения решения
  37. write(*,*) 'Iteration count:', n
  38. stop
  39. end
  40.  
  41. c Подпрограмма вычисления искомой функции
  42. subroutine iter(f0,f1,xmax,ymax,df)
  43. integer xmax,ymax
  44. real*8 f0(xmax,ymax), f1(xmax,ymax)
  45. real*8 dt,dx,dy
  46. real*8 df,dff,df1
  47. integer x,y,n
  48. dt=0.01
  49. dx=0.5
  50. dy=0.5
  51. df1=0.0
  52. c Вычисляем функцию в ячейках сетки
  53. do y=2,ymax-1
  54. do x=2,xmax-1
  55. dff=dt*(
  56. x (f0(x+1,y)-2*f0(x,y)+f0(x-1,y))/(dx*dx)
  57. x +
  58. x (f0(x,y+1)-2*f0(x,y)+f0(x,y-1))/(dy*dy)
  59. x )
  60. f1(x,y)=f0(x,y)+dff
  61. c Находм максимальную дельту
  62. if( df1 < abs(dff) ) df1=abs(dff)
  63. end do
  64. end do
  65. df=df1
  66. return
  67. end
  68.  
  69. c Подпрограмма задания начальных значений
  70. subroutine initial(f0,xmax,ymax)
  71. integer xmax,ymax,x,y
  72. real*8 f0(xmax,ymax)
  73. c Задаем начальные значения массива
  74. do x=1,xmax
  75. do y=1,ymax
  76. f0(x,y)=0.0
  77. end do
  78. end do
  79. return
  80. end
  81.  
  82. c Подпрограмма задания граничных условий
  83. subroutine boundary(f0,xmax,ymax)
  84. integer rank,xmax,ymax,x,y
  85. real*8 f0(xmax,ymax)
  86. common myid,np
  87. c Задаем граничные значения массива
  88. do y=1,ymax
  89. f0(1,y)=0.0
  90. f0(xmax,y)=0.0
  91. end do
  92. do x=1,xmax
  93. f0(x,1)=sin((x*1.0)/(xmax/2))
  94. f0(x,ymax)=0.0
  95. end do
  96. f0(xmax/2,ymax)=-5.0
  97. return
  98. end
  99.  

Как видите, программа достаточно проста. Здесь я ограничусь всего несколькими пояснениями. В качестве разностной сетки мы берем прямоугольник со сторонами 4000 ячеек по оси X и 6000 ячеек по оси Y. Размерность сетки задается в строка 4 и 6.

Далее, в строках 11 - 15 мы задаем начальные и граничные условия посредством вызова подпрограмм initial (строка 69) и boundary (строка 82) соответственно, заполняющих по некоторому правилу ячейки сетки.

Цикл с 19 по 34 строчку является основным итерационным процессом. В строке 34 принимается решение о продолжении итераций на основе максимальной разницы между значениями искомой функции на текущем и предыдущем слое по времени. Если разница больше некоторого заранее заданного значения, то итерации продолжаются. Само вычисление функции в ячейках оформлено в виде подпрограммы iter, код которой начинается со строки 42. Эта же подпрограмма вычисляет максимальное значение Δf.

В самом начале в качестве исходных данных берется массив f0, а вычисленные значения функции на следующем шаге по времени заносятся в массив f1 - строка 23. На следующей итерации за основу берется уже массив f1, то есть массивы меняются местами - строка 26. И так далее.

Теперь о вычислении самой функции. Выполнение этого действия выделено в подпрограмму iter (строка 42). Функция на k+1 слое по времени вычисляется на основе значений этой функции на k-ом слое. Делается это в два этапа. Сначала вычисляются значения внутренних ячеек на основе разностной формулы (строки 55-60), а затем находим максимальную разницу значений функции между слоями (строка 61).

В следующем разделе мы с вами посмотрим, как можно эту программу превратить в параллельную, что для этого надо и какие изменения в исходный код должны быть внесены.


Copyright © 1998-2011 Юрий Сбитнев