Passing a defined function to ODE solver - matlab

I have defined a function
function dy = toggle(t,y,p)
dy = zeros(2,1);
dy(1) = - y(1) + p(1)./(1+y(2).^p(2));
dy(2) = - y(2) + p(1)./(1+y(1).^p(3));
and saved it in an .m file with the same name as the function. In another file, caltoggle.m, I write:
[T,Y] = ode45(#toggle,[0 100],[0.2,0.1],[],[3,2,2]);
When I run the script caltoggle.m I get the error:
??? [T,Y] = ode45(#
|
Missing variable or function.
Error in ==> C:\MATLABR11\work\caltoggle.m
On line 1 ==>
caltoggle
The above code is an example from a tutorial so should be right. My problem is in general I am not able to call a defined function.

If the other file is not in the same directory, you should add the directory to the path.
Try to write in Matlab:
pathtool
Also, though it is probably not your case, if you name a file with a reserved word like "try", it can cause havoc.
Also, try to write
which toggle
it might be insightful.

In the Matlab documentation for the ODE solvers all of the examples pass as the first argument to ode45 a function of 2 variables, not three like your function toggle. Can you change your toggle function to accept only two input arguments and see if that fixes the problem (as a first test just set p(:)=1 or something similar)

Related

Undefined 'VARIABLE' error while defining a function in Octave [duplicate]

I got a problem with running Octave function (ODE), I've tried already present solutions for this problem but nothing is working. I've also tried by saving my filename as egzamin.m but it too not worked.
Code from octave :
function dx=egzamin(x,t)
dx=zeros(4,1);
b=0;
g=9.81;
x1=x(1);
y1=x(2);
Vx=x(3);
Vy=x(4);
dx(1)=Vx;
dx(2)=Vy;
dx(3)=-b*Vx*sqrt(Vx.^2+Vy.^2);
dx(4)=-b*Vy*sqrt(Vx.^2+Vy.^2)-g;
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
The error is :
error: 'x' undefined near line 5 column 4
error: called from
egzamin at line 5 column 3
Since the file starts with function, it is not a script file,
as explained in the doc:
Unlike a function file, a script file must not begin with the keyword
function
Add any statement (even dummy like 1;) before the function line to get a script file.
# dummy statement to get a script file instead of a function file
1;
function dx=egzamin(x,t)
g = 9.81;
Vx = x(3);
Vy = x(4);
dx = [Vx, Vy, 0, -g];
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
A very clear explanation of what's going on is given here.
You need to save the function (thus from function to endfunction and naught else) as egzamin.m, and then execute the rest of the code in a script or at the command line. Alternatively, provided Octave does that the same as what MATLAB does nowadays, first put your script (N=(..) to plot()) and then the function.
This is necessary since you are defining your function first, so it doesn't have any inputs yet, as you don't define them until later. The function needs to have its inputs defined before it executes, hence you need to save your function separately.
You can of course save your "script" bit, thus everything which is currently below your function declaration, as a function as well, simply don't give it in- and outputs, or, set all the input parameters here as well. (Which I wouldn't do as it's the same as your
egzamin then.) e.g.
function []=MyFunc()
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
endfunction

What is a good substitute for matlabFunction?

I wrote a small program in MATLAB to compute the Shapley value
using the multi-linear extension of a TU game. However, I run
into trouble with the Symbolic Math Toolbox of MATLAB. In
the program I have to integrate a set of functions to get the
Shapley value. However, inside a MATLAB program I cannot use
the int() command
Error using sym/subsindex (line 663) Ivalid indexing or function definition. When defining a function, ensure that the body of the function is a SYM object. When indexing, the input must be numeric, logical or ':'.
Error in ShapleyValueML (line 65)shv(jj)=int(dfy,0,1)
as a consequence I have to use integral() instead. In this case, I
need to transcribe the set of expressions into MATLAB function handle
with matlabFunction(). However, on all Linux machines (MATLAB R2014a) on
which I have access this command does not work (see the discussion below).
As a workaround, the MATLAB program returns the set of functions
into the current workspace, there the Shapley value can be computed
using the int() command.
To make the discussion more concrete, let us consider this small
MATLAB program first.
function [shv,F,dfm]=ShapleyValueML(v)
N=length(v);
[~, n]=log2(N);
S=1:N;
int=0:-1:1-n;
mat=(rem(floor(S(:)*pow2(int)),2)==1);
cmat=(rem(floor(S(:)*pow2(int)),2)==0);
x=sym('x',[1 n]);
mx=1-x;
y = sym('y');
vy=ones(1,n)*y;
F=0;
shv=zeros(1,n);
dfm=cell(1,n);
for ss=1:N
pd1=x(mat(ss,:));
pd2=mx(cmat(ss,:));
pd=prod(pd1)*prod(pd2)*v(ss);
F=pd+F;
end
F=expand(F);
for jj=1:n
dF=diff(F,x(jj));
dfy=subs(dF,x,vy);
%% Does not work!! MATLAB bug???
% mf=matlabFunction(dfy);
% shv(jj)=integral(mf,0,1);
%%
%% The best would be to use:
%%
% shv(jj)=int(dfy,0,1)
%% but it cannot be used inside a program.
dfm{jj}=dfy;
end
end
The commented parts are the parts that do not work inside
the program, but are needed to compute the Shapley value
with that program, which is its purpose. I tested this program
up to 12 players, and I was able to successfully calculate the
Shapley value by a two step procedure. Hence, the above program
specifies correctly the considered problem. To get a better
understanding of this two step procedure and of the functionality
of the above program, let us focus on a three person game.
The values of the coalitions are given by the following data array
>> v = [0,0,90,0,100,120,220];
Notice that coalitions are ordered in accordance with their unique
integer representations. The game is defined, we can now evaluate
the multi-linear extension and the set of partial derivatives with
the above program, but not the Shapley value.
>> [shv,F,dfm]=ShapleyValueML(v);
Integration of the set of partial derivatives runs over the diagonal
of the unit-cube, but then we can set the variables from [x1,x2,x3]
to [y,y,y], and integration runs from 0 to 1.
>> for k=1:3, shv(k)=int(dfm{k},0,1);end;
The solution of the integration is the Shapley value given by:
>> shv
shv =
65 75 80
Checking that this is indeed the Shapley value can be accomplished
with a potential function approach implemented in
>> sh_v=ShapleyValue(v)
sh_v =
65 75 80
that ships with my MATLAB Game Theory Toolbox MatTuGames from
http://www.mathworks.com/matlabcentral/fileexchange/35933-mattugames
Instead of integrating with int() one can also use integral(),
but then the contents like
>> dfm{1}
ans =
- 90*y^2 + 190*y
must be rewritten with matlabFunction() into a function handle. As I
have mentioned above this does not work under Linux
(MATLAB R2013a,R2013b,R2014a). To see this let us try to reproduce
the example
>> syms x y
>> r = sqrt(x^2 + y^2);
from the documentation at the URL:
http://www.mathworks.de/de/help/symbolic/generate-matlab-functions.html?searchHighlight=matlabFunction
This should give
ht =
#(x,y)tanh(sqrt(x.^2+y.^2))
but I get
>> ht = matlabFunction(tanh(r))
Cell contents reference from a non-cell array object.
Error in vectorize (line 15)
c = cells{i};
Error in sym/matlabFunction>mup2mat (line 319)
res = vectorize(res(2:end-1)); % remove quotes
Error in sym/matlabFunction>mup2matcell (line 304)
r = mup2mat(c{1});
Error in sym/matlabFunction (line 123)
body = mup2matcell(funs);
Here comes now my question: Exists there an alternative procedure to
get from
>> dfm{1}
ans =
- 90*y^2 + 190*y
a function handle
>> df=#(y) (- 90.*y.^2 + 190.*y)
df =
#(y)(-90.*y.^2+190.*y)
to integrate it by
>> integral(df,0,1)
ans =
65
Or to put it differently. Is there an alternative method available to
change multiplication * to element-wise multiplication .*, and the
power operation ^ to element-wise power.^?
Of course, any suggestions of improvement for the above MATLAB program
are highly appreciated.
I think I know what the problem is; Towards the beginning of ShapleyValueML function, you have a variable named int which shadows the builtin integration function:
...
int=0:-1:1-n; %# <-- problem!
...
shv(jj)=int(dfy,0,1)
...
That explains the error coming from sym/subsindex, you were using a symbolic object as an index into the numeric array int.
Change the variable name to something else, and the commented code runs fine (the symbolic integration)! Simple as that :)

MATLAB Using fzero - returns error

I'm trying to use the MATLAB function fzero properly but my program keeps returning an error message. This is my code (made up of two m-files):
friction_zero.m
function fric_zero = friction_zero(reynolds)
fric_zero = 0.25*power(log10(5.74/(power(reynolds,0.9))),-2);
flow.m
function f = flow(fric)
f = 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(power(10,4));
z = fzero(#flow,f_initial)
The goal is to return z as the root for the equation specified by f when flow.m is run.
I believe I have the correct syntax as I have spent a couple of hours online looking at examples. What happens is that it returns the following error message:
"Undefined function or variable 'fric'."
(Of course it's undefined, it's the variable I'm trying to solve!)
Can someone point out to me what I've done wrong? Thanks
EDIT
Thanks to all who helped! You have assisted me to eventually figure out my problem.
I had to add another file. Here is a full summary of the completed code with output.
friction_zero.m
function fric_zero = friction_zero(re)
fric_zero = 0.25*power(log10(5.74/(power(re,0.9))),-2); %starting value for fric
flow.m
function z = flow(fric)
re = power(10,4);
z = 1/(sqrt(fric))-1.873*log10(re*sqrt(fric))-233/((re*sqrt(fric))^0.9)-0.2361;
flow2.m
f_initial = friction_zero(re); %arbitrary starting value (Reynolds)
x = #flow;
fric_root = fzero(x,f_initial)
This returns an output of:
fric_root = 0.0235
Which seems to be the correct answer (phew!)
I realised that (1) I didn't define reynolds (which is now just re) in the right place, and (2) I was trying to do too much and thus skipped out on the line x = #flow;, for some reason when I added the extra line in, MATLAB stopped complaining. Not sure why it wouldn't have just taken #flow straight into fzero().
Once again, thanks :)
You need to make sure that f is a function in your code. This is simply an expression with reynolds being a constant when it isn't defined. As such, wrap this as an anonymous function with fric as the input variable. Also, you need to make sure the output variable from your function is z, not f. Since you're solving for fric, you don't need to specify this as the input variable into flow. Also, you need to specify f as the input into fzero, not flow. flow is the name of your main function. In addition, reynolds in flow is not defined, so I'm going to assume that it's the same as what you specified to friction_zero. With these edits, try doing this:
function z = flow()
reynolds = power(10,4);
f = #(fric) 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(reynolds);
z = fzero(#f, f_initial); %// You're solving for `f`, not flow. flow is your function name
The reason that you have a problem is because flow is called without argument I think. You should read a little more about matlab functions. By the way, reynolds is not defined either.
I am afraid I cannot help you completely since I have not been doing fluid mechanics. However, I can tell you about functions.
A matlab function definition looks something like this:
function x0 = f(xGuess)
a = 2;
fcn =#(t) a*t.^3+t; % t must not be an input to f.
disp(fcn);
a = 3;
disp(fcn);
x0 = fsolve(fcn1,xGuess); % x0 is calculated here
The function can then ne called as myX0 = f(myGuess). When you define a matlab function with arguments and return values, you must tell matlab what to do with them. Matlab cannot guess that. In this function you tell matlab to use xGuess as an initial guess to fsolve, when solving the anonymous function fcn. Notice also that matlab does not assume that an undefined variable is an independent variable. You need to tell matlab that now I want to create an anonymous function fcn which have an independent variable t.
Observation 1: I use .^. This is since the function will take an argument an evaluate it and this argument can also be a vector. In this particulat case I want pointwise evaluation. This is not really necessary when using fsolve but it is good practice if f is not a matrix equation, since "vectorization" is often used in matlab.
Observation 2: notice that even if a changes its value the function does not change. This is since matlab passes the value of a variable when defining a function and not the variable itself. A c programmer would say that a variable is passed by its value and not by a pointer. This means that fcn is really defined as fcn = #(x) 2*t.^3+t;. Using the variable a is just a conveniance (constants can may also be complicated to find, but when found they are just a value).
Armed with this knowledge, you should be able to tackle the problem in front of you. Also, the recursive call to flow in your function will eventuallt cause a crash. When you write a function that calls itself like this you must have a stopping criterium, something to tell the program when to stop. As it is now, flow will call ifself in the last row, like z = fzero(#flow,f_initial) for 500 times and then crash. Alos it is possible as well to define functions with zero inputs:
function plancksConstant = h()
plancksConstant = 6.62606957e−34;
Where the call h or h() will return Plancks constant.
Good luck!

MATLAB symbolic variables couldn't be used in nested function

I have a MATLAB function to solve a Inertia Tensor , and I have a nested function in my program . All the variables in it are symbolics but it told me
“Error using assignin: Attempt to add ”x“ to a static workspace”
and I don't understand why this happens . Here is my test.m code:
function test
syms x y z
f=x
f1=f+1
f2=f1^2
function r=test2
r=f2^3;
end
f3=test2
end
After searching this web-forum I have found some answers . But at the same time I just don't understand it
Andrew Janke explianed it like this : While syms A may look like a static variable declaration, it isn't. It's just a regular function call. It's using Matlab's "command" invocation style to look like syntax, but it's really equivalent to syms('a', 'b', 'c').
on this page : Matlab: "Error using assignin: Attempt to add "c" to a static workspace"
what does static variable mean ?
I also search the HELP doc and it said :In functions and scripts, do not use syms to create symbolic variables with the same names as MATLAB® functions. For these names MATLAB does not create symbolic variables, but keeps the names assigned to the functions.
I only know syms x to create a symbolic variable in the workspace but why does the documentation say MATLAB does not create ?
'Static' means fixed, 'workspace' is what Matlab calls the places where all of its variables are stored. For non-nested functions the workspace starts off as empty when Matlab is at the beginning of the function; as Matlab continues through function's lines of code it continuously add more variables to the workspace.
For functions with a nested function, Matlab first parses the function to see what variable will be created (it specifically looks for x = type lines), then it creates all of these variables (with value as 'unassigned'), and then only does it start to run through the code; but while running through the code, it can never create a new variable.
This is why the code
function TestNestedFunction
syms x;
function Nested()
end
end
generates an error, there is no x = to tell it to pre-create the unassigned variable x at the start of the code. It fails at syms x;, as that line tries to create a new variable x, which fails as it may not.
This is also why the following code runs
function TestNestedFunction
syms x;
x = x;
function Nested()
end
end
it sees the x = and then pre-creates x. (This is why your example of adding [x, y, z] = deal([]); also works).
You can test this with a break point at the beginning of simple non-nested function and a simple nested function. Just run it step by step.
This code works:
function test
x=sym('x')
y=sym('y')
z=sym('z')
f=x
f1=f+1
f2=f1^2
function r=test2
r=f2^3;
end
f3=test2
end
I think the pages you found are quite clear.
You need to declare the variables one by one and use:
x = sym('x')
Otherwise syms will try to assign the values into a workspace where this is not allowed.

Passing a strange function handle to MATLAB ode solvers - What does this code mean?

I know how to use ode15s or other ode solver in MATLAB, what I'm not sure about, is this code(from CellML) that seems vague to me:
[VOI, STATES] = ode15s(#(VOI, STATES)computeRates(VOI, STATES, CONSTANTS), tspan, INIT_STATES, options);
More specifilcly, what is the meaning of the following (?):
#(VOI, STATES)computeRates(VOI, STATES, CONSTANTS)
The header of the function, "computeRates", is the following:
function [RATES, ALGEBRAIC] = computeRates(t, STATES, CONSTANTS)
I know "#computeRates" meanse the handle of the function, but what is the meaning of
#(VOI, STATES)computeRates(VOI, STATES, CONSTANTS)
Why has it put (VOI, STATES) between # and "computeRates" ?
By the way, According the MATLAB help, if we want to integrate of the following function:
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
we only need to write:
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options)
As R. M. correctly points out, what you are seeing used in that code is an anonymous function. Creating one is done in the following way:
fhandle = #(arglist) expr
Where arglist is a list of input arguments that are used in the computation of the function expression expr.
What you may be confused about is why the code requires that an anonymous function be created instead of just using a function handle for an existing function. The MATLAB solver routines like ode15s and ode45 will only pass two inputs to the function handle passed to them: a scalar t and a column vector y. If you have a situation where you want more parameters to be passed to the function to define its behavior, you have to supply the function with those parameters in other ways as described in the documentation for parameterizing functions.
Anonymous functions are one way to do this. In your example, you can see that the function computeRates takes a third argument CONSTANTS that supplies the function with extra parameters. When the anonymous function is made, this third input is frozen at the value(s) it contained at that moment. The anonymous function therefore acts as a wrapper that makes a three-input function behave like a two-input function so that it can be used by the solver routines, supplying the wrapped function with the extra inputs it needs that the solver routines can't pass to it.
Those are called anonymous functions, and let you create short, nifty functions on the fly without having to create a separate m file. The two variables between the parentheses after the # symbol are the inputs to the function. What follows it is the definition of the function. For example,
f=#(x,y)x+y;%# define an anonymous function to add the two inputs
f(2,3)
ans =
5