# # Program that, with Runge-Kutta method, solves mxm system of IVP of ODE # x[i]' = f[i](t,x[1],x[2],...,x[m]), t in [a,b] # x[i](0) = x0[i], # i=1,2,...,m # # input: f --- a vector or list of operators # for example: # > f:=array(1..2); # > f[1]:=(t,x,y)->x-0.1*x*y; # f[2]:=(t,x,y)->-.5*y+.02*x*y; # a, b --- end points of the t interval # x0 --- array(1..m) of initial conditions # n --- number of subintervals dividing [a,b] # # output: t --- the array of nodes dividing [a,b] # x --- the array(1..m), each entry x[i] is an array(0..n) # x[i][j] is the approximate value of x[i](t[j]) # RungeKutta := proc( f::{list,Vector}, a::numeric, b::numeric, x0::{list,Vector}, n::integer ) local m, i, j, k, l, delta, delta2, t, x; if type(f,list) then m := nops(f) else m := LinearAlgebra:-Dimension(f) end if; delta:=evalf( (b-a)/n ); delta2:=0.5*delta; t:=Vector([ seq( evalf( a+i*delta ), i=0..n )]); x:=array(1..m, [ seq( Vector(n+1), i=1..m) ] ); k:=array(1..4, [ seq( array(1..m), i=1..4) ] ); for i to m do x[i][1]:=evalf(x0[i]) od; for i from 1 to n do for j to m do k[1][j]:= evalf( delta*f[j](t[i], seq( x[l][i], l=1..m ) ) ) end do; for j to m do k[2][j]:= evalf( delta*f[j](t[i]+delta2, seq( x[l][i]+0.5*k[1][l], l=1..m ) ) ) end do; for j to m do k[3][j]:= evalf( delta* f[j](t[i]+delta2, seq( x[l][i]+0.5*k[2][l], l=1..m ) ) ) end do; for j to m do k[4][j]:= evalf( delta*f[j](t[i]+delta, seq( x[l][i]+k[3][l], l=1..m ) ) ) end do; for j to m do x[j][i+1]:= evalf( x[j][i] + (k[1][j]+2.0*(k[2][j]+k[3][j])+k[4][j])/6.0 ) end do; end do; return t, x; end;