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

