I'm having this problem: Let's suposse that a user wants to add an arbitrary Force (a function of time) to a spring mass damper system. In order to do that, we request the force as an input, i.e. F = cos(t). Well, I noticed that if we add a function of time in the code where the F is placed (inside ODE), then the solutions for the movement equations are correct. But i can't find a way to achieve this goal. I mean, to request the force as input so that ODE changes everytime i put a new force. I've tried almost everything like converting the input F to a function, etc.
I hope you could help me. Here is the problem in the code:
F = input('Insert force F(t)..............[N] = ','s');
u0 = [x0,v0]; % INITIAL CONDITIONS AS A VECTOR
ODE = @(t,u) [u(2) ; F - (c/m)*u(2) - (k/m)*u(1)]; % FORCED SPRING MASS DAMPER SYSTEM
[t,u] = ode45(ODE, [0 tf], u0);
The fix code results:
m = input('Insert mass of the system..........................[kg] = ');
c = input('Insert viscosity coefficient........................[ ] = ');
k = input('Insert elasticity constant..........................[m] = ');
x0 = input('Insert initial position.............................[m] = ');
v0 = input('Insert initial velocity...........................[m/s] = ');
tf = input('Insert time of complete movement....................[s] = ');
F = input('Insert external force as F(t).......................[N] = ','s');
F = str2func( ['@(t)' F] ); % CONVERT STRING TO FUNCTION
%=========================================================== ODE 45 =======
u0 = [x0,v0]; % INITIAL CONDITIONS AS A VECTOR
ODE = @(t,u) [u(2) ; F(t) - (c/m)*u(2) - (k/m)*u(1)];
[t,u] = ode45(ODE, [0 tf], u0);
u(:,3) = F(t) - (c/m)*u(:,2) - (k/m)*u(:,1); % ACCELERATION
%============================================================= PLOT =======
v = {'x','dx/dt','d2x/dt2'}; % CHAR VECTOR FOR PLOT
for i = 1:3 % PLOT WITH LOOP
subplot(3,1,i)
plot(t,u(:,i));
xlabel('t');
ylabel(v(i));
grid on;
end
Code just for personal uses. Not public because input allows malicious commands.
Thanks to @Wolfie and @Ander Biguri.
I'm going to take the liberty of simplifying your problem down to its main parts.
You have some char array from your user input
which defines a function in terms of t
. I'm going to entirely ignore all the reasons that blindly evaluating user-input functions is dangerous, but you shouldn't.
You want to combine this function with an existing function in terms of t
to produce a single function
We can do this like so:
F = 'cos(t)'; % char version of function, e.g. from the input command
y = @(t) t; % some base function in terms of t
F = str2func( ['@(t)' F] ); % Convert function char to anonymous function
yF = @(t) y(t) + F(t); % combine the functions
You can test this with a quick plot
tt = 0:0.01:10; % axis data
figure; hold on;
plot( tt, y(tt), 'displayname', 'y(t)' );
plot( tt, yF(tt), 'displayname', 'yF(t)' );
legend('show');
In your actual example you have ODE
in place of my example f
, so assuming F
is converted to an anonymous function as shown above, you would get
ODE = @(t,u) [u(2) ; F(t) - (c/m)*u(2) - (k/m)*u(1)];