Forward Euler to solve a system of first order ODEs in Matlab - matlab

I have two first order ODEs that I got from a second order ODE:
y(0)=1
y'(0)=-1/3
u1'=u2
u2=u/9-(pi*u1*e^(x/3)*(2u2*sin(pi*x)+pi*u1cos(pi*x))
u1(0)=y(0)=1
u2(0)=y'(0)=-1/3
My question is how to set up forward Euler? I have that:
n=[0:0.01:2];
h=2./n;

Our equations are:
u1' = u2
u2' = u1/9 - \pi u1 exp(x/3)(2u2 sin(\pi x) + \pi u1 cos(\pi x))
Now the Euler Method for solving an y' = f(x,y) is:
y_{n+1} = y_{n} + h * f(x_n, y_n)
As MATLAB code, we could write this as:
h = 0.01; % Choose a step size
x = [0:h:2]; % Set up x
u = zeros(length(x),2);
u(1,:) = [1; -1/3]; % Initial Conditions for y
for ii = 2:length(x)
u(ii,:) = u(ii-1,:) + h * CalculateDeriv(x(ii-1),u(ii-1,:)); % Update u at each step
end
function deriv = CalculateDerivative(x,u)
deriv = zeros(2,1);
deriv(1) = u(2);
deriv(2) = u(1)/9 - pi*u(1)*exp(x/9)*(2*u(2)*sin(pi*x) + pi*u(1)*cos(pi*x))
end

Related

system of equation Runge-Kutta 4th order for system of equation using matlab [duplicate]

This question already has answers here:
Solve a system of equations with Runge Kutta 4: Matlab
(2 answers)
Closed 4 years ago.
I need to do matlab code to solve the system of equation by using Runge-Kutta method 4th order but in every try i got problem and can't solve
the derivative is
(d^2 y)/dx^(2) +dy/dx-2y=0
, h=0.1 Y(0)=1 , dy/dx (0)=-2
{clear all, close all, clc
%{
____________________TASK:______________________
Solve the system of differential equations below
in the interval 0<x<1, with stepsize h = 0.1.
y= y1 y(0)=0
y3= 2y1-y2 y2(0)=-2
_______________________________________________
%}
h = 0.1;
x = 0:h:1
N = length(x);
y = zeros(N,1);
y3 = zeros(N,1);
g = #(x, y, y1, y2) y1;
f = #(x, y, y1, y2) 2*y1-y2;
y1(1) = 0;
y2(1) =-2;
for i = 1:(N-1)
k_1 = x(i)+y(i)
k_11=g(x(i),y,y(i))
k_2 = (x(i)+h/2)+(y(i)+0.5*h*k_1)
k_22=g((x(i)+0.5*h),y,(y(i)+0.5*h*k_11))
k_3 = (x(i)+h/2)+(y(i)+0.5*h*k_2)
k_33=g((X(i)+0.5*h),y,(y(i)+0.5*h*k_22));
k_4 = (x(i)+h)+(y(i)+h*k_33)
k_44=g((x(i)+h),y,(y(i)+k_33*h));
y3(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h
y3(:,i)=y;
end
Answer_Matrix = [x' y3 ];}
You used functions, that's not really necessary, but it might be easier that way to see the formula more clearly. In your functions however, you list arguments that used present in the function. That's not needed, and creates unwanted overhead.
In your initial conditions you should use y and y3, since that are the ones you use in the loop. Also in the first condition you've made a typo.
In the loop you forget to call the function f, and to update the y vector.
Making these changes in your code results in the following:
h = 0.1;
x = 0:h:1;
N = length(x);
y = zeros(N,1);
y3 = zeros(N,1);
g = #(y2) y2;
f = #(y1, y2) 2*y1-y2;
y(1) = 1;
y3(1) = -2;
for i = 1:(N-1)
k_1 = f(y(i), y3(i));
k_11 = g(y3(i));
k_2 = f(y(i)+0.5*h*k_1, y3(i) +0.5*h*k_11);
k_22 = g((y3(i)+0.5*h*k_11));
k_3 = f(y(i)+0.5*h*k_2, y3(i) +0.5*h*k_22);
k_33 = g((y3(i)+0.5*h*k_22));
k_4 = f(y(i)+h*k_3, y3(i) +h*k_33);
k_44 = g((y3(i)+h*k_33));
y3(i+1) = y3(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h ;
y(i+1) = y(i) + (1/6)*(k_11+2*k_22+2*k_33+k_44)*h ;
end
Answer_Matrix = [x' y];
% solution of DE is exp(-2x) and is plotted as reference
plot(x,y,x,exp(-2*x))
As mentioned before, you can also solve this without the use of functions:
h = .1;
x = 0:h:1;
N = length(x);
% allocate memory
y = zeros(N,1);
z = zeros(N,1);
% starting values
y(1) = 1;
z(1) = -2;
for i=1:N-1
ky1 = z(i);
kz1 = -z(i) + 2*y(i);
ky2 = z(i) + h/2*kz1;
kz2 = -z(i) - h/2*kz1 + 2*y(i) + 2*h/2*ky1;
ky3 = z(i) + h/2*kz2;
kz3 = -z(i) - h/2*kz2 + 2*y(i) + 2*h/2*ky2;
ky4 = z(i) + h*kz3;
kz4 = -z(i) - h*kz3 + 2*y(i) + 2*h*ky3;
y(i+1) = y(i) + h/6*(ky1 + 2*ky2 + 2*ky3 + ky4);
z(i+1) = z(i) + h/6*(kz1 + 2*kz2 + 2*kz3 + kz4);
end
% exp(-2*x) is solution of DE and is plotted as reference
plot(x,y,x,exp(-2*x))

Solving System of Second Order Ordinary Differential Equation in Matlab

Introduction
I am using Matlab to simulate some dynamic systems through numerically solving systems of Second Order Ordinary Differential Equations using ODE45. I found a great tutorial from Mathworks (link for tutorial at end) on how to do this.
In the tutorial the system of equations is explicit in x and y as shown below:
x''=-D(y) * x' * sqrt(x'^2 + y'^2)
y''=-D(y) * y' * sqrt(x'^2 + y'^2) + g(y)
Both equations above have form y'' = f(x, x', y, y')
Question
However, I am coming across systems of equations where the variables can not be solved for explicitly as shown in the example. For example one of the systems has the following set of 3 second order ordinary differential equations:
y double prime equation
y'' - .5*L*(x''*sin(x) + x'^2*cos(x) + (k/m)*y - g = 0
x double prime equation
.33*L^2*x'' - .5*L*y''sin(x) - .33*L^2*C*cos(x) + .5*g*L*sin(x) = 0
A single prime is first derivative
A double prime is second derivative
L, g, m, k, and C are given parameters.
How can Matlab be used to numerically solve a set of second order ordinary differential equations where second order can not be explicitly solved for?
Thanks!
Your second system has the form
a11*x'' + a12*y'' = f1(x,y,x',y')
a21*x'' + a22*y'' = f2(x,y,x',y')
which you can solve as a linear system
[x'', y''] = A\f
or in this case explicitly using Cramer's rule
x'' = ( a22*f1 - a12*f2 ) / (a11*a22 - a12*a21)
y'' accordingly.
I would strongly recommend leaving the intermediate variables in the code to reduce chances for typing errors and avoid multiple computation of the same expressions.
Code could look like this (untested)
function dz = odefunc(t,z)
x=z(1); dx=z(2); y=z(3); dy=z(4);
A = [ [-.5*L*sin(x), 1] ; [.33*L^2, -0.5*L*sin(x)] ]
b = [ [dx^2*cos(x) + (k/m)*y-g]; [-.33*L^2*C*cos(x) + .5*g*L*sin(x)] ]
d2 = A\b
dz = [ dx, d2(1), dy, d2(2) ]
end
Yes your method is correct!
I post the following code below:
%Rotating Pendulum Sym Main
clc
clear all;
%Define parameters
global M K L g C;
M = 1;
K = 25.6;
L = 1;
C = 1;
g = 9.8;
% define initial values for theta, thetad, del, deld
e_0 = 1;
ed_0 = 0;
theta_0 = 0;
thetad_0 = .5;
initialValues = [e_0, ed_0, theta_0, thetad_0];
% Set a timespan
t_initial = 0;
t_final = 36;
dt = .01;
N = (t_final - t_initial)/dt;
timeSpan = linspace(t_final, t_initial, N);
% Run ode45 to get z (theta, thetad, del, deld)
[t, z] = ode45(#RotSpngHndl, timeSpan, initialValues);
%initialize variables
e = zeros(N,1);
ed = zeros(N,1);
theta = zeros(N,1);
thetad = zeros(N,1);
T = zeros(N,1);
V = zeros(N,1);
x = zeros(N,1);
y = zeros(N,1);
for i = 1:N
e(i) = z(i, 1);
ed(i) = z(i, 2);
theta(i) = z(i, 3);
thetad(i) = z(i, 4);
T(i) = .5*M*(ed(i)^2 + (1/3)*L^2*C*sin(theta(i)) + (1/3)*L^2*thetad(i)^2 - L*ed(i)*thetad(i)*sin(theta(i)));
V(i) = -M*g*(e(i) + .5*L*cos(theta(i)));
E(i) = T(i) + V(i);
end
figure(1)
plot(t, T,'r');
hold on;
plot(t, V,'b');
plot(t,E,'y');
title('Energy');
xlabel('time(sec)');
legend('Kinetic Energy', 'Potential Energy', 'Total Energy');
Here is function handle file for ode45:
function dz = RotSpngHndl(~, z)
% Define Global Parameters
global M K L g C
A = [1, -.5*L*sin(z(3));
-.5*L*sin(z(3)), (1/3)*L^2];
b = [.5*L*z(4)^2*cos(z(3)) - (K/M)*z(1) + g;
(1/3)*L^2*C*cos(z(3)) + .5*g*L*sin(z(3))];
X = A\b;
% return column vector [ed; edd; ed; edd]
dz = [z(2);
X(1);
z(4);
X(2)];

The Fastest Method of Solving System of Non-linear Equations in MATLAB

Assume we have three equations:
eq1 = x1 + (x1 - x2) * t - X == 0;
eq2 = z1 + (z1 - z2) * t - Z == 0;
eq3 = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1 == 0;
while six of known variables are:
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
So we are looking for three unknown variables that are:
X , Z and t
I wrote two method to solve it. But, since I need to run these code for 5.7 million data, it become really slow.
Method one (using "solve"):
tic
S = solve( eq1 , eq2 , eq3 , X , Z , t ,...
'ReturnConditions', true, 'Real', true);
toc
X = double(S.X(1))
Z = double(S.Z(1))
t = double(S.t(1))
results of method one:
X = 316190;
Z = 234060;
t = -2.9280;
Elapsed time is 0.770429 seconds.
Method two (using "fsolve"):
coeffs = [a,b,x1,x2,z1,z2]; % Known parameters
x0 = [ x2 ; z2 ; 1 ].'; % Initial values for iterations
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
options = optimoptions('fsolve','Display','none');
tic
M = fsolve(f_d,x0,options);
toc
results of method two:
X = 316190; % X = M(1)
Z = 234060; % Z = M(2)
t = -2.9280; % t = M(3)
Elapsed time is 0.014 seconds.
Although, the second method is faster, but it still needs to be improved. Please let me know if you have a better solution for that. Thanks
* extra information:
if you are interested to know what those 3 equations are, the first two are equations of a line in 2D and the third equation is an ellipse equation. I need to find the intersection of the line with the ellipse. Obviously, we have two points as result. But, let's forget about the second answer for simplicity.
My suggestion it's to use the second approce,which it's the recommended by matlab for nonlinear equation system.
Declare a M-function
function Y=mysistem(X)
%X(1) = X
%X(2) = t
%X(3) = Z
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
Y(1,1) = x1 + (x1 - x2) * X(2) - X(1);
Y(2,1) = z1 + (z1 - z2) * X(2) - X(3);
Y(3,1) = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1;
end
Then for solving use
x0 = [ x2 , z2 , 1 ];
M = fsolve(#mysistem,x0,options);
If you may want to reduce the default precision by changing StepTolerance (default 1e-6).
Also for more increare you may want to use the jacobian matrix for greater efficencies.
For more reference take a look in official documentation:
fsolve Nonlinear Equations with Analytic Jacobian
Basically giving the solver the Jacobian matrix of the system(and special options) you can increase method efficency.

matlab and matrix dimensions

Got one more problem with matrix multiplication in Matlab. I have to plot Taylor polynomials for the given function. This question is similar to my previous one (but this time, the function is f: R^2 -> R^3) and I can't figure out how to make the matrices in order to make it work...
function example
clf;
M = 40;
N = 20;
% domain of f(x)
x1 = linspace(0,2*pi,M).'*ones(1,N);
x2 = ones(M,1)*linspace(0,2*pi,N);
[y1,y2,y3] = F(x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','k');
axis equal;
axis vis3d;
axis manual;
hold on
% point for our Taylor polynom
xx1 = 3;
xx2 = 0.5;
[yy1,yy2,yy3] = F(xx1,xx2);
% plots one discrete point
plot3(yy1,yy2,yy3,'ro');
[y1,y2,y3] = T1(xx1,xx2,x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','g');
% given function
function [y1,y2,y3] = F(x1,x2)
% constants
R=2; r=1;
y1 = (R+r*cos(x2)).*cos(x1);
y2 = (R+r*cos(x2)).*sin(x1);
y3 = r*sin(x2);
function [y1,y2,y3] = T1(xx1,xx2,x1,x2)
dy = [
-(R + r*cos(xx2))*sin(xx1) -r*cos(xx1)*sin(xx2)
(R + r*cos(xx2))*cos(xx1) -r*sin(xx1)*sin(xx2)
0 r*cos(xx2) ];
y = F(xx1, xx2) + dy.*[x1-xx1; x2-xx2];
function [y1,y2,y3] = T2(xx1,xx2,x1,x2)
% ?
I know that my code is full of mistakes (I just need to fix my T1 function). dy represents Jacobian matrix (total derivation of f(x) - I hope I got it right...). I am not sure how would the Hessian matrix in T2 look, by I hope I will figure it out, I'm just lost in Matlab...
edit: I tried to improve my formatting - here's my Jacobian matrix
[-(R + r*cos(xx2))*sin(xx1), -r*cos(xx1)*sin(xx2)...
(R + r*cos(xx2))*cos(xx1), -r*sin(xx1)*sin(xx2)...
0, r*cos(xx2)];
function [y1,y2,y3]=T1(xx1,xx2,x1,x2)
R=2; r=1;
%derivatives
y1dx1 = -(R + r * cos(xx2)) * sin(xx1);
y1dx2 = -r * cos(xx1) * sin(xx2);
y2dx1 = (R + r * cos(xx2)) * cos(xx1);
y2dx2 = -r * sin(xx1) * sin(xx2);
y3dx1 = 0;
y3dx2 = r * cos(xx2);
%T1
[f1, f2, f3] = F(xx1, xx2);
y1 = f1 + y1dx1*(x1-xx1) + y1dx2*(x2-xx2);
y2 = f2 + y2dx1*(x1-xx1) + y2dx2*(x2-xx2);
y3 = f3 + y3dx1*(x1-xx1) + y3dx2*(x2-xx2);

How to solve a differential equation with MATLAB

i have a problem. that is :
y"^2 + 2*y'+ 3*y = sin(x), y'(0)=0, y(0)=1
I want solve this problem with MATLAB but I can't.
Can you help me ?
First, you have to reduce the order. Let z = y' => z' = y"
Your ODE then becomes
z' = sqrt(-2*z - 3*y + sin(x)), with z(0) = 0
y' = z, with y(0) = 1
You can now write a function in MATLAB to represent this ODE: (where M = [ z y ]')
function dMdx = odefunc(x,M)
z = M(1);
y = M(2);
dMdx(1) = sqrt(-2*z - 3*y + sin(x));
dMdx(2) = z;
end
You can then call this function as follows:
M0 = [ 0 1 ]; % Initial values of ODE
tfinal = 12; % Final integration time
[x,M] = ode45(#odefunc,[0 tfinal],M0) % Integration using the RK-45 algorithm