Олександ Рудик

Модифікація Мерсона (Merson)
методу Рунге-Кутти (Runge–Kutta)
п'ятого порядку

Розглянемо звичайне диференціальне рівняння: dx/dt = f (t, x), у якому:
t — дійсна незалежна змінна (час);
x — змінна, залежна від t, що набуває величин у Rn;
f — функція з Rn + 1 в Rn, що задовольняє умови теореми існування і єдиності розв'язку задачі Коші.

При лінійній залежності f від x можна явно вирахувати розв'язки рівняння. У випадку нелінійної залежності при наближеному інтегруванні за допомогою різницевих схем бажано інтегрувати з якомога більшим кроком, щоб зменшити кількість обчислень нелінійного поля напрямків f. Відомі методи Рунге-Кутти різних порядків точності для інтегрування рівнянь. Похибка на кроці інтегрування h методу m-го порядку складає Ahm + 1. При сталому кроці інтегрування без знання верхньої межі для сталої A неможливо вибрати максимальний крок інтегрування, при якому похибка інтегрування на одному кроці не перевищує певну сталу C.

Запровадимо такі позначення:

xt — величина x певній величині t ;

y1 = 1/3 h f (t, xt) ;

y2 = 1/3 h f (t + 1/3 h, xt+ y1) ;

y3 = 1/3 h f (t + 1/3 h, xt+ 1/2 y1 + 1/2 y2) ;

y4 = 1/3 h f (t + 1/2 h, xt + 3/8 y1 + 9/8 y3) ;

y5 = 1/3 h f (t + h, xt + 3/2 y19/2 y3 + 6y4) ;

xt + h = xt + 1/2(y1 + 4y4 + y5) + O(h5) — величина x для часу (t + h) ;

d = y19/2 y3 + 4y41/2 y5 — похибка кроку інтегрування.

У численній літературі можна зустріти формули, що відрізняються сталими множниками для проміжних величин, але збігаються щодо кінцевого результату. Така модифікація Мерсона методу Рунге-Кутти (R.H. Merson, «An operational method for the study of integration processes», Proc. Symp. Data Processing , Weapons Res. Establ. Salisbury, Salisbury (1957) p. 110–125) передбачає автоматичний вибір кроку інтегрування:

Тут || d || — величина норми (довжини) вектора d = (d1; d2; d3; …; dn).

Відомі такі норми для векторних просторів R n :

|| d ||p = ( | d1| p + | d2| p + | d3| p + … + | dn| p) 1/p при 1 ≤ p.

Найменшу кількість обчислень здійснюють при обчисленні такої норми:

|| d ||1 = | d1| + | d2| + | d3| + … + | dn|.

Подамо приклад програмної реалізації мовою Turbo Pascal 7.0.

{$N+}
const n=2;
type num=extended;
     arr=array[1..n] of num;
var
f,  {поле напрямків}
x,  {точка, у якiй вираховують f}
x0, {початкове значення, розв'язок}
y1,y2,y3,y4,y5: arr;    {див. опис}
t,               {час - аргумент f}
t0,           {поточний час для x0}
t1,           {кiнцевий час}
h,              {крок інтегрування}
err,   {похибка кроку інтегрування}
errup: num;       {верхня межа err}
d,g,nx,ny: integer;
j: byte;
o: text;            {вихiдний файл}

procedure flow; BEGIN
f[1]:=-x[2];
f[2]:= x[1];      END;

procedure merson;            BEGIN
             if (t0>t1) then begin
writeln('Wrong time limits!');
                          halt end;
repeat
 if t0+h>t1 then h:=t1-t0;
 for j:=1 to n do x[j]:=x0[j];
 flow;
 t:=t0+h/3;
 for j:=1 to n do            begin
 y1[j]:=f[j]*h/3;
  x[j]:=x0[j]+y1[j]            end;
 flow;
 for j:=1 to n do            begin
 y2[j]:=f[j]*h/3;
  x[j]:=x0[j]+(y1[j]+y2[j])/2  end;
 flow;
 t:=t0+h/2;
 for j:=1 to n do            begin
 y3[j]:=f[j]*h/3;
  x[j]:=x0[j]+3*y1[j]/8
             +9*y3[j]/8        end;
 flow;
 t:=t0+h;
 for j:=1 to n do            begin
 y4[j]:=f[j]*h/3;
  x[j]:=x0[j]+3*y1[j]/2-9*y3[j]/2
             +6*y4[j]          end;
 flow;
 err:=0;
 for J:=1 to n do            begin
 y5[j]:=f[j]*h/3;
 err:=err+abs(y1[j]-9*y3[j]/2
           +4*y4[j]-  y5[j]/2) end;
 if err>errup*5 then h:=h/2
                      else   begin
 for j:=1 to n do            begin
 x0[j]:=x0[j]+(y1[j]
      +4*y4[j]+y5[j])/2        end;
  t0:=t;
 if err < errup*0.15625
 then h:=h*2 end
until t0 > t1;                END;
BEGIN
errup:=1.E-13;
x0[1]:=1;
x0[2]:=0;
t0:=0;
t1:=33*pi;
h:=1.;
merson;
assign(o,'OUTPUT.txt');
append(o);
writeln(o,x0[1],' ',x0[2],' ',
        sqr(x0[1])+sqr(x0[2]));
close(o);
END.

За поле напрямів вибрано поле поворотів навколо початку координат, що зберігає суму квадратів динамічних змінних.

Для типу змінних real маємо такий рядок вихідного файлу.

-1.00000000000364E+0000  5.70762659357626E-0010  1.00000000000728E+0000

Для типу змінних extended маємо наступний рядок вихідного файлу.

-1.00000000000000E+0000  5.36411451727628E-0010  1.00000000000000E+0000