Euler's explicit method on MATLAB raises error with example - matlab

This is my code for Euler's explicit Method on MATLAB
function [t,x] = meuler(f, intervalo, x0, N)
h = (intervalo(2)-intervalo(1))/N;
t = intervalo(1):h:intervalo(2);
x(:,1) = x0(:);
for i = 1:N
x(i+1,:) = x(i,:) + h*(f(t(i),x(i,:)));
end
It takes a function f defined in another file. When I try to run the code with the following function
function f = funccorazon(t,x)
f1 = x(2);
f2 = 16*x(1)+4*sin(2*t);
f=[f1;f2];
I get this error
>> meuler(#funccorazon, [0 2*pi], [0 2], 1000)
Attempted to access y(2); index out of bounds because numel(y)=1.
Error in funccorazon (line 2)
f1 = y(2);
and I don't know why. Apparently, when I solve the differential equation using ode45, nothing seems to go wrong. Any help with that would be appreciated. Thank you!

The reason for the error is that you need to work with row vectors instead of column vectors.
first, in your function call, define the input x0 as row vector:
meuler(#funccorazon, [0 2*pi], [0,2], 1000)
second, in funccorazon function, define the output f similarly:
f=[f1,f2];
lastly, in meuler function do the following changes:
x = zeros(N,2);
x(1,:) = x0;

Related

How to write an Ordinary Differential Equation in MATLAB?

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.

Error using anonymous function for system of ODE using ode45 in MATLAB

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;

Taylor Method ODE

I am trying to implement the Taylor method for ODEs in MatLab:
My code (so far) looks like this...
function [x,y] = TaylorEDO(f, a, b, n, y0)
% syms t
% x = sym('x(t)'); % x(t)
% f = (t^2)*x+x*(1-x);
h = (b - a)/n;
fprime = diff(f);
f2prime = diff(fprime);
y(0) = y0,
for i=1:n
T((i-1)*h, y(i-1), n) = double(f((i-1)*h, y(i-1)))+(h/2)*fprime((i-1)*h, y(i-1))
y(i+1) = w(i) + h*T(t(i), y(i), n);
I was trying to use symbolic variables, but I donĀ“t know if/when I have to use double.
I also tried this other code, which is from a Matlab function, but I do not understand how f should enter the code and how this df is calculated.
http://www.mathworks.com/matlabcentral/fileexchange/2181-numerical-methods-using-matlab-2e/content/edition2/matlab/chap_9/taylor.m
As error using the function from this link, I got:
>> taylor('f',0,2,0,20)
Error using feval
Undefined function 'df' for input arguments of type 'double'.
Error in TaylorEDO (line 28)
D = feval('df',tj,yj)
The f I used here was
syms t
x = sym('x(t)'); % x(t)
f = (t^2)*x+x*(1-x);
This is a numerical method, so it needs numerical functions. However, some of them are computed from the derivatives of the function f. For that, you need symbolic differentiation.
Relevant Matlab commands are symfun (create a symbolic function) and matlabFunction (convert a symbolic function to numerical).
The code you have so far doesn't seem salvageable. You need to start somewhere closer to basics, e.g., "Matlab indices begin at 1". So I'll fill the gap (computation of df) in the code you linked to. The comments should explain what is going on.
function [T,Y] = taylor(f,a,b,ya,m)
syms t y
dfs(1) = symfun(f, [t y]); % make sure that the function has 2 arguments, even if the user passes in something like 2*y
for k=1:3
dfs(k+1) = diff(dfs(k),t)+f*diff(dfs(k),y); % the idea of Taylor method: calculate the higher derivatives of solution from the ODE
end
df = matlabFunction(symfun(dfs,[t y])); % convert to numerical function; again, make sure it has two variables
h = (b - a)/m; % the rest is unchanged except one line
T = zeros(1,m+1);
Y = zeros(1,m+1);
T(1) = a;
Y(1) = ya;
for j=1:m
tj = T(j);
yj = Y(j);
D = df(tj,yj); % syntax change here; feval is unnecessary with the above approach to df
Y(j+1) = yj + h*(D(1)+h*(D(2)/2+h*(D(3)/6+h*D(4)/24)));
T(j+1) = a + h*j;
end
end
Example of usage:
syms t y
[T, Y] = taylor(t*y, 0, 1, 2, 100);
plot(T,Y)

MATLAB solve Ordinary Differential Equations

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,:)

How to calculate the integral of the exp of the sum of function handles in a cell

I don't know how to calculate the integral of the sum of function handles in a cell. Please see the below examples:
f{1} = #(x) x;
f{2} = #(x) x^2;
g = #(x) sum(cellfun(#(y) y(x), f));
integral(#(x) exp(g), -3,3);
Error: Input function must return 'double' or 'single' values. Found 'function_handle'.
PS: please don't change the formula, because this is just an example. My real problem is far more complicated than this. It has log and exp of this sum (integral(log(sum), -inf, inf)). So I can't break them up to do the integral individually and sum the integrals.I need to use sum(cellfun). Thank you.
Version: Matlab R2012a
Can anyone help me? Really appreciate.
You cannot add function handles, so anything that tries f{1}+f{2}+... would give an error.
But you can compute the integral of the sums like this, evaluating the function values one at a time and adding up the results:
function cellsum
f{1} = #(x) x;
f{2} = #(x) x.^2;
integral(#(x)addfcn(f,x), -3, 3)
end
function s = addfcn(f,x)
s = zeros(size(x));
for k = 1:length(f)
s = s + f{k}(x);
end
end
Note that x will usually be a vector when the integral command calls your functions with it. So your function definitions should be vectorized, .i.e., x.^2 instead of x^2, etc.