I have a vector x
of length N and I want to use its values for solving the differential equation: dy/dt = x - 4*y
. For each step I want the ode solver function to use one value of the vector and then use the next value of the matrix for the next step.
I tried doing so by declaring the vector a global variable and use it like this inside the ode solver:
global x
tspan = 0:0.01:10;
[t,filter_coef] = ode45(@ode_filter,tspan,0);
and the solving function like this:
function dx = ode_filter(t,fil)
global x
dx = x - 4*fil(1);
end
Following error was produced
ODE_FILTER returns a vector of length 1002, but the length of initial conditions vector is 1. The vector returned by
ODE_FILTER and the initial conditions vector must have the same number of elements.
You might be basing your approach on your understanding of the explicit Euler method. If that is the case you would be best served by implementing the (exponential) explicit Euler method.
The solver ode45
, as all of the other matlab ODE solvers (without specific options?) has variable step size which is automatically adapted to the problem and the current state. Additionally, during each step the passed right side ODE function is evaluated multiple times. Further, the step size regulator depends on the smoothness to a high order of the right side function, non-smooth loci lead to a drastic reduction in step size and possibly multiple restarts from the same current state, further contradicting your assumptions.
Thus, even if you succeed in implementing your idea, you are adding essentially random noise to your function, rendering the solver useless as basic assumptions are violated. Even if a result is produced, it will have almost nothing to do with what you wanted to achieve.
The fastest way to achieve something like what you want to produce is to identify the times at to which the x
values are associated and use some interpolation function, zero order hold or linear interpolation, to get the correct value at variable times.
Use solution extension to solve every segment using a smooth right side, changing the constant x(k)
for each segment [ tx(k), tx(k+1) ]
. Define the function to have a parameter, avoiding the hassle of global
variables
function dy = ode_filter(t,y,x)
dy = x - 4*y;
end
then call the integrator for the first segment to initialize and then for all the remaining segments using their constant and the segment end.
sol = ode45(@(t,y)ode_filter(t,y,x(1)), [ tx(1) tx(2) ], y0)
for k in 2:N
sol = odextend(sol,@(t,y)ode_filter(t,y,x(k)),tx(k+1));
end
(Always think about using the options mechanism to set costumized, problem specific error tolerances.)
![](https://www.manongdao.com/static/images/pcload.jpg)
y
is a function of t
, not function of x
.
From the above equation unless you define x
value first, y
will be a
function of t
and x
.
Also ode45
return only double values, not the function y itself
but it's evaluation at different t
What can be done is defining a function that throws a given unknown
value x
to ode45
. Then you get the function I deduct above.
Next Just set a given x
and evaluate the function. The function
evaluation gives structure data type which main fields are x
and y
. x
is your t
and y remains your y
global x
tspan = 0:0.01:10;
f = @(x)ode45(@ode_filter, tspan,0);
%% Set x Value First
x = 2;
var = f(x);
t = var.x;
y = var.y;