Solving Set of Second Order ODEs with Matlab ODE45 function - matlab

Introduction
NOTE IN CODE AND DISUSSION:
A single d is first derivative A double d is second derivative
I am using Matlab to simulate some dynamic systems through numerically solving the governing LaGrange Equations. Basically a set of Second Order Ordinary Differential Equations. I am using ODE45. I found a great tutorial from Mathworks (link for tutorial below) on how to solve a basic set of second order ordinary differential equations.
https://www.mathworks.com/academia/student_center/tutorials/source/computational-math/solving-ordinary-diff-equations/player.html
Based on the tutorial I simulated the motion for an elastic spring pendulum by obtaining two second order ordinary differential equations (one for angle theta and the other for spring elongation) shown below:
theta double prime equation:
M*thetadd*(L + del)^2 + M*g*sin(theta)*(L + del) + M*deld*thetad*(2*L + 2*del) = 0
del (spring elongation) double prime equation:
K*del + M*deldd - (M*thetad^2*(2*L + 2*del))/2 - M*g*cos(theta) = 0
Both equations above have form ydd = f(x, xd, y, yd)
I solved the set of equations by a common reduction of order method; setting column vector z to [theta, thetad, del, deld] and therefore zd = [thetad, thetadd, deld, deldd]. Next I used two matlab files; a simulation file and a function handle file for ode45. See code below of simulation file and function handle file:
Simulation File
%ElasticPdlmSymMainSim
clc
clear all;
%Define parameters
global M K L g;
M = 1;
K = 25.6;
L = 1;
g = 9.8;
% define initial values for theta, thetad, del, deld
theta_0 = 0;
thetad_0 = .5;
del_0 = 1;
deld_0 = 0;
initialValues = [theta_0, thetad_0, del_0, deld_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(#OdeFunHndlSpngPdlmSym, timeSpan, initialValues);
Here is the function handle file:
function dz = OdeFunHndlSpngPdlmSym(~, z)
% Define Global Parameters
global M K L g
% Take output from SymDevFElSpringPdlm.m file for fy1 and fy2 and
% substitute into z2 and z4 respectively
% z1 and z3 are simply z2 and z4
% fy1=thetadd=z(2)= -(M*g*sin(z1)*(L + z3) + M*z2*z4*(2*L + 2*z3))/(M*(L + z3)^2)
% fy2=deldd=z(4)=((M*(2*L + 2*z3)*z2^2)/2 - K*z3 + M*g*cos(z1))/M
% return column vector [thetad; thetadd; deld; deldd]
dz = [z(2);
-(M*g*sin(z(1))*(L + z(3)) + M*z(2)*z(4)*(2*L + 2*z(3)))/(M*(L + z(3))^2);
z(4);
((M*(2*L + 2*z(3))*z(2)^2)/2 - K*z(3) + M*g*cos(z(1)))/M];
Question
However, I am coming across systems of equations where the variables can not be solved for explicitly as is the case with spring pendulum example. For one case I have the following set of ordinary differential equations:
y double prime equation
ydd - .5*L*(xdd*sin(x) + xd^2*cos(x) + (k/m)*y - g = 0
x double prime equation
.33*L^2*xdd - .5*L*ydd*sin(x) - .33*L^2*C*cos(x) + .5*g*L*sin(x) = 0
L, g, m, k, and C are given parameters.
Note that x'' term appears in y'' equation and y'' term appears in x'' equation so I am not able to use reduction of order method. Can I use Matlab ODE45 to solve the set of ordinary differential equations in the second example in a manner similar to first example?
Thanks!

This problem can be solved by working out some of the math by hand. The equations are linear in xdd and ydd so it should be straightforward to solve.
ydd - .5*L*(xdd*sin(x) + xd^2*cos(x)) + (k/m)*y - g = 0
.33*L^2*xdd - .5*L*ydd*sin(x) - .33*L^2*C*cos(x) + .5*g*L*sin(x) = 0
can be rewritten as
-.5*L*sin(x)*xdd + ydd = -.5*L*xd^2*cos(x) - (k/m)*y + g
.33*L^2*xdd - .5*L*sin(x)*ydd = .33*L^2*C*cos(x) - .5*g*L*sin(x)
which is the form A*x=b.
For more complex systems, you can look into the fsolve function.

Related

Solve optimization using fmincon MATLAB when objective function is in constraints

I want to solve:
I use following MATLAB code, but it does not work.
Can someone please guide me?
function f=objfun
f=-f;
function [c1,c2,c3]=constraint(x)
a1=1.1; a2=1.1; a3=1.1;
c1=f-log(a1)-log(x(1)/(x(1)+1));
c2=f-log(a2)-log(x(2)/(x(2)+1))-log(1-x(1));
c3=f-log(a3)-log(1-x(1))-log(1-x(2));
x0=[0.01;0.01];
[x,fval]=fmincon('objfun',x0,[],[],[],[],[0;0],[1;1],'constraint')
You need to flip the problem around a bit. You are trying to find the point x (which is (l_1,l_2)) that makes the minimum of the 3 LHS functions the largest. So, you can rewrite your problem as, in pseudocode,
maximise, by varying x in [0,1] X [0,1]
min([log(a1)+log(x(1)/(x(1)+1)) ...
log(a2)+log(x(2)/(x(2)+1))+log(1-x(1)) ...
log(a3)+log(1-x(1))+log(1-x(2))])
Since Matlab has fmincon, rewrite this as a minimisation problem,
minimise, by varying x in [0,1] X [0,1]
max(-[log(a1)+log(x(1)/(x(1)+1)) ...
log(a2)+log(x(2)/(x(2)+1))+log(1-x(1)) ...
log(a3)+log(1-x(1))+log(1-x(2))])
So the actual code is
F=#(x) max(-[log(a1)+log(x(1)/(x(1)+1)) ...
log(a2)+log(x(2)/(x(2)+1))+log(1-x(1)) ...
log(a3)+log(1-x(1))+log(1-x(2))])
[L,fval]=fmincon(F,[0.5 0.5])
which returns
L =
0.3383 0.6180
fval =
1.2800
Can also solve this in the convex optimization package CVX with the following MATLAB code:
cvx_begin
variables T(1);
variables x1(1);
variables x2(1);
maximize(T)
subject to:
log(a1) + x1 - log_sum_exp([0, x1]) >= T;
log(a2) + x2 - log_sum_exp([0, x2]) + log(1 - exp(x1)) >= T;
log(a3) + log(1 - exp(x1)) + log(1 - exp(x2)) >= T;
x1 <= 0;
x2 <= 0;
cvx_end
l1 = exp(x1); l2 = exp(x2);
To use CVX, each constraint and the objective function has to be written in a way that is proveably convex using CVX's ruleset. Making the substitution x1 = log(l1) and x2 = log(l2) allows one to do that. Note that: log_sum_exp([0,x1]) = log(exp(0) + exp(x1)) = log(1 + l1)
This also returns the answers: l1 = .3383, l2 = .6180, T = -1.2800

Use Matlab/Maple to find roots of a nonlinear equation

I am having difficulty in finding roots of a nonlinear equation. I have tried Matlab and Maple both, and both give me the same error which is
Error, (in RootFinding:-NextZero) can only handle isolated zeros
The equation goes like
-100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H)
The variable is H in the equation.
How do I find the roots (or the approximate roots) of this equation?
Matlab Code:
The function file:
function hor_force = horizontal(XY, XZ, Lo, EAo, qc, VA)
syms H
equation = (-1*ZZ) + (H/qc)*(cosh((qc/H)*(XZ- XB))) - H/qc + ZB;
hor_force = `solve(equation);`
The main file:
EAo = 7.5*10^7;
Lo = 100.17;
VA = 2002;
XY = 0;
ZY = 0;
XB = 50;
ZB = -2;
XZ = 100;
ZZ = 0;
ql = 40;
Error which Matlab shows:
Error using sym/solve (line 22)
Error using maplemex
Error, (in RootFinding:-NextZero) can only handle isolated zeros
Error in horizontal (line 8)
hor_force = solve(equation);
Error in main (line 34)
h = horizontal(XY, XZ, Lo, EAo, ql, VA)
http://postimg.org/image/gm93z3b7z/
You don't need the symbolic toolbox for this:
First, create an anonymous function that can take vectors at input (use .* and ./:
equation = #(H) ((-1*ZZ) + (H./qc).*(cosh((qc./H).*(XZ- XB))) - H./qc + ZB);
Second, create a vector that you afterwards insert into the equation to find approximately when the sign of the function changes. In the end, use fzero with x0 as the second input parameter.
H = linspace(1,1e6,1e4);
x0 = H(find(diff(sign(equation(H))))); %// Approximation of when the line crosses zero
x = fzero(equation, x0) %// Use fzero to find the crossing point, using the initial guess x0
x =
2.5013e+04
equation(x)
ans =
0
To verify:
You might want to check out this question for more information about how to find roots of non-polynomials.
In Maple, using the expression from your question,
restart:
ee := -100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H):
Student:-Calculus1:-Roots(ee, -1e6..1e6);
[ 5 ]
[-1.240222868 10 , -21763.54830, 18502.23816]
#plot(ee, H=-1e6..1e6, view=-1..1);

linear two-equation system, two variables to second derivative in both

Forgive me if this is considered reposting, but I've been advised I might have given a bad format.
I'm trying to solve the two linear, second order differential equations. I want to break them into single order equations, but I can't see how as both variables have second order derivatives in both problems.
(m*a)u” + (I + m*a^2 )θ” + (d*a^2 )θ’ + (K - m*g*a)θ = 0
(M + m)u” + (m*a)θ” = -F
I've gone to some lengths with both dsolve and ode45
This is my dsolve code:
M =70-5.876;
m =5.876;
a =(((0.05)^2)+((0.13^2))^0.5);
IG = 0.0233;
d = 500;
k = 500;
g = 9.81;
f = 628;
%y is u, x is theta
syms M m a IG d k g y(t) x(t)
Dy = diff(y);
Dx = diff(x);
eqn1 = (M+m)*diff(y,2) + M*diff(x,2) == -f;
eqn2 = m*a*diff(y,2) + (IG + m*a*a)*diff(x,2) + (d*a*a)*diff(x) + (k - m*g*a)*x == 0;
t=0:0.01:10;
z = dsolve(eqn1,eqn2, y(0)==0, Dy(0)==0, x(0)==0, Dx(0)==0, 't');
z.x
z.y
It does give me very, very long equations that I can't seem to plot with respect to time and I don't know why. If anyone can advise me I'd be very grateful. Thanks for looking!
In this case u" can be replaced out of the general equation with simple algebraic manipulation. The resulting equation will be of the order:
Eq1: K1*θ” + K2*θ’ + K3*θ = -F
u can be solved directly with the solution of Eq1. Try to avoid placing u in the equation. If you must, you'll need to rewrite the equations so as to solve with the third differential of θ.

how to solve a system of Ordinary Differential Equations (ODE's) in Matlab

I have to solve a system of ordinary differential equations of the form:
dx/ds = 1/x * [y* (g + s/y) - a*x*f(x^2,y^2)]
dy/ds = 1/x * [-y * (b + y) * f()] - y/s - c
where x, and y are the variables I need to find out, and s is the independent variable; the rest are constants. I've tried to solve this with ode45 with no success so far:
y = ode45(#yprime, s, [1 1]);
function dyds = yprime(s,y)
global g a v0 d
dyds_1 = 1./y(1) .*(y(2) .* (g + s ./ y(2)) - a .* y(1) .* sqrt(y(1).^2 + (v0 + y(2)).^2));
dyds_2 = - (y(2) .* (v0 + y(2)) .* sqrt(y(1).^2 + (v0 + y(2)).^2))./y(1) - y(2)./s - d;
dyds = [dyds_1; dyds_2];
return
where #yprime has the system of equations. I get the following error message:
YPRIME returns a vector of length 0, but the length of initial
conditions vector is 2. The vector returned by YPRIME and the initial
conditions vector must have the same number of elements.
Any ideas?
thanks
Certainly, you should have a look at your function yprime. Using some simple model that shares the number of differential state variables with your problem, have a look at this example.
function dyds = yprime(s, y)
dyds = zeros(2, 1);
dyds(1) = y(1) + y(2);
dyds(2) = 0.5 * y(1);
end
yprime must return a column vector that holds the values of the two right hand sides. The input argument s can be ignored because your model is time-independent. The example you show is somewhat difficult in that it is not of the form dy/dt = f(t, y). You will have to rearrange your equations as a first step. It will help to rename x into y(1) and y into y(2).
Also, are you sure that your global g a v0 d are not empty? If any one of those variables remains uninitialized, you will be multiplying state variables with an empty matrix, eventually resulting in an empty vector dyds being returned. This can be tested with
assert(~isempty(v0), 'v0 not initialized');
in yprime, or you could employ a debugging breakpoint.
the syntax for ODE solvers is [s y]=ode45(#yprime, [1 10], [2 2])
and you dont need to do elementwise operation in your case i.e. instead of .* just use *

Solving coupled Differential Equation by Matlab or by calculations

Solving coupled non linear differential equation by Mat-lab or by calculations
equation 1: x'(t) = -a* x(t) /(x(t) + y(t))
equation 2: y'(t) = -b* y(t) /(x(t) + y(t))
I tried in mathematica but got a very comlicated solution.
Solve[{x'[t] == -a* x[t] /(x[t] + y[t]), y'[t] == -b* y[t] /(x[t] + y[t])}, {x, y}, t]
How can I plot it?
My initial conditions are
x(0) = xo
y(0) = yo
Also, a and b are constants.
I have to plot x and y wrt t after inserting values of a and b . ( a= 2 , b =5 say )
A lot of things to note in this situation:
You need to create a function that contains both a and b:
function dy =soProblem(t,y,a,b)
dy=[-a*y(1)/(y(1)+y(2)); -b*y(2)/(y(1)+y(2))];
end
Call the standard ode function:
a = 2;
b = 5; tend = 10; x0 = 1; y0 = 2;
[T,Y] = ode45(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
plot (T,Y)
Realize you may have a stiff equation on your hands.
Have fun identifying the ideal function call:
[T15,Y15] = ode15s(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
[T23t,Y23t] = ode23t(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
[T23tb,Y23tb] = ode23tb(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
%note ode23s doesn't converge (or at least takes forever)
plot (T,Y,T15,Y15,T23t,Y23t,T23tb,Y23tb)
Understand why mathematica becomes restless
In mathematica:
Try ndsolve
In matlab:
Create a function file yourfunction.m:
function [Y_prime]=yourfunction(t, Y)
Y_prime=[-2*Y(1)./(Y(1) + Y(2)) -5*Y(2)./(Y(1) + Y(2))];
end
and then
[T,Y] = ode45(yourfunction,[0 t_end],[x0 y0]);
plot(T,Y(:,1));
hold on
plot(T,Y(:,2));