I have a function with the handle #func with initial condition y0 that I want to test over t = [0, tspan]. What, exactly, do I need to do to increase the number of time steps ode45 uses, without changing tspan?
I saw the MATLAB documentation of ode45 and saw that I need to somehow change the options input to ode45. However, I do not really understand how to do this because no example code was provided.
You need to look at odeset which creates an options structure to be used in ODE solvers, like ode45. You're looking at changing the MaxStep parameter.
The documentation for this (MATLAB R2015a) says:
MaxStep - Upper bound on step size [ positive scalar ]
MaxStep defaults to one-tenth of the tspan interval in all solvers.
Therefore, you can make it something smaller than 0.1*tspan... something like 1e-6 or something like that. This depends on what tspan is, so you'll need to make it smaller than 0.1*tspan if you want to increase the total number of time steps / output points.
As such, create an odeset structure and override the MaxStep parameter. The rest of the values will remain as default:
options = odeset('MaxStep', 1e-6);
Now that you're done, call ode45 on your problem:
[tout,yout] = ode45(#func, tspan, y0, options);
Simply play around with the MaxStep until you get the desired granularity.
Minor Note
Though a bit buried, the documentation does tell you on how to change the options. This is the section that talks about how to call ode45 with options. Please take note of what is highlighted in bold. This is the documentation for MATLAB R2015a:
[TOUT,YOUT] = ode45(ODEFUN,TSPAN,Y0,OPTIONS) solves as above with default
integration properties replaced by values in OPTIONS, an argument created
with the ODESET function. See ODESET for details. Commonly used options
are scalar relative error tolerance 'RelTol' (1e-3 by default) and vector
of absolute error tolerances 'AbsTol' (all components 1e-6 by default).
If certain components of the solution must be non-negative, use
ODESET to set the 'NonNegative' property to the indices of these
components.
Related
I would like to solve the following optimization problem with Matlab: minimize f(t) when t >= 0.
There's fseminf function but i didn't understand well how to apply it to my case. Also it seems a bit overkill to use such a powerful tool for such a seemingly easy problem. I'll be grateful for any tips on how to apply fseminf here and any suggestions how else it can be solved.
Matlab is a numerical software so one 'simple' way to solve this problem is to calculate the value of f(t) for values of t>0 and then find the minimum of that. Depending on the function the number of ts that you want to evaluate might be smaller or larger.
One possible solution could be:
t = 0:0.001:10; % create values from 0 to 10 in steps of 0.001
f = t.^3+5; % evaluate the function for each value of 't'
[minF, locT] = min(f);
minF % this is the smallest value of the function
t(locT) % the minimum value occurred at this 't'
You should define t to be in the region where you expect the minimum to, if you define it wrong this would only find the local minimum. If the spacing between separate 't's is too large the minimum might also fall between them, that is why I choose a relatively small step of '0.001'.
I used ode45 and ode23 for a set of non-stiff differential equations. However, both methods converge to a slightly different solution. How can I find out which one is correct? See attached plot where blue is ode45, red is ode23. The dashed lines are the final values for each solver. Also, ode15s is a bit different (less than 1 m)...
Matlab's ODE solvers are adaptive so one specifies tolerances rather than a step size (see also this answer). Given the code in the PDF linked in the comments, if you specify a smaller value for the relative tolerance, the solutions from ode45 and ode23 will converge after the same amount of time. You can use odeset to set 'RelTol':
...
opts = odeset('RelTol', 1e-12);
[t, oput] = ode23(#(t,y)secondode(t,y,C,g), tspan, IC, opts);
...
Note that I also got rid of the global variables used in the linked code (they're bad and inefficient). You also need to change the function definition for secondode to:
function z = secondode(t, indata, C, g)
...
I need to numerically integrate the following system of ODEs:
dA/dR = f(R,A,B)
dB/dR = g(R,A,B)
I'm solving the ODEs for a Initial-value stability problem. In this problem, the system is initially stable but goes unstable at some radius. However, whilst stable, I don't want the amplitude to decay away from the starting value (to O(10^-5) for example) as this is non-physical since the system's stability is limited to the background noise amplitude. The amplitude should remain at the starting value of 1 until the system destabilises. Hence, I want to overwrite the derivative estimate to zero whenever it is negative.
I've written some 4th order Runge-Kutta code that achieves this, but I'd much prefer to simply pass ODE45 (or any of the built in solvers) a parameter to make it overwrite the derivative whenever it is negative. Is this possible?
A simple, fast, efficient way to implement this is via the max function. For example, if you want to make sure all of your derivatives remain non-negative, in your integration function:
function ydot = f(x,y)
ydot(1) = ...
ydot(2) = ...
...
ydot = max(ydot,0);
Note that this is not the same thing as the output states returned by ode45 remaining non-negative. The above should ensure that your state variables never decay.
Note, however, that that this effectively makes your integration function stiff. You might consider using a solver like ode15s instead, or at least confirming that the results are consistent with those from ode45. Alternatively, you could use a continuous sigmoid function, instead of the discontinuous, step-like max. This is partly a modeling decision.
I'm using fminunc. Specifically, I'm using a quasi-newton method with BFGS and a user supplied gradient to minimize a function. It goes for about 3 iterations, then does a bunch of function evaluations. I have the function I am trying to minimize display its value when it is called, and I can see that after a few calls on the 4th iteration it is significantly smaller than it was on the third iteration, but Matlab continues to evaluate the function and I'm not sure why. Is there something I can adjust to tell it to accept the update and move to the next iteration?
Sounds like you understand the optimizer pretty well, let's see if we can help with the optimset settings. From the mathworks docs it calls out how to relax the tolerances to terminate the optimization with the following parameters:
TolFun Termination tolerance on the function value, a positive scalar. The
default is 1e-6.
TolX Termination tolerance on x, a positive scalar. The default value is
1e-6.
Sounds like you have the Optimization Toolbox, in which case I believe you can use optimset to get the optimization parameters and then use the fminunc to initialize it.(The docs for the regular optimset don't call out that you can pass the fminunc as an argument, but I would think it would work for the toolbox version.
options = optimset('fminunc');
% you can try either of these two or both, but I would
% recommend only changing one at a time :-)
options = optimset(options,'TolFun',myNewTolFun)
options = optimset(options,'TolX',myNewTolX)
% then you can make your call to the optimizer
x = fminunc(fun,x0,options)
Excruciating detail on the optim-settings can be found here.
I am using ode45 and I can't figure out what to do in this case. I have a differential equation where my paramters change very quickly with time. Ideally, I would like to choose tspan to be like 0:epsilon:10*epsilon where epsilon is of an appropriately small order considering whatever I have in the factors of my DE. However, this does not work and MATLAB simply gives me a plot where nothing changes from my initial conditions.
I did the obvious thing to fix it which was the following. Say I have xdot(t)=10^9*x(t). I rewrite it as xdot(t)=x(t) and label my time axis as nanoseconds instead of seconds.
Just curious if MATLAB can do this on its own.
You can set a maximum time step using ODE options.
opt = odeset('MaxStep',epsilon)
[t,y] = ode45(odeFun,tSpan,y0,opt)
To get an idea of all the options that you can change when customizing an ODE solver look at docsearch odeset.