Simple question about creating an anonymous function,

7 views (last 30 days)
Hi there!
Using a Matlab function file, I wrote an ode model model(t, z, p), where p stores all of my physical parameters, such as p.mass, p.volume, p.area, etc. Now, when I go to solve it with ode45, I first create an anonymous function for the above model, by writing the code:
myrhs = @(t, z) model(t,z,p)
Then use myrhs as input into ode45, along with initial conditions.
However, how come I don't write:
myrhs = @(t, z, p) model(t, z, p)
?
Why do we drop the parameter table, p, from the @( ) expression?
Is @(t, z) about specifying outputs time t and state z?
Or is @(t, z) about specifying inputs to the model, current time t and current state z?
I'm a little confused.
If it's about specifying inputs, then I would imagine we should write @(t, z,p), not just @(t, z).
Thanks!

Accepted Answer

Steven Lord
Steven Lord on 20 Oct 2024
The ode45 function requires the function handle you specify as the first input to accept two input arguments and return an output argument. See the description of the odefun input argument.
Your function, as you've defined it, requires three inputs to run: t, y, and p. So you can't just pass a function handle to it into ode45 as the first input; the signatures ode45 requires and your function requires are not compatible.
So you can use an anonymous function as an "adapter". It accepts two inputs (like ode45 requires) and calls your function with three inputs (like it requires.)
So where does p with which the anonymous function calls your function come from? The anonymous function "remembers" it from when the anonymous function was created. See the "Variables in the Expression" section on this documentation page for a brief explanation.
  4 Comments
Steven Lord
Steven Lord on 21 Oct 2024
That's correct. The anonymous function A1 "remembers" A2, in much the same way that an anonymous function @(x) x.^n would "remember" the value of n.
For diagnostic and debugging purposes you can see what A1 "remembers" using the functions function. [This is read-only, you cannot change the anonymous function this way, and I strongly agree with the Note on the documentation page that cautions you not try to use this as a part of the normal programmatic workflow of your code.]
A2 = @(x) x*2;
n = 2;
A1 = @(x) n*A2(x);
info = functions(A1)
info = struct with fields:
function: '@(x)n*A2(x)' type: 'anonymous' file: '/tmp/Editor_ydlah/LiveEditorEvaluationHelperEeditorId.m' within_file_path: '' workspace: {[1x1 struct]}
ws = info.workspace{1}
ws = struct with fields:
n: 2 A2: @(x)x*2
Paul
Paul on 21 Oct 2024
Edited: Paul on 21 Oct 2024
Hi Steve,
Are you able and willing to discuss that design choice as to how A1 treats A2?
If A2 were an m-function and A2.m changes (or is perhaps even deleted) after A1 is defined, then A1 would (I assume) always execute in terms of how A2 is implemented at the time of A1 invocation, as would be the case for any other m-function called from within another m-function.
For some time my mental model of an anonymous function was that it is alternate and interchangeable with a same-named m-function with the same implementation. But that's not the case here. Do you know of any other cases where anonymous A2 is not A&I with A2.m ?

Sign in to comment.

More Answers (1)

Umar
Umar on 20 Oct 2024

Hi @Noob,

In MATLAB, when you create an anonymous function like myrhs = @(t, z) model(t, z, p), you are indeed specifying the inputs to the model, which are the current time t and the current state z. The parameter structure p is not included in the anonymous function because it is treated as a constant or fixed parameter that does not change during the integration process. The ode45 solver calls myrhs multiple times during its execution, passing different values of t and z while keeping p constant. This is a common practice in MATLAB to simplify the function signature when the parameters do not vary. If you were to include p in the anonymous function, it would imply that p could change with each call, which is not the case here. Thus, the correct interpretation is that @(t, z) specifies the inputs to the model, allowing ode45 to efficiently compute the solution while treating p as a fixed parameter. Here is a simple example for clarity:

function dzdt = model(t, z, p)
  dzdt = p.mass * z; % Example equation
end
p.mass = 5; % Example parameter
myrhs = @(t, z) model(t, z, p); % Anonymous function without p
[t, z] = ode45(myrhs, [0 10], initial_conditions);

In this example, p is fixed, and myrhs only needs t and z as inputs.

Hope this helps.

Products


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!