I'm working in MATLAB and I have a problem with a system of differential equations. My system is dvdt = (-2*T)-4*v and dTdt = 6*T+v and I want to resolve it using Runge-Kutta of 4th order. I wrote the following code:
If I run only the function odefun, my code works! But my code didn't work if I run the complete program:
clear all
yy=#(t,y)[dvdt;dTdt]
[t,y]= ode45(#(t,y)yy,[0 1.5],[1 1/2 ]);
function res = odefun(t , y )
% i define two variable i will use: v and TT
v = y(1,:);
T = y(2,:);
% i define the two partial derivative:
res(1,:) = dvdt
res(2,:) = dTdt
dvdt = (-2*T)-4*v
dTdt = 6*T+v;
end
This is my results. I don't know to write a vector of a correct length:
Error using odearguments (line 95)
#(T,Y)YY returns a vector of length 1, but the length of initial conditions vector is 2. The vector returned by #(T,Y)YY 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);
Error in sys_ode (line 4)
[t,y]= ode45(#(t,y)yy,[0 1.5],[1 1/2 ]);
y as passed from ode45 to odefun is a flat, one-dimensional array. Your variable assignment like you were dealing with a 2-dimensional array makes no sense. It should be v=y(1); T=y(2);.
In a code block, you need to observe causality. You need to declare/define a variable before you can use it in another code line.
Without calling odefun you will not get an error as each line in odefun is syntactically correct. However you get an error in its execution as the semantic is wrong.
Try
clear all
[t,y]= ode45(odefun,[0 1.5],[1 1/2 ]);
function res = odefun(t , y )
% i define two variable i will use: v and T
v = y(1);
T = y(2);
% i define the two derivatives:
dvdt = (-2*T)-4*v
dTdt = 6*T+v;
res = [ dvdt dTdt ]
end
Related
The following code runs fine and gives the accurate result.
c1...c5 are known constants, and x(1)...x(5) (anonymous vector) are unknown variables which to be fitted by fminsearch using the least square method. (t,y) is the given data (curve) to fit the equation, myfunc is a ode45 function saved in a separate .m file.
% run the solver
options = optimset('MaxFunEvals',10000,'MaxIter',10000,'Display','iter');
[x,fval,exitflag,output] = fminsearch(#(x) Obj(x,initial_p,c1,c2,c3,c4,c5,c6,t,y),x0,options);
function F = Obj(x,initial_p,c1,c2,c3,c4,c5,c6,t,y)
p = myfunc(x(2:end),initial_p,t,c1,c4);
yt = mainfunc(x,p,c1,c2,c3,c4,c5,c6);
F = sqrt(sum((yt-y).^2));
disp(x);
end
function yt = mainfunc(x,p,c1,c2,c3,c4,~,~)
yf = c1*c2*c3*c4*sqrt(p);
yt = x(1)+yf;
end
But error occurs (Assignment has more non-singleton rhs dimensions than non-singleton subscripts) when I rewrite mainfunc (all else being same):
function yt = mainfunc(x,p,c1,c2,c3,c4,c5,c6)
ys = c1*c3*(c5/(c6*sqrt(p)));
yf = c1*c2*c3*c4*sqrt(p);
yt = x(1)+ys+yf;
end
p is a curve (t,p) coming from ode45 in myfunc, it is working fine in the first version of code so no problem there. Is having two terms with sqrt(p) in mainfunc causing the problem?
I tried writing an Ordinary Differential Equation in MATLAB.
I wrote this code:
function [y] = odefun(t,y)
t = [0:0.01:10];
y = [0 0]';
y(1) = y(2);
y(2) = sin(2*t)-2*y(2)-2*y(1); % I get an error here
end
I get an error in the last line in this code. MATLAB doesn't show me what the error is. It just tells me I have an error in that line.
Why do I get this error and how to resolve it?
What you want is to carefully read the documentation of the diverse ode solvers and the examples there and then correct your code to something like
% Solve ODE y''(t)+2*y'(t)+2*y(t) = sin(2*t), y(0)=y'(0)=0
function ydot = odefun(t,y)
ydot = zeros_like(y)
ydot(1) = y(2);
ydot(2) = sin(2*t)-2*y(2)-2*y(1);
end
% or
% odefun = #(y,t) [ y(2); sin(2*t)-2*y(2)-2*y(1) ]
% define sample points
tspan = [0:0.01:10];
% define initial value to t=tspan(1)
y0 = [0 0]';
[ t, y ] = ode45(odefunc, tspan, y0)
% t,y now contain the times and values that
% the solution was actually computed for.
You try to assign to y(2) a vector of 1001 elements:
>> size(sin(2*t)-2*y(2)-2*y(1))
ans =
1 1001
The error message is pretty clear:
In an assignment A(:) = B, the number of elements in A and B must be the same.
Also, y and t are never use since you redefined them in the function.
I am trying to solve a system of n coupled ODE in MATLAB. The code:
clear all
n = 21;
dx = 1./(n-1);
x = [0:dx:1];
u0 = sin(0.5*n*pi*x);
f1 = #(t,u) [0, u(1:n-2)-2*u(2:n-1)-u(3:n), 2*(u(n-1)-u(n))]'/dx^2;
% f1 = #(t,u) [0; u(1:n-2)'-2*u(2:n-1)'-u(3:n)'; 2*(u(n-1)-u(n))]/dx^2;
[t,U] = ode45(f1, [0,2.5], u0');
gives the error:
Dimensions of matrices being concatenated are not consistent.
Error in t1>#(t,u)[0,u(1:n-2)-2*u(2:n-1)-u(3:n),2*(u(n-1)-u(n))]'/dx^2
I get errors from both forms (one commented out) of the anonymous function when u is a column vector, as it is when the function is called through ode45.
The u passed to f1 by ode45 is a column vector. The concatenation must reflect this:
f1 = #(t,u) [0 ; u(1:n-2)-2*u(2:n-1)-u(3:n) ; 2*(u(n-1)-u(n))]/dx^2;
How can I use matlab to solve the following Ordinary Differential Equations?
x''/y = y''/x = -( x''y + 2x'y' + xy'')
with two known points, such as t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 ?
It doesn't need to be a complete formula if it is difficult. A numerical solution is ok, which means, given a specific t, I can get the value of x(t) and y(t).
If matlab is hard to do this, mathematica is also OK. But as I am not familiar with mathematica, so I would prefer matlab if possible.
Looking forward to help, thanks!
I asked the same question on stackexchange, but haven't get good answer yet.
https://math.stackexchange.com/questions/812985/matlab-or-mathematica-solve-ordinary-differential-equations
Hope I can get problem solved here!
What I have tried is:
---------MATLAB
syms t
>> [x, y] = dsolve('(D2x)/y = -(y*D2x + 2Dx*Dy + x*D2y)', '(D2y)/x = -(y*D2x + 2Dx*Dy + x*D2y)','t')
Error using sym>convertExpression (line 2246)
Conversion to 'sym' returned the MuPAD error: Error: Unexpected 'identifier'.
[line 1, col 31]
Error in sym>convertChar (line 2157)
s = convertExpression(x);
Error in sym>convertCharWithOption (line 2140)
s = convertChar(x);
Error in sym>tomupad (line 1871)
S = convertCharWithOption(x,a);
Error in sym (line 104)
S.s = tomupad(x,'');
Error in dsolve>mupadDsolve (line 324)
sys = [sys_sym sym(sys_str)];
Error in dsolve (line 186)
sol = mupadDsolve(args, options);
--------MATLAB
Also, I tried to add conditions, such as x(0) = 2, y(0)=8, x(1) = 7, y(1) = 18, and the errors are still similar. So what I think is that this cannot be solve by dsolve function.
So, again, the key problem is, given two known points, such as when t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 , how I get the value of x(t) and y(t)?
Update:
I tried ode45 functions. First, in order to turn the 2-order equations into 1-order, I set x1 = x, x2=y, x3=x', x4=y'. After some calculation, the equation becomes:
x(1)' = x(3) (1)
x(2)' = x(4) (2)
x(3)' = x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)) (3)
x(4)' = -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2) (4)
So the matlab code I wrote is:
myOdes.m
function xdot = myOdes(t,x)
xdot = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)]
end
main.m
t0 = 0;
tf = 1;
x0 = [2 3 5 7]';
[t,x] = ode45('myOdes',[t0,tf],x0);
plot(t,x)
It can work. However, actually this is not right. Because, what I know is that when t=0, the value of x and y, which is x(1) and x(2); and when t=1, the value of x and y. But the ode functions need the initial value: x0, I just wrote the condition x0 = [2 3 5 7]' randomly to help this code work. So how to solve this problem?
UPDATE:
I tried to use the function bvp4c after I realized that it is a boundary value problem and the following is my code (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)
It can work, but I don't know whether it is right. I will check it again to make sure it is the right code.
As mentioned, this isn't a math site, so try to give code or something showing some effort.
However, the first step you need to do is turn the DE into normal form (i.e., no 2nd derivatives). You do this by making a separate variable equal to the derivative. Then, you use
syms x y % or any variable instead of x or y
to define variables as symbolic. Use matlabfunction to create a symbolic function based on these variables. Finally, you can use the ode45 function to solve the symbolic function while passing variable values. I recommend you look up the full documentation in matlab in order to understand it better, but here is a very basic syntax:
MyFun= matlabFunction(eq,'vars',{x,y});
[xout,yout]=ode45(#(x,Y) MyFun(variables),[variable values],Options);
Hopefully this puts you in the right direction, so try messing around with it and provide code if you need more help.
EDIT:
This is how I would solve the problem. Note: I don't really like the matlabFunction creator but this is simply a personal preference for various reasons I won't go into.
% Seperate function of the first order state equations
function dz = firstOrderEqns(t,z)
dz(4,1) = 0;
dz(1) = -2.*z(3).*z(1).*z(4)./(1 + z(4).^2 + z(2).^2);
dz(2) = z(1);
dz(3) = -2.*z(2).*z(3).*z(1)./(1 + z(4).^2 + z(2).^2);
dz(4) = z(3);
end
% runfirstOrderEqns
%% Initial conditions i.e. # t=0
z1 = 5; % dy/dt = 5 (you didn't specify these initial conditions,
% these will depend on the system which you didn't really specify
z2 = 0; % y = 0
z3 = 5; % dx/dt = 5 (The same as for z1)
z4 = 0; % x = 0
IC = [z1, z2, z3, z4];
%% Run simulation
% Time vector: i.e closed interval [0,20]
t = [0,20]; % This is where you have to know about your system
% i.e what is it's time domain.
% Note: when a system has unstable poles at
% certain places the solver can crash you need
% to understand these.
% using default settings (See documentation ode45 for 'options')
[T,Y] = ode45(#firstOrderEqns,t,IC);
%% Plot function
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),':',T,Y(:,4),'.');
legend('dy/dt','y','dx/dt','x')
As in my comments I have made a lot of assumtions that you need to fix for example, you didn't specify what the initial conditions for the first derivatives of the states are i.e. (z1, z3) which is important for the response of the system. Also you didn't specify the time interval your interested for the simulation etc.
Note: The second m file can be used with any state function in the correct format
The following is the answer we finally get #Chriso: use matlab bvp4c function to solve this boundary value problem (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)
So I need to solve x''(t) = -x(t)^p with initial conditions x(0)= 0 and v(0) = x'(0) = v_o = 1.
The value of the parameter p is 1.
This is what I have:
function [t, velocity, x] = ode_oscilation(p)
y=[0;0;0];
% transform system to the canonical form
function y = oscilation_equation(x,p)
y=zeros(2,1);
y(1)=y(2);
y(2)=-(x)^p;
% to make matlab happy we need to return a column vector
% so we transpose (note the dot in .')
y=y.';
end
tspan=[0, 30]; % time interval of interest
[t,velocity,x] = ode45(#oscilation_equation, tspan, 1);
t = y(:,1);
xposition=y(:,3);
velocity=y(:,2);
end
and this is the error message I receive:
ode_oscillation(1)
Error using odearguments (line 91)
ODE_OSCILLATION/OSCILATION_EQUATION must return a
column vector.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0,
odeArgs, odeFcn, ...
Error in ode_oscillation (line 17)
[t,velocity,x] = ode45(#oscilation_equation, tspan,1);
There's a few things going wrong here. First, from help ode45:
ode45 Solve non-stiff differential equations, medium order method.
[TOUT,YOUT] = ode45(ODEFUN,TSPAN,Y0) with TSPAN = [T0 TFINAL] integrates
the system of differential equations y' = f(t,y) from time T0 to TFINAL
with initial conditions Y0.
Note that ode45 expects a function f(t,y), where size(t) == [1 1] for time and size(y) == [1 N] or [N 1] for solution values. Your oscilation_equation has the order of input arguments inverted, and you input a constant parameter p instead of time t.
Also, the initial conditions Y0 should have the same size as y; so size(y0) == [N 1] or [1 N]. You just have 1, which is clearly causing errors.
Also, your output arguments t, xposition and velocity will be completely ignored and erroneous, since y is not set as output argument from ode45, and most of all, their names do not correspond to ode_oscilation's output arguments. Also, their order of extracting from columns of y is incorrect.
So, in summary, change everything to this:
function [t, v, x] = ode_oscilation(p)
% initial values
y0 = [0 1];
% time interval of interest
tspan =[0 30];
% solve system
[t,y] = ode45(#(t,y) [y(2); -y(1)^p], tspan, y0);
% and return values of interest
x = y(:,1);
v = y(:,2);
end