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

4 ビュー (過去 30 日間)
Marton Bendeguz Gyani 2020 年 12 月 23 日

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 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 件のコメント表示非表示 4 件の古いコメント
Stephen23 2020 年 12 月 24 日

"... 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 2020 年 12 月 23 日
See odeFunction and see the work flow there in the first example.
##### 0 件のコメント表示非表示 -1 件の古いコメント

サインインしてコメントする。

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);
##### 1 件のコメント表示非表示 なし
Marton Bendeguz Gyani 2020 年 12 月 23 日
It works! Thank you for you quick response!

サインインしてコメントする。

### カテゴリ

Find more on Ordinary Differential Equations in Help Center and File Exchange

R2020b

### Community Treasure Hunt

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

Start Hunting!