3.3. Метод рунге-кутта 2-го порядка
Пусть имеем дифференциальное уравнение y'=f(x,y) с начальными условиями у(x0)=y0.
Ищем решение на отрезке [x0,xn].
Пусть имеем точку (xm,ym), принадлежащему искомому решению. Для того, чтобы найти следующую точку проведем касательную к кривой в точке (xm,ym) до пересечения с прямой x=xm+0.5, где xm+0.5=xm+h/2. Тогда получим координату (по формуле Эйлера)
ym+0.5=ym+h/2·f(xm,ym).
Теперь найдём тангенс угла наклона касательной в т.В (xm+0.5,ym+0.5), (прямая L). Через точку А проведём прямую L'||L. Ординату точки пересечения прямых L' и x=xm+1 возьмём в качестве ym+1.
Таким образом
ym+0.5= ym+h/2·f(xm,ym), xm+0.5=xm+h/2
ym+1= ym+h·f(xm+0.5,ym+0.5), xm+1=xm+h
Для системы дифференциальных уравнений
yi'= fi(x,y1,y2,…yk),
yi(x0)= yi0, i= 1,2,…k
расчетные формулы имеют вид:
yim+0.5= yim+h/2·fi(xm,y1m,y2m,…ykm), xm+0.5= xm+h/2;
yim+1= yim+h·fi(xm+0.5,y1m+0.5,y2m+0.5,…ykm+0.5);
xm+1= xm+h.
ПРОГРАММА РУНГЕ-КУТТА 2-ГО ПОРЯДКА
Program Runge_Kutte_Method;
Uses Crt;
Type Vec=Array[1..6] of Real;
Var y, y0, k, f:Vec;
i, KolKom, KolRec, KolForPrint, count:Byte;
x, xk, h, s:Real;
Fout:text;
NameOut:string[12];
Procedure f_dir(y:vec; var f:vec);
var r:vec;
begin
r[1]:=k[1]*y[1];
r[2]:=k[2]*y[2];
r[3]:=k[3]*y[2];
r[4]:=k[4]*y[3];
r[5]:=k[5]*y[2];
f[1]:=-r[1]+r[5] ;
f[2]:=r[1]-r[2]-r[3]+r[4]-r[5];
f[3]:=r[2]-r[4];
f[4]:=r[3]
end;
BEGIN
ClrScr;
x:=0; xk:=15; h:=0.1;count:=0;s:=0;
write('введите количество компонентов ');readln(KolKom);
For i:=1 to KolKom do
begin
write(i,’введите концентрации компонентов ');readln(y[i])
end;
write('введите количество химических реакций ');readln(KolRec);
For i:=1 to KolRec do
begin
write(i,'введте константы химических реакции');readln(k[i])
end;
write('введите число точек для вывода значения на экран ');
readln(KolForPrint);
write('введите имя файлов для результатов');
readln(NameOut);
ClrScr;
assign(fout,NameOut);
rewrite(fout);
write(' время ');write(fout,' время ');
For i:=1 to KolKom do begin
write(' y[',i,']');
write(fout,' y[',i,']'); end;
writeln(' сумма '); writeln(fout,' сумма ');
write(x:5:1);write(fout,x:5:1);
for i:=1 to KolKom do
begin s:=s+y[i];write(y[i]:8:5);write(fout,y[i]:8:5) end;
writeln(s:8:2);writeln(fout,s:8:2);
repeat
f_dir(y,f);
For i:=1 to KolKom do
begin
y0[i]:=y[i];
y[i]:=y0[i]+0.5*h*f[i];
end;
f_dir(y,f);
For i:=1 to KolKom do y[i]:=y0[i]+h*f[i];
x:=x+h;
count:=count+1;
if count=round(xk/h/KolForPrint) then
begin
write(x:5:1);write(fout,x:5:1);s:=0;
for i:=1 to KolKom do
begin
s:=s+y[i];write(y[i]:8:5);write(fout,y[i]:8:5);
end;
writeln(s:8:2);writeln(fout,s:8:2);count:=0
end;
until x>xk;
close(fout);
readkey
end.