This chapter describes functions for solving ordinary differential equation (ODE) initial value problems. GSL Shell gives you access to a variety of methods provided by the GSL library, such as Runge-Kutta and Bulirsch-Stoer routines with an high-level interface and an adaptive step-size control. The interface can be used to easily achieve the desired solution, with full access to any intermediate steps.
In GSL Shell an ODE system is integrated by using an ode solver object. This kind of objects store internally the state of the solver and you can advance the solution step-by-step until, eventually, the desired value of t is reached.
An ODE solver allows users to obtain a numerical solution of an Ordinary Differential Equation (ODE) system. The ODE solver lets you solve the general n-dimensional first-order system,
for . The stepping functions rely on the
vector of derivatives
and the Jacobian matrix,
Here an examples about the usage of an ODE solver for real numbers. The differential equation that we want integrate is:
and here the code that we can write to implement it:
-- define the ODE function
odef = function(t, y, f)
f:set(1,1, -y[2]-y[1]^2)
f:set(2,1, 2*y[1] - y[2]^3)
end
-- create the ODE solver
s = ode {f = odef, n= 2, eps_abs= 1e-6}
-- we define initial values
t0, t1, tstep = 0, 30, 0.04
y0 = vector {1, 1}
-- the ODE solver is iterated till the time t1 is reached
for t, y in s:iter(t0, y0, t1, tstep) do
print(t, tr(y))
end
In anternative you may want to make a plot of the curve that you obtain. Here an example, we create a “path” to describe the curve that we want to plot and then we iterate with the ODE solver and we add all the points with the “line_to” method. The we create an empy plot and we add the line that we have just created:
-- we create a line and add the points obtained by integrating the ODE
ln = path(y0[1], y0[2])
for t, y in s:iter(t0, y0, t1, tstep) do
ln:line_to(y[1], y[2])
end
-- we create the plot by adding the line
local p = plot('ODE integration example')
p:addline(ln)
p:show()
And here the plot that you will obtain:
Curve obtained by integration of the above ODE system.
We present also a simple example with complex numbers. In this example we show also how to use the bsimp integration method that requires the derivatives of the ODE system function. Here the code:
t0, t1, tstep = 0, 30, 0.05
alpha = 1i - 0.08
z0 = 1.0 + 0.0i
odef = function(t, z, f)
f:set(1,1, alpha * z[1])
end
odedf = function(t,y,dfdy,dfdt)
dfdy:set(1,1, alpha)
null(dfdt)
end
s = code {f= odef, df= odedf, n= 1, method='bsimp'}
ln = path(real(z0), imag(z0))
for t, z in s:iter(t0, cvector {z0}, t1, tstep) do
ln:line_to(real(z[1]), imag(z[1]))
end
p = plot('Spiral by complex ODE integration')
p:addline(ln)
p:show()
-- in the following example we add the points that we would obtain
-- by not giving a fixed "step"
ln = path(real(z0), imag(z0))
for t, z in solver:iter(t0, cvector {z0}, t1) do
ln:line_to(real(z[1]), imag(z[1]))
end
p:add(ln, 'black', {{'marker', size=5}})
Solver of ODE system.
Create a new solver for an ODE system. The spec should be a table containing the following fields:
The low-level integration method used. Can be choosed between:
Provides an iterators that can be used in a for loop. The iterators returns the couple (t, y) at each step and terminate when t1 is reached.
The method iter() is defined with the following function:
function ode_iter(s, t0, y0, t1, tstep)
s:set(t0, y0)
return function()
local t, y = s.t, s.y
if t < t1 then
s:evolve(t1, tstep)
return t, y
end
end
end