Розглянемо звичайне диференціальне рівняння: 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 y1 – 9/2 y3 + 6y4) ;
xt + h = xt + 1/2(y1 + 4y4 + y5) + O(h5) — величина x для часу (t + h) ;
d = y1 – 9/2 y3 + 4y4 – 1/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 || < 5/32 C інтегрування продовжують з нової точки xt + h з подвоєним кроком інтегрування 2h;
при справдженні нерівностей 5/32 C ≤ || d || ≤ 5C інтегрування продовжують з нової точки xt + h з тим самим кроком інтегрування h;
при справдженні нерівності 5C < || d || інтегрування продовжують з попередньої точки xt зі зменшеним удвічі кроком інтегрування h/2.
Тут || 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