I have an ordinary differential equation (ODE) -- Van Der Pol oscillator Problem:
y\'\'-2a (1-y^2)y\'+y=0,
y(0)=0, y\'(0)=0.5, x in [0,10], a =0.025.
Th
The way to find a numerical solution in matlab is to define
a=0.025;
VDP_ODE = @(t,u) [ u(2), -u(1)+2*a*u(2)*(1-u(1)^2) ]; % u = [ y, z ]
(or define it using the full function
declaration) and call this with a numerical solver
h=0.1;
t = 0:h:10;
y0 = 0; z0 = 0.5;
u0 = [y0, z0 ];
[t,u] = ode45(VDP_ODE, t, u0);
figure(1); plot(t,u(:,1));
figure(2); plot(u(:,1),u(:,2));
If you want to build your own solver, you should first understand the method. It seems that it is a 4th order method similar but not exactly equal to a linear multi-step method, like the Beeman-Schofield methods introduced to compute molecular dynamics.
The input to each step are the values y(n), y(n+1)
, the output reduces to y(n+2)
with no other values taken over to the next step. Inside the method step additional values are computed for y(n+3/2)
and derivatives z
at all sample times t(n), t(n+1), t(n+3/2), t(n+2)
. The aim is to get floating point results, thus it makes no sense to define the equations symbolically, thus adapt the system to the interface of fsolve
.
The system that is solved in the Maple code can be simplified by observing that there are 6 equations, thus 6 unknown parameters. The method is based on a 5th degree polynomial with 6 coefficients as unknowns which interpolates the values, first and second derivatives of the solution. This gives 2 equations for the given values y0,y1
and 4 equations for the exact satisfaction of the differential equation at the interpolation points.
Y = [ y0, step0(y0,z0) ]
for n=1:N-2
Y(n+2,:)=stepN(Y(n,:), Y(n+1,:), h)
end
and for the step of the method do something like
%%%% ======== General step ========
%% fit a degree 5 polynomial to values, 1st and 2nd derivatives
%% at t0, t1, t1h=t1+0.5*h, t2
%% p(s) = sum c_k s^k/k!, c0=y1, y(t1+s) ~ p(s)
%% eqn y0 = p(-h)
%% def z0 = p'(-h)
%% eqn f(y0,z0) = p''(-h)
%% def z1 = p'(0)
%% eqn f(y1,z1) = p''(0)
%% eqn y2 = p(h), etc
%%
%% state vector for non-lin solver is u = [y2, c1, c2, ...c5 ]
function y2 = stepN(y0,y1,h)
zz = (y1-y0)/h;
predict = [ y1+h*zz, zz, f(y1,zz), 0, 0, 0];
options = optimset("TolX", 1e-1*h^6, "TolFun", 1e-2*h^6);
u = fsolve(@(u) systemN(u,[y0,y1], h), predict, options);
y2 = u(1);
end
which set some predictor values (only O(h) exact), sets the tolerances for the solver so that the solver error is hopefully smaller than the discretization error which is O(h^6)
, calls the solver end extracts the wanted value from the solution array.
For the system to solve the function first extracts the constants and variables into named variables for better readability, computes the function values at the given point and then returns the array of the defects in the discretized equations.
function eqn = systemN(u,init,h)
[ y0, y1 ] = num2cell(init){:};
[ y2, c1, c2, c3, c4, c5 ] = num2cell(u){:};
p = @(h) y1 + h*(c1+h/2*(c2+h/3*(c3+h/4*(c4+h/5*c5))));
dp = @(h) c1+h*(c2+h/2*(c3+h/3*(c4+h/4*c5)));
d2p = @(h) c2+h*(c3+h/2*(c4+h/3*c5));
z0 = dp(-h); z1 = c1;
y1h = p(0.5*h); z1h = dp(0.5*h);
z2 = dp(h);
eqn = [ y2-p(h),
y0-p(-h),
f(y0,z0)-d2p(-h),
f(y1,z1)-c2,
f(y1h,z1h)-d2p(0.5*h),
f(y2,z2)-d2p(h) ];
end