MATLAB Answers

Nshine
0

ode45 varargin - additional arguments after options

Asked by Nshine
on 28 Jun 2019
Latest activity Commented on by Nshine
on 30 Jun 2019
Hi.
I'm looking at some code which calls ode45 using the following code:
[t_intermediate,x_intermediate] = ode45(system,[t0, t0+T], x0, options, u);
wheer the function system is defined as
function y = system(t, x, u, T)
y = x+u;
end
I am confused about the additional last argument 'u' of the call to ode45, and how this feeds into the solver. The documentation doesnt list any arguments after options, but opening the code I can see it accepts additional arguments through varargin, but I cant find any information about how 'u' would fit into this. Within the ode45 code, It looks like the varargin are processed in the function "odearguments", but there is no documentation on this function either.
In this example, 'u' is a control input into the system.
Thanks for the help in advance!

  4 Comments

Show 1 older comment
Thanks Torsten
I know that what you suggest is the 'normal' way to call ode45 when you want to include additional parameters in odefun. I'm curious why the prgrammer has chosen a different 'non-standard' and apparently undocumented way to achieve the same result?
Because this was the 'normal' way in former MATLAB days.
That code would have failed.
ode45(system,....)
would have called system with no arguments and expected it to return a function handle. The call would fail due to not enough inputs.

Sign in to comment.

1 Answer

Answer by John D'Errico
on 28 Jun 2019
Edited by John D'Errico
on 28 Jun 2019
 Accepted Answer

Long ago and far away, in an age long since past, MATLAB did not have function handles. There were no anonymous functions. There were no nested functions.
So the writers of MATLAB came up with a way to pass in arguments through functions like ODE45, like FMINSEARCH and FMINCON, etc. This was because all of these functions sometimes need to allow extra arguments to be passed in, essentially through those tools.
The idea was that if your function has "extra" arguments beyond those expected, then they are added as extra arguments to the optimizer or the ODE solver. Then the solver is smart enough to attach them to the function call itself when that call is done internally. It worked, but it was a programming kludge, and a massive one. It was confusing to users. To be honest, global variables were a better solution, and I hate global variables.
So at some point, the powers at MATLAB realized that this was indeed a bad idea. So, for years they warned us users that the option would be "removed" from those tools, but they had by then provided us with function handles, with nested functions. They had provided us with better ways to solve the problem.
At some point, they removed the option from the documentation for those functions, although I think it still worked for some years, so that legacy code would not fail. Without testing some code, a quick scan through the code for fminsearch suggests that it still (in R2019a) allows that legacy form of call for extra arguments, although I saw nothing in the help that said it was legal. I also just scanned the code for ODE45, and it too looks like it is allowed as a hidden option. Without testing, I would not state this to be true though.
You must remember that it is important that legacy code should generally work, if at all possible. I have code that is now over 30 years old, code that still works nicely. Unfortunately, that means sometimes people who never saw this capability will not know it ever existed. And some people like you will be confused when looking at legacy code, perhaps written by a MATLAB neanderthal like me.

  2 Comments

The idea was that if your function has "extra" arguments beyond those expected, then they are added as extra arguments to the optimizer or the ODE solver.
It was even more confusing than that. When you call an ODE solver you must pass in your ODE function but you can also pass in Events functions, OutputFcn functions, etc. via the options structure.
If you used that very old syntax (which we stopped documenting about 15 years ago when we introduced anonymous functions in release R14[*]) all those functions that you specified had to accept all those additional inputs even if only one of your functions used them. Using anonymous functions or one of the other techniques for parameterizing functions avoids that particular issue; you can pass additional parameters into just the functions that require them.
[*] No, I don't mean release R2014a or R2014b. Release R14 predates the Ryear{a,b} release naming convention. I mean the release that came out in June 2004.
Thanks for that clear answer. Its so helpful and fascinating to know some of the history of the development of Matlab.

Sign in to comment.