How to turn a string into a line of differential equation for ode45?
1 view (last 30 days)
Show older comments
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.
0 Comments
Answers (3)
Stephen23
on 23 Dec 2020
Edited: Walter Roberson
on 23 Dec 2020
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 Comments
Walter Roberson
on 24 Dec 2020
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
on 24 Dec 2020
Edited: Stephen23
on 25 Dec 2020
"... 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
on 23 Dec 2020
See odeFunction and see the work flow there in the first example.
0 Comments
Nirvik Sinha
on 23 Dec 2020
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);
See Also
Categories
Find more on Whos in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!