My code is
I am trying to plot a graph of second order differential equation
clc;
funcprot(0);
function dx = f(t,x)
dx(1) = x(2);
dx(2) = sin(2 * t);
endfunction
t = 0: 0.1 : 4 * %pi;
y = ode ([0,-1/2],0,t,f);
plot2d(t',[y(1,:)',y(2,:)']);
xlabel('t'); ylabel('y and derivative');
xtitle('Plot of solution of 2nd order ODE')
Just transpose the initial condition:
clc;
funcprot(0);
function dx = f(t,x)
dx(1) = x(2);
dx(2) = sin(2 * t);
endfunction
t = 0: 0.1 : 4 * %pi;
y = ode ([0,-1/2]',0,t,f);
plot2d(t',[y(1,:)',y(2,:)']);
xlabel('t'); ylabel('y and derivative');
xtitle('Plot of solution of 2nd order ODE')
Related
I want to create an ODE file for the equation d^2theta/dt^2 - cos(theta) = 0
I have this:
function dYdt = osciODE(t,Y,~,theta)
dYdt = zeros(2,1);
dYdt (1) = Y(2);
dYdt (2) = -cos(theta1);
But I don't think this is right as dYdt (1) would be for d^2x/dt^2
Can I replace it with theta like this?
One way to solve this ODE is :
[t,y] = ode23(#osciode,[0 20],[2; 0]);
plot(t,y(:,1),'-o',t,y(:,2),'-o')
title('Solution osciode with ODE23 : y1=y ; y2=dy/dt');
grid on
xlabel('t');ylabel('y');
legend('y_1','y_2')
%%
function dydt = osciode(t,y)
dydt = [y(2); cos(y(1))];
end
y is theta
So I am trying to model simple projectile motion (no air resistance etc) using the ode45 solver in Matlab. This is my code so far:
function [x,y] = trajectory_without_AR_45(v0,theta, dt)
%Path of mortar without air resistance using ode45
g = 9.81;
t_start = 0;
t_end = 100;
%Initial Conditions
y01 = 0; %initial x
y02 = v0 * cos(theta); %finding initial velocity in x direction
y03 = 0; %initial y
y04 = v0 * sin(theta); % finding intial velocity in y direction
y0 = [y01;y02;y03;y04];
%Derivatives
dy1 = y0(2); %vx
dy2 = 0; %ax
dy3 = y0(4); %vy
dy4 = -g; %ay
dy = [dy1;dy2;dy3;dy4];
%Using ODE45
f = # (t, y) (dy);
solution = ode45(f, [t_start, t_end], y0);
t = t_start : 0.01: t_end;
y = deval(solution, t);
plot (y(:,1), y(:,3)); %plotting trajectory
end
However, the plot I am getting is just a straight line which clearly is not correct. Any help would be appreciated.
I think you're not calling the ode solver properly, you only seem to be using the initial conditions to compute dy, which is wrong. Best to put the ode function in a separate function (file). For example, the following is in missile.m:
function dY = missile(t,Y)
g = 9.81;
dY(1) = Y(2); %vx
dY(2) = 0; %ax
dY(3) = Y(4); %vy
dY(4) = -g; %ay
end
Which you would then call as follows:
t_start = 0;
t_end = 2.3; % changed to something more consistent with when y<0
v0 = 10; % made up
theta=pi/4; % made up
y01 = 0; %initial x
y02 = v0 * cos(theta); %finding initial velocity in x direction
y03 = 0; %initial y
y04 = v0 * sin(theta); % finding intial velocity in y direction
y0 = [y01;y02;y03;y04];
opts = odeset('MaxStep',0.01,'InitialStep',0.001);
[t,y] = ode45(#missile, [t_start, t_end], y0, opts);
plot(t,y)
legend('x','dx','y','dy')
which gives the following results:
This question already has an answer here:
Finding solution to Cauchy prob. in Matlab
(1 answer)
Closed 5 years ago.
I have solved a ODE first order equation using matlab. The equation is $$y' = t^2$$. Now I want to solve second order differential equation using the same code. y''(x) = -y, where $y(0) =1$ and $y'(x=0) = 0$.
How to change the below code so i can find the value of y? What I tried is that, i made it to a first order differential equation, but I'm confused how to change the code.
clc; % Clears the screen
clear all;
h=0.2; % step size
x = 0:h:1; % Calculates upto y(3)
y = zeros(1,length(x));
y(1) = 1; % initial condition
F_x = #(t) t.^2; % change the function as you desire
for i=1:(length(x)-1) % calculation loop
k_1 = F_x(x(i));
k_2 = F_x(x(i)+0.5*h);
k_3 = F_x((x(i)+0.5*h));
k_4 = F_x((x(i)+h));
y(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h; % main equation
end
So, you want to split your 2nd order ODE to 2 1st order ODE. So your system of equations is
y' = u
u' = -y
where
y(0)=1
u(0)=0
Therefore, we can modify your program
function StackOverflow
close all
set(groot,'defaultLineLineWidth',3)
dx=pi/100;
x = (0:dx:2*pi)';
N = length(x);
Y = nan(size(x,1),2);
Y(1,:) = [1, 0];
F = { #(x,y) y(2) , #(x,y) -y(1) };
for i=1:N-1 % calculation loop
k_1 = cellfun(#(f) f(x(i) , Y(i,:)) , F);
k_2 = cellfun(#(f) f(x(i) + 0.5*dx, Y(i,:) + 0.5*dx*k_1) , F);
k_3 = cellfun(#(f) f(x(i) + 0.5*dx, Y(i,:) + 0.5*dx*k_2) , F);
k_4 = cellfun(#(f) f(x(i) + dx, Y(i,:) + dx*k_3) , F);
Y(i+1,:) = Y(i,:) + (dx/6)*(k_1+2*k_2+2*k_3+k_4); % main equation
end
y = Y(:,1);
u = Y(:,2);
figure(1)
set(gcf, 'units', 'normalized')
subplot(2,1,1)
plot(x , y , '--', x, cos(x), ':')
axis('tight')
set(gca,'fontsize',14, 'Position',[0.12 0.55 0.84 0.4])
xticks(0:pi/2:2*pi)
xticklabels({})
ylabel('$y(x)=\cos(x)$', 'Interpreter', 'latex')
subplot(2,1,2)
plot(x , u, '--', x, -sin(x), ':')
set(gca,'fontsize',14, 'Position',[0.12 0.1 0.84 0.4])
axis('tight')
xticks(0:pi/2:2*pi)
xticklabels({'0', '\pi/2', '\pi', '3\pi/2', '2\pi'})
xlabel('x', 'Interpreter', 'latex')
ylabel('$y''(x)=-\sin(x)$', 'Interpreter', 'latex')
end
How do you look at only the endpoint in time (12 in this case) and see how changing a parameter at that point, such as a scalar in one of the differential equations, changes the data?
function test
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.')
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
end
end
You can just add a parameter to your ode, and accumulate the results in cell arrays.
function test
close all
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
%// List of parameter values.
kList = 0:0.5:2;
%// Cells were save the single time histories.
tList = cell(length(kList),1);
yList = cell(length(kList),1);
%// Last values of each integration.
yEnd = zeros(length(kList), 3);
%// Loop over the parameter values.
for i = 1:length(kList)
%// Select the parameter value.
k = kList(i);
%// Call ode45 with k at the end.
[tList{i},yList{i}] = ode45(#rigid,[0 12],[0 1 1],options,k);
figure();
plot(tList{i},yList{i}(:,1),'-', ...
tList{i},yList{i}(:,2),'-.', ...
tList{i},yList{i}(:,3),'.');
yEnd(i,:) = yList{i}(end,:);
end
disp(yEnd);
%// Make the ode dependent from k.
function dy = rigid(t,y,k)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = k * y(1) * y(2);
end
end
How can I solve a 2nd order differential equation with boundary condition like z(inf)?
2(x+0.1)·z'' + 2.355·z' - 0.71·z = 0
z(0) = 1
z(inf) = 0
z'(0) = -4.805
I can't understand where the boundary value z(inf) is to be used in ode45() function.
I used in the following condition [z(0) z'(0) z(inf)], but this does not give accurate output.
function [T, Y]=test()
% some random x function
x = #(t) t;
t=[0 :.01 :7];
% integrate numerically
[T, Y] = ode45(#linearized, t, [1 -4.805 0]);
% plot the result
plot(T, Y(:,1))
% linearized ode
function dy = linearized(t,y)
dy = zeros(3,1);
dy(1) = y(2);
dy(2) = y(3);
dy(3) = (-2.355*y(2)+0.71*y(1))/((2*x(t))+0.2);
end
end
please help me to solve this differential equation.
You seem to have a fairly advanced problem on your hands, but very limited knowledge of MATLAB and/or ODE theory. I'm happy to explain more if you want, but that should be in chat (I'll invite you) or via personal e-mail (my last name AT the most popular mail service from Google DOT com)
Now that you've clarified a few things and explained the whole problem, things are a bit more clear and I was able to come up with a reasonable solution. I think the following is at least in the general direction of what you'd need to do:
function [tSpan, Y2, Y3] = test
%%# Parameters
%# Time parameters
tMax = 1e3;
tSpan = 0 : 0.01 : 7;
%# Initial values
y02 = [1 -4.805]; %# second-order ODE
y03 = [0 0 4.8403]; %# third-order ODE
%# Optimization options
opts = optimset(...
'display', 'off',...
'TolFun' , 1e-5,...
'TolX' , 1e-5);
%%# Main procedure
%# Find X so that z2(t,X) -> 0 for t -> inf
sol2 = fminsearch(#obj2, 0.9879680932400429, opts);
%# Plug this solution into the original
%# NOTE: we need dense output, which is done via deval()
Z = ode45(#(t,y) linearized2(t,y,sol2), [0 tMax], y02);
%# plot the result
Y2 = deval(Z,tSpan,1);
plot(tSpan, Y2, 'b');
%# Find X so that z3(t,X) -> 1 for t -> inf
sol3 = fminsearch(#obj3, 1.215435887288112, opts);
%# Plug this solution into the original
[~, Y3] = ode45(#(t,y) linearized3(t,y,sol3), tSpan, y03);
%# plot the result
hold on, plot(tSpan, Y3(:,1), 'r');
%# Finish plots
legend('Second order ODE', 'Third order ODE')
xlabel('T [s]')
ylabel('Function value [-]');
%%# Helper functions
%# Function to optimize X for the second-order ODE
function val = obj2(X)
[~, y] = ode45(#(t,y) linearized2(t,y,X), [0 tMax], y02);
val = abs(y(end,1));
end
%# linearized second-order ODE with parameter X
function dy = linearized2(t,y,X)
dy = [
y(2)
(-2.355*y(2) + 0.71*y(1))/2/(X*t + 0.1)
];
end
%# Function to optimize X for the third-order ODE
function val = obj3(X3)
[~, y] = ode45(#(t,y) linearized3(t,y,X3), [0 tMax], y03);
val = abs(y(end,2) - 1);
end
%# linearized third-order ODE with parameters X and Z
function dy = linearized3(t,y,X)
zt = deval(Z, t, 1);
dy = [
y(2)
y(3)
(-1 -0.1*zt + y(2) -2.5*y(3))/2/(X*t + 0.1)
];
end
end
As in my comment above, I think you're confusing a couple of things. I suspect this is what is requested:
function [T,Y] = test
tMax = 1e3;
function val = obj(X)
[~, y] = ode45(#(t,y) linearized(t,y,X), [0 tMax], [1 -4.805]);
val = abs(y(end,1));
end
% linearized ode with parameter X
function dy = linearized(t,y,X)
dy = [
y(2)
(-2.355*y(2) + 0.71*y(1))/2/(X*t + 0.1)
];
end
% Find X so that z(t,X) -> 0 for t -> inf
sol = fminsearch(#obj, 0.9879);
% Plug this ssolution into the original
[T, Y] = ode45(#(t,y) linearized(t,y,sol), [0 tMax], [1 -4.805]);
% plot the result
plot(T, Y(:,1));
end
but I can't get it to converge anymore for tMax beyond 1000 seconds. You may be running into the limits of ode45 capabilities w.r.t. accuracy (switch to ode113), or your initial value is not accurate enough, etc.