Finding solution to Cauchy prob. in Matlab - matlab

I need some help with finding solution to Cauchy problem in Matlab.
The problem:
y''+10xy = 0, y(0) = 7, y '(0) = 3
Also I need to plot the graph.
I wrote some code but, I'm not sure whether it's correct or not. Particularly in function section.
Can somebody check it? If it's not correct, where I made a mistake?
Here is separate function in other .m file:
function dydx = funpr12(x,y)
dydx = y(2)+10*x*y
end
Main:
%% Cauchy problem
clear all, clc
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(#funpr12,xint,y0);
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
I get this graph:

ode45 and its related ilk are only designed to solve first-order differential equations which are of the form y' = .... You need to do a bit of work if you want to solve second-order differential questions.
Specifically, you'll have to represent your problem as a system of first-order differential equations. You currently have the following ODE:
y'' + 10xy = 0, y(0) = 7, y'(0) = 3
If we rearrange this to solve for y'', we get:
y'' = -10xy, y(0) = 7, y'(0) = 3
Next, you'll want to use two variables... call it y1 and y2, such that:
y1 = y
y2 = y'
The way you have built your code for ode45, the initial conditions that you specified are exactly this - the guess using y and its first-order guess y'.
Taking the derivative of each side gives:
y1' = y'
y2' = y''
Now, doing some final substitutions we get this final system of first-order differential equations:
y1' = y2
y2' = -10*x*y1
If you're having trouble seeing this, simply remember that y1 = y, y2 = y' and finally y2' = y'' = -10*x*y = -10*x*y1. Therefore, you now need to build your function so that it looks like this:
function dydx = funpr12(x,y)
y1 = y(2);
y2 = -10*x*y(1);
dydx = [y1 y2];
end
Remember that the vector y is a two element vector which represents the value of y and the value of y' respectively at each time point specified at x. I would also argue that making this an anonymous function is cleaner. It requires less code:
funpr12 = #(x,y) [y(2); -10*x*y(1)];
Now go ahead and solve it (using your code):
%%// Cauchy problem
clear all, clc
funpr12 = #(x,y) [y(2); -10*x*y(1)]; %// Change
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(funpr12,xint,y0); %// Change - already a handle
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
Take note that the output when simulating the solution to the differential equation by deval will be a two column matrix. The first column is the solution to the system while the second column is the derivative of the solution. As such, you'll want to plot the first column, which is what the plot syntax is doing.
I get this plot now:

Related

Solve a nonlinear equation using ODE45 function in matlab for different values of initial conditions

I have written a script to compute and solve a simple inverted pendalum system.Now suppose that I want to solve the nonlinear dynamic equation of the system with ODE45 function with different values of initial conditions.How could I use a for loop to solve for state vector of X for different values of initial conditions?I wrote a for loop to do that but I could not get the answer I wanted.Help me please.Here are my function and mfile as follows:
function xDot = of(x,g,L,u)
xDot = zeros(2,1);
xDot(1) = x(2);
xDot(2) = ((g./L)*sin(x(1)))+u;
end
And this is my main code:
clc;
clear;close all;
%% Solve The Nonlinear Equation
L = 1;
g = 9.81;
h = 0.25;
t = [0:h:5];
A = [0 1;(g/L) 0];
B =[0 1]';
Ics = [pi,0;pi/2 0;pi/5 0;0.001 0;pi 0.5;pi/2 0.5;pi/5 0.5;0.001 0.5];
[Poles,~] = eig(A); %Poles Of Closed LOop System
R = 0.01;
Q = eye(2);
K = lqr(A,B,Q,R);
u = #(x)-K*(x);
for i=1:size(Ics,1)
[~,X] = ode45(#(t,x)of(x,g,L,u(x)),t,Ics(i,:));
end
Also note that I want the first column of X vector which is the angular displacements of the pendulum in each iteration because the second column of X vector in ODE45 is always the Derivative of the main state vector.
You can store all the integration outputs for the different initial conditions in a 3D array.
The number of rows of Xout will equal the number of time steps at which you want to evaluate your solution, so numel(t). The number of columns is the number of states, and then the third dimension will be the number of initial conditions you want to test.
Xout = zeros(numel(t), size(Ics, 2), size(Ics, 1)); % initialize the 3D array
for k = 1:size(Ics, 1)
[~, Xout(:, :, k)] = ode45(#(t, x)of(x, g, L, u(x)), t, Ics(k, :));
end

Spring/Damper Calculation & Plotting

Given two systems with damper/spring:
First system's simulink model with step time 2, final value 0.5:
Simulink of the second system with same input:
I have to find the code using dsolve and ode45 to generate the same graph with Simulink. Given values are:
m1 = 500
c1 = 1200
k1 = 25000
k2 = 15000
m2 = 50
I tried to find dsolve but it couldn't solve it. So I got to use ode45, and I am totally lost.
Differential equation of the first system:
syms x(t) y(t)
Dy = diff(y,t);
Dx = diff(x,t);
D2x = diff(x,2,t);
cond = [x(0)==0, y(0)==0, Dy(0)==0, Dx(0)==5];
eqn33 = D2x + (2*0.2121*0.1414*Dx) + (0.1414^2)*x==2*0.2121*0.1414*Dy+(0.1414^2)*y;
sol33 = dsolve(eqn33,cond)
pretty(sol33)
Answer updated to match Simulink model implementation
To use ode45, you first need to write a function that computes the derivative of you input vector (i.e. your differential equation), and store that function in a separate file with the function name as the filename. Please note that the ode solvers can only solve first-order differential equations, so you first need to do a bit of work to convert your second-order differential equation to a first-order one. For more details, see the documentation on ode45.
Based on what you have done in your Simulink model, D2y is known for all values of t (it's the step input), so we need to integrate it with respect to time to get Dy and y. So our state vector is X = [x; Dx; y; Dy] and our function looks like (stored in diff_eqn.m):
function dX = diff_eqn(t,X)
m1=500;
c=1200;
k1=25000;
dX(1) = X(2); % Dx
dX(2) = -(1/m1)*(c*(X(2)-X(4)/m1) + k1*(X(1)-X(3)/m1));; % D2x
dX(3) = X(4); % Dy
if t<2
dX(4) = 0; % D2y
else
dX(4) = 0.5;
end
as dX = [Dx; D2x; Dy; D2y].
In your script or your MATLAB command window, you can then call the ode solver (initial conditions all being equal to zero for Dx, x, Dy and y, as per your Simulink model):
[t,X] = ode45(#diff_eqn,[0 20],[0; 0; 0; 0]);
Adjust the ode solver options (e.g. max step size, etc...) to get results with more data points. To get the same plot as in your Simulink model, you can then process the results from the ode solver:
D2x = diff(X(:,2))./diff(t);
D2x = [0; D2x];
D2y = zeros(size(D2x));
D2y(t>=2) = 0.5;
plot(t,[D2y 500*D2x])
grid on
xlabel('Time [s]')
legend('D2y','m1*D2x','Location','NorthEast')
Which gives the following plot, matching the results from your Simulink model:

Solving time-dependent Schrodinger equation using MATLAB ode45

The Schrodinger equation for a time-dependent Hamiltonian is:
I try to implement a solver for the Schrodinger equation for a time-dependent Hamiltonian in ode45. However, because the Hamiltonian $H(t)$ is dependent on time. I do not know how to do interpolation in ode45. Can you give me some hints?
psi0 = [0 1];
H = [1 0;0 1]*cos(t); %this is wrong, I do not know how to implement this and pass it to ode45
hbar = 1;
t = [0:1:100];
[T, psi] = ode45(dpsi, t, psi);
function dpsi = f(t, psi, H, psi0)
dpsi = (1/i)*H*psi;
I also try to come up with a solution of matrix interpolation in
MATLAB: Interpolation that involve a matrix.
H is just an identity matrix in your case, so we can just multiply it with the psi vector to get back the psi vector itself. Then, we bring i*hbar to the right-hand-side of the equation so that the final equation is in a form that ode45 accepts. Finally, we use the following code to solve for psi:
function schrodinger_equation
psi0 = [0;1];
hbar = 1;
t = [0 100];
[T,psi] = ode45(#(t,psi)dpsi(t,psi,hbar),t,psi0);
for i = 1:length(psi0)
figure
plot(T,real(psi(:,i)),T,imag(psi(:,i)))
xlabel('t')
ylabel('Re(\psi) or Im(\psi)')
title(['\psi_0 = ' num2str(psi0(i))])
legend('Re(\psi)','Im(\psi)','Location','best')
end
end
function rhs = dpsi(t,psi,hbar)
rhs = 1/(1i*hbar)*cos(t).*ones(2,1);
end
Note that I have plotted the two components of psi separately and for each such plot, I have also plotted the real and imaginary components separately. Here are the plots for two different values of psi0:

Computing an ODE in Matlab

Given a system of the form y' = A*y(t) with solution y(t) = e^(tA)*y(0), where e^A is the matrix exponential (i.e. sum from n=0 to infinity of A^n/n!), how would I use matlab to compute the solution given the values of matrix A and the initial values for y?
That is, given A = [-2.1, 1.6; -3.1, 2.6], y(0) = [1;2], how would I solve for y(t) = [y1; y2] on t = [0:5] in matlab?
I try to use something like
t = 0:5
[y1; y2] = expm(A.*t).*[1;2]
and I'm finding errors in computing the multiplication due to dimensions not agreeing.
Please note that matrix exponential is defined for square matrices. Your attempt to multiply the attenuation coefs with the time vector doesn't give you what you'd want (which should be a 3D matrix that should be exponentiated slice by slice).
One of the simple ways would be this:
A = [-2.1, 1.6; -3.1, 2.6];
t = 0:5;
n = numel(t); %'number of samples'
y = NaN(2, n);
y(:,1) = [1;2];
for k =2:n
y(:,k) = expm(t(k)*A) * y(:,1);
end;
figure();
plot(t, y(1,:), t, y(2,:));
Please note that in MATLAB array are indexed from 1.

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