Simple script that computes a solution of linear ODEs giving wrong result - matlab

this a question that envolves both programming and mathematics. So, I'm trying to write a code that computes the general solution of a system of linear ODEs described by . The mathematical formula it's shown above:
where the greek symbol \PHI that appers in the equation is the expm(A*t)
clear all
A=[-2]; %system matrix
t0=1; %initial time of simulation
tf=2; %final time of simulation
syms t x_0
x0=x_0;
hom=expm(A*t); %hom means "homogeneous solution"
hom_initialcond=hom*x0;%this is the homogeneous solution multiplied by the initial conditon
invhom=inv(hom); %this is the inverse of the greek letter at which, multiplied by the input of the system, composes the integrand of the integral
g=5*cos(2*t); %system input
integrand=invhom*g; %computation of the integrand
integral=int(integrand,t0,t); %computation of the definite integral from t0 to t, as shown by the math formula
partsol=hom*integral; %this is the particular solution
gen_sol=partsol+hom_initialcond %this is the general solution
x_0=1; %this is the initial condition
t=linspace(t0,tf); %vector of time from t0 to tf
y=double(subs(gen_sol)); %here I am evaluating my symbolic expression
plot(t,y)
The problem is that my plot of the ODE's solution it's not looking well, as you can see:
The solution it's wrong because the curve shown in the graph doesnt start at the initial value equals 1. But the shape it's very similar from the plot gave by the MATLAB ODE solver:
However, if I set t0=0 then the plot gave by my code and by MATLAB solver it's exacly equal to each other. So, my code it's fine for t0=0 but with any other values my code goes wrong.

The general solution in terms of fundamental matrices is
or more often seen as
But since the initial time is often taken to be zero, the inverse of the fundamental matrix is often omitted since it is the identity for linear, constant coefficient problems at zero (i.e., expm(zeros(n)) == eye(n)) and the c vector is equivalent to the initial condition vector.
Swapping some of the lines around near your symbolic declaration to this
syms t x_0 c_0
hom = expm(A*t) ;
invhom = inv(hom) ;
invhom_0 = subs(invhom,t,sym(t0)) ;
c_0 = invhom_0 * x_0 ;
hom_initialcond = hom * c_0 ;
should provide the correct solution for non-zero initial time.

Related

matlab solving numerical differential equations [pic]

I'm trying to solve this numerical differential equations, can someone help?
clc;
clear;
syms A1(z) A2(z)
lamda1 = 1560*(10^-9);
c=3*(10^8);
d_eff=27*(10^-12);
omga1=(2*pi*c)/(lamda1);
omga2=omga1*2;
n=2.2;
k1=(n*omga1)/c;
k2=(n*omga2)/c;
ode1 = diff(A1) == (2*i*(omga1^2)*d_eff*A2*conj(A1)*exp(-i*(2*k1-k2)*z))/(k1*(c^2));
ode2 = diff(A2) == (i*(omga2^2)*d_eff.*(A1.^2).*exp(i*(2*k1-k2)*z))/(k2*(c^2));
odes = [ode1; ode2];
cond1 = A1(0) == 1;
cond2 = A2(0) == 0;
conds = [cond1; cond2];
M = matlabFunction(odes)
sol = ode45(M(1),[0 20],[2 0]);
in this question both ODE are coupled, hence there's only 1 ODE to solve:
1.- use 1st equation to write
A1=f(A2,dA2/dz)
and feed this expression into 2nd equation.
2.- regroup
n1=1j*k1^4/k2^2*1/deff*.25
n2=1j*3*(k1-k2)
now the ODE to solve is
y'=n1/y^2*exp(n2*z)
3.- It can obviously be done in MATLAB, but for this particular ODE in my opinion the Wolfram online ODE Symbolic Solver does a better job.
Input the obtained ODE of previous point into the ODE solver available in this link
https://www.wolframalpha.com/input?i=y%27%27+%2B+y+%3D+0
and solve
4.- The general (symbolic) solutions for A2 are
Note that I used k1 instead of n1 and k2 instead of n2 just in the Wolfram ODE Solver.
Rewording ; the k1 k2 expressions of the general solutions are not the wave numbers k1 k2 of the equations in the question. Just replace accordingly.
5.- Now get A1 using expression in point 2.
6.- I have spotted 2 possible errors in the MATLAB code posted in the question that shouldn't be ignored by the question originator:
In the far right side of the posted MATLAB code, the exponential expressions
6.1.- both show
exp(-i(2*k1-k2)z))/(k1(c^2))
there's this (k1*(c^2)) dividing the exponent wheras in the question none of the exponentials show such denominator their respective exponents.
6.2.- the dk or delta k expression in the exponentials of the question are obviously k2-k1 or k1-k2 , here there may be room for a sign ambiguity, that may shoot a wave solution onto the opposite direction, yet the point here is where
*exp(-1i*(2*k1-k2)*z)
should probably be
*exp(-1i*2*(k1-k2)*z)
or just
exp(-1i*(k1-k2)*z)
6.3.- and yes, in MATLAB (-1)^.5 can be either expressed with 1j or 1i but as written in the MATLAB code made available in the question, since only a chunk of code has been made available, it's fair to assume that no such i=1j has been done.

Equation system with derivatives

I have to solve the following system:
X'(t) = -D(t)x(t)+μ(s(t), p(t))x(t);
S'(t) = D(t)(s(t)^in - s(t)) - Yxsμ(s(t), p(t))x(t)
p'(t) = -D(t)p(t)+(aμ(s(t), p(t))+b)x(t)
where
μ(s(t), p(t)) = Μmax ((1 - (p(t)/pm))s(t)) / (km+s(t)+(s(t) ^ 2)/ki)
where Yxs, a,b, Mmax, Pm, km, ki are constant variables, then I have to linearizate the system and find the balance Points of thiw system. any suggestion how to do it with Matlab or Mathematica??
Matlab can help with some steps, but there might be few where you do have to write down some equations yourself.
To start with a simple side note: Matlabs ODE45 function allows to simulate any function of the form dx/dt = f(x,u), regardless of how non-linear or time variant they might become.
to linearize such a system, you need to derive a jacobian matrix and substitute the linearization point in this matrix. This linearization point is any point where all state derivatives equal 0, it does not need to be a balance point. However, it is desired to have it a balance point as this means the linearization point is a stable equilibrium.
So in MATLAB:
create symbolic variables for all states and inputs (so x(t), s(t) and p(t))
create symbolic state equations dx/dt = f(x,u) and output equation y = g(x,u)
derive symbolic State space matrices A,B,C,D using the "jacobian" function
substitute linearization point in these symbolic state space matrices using "subs"
use eval(symbolic matrix) to retrieve a numeric matrix.
Depending on the non-linear complexity and the chosen linearization point, the linearized system might only within acceptable bounds from the actual system for a very tight region, so be aware of that.

How to solve equations with complex coefficients using ode45 in MATLAB?

I am trying to solve two equations with complex coefficients using ode45.
But iam getting an error message as "Inputs must be floats, namely single or
double."
X = sym(['[',sprintf('X(%d) ',1:2),']']);
Eqns=[-(X(1)*23788605396486326904946699391889*1i)/38685626227668133590597632 + (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632; (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632 + X(1)*(- 2500000 + (5223289665997855453060886952725538686654593059791*1i)/324518553658426726783156020576256)] ;
f=#(t,X)[Eqns];
[t,Xabc]=ode45(f,[0 300*10^-6],[0 1])
How can i fix this ? Can somebody can help me ?
Per the MathWorks Support Team, the "ODE solvers in MATLAB 5 (R12) and later releases properly handle complex valued systems." So the complex numbers are the not the issue.
The error "Inputs must be floats, namely single or double." stems from your definition of f using Symbolic Variables that are, unlike complex numbers, not floats. The easiest way to get around this is to not use the Symbolic Toolbox at all; just makes Eqns an anonymous function:
Eqns= #(t,X) [-(X(1)*23788605396486326904946699391889*1i)/38685626227668133590597632 + (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632; (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632 + X(1)*(- 2500000 + (5223289665997855453060886952725538686654593059791*1i)/324518553658426726783156020576256)] ;
[t,Xabc]=ode45(Eqns,[0 300*10^-6],[0 1]);
That being said, I'd like to point out that numerically time integrating this system over 300 microseconds (I assume without units given) will take a long time since your coefficient matrix has imaginary eigenvalues on the order of 10E+10. The extremely short wavelength of those oscillations will more than likely be resolved by Matlab's adaptive methods, and that will take a while to solve for a time span just a few orders greater than the wavelength.
I'd, therefore, suggest an analytical approach to this problem; unless it is a stepping stone another problem that is non-analytically solvable.
Systems of ordinary differential equations of the form
,
which is a linear, homogenous system with a constant coefficient matrix, has the general solution
,
where the m-subscripted exponential function is the matrix exponential.
Therefore, the analytical solution to the system can be calculated exactly assuming the matrix exponential can be calculated.
In Matlab, the matrix exponential is calculate via the expm function.
The following code computes the analytical solution and compares it to the numerical one for a short time span:
% Set-up
A = [-23788605396486326904946699391889i/38685626227668133590597632,23788605396486326904946699391889i/38685626227668133590597632;...
-2500000+5223289665997855453060886952725538686654593059791i/324518553658426726783156020576256,23788605396486326904946699391889i/38685626227668133590597632];
Eqns = #(t,X) A*X;
X0 = [0;1];
% Numerical
options = odeset('RelTol',1E-8,'AbsTol',1E-8);
[t,Xabc]=ode45(Eqns,[0 1E-9],X0,options);
% Analytical
Xana = cell2mat(arrayfun(#(tk) expm(A*tk)*X0,t,'UniformOutput',false)')';
k = 1;
% Plots
figure(1);
subplot(3,1,1)
plot(t,abs(Xana(:,k)),t,abs(Xabc(:,k)),'--');
title('Magnitude');
subplot(3,1,2)
plot(t,real(Xana(:,k)),t,real(Xabc(:,k)),'--');
title('Real');
ylabel('Values');
subplot(3,1,3)
plot(t,imag(Xana(:,k)),t,imag(Xabc(:,k)),'--');
title('Imaginary');
xlabel('Time');
The comparison plot is:
The output of ode45 matches the magnitude and real parts of the solution very well, but the imaginary portion is out-of-phase by exactly π.
However, since ode45's error estimator only looks at norms, the phase difference is not noticed which may lead to problems depending on the application.
It will be noted that while the matrix exponential solution is far more costly than ode45 for the same number of time vector elements, the analytical solution will produce the exact solution for any time vector of any density given to it. So for long time solutions, the matrix exponential can be viewed as an improvement in some sense.

matlab differential equation

I have the following differential equation which I'm not able to solve.
We know the following about the equation:
D(r) is a third grade polynom
D'(1)=D'(2)=0
D(2)=2D(1)
u(1)=450
u'(2)=-K * (u(2)-Te)
Where K and Te are constants.
I want to approximate the problem using a matrix and I managed to solve
the similiar equation: with the same limit conditions for u(1) and u'(2).
On this equation I approximated u' and u'' with central differences and used a finite difference method between r=1 to r=2. I then placed the results in a matrix A in matlab and the limit conditions in the vector Y in matlab and ran u=A\Y to get how the u value changes. Heres my matlab code for the equation I managed to solve:
clear
a=1;
b=2;
N=100;
h = (b-a)/N;
K=3.20;
Ti=450;
Te=20;
A = zeros(N+2);
A(1,1)=1;
A(end,end)=1/(2*h*K);
A(end,end-1)=1;
A(end,end-2)=-1/(2*h*K);
r=a+h:h:b;
%y(i)
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
A(2:end-1,2:end-1)=A(2:end-1,2:end-1)+diag(yi);
%y(i-1)
for i=1:1:length(r)-1
ymin(i)=r(i+1)*(1/(h^2))-1/(2*h);
end
A(3:end-1,2:end-2) = A(3:end-1,2:end-2)+diag(ymin);
%y(i+1)
for i=1:1:length(r)
ymax(i)=r(i)*(1/(h^2))+1/(2*h);
end
A(2:end-1,3:end)=A(2:end-1,3:end)+diag(ymax);
Y=zeros(N+2,1);
Y(1) =Ti;
Y(2)=-(Ti*(r(1)/(h^2)-(1/(2*h))));
Y(end) = Te;
r=[1,r];
u=A\Y;
plot(r,u(1:end-1));
My question is, how do I solve the first differential equation?
As TroyHaskin pointed out in comments, one can determine D up to a constant factor, and that constant factor cancels out in D'/D anyway. Put another way: we can assume that D(1)=1 (a convenient number), since D can be multiplied by any constant. Now it's easy to find the coefficients (done with Wolfram Alpha), and the polynomial turns out to be
D(r) = -2r^3+9r^2-12r+6
with derivative D'(r) = -6r^2+18r-12. (There is also a smarter way to find the polynomial by starting with D', which is quadratic with known roots.)
I would probably use this information right away, computing the coefficient k of the first derivative:
r = a+h:h:b;
k = 1+r.*(-6*r.^2+18*r-12)./(-2*r.^3+9*r.^2-12*r+6);
It seems that k is always positive on the interval [1,2], so if you want to minimize the changes to existing code, just replace r(i) by r(i)/k(i) in it.
By the way, instead of loops like
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
one usually does simply
yi=-r*(2/(h^2));
This vectorization makes the code more compact and can benefit the performance too (not so much in your example, where solving the linear system is the bottleneck). Another benefit is that yi is properly initialized, while with your loop construction, if yi happened to already exist and have length greater than length(r), the resulting array would have extraneous entries. (This is a potential source of hard-to-track bugs.)

ODE System, IVP with differential initial condition

I am trying to model a system of three differential equations. This is a droplet model, parametrized vs the arc length, s.
The equations are:
dx/ds=cos(theta)
dz/ds=sin(theta)
(theta)/ds=2*b+c*z-sin(theta)/x
The initial conditions are that x,z, and theta are all 0 at s=0. To avoid the singularity on d(theta)/ds, I also have the condition that, at s=0, d(theta)/ds=b. I have already written this code:
[s,x]=ode23(#(s,x)drpivp(s,x,p),sspan,x0);
%where p contains two parameters and x0 contains initial angle theta, x, z values.
%droplet ODE function:
function drpivp = drpivp(s,x,p);
%x(1)=theta
%x(2)=x
%x(3)=z
%b is curvature at apex
%c is capillarity constant
b=p(1);
c=p(2);
drpivp=[2/p(1)+p(2)*x(3)-sin(x(1))/x(2); cos(x(1)); sin(x(1))];
Which yields a solution that spirals out. Instead of creating one droplet profile, it creates many. Of course, here I have not initialized the equation properly, because I am not certain how to use a different equation for theta at s=0.
So the question is: How do I include the initial condition that d(theta)/ds=b instead of it's usual at s=0? Is this possible using the built-in solvers on matlab?
Thanks.
There are several ways of doing this, the easiest is to simply add an if statement into your equation:
function drpivp = drpivp(s,x,p);
%x(1)=theta
%x(2)=x
%x(3)=z
%b is curvature at apex
%c is capillarity constant
b=p(1);
c=p(2);
if (s == 0)
drpivp=[b; cos(x(1)); sin(x(1))];
else
drpivp=[2/p(1)+p(2)*x(3)-sin(x(1))/x(2); cos(x(1)); sin(x(1))];
end