How to turn a string into a line of differential equation for ode45?

2 次查看(过去 30 天)
I have a system which can be described at any time with the help of ode45. However, changing the parameters of the system changes the last 3 lines of the differential eq. system, so I wrote a matlab code for deriving these equations. It works fine, it can create these equation lines as strings, but then I am not able to transform them so that ode45 could use them. Instead, I have to copy those lines into the f function by hand.
eq1_string=['-(2*Y(5)*sin(Y(2))*(12*Y(6) - 115*Y(4)*cos(Y(2))))/(127*(cos(Y(2))^2 - 1))'];
%in my code, this string is created by matlab
eq1=str2sym(eq1_string); % trying to transform the string into an expression, that ode45 understands
Y0=[0.5*pi() 0.5*pi() 0 0 0 40]; %initial conditions
f=@(t,Y) [Y(4);...
Y(5);...
Y(6);...
eq1;... %this does not work
(103*sin(2*Y(2))*Y(4)^2)/254 - (24*Y(6)*sin(Y(2))*Y(4))/127 - (5886*sin(Y(2)))/635;...
-(Y(5)*sin(Y(2))*(127*Y(4) - 24*Y(6)*cos(Y(2)) + 103*Y(4)*cos(Y(2))^2))/(127*(cos(Y(2))^2 - 1))];
% I have to copy the lines by hand, like the last 2 lines
[t,Y]=ode45(f,0:0.01:10,Y0);
Is there any way to solve it? I tried str2sym and str2func, neither of them worked. Should I use structures? If yes, how?
I know, that renaming a variable while running the code is not recommended, but here I am not renaming or creating any variable.

回答(3 个)

Stephen23
Stephen23 2020-12-23
编辑:Walter Roberson 2020-12-23
Ugh, do NOT use eval for this!
If the string is actually a symbolic expression then use odeFunction as Walter Roberson stated.
If the string is actually a character vector, then use str2func like this (converting to symbolic is a red herring):
eq1 = '-(2*Y(5)*sin(Y(2))*(12*Y(6) - 115*Y(4)*cos(Y(2))))/(127*(cos(Y(2))^2 - 1))'; % removed superfluous square brackets
fn1 = str2func(sprintf('@(Y)%s;',eq1)); % convert string to function handle
Y0 = [0.5*pi(),0.5*pi(),0,0,0,40]; % initial conditions
fun = @(t,Y) [...
Y(4);...
Y(5);...
Y(6);...
fn1(Y);... % call function handle
(103*sin(2*Y(2))*Y(4)^2)/254 - (24*Y(6)*sin(Y(2))*Y(4))/127 - (5886*sin(Y(2)))/635;...
-(Y(5)*sin(Y(2))*(127*Y(4) - 24*Y(6)*cos(Y(2)) + 103*Y(4)*cos(Y(2))^2))/(127*(cos(Y(2))^2 - 1))];
[t,Y] = ode45(fun,0:0.01:10,Y0);
plot(t,Y)
  5 个评论
Walter Roberson
Walter Roberson 2020-12-24
Every user input to the command line is eval()'d. Every user input at the keyboard() command is eval()'d. Every input to input() that does not have the 's' option is eval()'d. Everything passed to str2num() is eval()'d. Every call to an inline() object is eval()'d
... all of which should be treated as internal implementation, not as a recommendation for user code.
With eval(), you can construct blocks of code on the fly and evaluate them without having to write them out to disk... but that does not mean that you should do that.
Stephen23
Stephen23 2020-12-24
编辑:Stephen23 2020-12-25
"... what are then the specific use cases of eval ? ... Where and when?"
Some are listed here:
Personally I don't think of eval as being any different to any other tool, I would apply exactly the same question for any tool X: what is an appropriate use case for tool X? When on balance of X's pros and cons, it is the best choice for that specific task, where "best" could be determined by a kind of weighted sum of various metrics and scales, e.g.:
  • providing the correct result
  • runtime efficiency
  • coding time, debugging time, etc.
  • clarity vs. obfuscation of intent
  • extensibility, generalizability, etc.
  • robustness, edge-cases, numeric stability, etc.
  • availability (MATLAB version, third-party, DIY, etc.)
  • security, unintended behaviors, etc.
  • maintainability, understandability for future readers
  • ... etc.
Note that some of these metrics also depend on external factors as well, e.g. where the code will be used (playing around with code on my local computer vs. distributing code on MATLAB FEX to unknown users vs. legal/standard requirements for the industry I work in).
My own experience has been that writing code following some kind of best-practice has immediate benefits, e.g. moving repeated code to its own function has on several occasions allowed me to note where that functionality could be generalized, or applied to more cases, or made me aware of missing cases. The MATLAB data type for storing functions is the function handle, so the first thing I would do is make sure that it is a function handle... and often right after that I notice that this function handle can be stored, or passed as a variable, or efficiently used again for plotting, or some other operation, which can then be added with very little effort. End result: I am more productive in less time.

请先登录,再进行评论。


Walter Roberson
Walter Roberson 2020-12-23
See odeFunction and see the work flow there in the first example.

Nirvik Sinha
Nirvik Sinha 2020-12-23
You can use eval for this purpose instead of symbolic math:
eq1_string=['-(2*Y(5)*sin(Y(2))*(12*Y(6) - 115*Y(4)*cos(Y(2))))/(127*(cos(Y(2))^2 - 1))'];
Y0=[0.5*pi() 0.5*pi() 0 0 0 40]; %initial conditions
f=@(t,Y) [Y(4);...
Y(5);...
Y(6);...
eval(eq1_string);...
(103*sin(2*Y(2))*Y(4)^2)/254 - (24*Y(6)*sin(Y(2))*Y(4))/127 - (5886*sin(Y(2)))/635;...
-(Y(5)*sin(Y(2))*(127*Y(4) - 24*Y(6)*cos(Y(2)) + 103*Y(4)*cos(Y(2))^2))/(127*(cos(Y(2))^2 - 1))];
[t,Y]=ode45(f,0:0.01:10,Y0);

类别

Help CenterFile Exchange 中查找有关 Whos 的更多信息

产品


版本

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by