How to declare parameters in matlabFunction?

91 Ansichten (letzte 30 Tage)
Abiy Wubneh
Abiy Wubneh am 24 Sep. 2019
Bearbeitet: Walter Roberson am 2 Okt. 2019
Hi there,
I have been struggling with this for a while, and I am hoping someone will be able to tell me where I am making mistakes. Thank you very much in advance for taking your time to look into this :)
I have been trying to convert symbolic expressions into MATLAB functions using matlabFunction. The original symbolic expressions were generated by another function and contain both parameters and variables, and the converted function doesn't seem to understand the difference btween the two. I am interested in converting the symbolic expressions into a MATLAB functions, and only then bind the values of the parameters in. I am doing this because it takes about an hour and half to do the conversion (not the example shown below!). Delaying the binding to a later stage would allow me to avoid running matlabFunction every time I run my code for a different set of parameter values. The ultimate goal is to use these functions in ode45.
Here is an example:
syms a b c d e % parameters
syms u v w x y z % variables
M_sym = [a*b*w c*x e*d*v;
c*y a*e*w z;
c*e*y a*b*u a*c*e*z];
B_sym = [a*x + b*y - e*z;
c*x + d*u - a*e*v;
d*w + e*a];
param = [c a d e b]
var = [u x y w z u v]
vec = [param var];
M_fun = matlabFunction(M_sym,'Vars',{vec});
B_fun = matlabFunction(B_sym,'Vars',{vec});
The resulting function handles M_fun and B_fun expect a vector input argument with the parameters and the variables combined as elements of the vector (length = 12). Ideally, what I want is to bind in the values of the parameters in M_fun and B_fun first and use the resulting functions in ode45 as M(var,t) and the B(var,t) (M*y = B).
My question is:
a) Is there a way to tell matlabFunction in advance what the parameters are and what their order/sequence is?
Eg. param = [c a d e b]
b) If (a) is not an option, is there a method for passing the parameter values to M_fun and B_fun in a vector form and still use the results in ode45?
Eg. param_val = [0.1 0.25 0.012 0.5 0.33]
I have tried something like the following, but it didn't work (probably because M_fun and B_fun don’t recognize param and var)
f1 = @(param,var)(@(var)M_fun);
f2 = @(param,var)(@(var)B_fun);
param_val = [0.1 0.25 0.012 0.5 0.33]
g1 = f1(param_val);
g2 = f2(param_val);
M = @(t,Y_val)g2(Y_val);
B = @(t,Y_val)g1(Y_val);
time_span = linspace(0.0, 5, 30);
int_cond = [0.0 0.01 0.02 0.1 0.13 0.12 0.05];
opt = odeset('Mass',M);
[t_span,QUf_sol] = ode45(B,time_span,int_cond,opt);
And i am getting the following error:
Error using odearguments (line 95)
@(T,Y_VAL)G1(Y_VAL) returns a vector of length 1, but the length of initial conditions vector is 7. The vector returned by @(T,Y_VAL)G1(Y_VAL) and the initial conditions vector must have the same number of elements.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Any help will be greatly appreciated.
Thanks,
  2 Kommentare
darova
darova am 24 Sep. 2019
Maybe odeToVectorField wil help
Abiy Wubneh
Abiy Wubneh am 28 Sep. 2019
Hi darova,
Thank you for your comment! Could you please elaborate or provide an example?
Cheers!

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Walter Roberson
Walter Roberson am 29 Sep. 2019
Bearbeitet: Walter Roberson am 2 Okt. 2019
MATLAB does not have any distinction between parameters and variables.
You should probably be looking more closely at the 'vars' option of matlabFunction. It accepts a cell array. Within the cell array you can have vectors (even arrays) of variables as entries. All of the entries that are in the same vector or array are bundled into the same input slot.
matlabFunction(a+b+c, 'vars', {a, b, c}) -> @(a, b, c) a+b+c
matlabFunction(a+b+c, 'vars', {a, [b c]}) -> @(a, in1) a+in1(:,1)+in2(:,2)
matlabFunction(a+b+c, 'vars', {a, [b;c]}) -> @(a, in1) a+in1(1,:)+in2(2,:)
The state information for ode45 calls should go into a column vector of variables.
If you use odeFunction instead of matlabFunction then it constructs the state information automatically.
  6 Kommentare
darova
darova am 30 Sep. 2019
ok
Abiy Wubneh
Abiy Wubneh am 1 Okt. 2019
Hi Walter,
The odeFunction you suggested resolved the problem. I created vectors of the state variables and the parameters symbols and passed them to odeFunction as in1 and in2, respectively.
Thank you so much for your help!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

darova
darova am 28 Sep. 2019
clc,clear
syms x(t) y(t) z(t) % variables
syms a b c % parameters
% set up derivatives
d2y = diff(y,2);
dx = diff(x);
d3z = diff(z,3);
% equations
eqn = [d2y + y^2 + 3*t
dx*y - a
d3z/t - b - c];
% let MATLAB do all work for us
[Y, Y_subs] = odeToVectorField(eqn);
% create a function for ode45
F = matlabFunction(Y,'vars',{'t' 'Y' [a b c]});
% set up order of initial conditions
X0 = matlabFunction(Y_subs,'vars',{'x' 'y' 'z' 'Dy' 'Dz' 'D2z'});
tspan = [0.1 2];
x0 = X0( 0,1,1,2,0.5,1.1 ); % initial x y z Dy Dz D2z (order is important)
in3 = [2 1 -0.5]; % parameters (a,b,c)
[t, X] = ode45(@(t,y)F(t,y,in3), tspan, x0);
plot(t,X)
And here is outputs
% EQUATIONS CONVERTED TO FIRST ORDER
Y =
a/Y[2]
Y[3]
- 3*t - Y[2]^2
Y[5]
Y[6]
t*(b + c)
% SUBSTITUTIONS WERE MADE
Y_subs =
x
y
Dy
z
Dz
D2z
% MATLAB FUNCTION FOR ode45 INPUT (in3 - a,b,c coeffs)
F =
@(t,Y,in3)[in3(:,1)./Y(2);Y(3);t.*-3.0-Y(2).^2;Y(5);Y(6);t.*(in3(:,2)+in3(:,3))]
% ORDER OF INITIAL CONDITIONS
X0 =
@(x,y,z,Dy,Dz,D2z)[x;y;Dy;z;Dz;D2z]
See also HERE

Produkte


Version

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by