MATLAB System of Dependent Differential Equations - matlab

Given a system of differential equations such as:
dy/dt = f(t)
dx/dt = g(t)
A solution can be found using dsolve, such as:
dsolve(diff(y) == f(t), diff(x) == g(t), y(0) == 1, x(0) == 1);
But what about a system where all the variables depend on each other:
dy/dt = f(y,z)
dx/dt = g(x,y)
dz/dt = h(z,x)
When approached in the same way, with initial conditions, for a system which does have a solution, I cannot find a solution.
I know the system I have tried can produce solutions as I have used a stochastic/deterministic simulator - think there's probably some strange syntax to use.
I'm specifically looking for the solution where the derivatives are all zero, if that helps.
EDIT:
Here is an example:
PX/dt = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PZ^n))))/kd_mRNA)-kd_prot*PX;
PY/dt = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PX^n))))/kd_mRNA)-kd_prot*PY;
PZ/dt = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PY^n))))/kd_mRNA)-kd_prot*PZ;
with the coefficients:
eff = 20;
KM = 40;
tau_mRNA=2.0;
tau_prot=10;
ps_a=0.5;
ps_0=5.0E-4;
t_ave = tau_mRNA/log(2);
k_tl=eff/t_ave;
a_tr=(ps_a-ps_0)*60;
a0_tr=ps_0*60;
kd_mRNA = log(2)/tau_mRNA;
kd_prot = log(2)/tau_prot;
beta = tau_mRNA/tau_prot;
alpha = a_tr*eff*tau_prot/(log(2)*KM);
alpha0 = a0_tr*eff*tau_prot/(log(2)*KM);
n=2;
And the initial conditions:
PX0 = 20;
PY0 = 0;
PZ0 = 0;
This produces a response:
This clearly has a steady state solution (all derivatives 0).
In MATLAB I have tried:
%%
syms PX(t) PY(t) PZ(t);
z = dsolve(diff(PX) == (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PZ^n))))/kd_mRNA)-kd_prot*PX, diff(PY) == (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PX^n))))/kd_mRNA)-kd_prot*PY, diff(PZ)==(k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PY^n))))/kd_mRNA)-kd_prot*PZ,PX(0)==20)
and:
%%
eq1 = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PZ^n))))/kd_mRNA)-kd_prot*PX;
eq2 = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PX^n))))/kd_mRNA)-kd_prot*PY;
eq3 = (k_tl*(a0_tr + ((a_tr*KM^n)/((KM^n) + (PY^n))))/kd_mRNA)-kd_prot*PZ;
dsolve(diff(PX)==eq1,PX(0)==20,diff(PY)==eq2,PY(0)==0,diff(PZ)==eq3,PZ(0)==0)
Both produce no errors but return an empty sym.

Your numeric solution appears to have an oscillatory component. The "steady state" may be a zero amplitude limit cycle, which is a non-trivial solution. You definitely shouldn't expect a system like this to have an easy-to-find analytic solution. The cyclic relations between your three variables also doesn't help. For what it's worth, Mathematica 10's DSolve also is unable to find a solution.
Though it won't get you to a solution, the way you're using symbolic math is less than optimal. When you use something like log(2) in a symbolic math equation, 2 should be converted to a symbolic value first. For example, sym(log(2)) yields the approximation 6243314768165359/9007199254740992, whereas log(sym(2)) returns the exact log(2). This latter form is much more likely to lead to solutions if they exist. Here's a modified version of your code, which unfortunately still returns "Warning: Explicit solution could not be found":
eff = 20;
KM = 40;
tau_mRNA=2;
tau_prot=10;
ps_a=1/sym(2);
ps_0=5/sym(10000);
ln2 = log(sym(2));
t_ave = tau_mRNA/ln2;
k_tl=eff/t_ave;
a_tr=(ps_a-ps_0)*60;
a0_tr=ps_0*60;
kd_mRNA = ln2/tau_mRNA;
kd_prot = ln2/tau_prot;
beta = tau_mRNA/tau_prot;
alpha = a_tr*eff*tau_prot/(ln2*KM);
alpha0 = a0_tr*eff*tau_prot/(ln2*KM);
n=2;
PX0 = 20;
PY0 = 0;
PZ0 = 0;
syms PX(t) PY(t) PZ(t);
eq1 = (k_tl*(a0_tr + a_tr*KM^n/(KM^n + PZ^n))/kd_mRNA)-kd_prot*PX;
eq2 = (k_tl*(a0_tr + a_tr*KM^n/(KM^n + PX^n))/kd_mRNA)-kd_prot*PY;
eq3 = (k_tl*(a0_tr + a_tr*KM^n/(KM^n + PY^n))/kd_mRNA)-kd_prot*PZ;
s = dsolve(diff(PX,t)==eq1,diff(PY,t)==eq2,diff(PZ,t)==eq3,PX(0)==20,PY(0)==0,PZ(0)==0)

Related

How to solve a system of equations which contains symbols in MATLAB?

I am trying to solve those four equations for "p, x, y, z," , which contains two parameters "b", "a", and I have used solve command as shown in the code:
clc,clear;
syms p x y z b a
eqn1 = (1)*p + (exp(0.5*b^(1/3)))*x + (exp(-0.25*b^(1/3)) * cos(0.25*sqrt(3)*b^(1/3)))*y + (exp(-0.25*b^(1/3)) * sin(0.25*sqrt(3)*b^(1/3)))*z == 0;
eqn2 = (1)*p + (exp(-0.5*b^(1/3)))*x + (exp(0.25*b^(1/3)) * cos(0.25*sqrt(3)*b^(1/3)))*y - (exp(0.25*b^(1/3)) * sin(0.25*sqrt(3)*b^(1/3)))*z == 0;
eqn3 = (b^(1/3)*exp(0.5*b^(1/3))+a*b^(2/3)*exp(0.5*b^(1/3)))*x + (-.866*b^.333*sin(.433*b^.333)*exp(-.25*b^.333)-.5*cos(.433*b^.333)*b^.333*exp(-.25*b^.333) + a(-.5*b^.666*cos(.433*b^.333)*exp(-.25*b^.333)+.866*b^.666*sin(.433*b^.333)*exp(-.25*b^.333)))*y + (.866*cos(.433*b^.333)*b^.333*exp(-.25*b^.333)-.5*b^.333*sin(.433*b^.333)*exp(-.25*b^.333)+a(-.5*b^.666*sin(.433*b^.333)*exp(-.25*b^.333)-.866*b^.666*cos(.433*b^.333)*exp(-.25*b^.333)))*z == 0;
eqn4 = (b^(1/3)*exp(-0.5*b^(1/3))-a*b^(2/3)*exp(-0.5*b^(1/3)))*x + (.866*b^.333*sin(.433*b^.333)*exp(.25*b^.333)-.5*cos(.433*b^.333)*b^.333*exp(.25*b^.333) - a(-.5*b^.666*cos(.433*b^.333)*exp(.25*b^.333)-.866*b^.666*sin(.433*b^.333)*exp(.25*b^.333)))*y + (.866*cos(.433*b^.333)*b^.333*exp(.25*b^.333)+.5*b^.333*sin(.433*b^.333)*exp(.25*b^.333)-a(.5*b^.666*sin(.433*b^.333)*exp(.25*b^.333)-.866*b^.666*cos(.433*b^.333)*exp(.25*b^.333) ))*z == 0;
sol = solve([eqn1, eqn2, eqn3, eqn4 ], [p, x, y, z]);
pSol = sol.p
xSol = sol.x
ySol = sol.y
zSol = sol.z
, but it keeps showing errors, would you please suggest any solution to this issue.
Let's look at this :
eqn3 = (b^(1/3)*exp(0.5*b^(1/3))+a*b^(2/3)*exp(0.5*b^(1/3)))*x + (-.866*b^.333*sin(.433*b^.333)*exp(-.25*b^.333)-.5*cos(.433*b^.333)*b^.333*exp(-.25*b^.333) + a(-.5*b^.666*cos(.433*b^.333)*exp(-.25*b^.333)+.866*b^.666*sin(.433*b^.333)*exp(-.25*b^.333)))*y + (.866*cos(.433*b^.333)*b^.333*exp(-.25*b^.333)-.5*b^.333*sin(.433*b^.333)*exp(-.25*b^.333)+a(-.5*b^.666*sin(.433*b^.333)*exp(-.25*b^.333)-.866*b^.666*cos(.433*b^.333)*exp(-.25*b^.333)))*z == 0;
I pick one of the wrong parts out, 4 in total.
a(-.5*b^.666
You see, if a(index) exists, index must be a positive integer. However, in your code the value of -.5*b^.666*cos(.433*b^.333)*exp(-.25*b^.333)+.866*b^.666*sin(.433*b^.333)*exp(-.25*b^.333) might not be a positive integer. And A may not even be a matrix, let alone an index.
Plus, before you post your question, you' d better check the basic grammar issues to save each other's time.

ODE solver using Lobatto IIIA with table of coefficients

So I'm trying to figure out how to solve a given equation y'=-y+2te^(-t+2) for t in [0,10], step of 0.01 and y(0)=0.
I am supposed to solve it using the Lobatto IIIA method following a Butcher tableau:
Coefficients table
So far, this is what I got:
function lob = Lobatto_solver()
h = 0.01;
t = 0:h:10;
y = zeros(size(t));
y(1) = 0;
f = #(t,y) -y + (2*t*(exp(-t+2)));
% Lobatto IIIA Method
for i=1:numel(y)-1
f1 = f(t(i), y(i));
f2 = f(t(i)+(1/2)*h, y(i) + (5/24)*h*f1 + (1/3)*h*f2 + (-1/24)*h*f3);
f3 = f(t(i)+h, y(i) + (1/6)*h*f1 + (2/3)*h*f2 + (1/6)*h*f3);
y(x) = y(i) + h*((-1/2)*f1 + (2)*f2 + (-1/2)*f3);
end
end
It obviously makes no sense from the point when I equal f2 to itself, when the variable is still undefined.
Any help would be much appreciated :)
Cheers
You will need a predictor-corrector loop, in the simple case the corrector uses the slope-equations as basis of a fixed-point iteration. In the code below I use also the value of an explicit Euler step, in principle you could initialize all slopes with f1.
function lob = Lobatto_solver()
h = 0.01;
t = 0:h:10;
y = zeros(size(t));
y(1) = 0;
f = #(t,y) -y + (2*t*(exp(-t+2)));
% Lobatto IIIA Method
for i=1:numel(y)-1
f1 = f(t(i), y(i));
f3 = f(t(i)+h, y(i)+h*f1)
f2 = (f1+f3)/2;
for k=1:3
f2 = f(t(i)+(1/2)*h, y(i) + (5/24)*h*f1 + (1/3)*h*f2 + (-1/24)*h*f3);
f3 = f(t(i)+h, y(i) + (1/6)*h*f1 + (2/3)*h*f2 + (1/6)*h*f3);
end;
y(i+1) = y(i) + h*((-1/2)*f1 + (2)*f2 + (-1/2)*f3);
end
plot(t,y,t,0.05+t.^2.*exp(-t+2))
end
The graph shows that the result (blue) is qualitatively correct, the exact solution curve (green) is shifted so that two distinct curves can be seen.

Solving mulitple nonlinear equations in MATLAB

Hi I am very new to MATLAB. I was trying to solve these equations to either get an analytical solution or solve them numerically. For the analytical solution, I get the following error:
Warning: Cannot solve symbolically. Returning a numeric approximation instead.
In solve (line 305)
Here is my code:
syms A B Ph Pl
delta = 0.1;
mu = 0.02;
sigma = 0.2;
w = 1;
k = 3;
l = 2;
beta = (0.5 - mu/sigma^2) + ((mu/sigma^2 - 0.5)^2 + 2*delta/sigma^2)^0.5;
alpha = -((0.5 - mu/sigma^2) - ((mu/sigma^2 - 0.5)^2 + 2*delta/sigma^2)^0.5);
eqn1 = (A*(Ph^(-alpha)) + (Ph/delta-mu)) -(B*Ph^beta)-k;
eqn2 = (A*Pl^(-alpha) + Pl/(delta-mu) -w/delta) - B*Pl^beta + l;
eqn3 = -alpha*A*(Ph^(-alpha-1)) + 1/(delta-mu) - (beta*B*Ph^(beta-1));
eqn4 = alpha*A*Pl^(-alpha-1)- (beta*B*Pl^(beta-1));
sol = solve([eqn1==0, eqn2==0, eqn3==0, eqn4==0], [A, B, Ph, Pl]);
Matlab is telling you it can't find an analytic solution, but it is definitely finding numerical solutions when I run it, however, they're all complex. Type:
sol.A
in your command window to see what A looks like, same with B, Ph and Pl.

Matlab - Unexpected Results from Differential Equation Solver Ode45

I am trying to solve a differential equation with the ode solver ode45 with MATLAB. I have tried using it with other simpler functions and let it plot the function. They all look correct, but when I plug in the function that I need to solve, it fails. The plot starts off at y(0) = 1 but starts decreasing at some point when it should have been an increasing function all the way up to its critical point.
function [xpts,soln] = diffsolver(p1x,p2x,p3x,p1rr,y0)
syms x y
yp = matlabFunction((p3x/p1x) - (p2x/p1x) * y);
[xpts,soln] = ode45(yp,[0 p1rr],y0);
p1x, p2x, and p3x are polynomials and they are passed into this diffsolver function as parameters.
p1rr here is the critical point. The function should diverge after the critical point, so i want to integrate it up to that point.
EDIT: Here is the code that I have before using diffsolver, the above function. I do pade approximation to find the polynomials p1, p2, and p3. Then i find the critical point, which is the root of p1 that is closest to the target (target is specified by user).
I check if the critical point is empty (sometimes there might not be a critical point in some functions). If its not empty, then it uses the above function to solve the differential equation. Then it plots the x- and y- points returned from the above function basically.
function error = padeapprox(m,n,j)
global f df p1 p2 p3 N target
error = 0;
size = m + n + j + 2;
A = zeros(size,size);
for i = 1:m
A((i + 1):size,i) = df(1:(size - i));
end
for i = (m + 1):(m + n + 1)
A((i - m):size,i) = f(1:(size + 1 - i + m));
end
for i = (m + n + 2):size
A(i - (m + n + 1),i) = -1;
end
if det(A) == 0
error = 1;
fprintf('Warning: Matrix is singular.\n');
end
V = -A\df(1:size);
p1 = [1];
for i = 1:m
p1 = [p1; V(i)];
end
p2 = [];
for i = (m + 1):(m + n + 1)
p2 = [p2; V(i)];
end
p3 = [];
for i = (m + n + 2):size
p3 = [p3; V(i)];
end
fx = poly2sym(f(end:-1:1));
dfx = poly2sym(df(end:-1:1));
p1x = poly2sym(p1(end:-1:1));
p2x = poly2sym(p2(end:-1:1));
p3x = poly2sym(p3(end:-1:1));
p3fullx = p1x * dfx + p2x * fx;
p3full = sym2poly(p3fullx); p3full = p3full(end:-1:1);
p1r = roots(p1(end:-1:1));
p1rr = findroots(p1r,target); % findroots eliminates unreal roots and chooses the one closest to the target
if ~isempty(p1rr)
[xpts,soln] = diffsolver(p1x,p2x,p3fullx,p1rr,f(1));
if rcond(A) >= 1e-10
plot(xpts,soln); axis([0 p1rr 0 5]); hold all
end
end
I saw some examples using another function to generate the differential equation but i've tried using the matlabFunction() method with other simpler functions and it seems like it works. Its just that when I try to solve this function, it fails. The solved values start becoming negative when they should all be positive.
I also tried using another solver, dsolve(). But it gives me an implicit solution all the time...
Does anyone have an idea why this is happening? Any advice is appreciated. Thank you!
Since your code seems to work for simpler functions, you could try to increase the accuracy options of the ode45 solver.
This can be achieved by using odeset:
options = odeset('RelTol',1e-10,'AbsTol',1e-10);
[T,Y] = ode45(#function,[tspan],[y0],options);

Fourth-order Runge–Kutta method (RK4) collapses after a few iterations

I'm trying to solve:
x' = 60*x - 0.2*x*y;
y' = 0.01*x*y - 100* y;
using the fourth-order Runge-Kutta algorithm.
Starting points: x(0) = 8000, y(0) = 300 range: [0,15]
Here's the complete function:
function [xx yy time r] = rk4_m(x,y,step)
A = 0;
B = 15;
h = step;
iteration=0;
t = tic;
xh2 = x;
yh2 = y;
rr = zeros(floor(15/step)-1,1);
xx = zeros(floor(15/step)-1,1);
yy = zeros(floor(15/step)-1,1);
AA = zeros(1, floor(15/step)-1);
while( A < B)
A = A+h;
iteration = iteration + 1;
xx(iteration) = x;
yy(iteration) = y;
AA(iteration) = A;
[x y] = rkstep(x,y,h);
for h2=0:1
[xh2 yh2] = rkstep(xh2,yh2,h/2);
end
r(iteration)=abs(y-yh2);
end
time = toc(t);
xlabel('Range');
ylabel('Value');
hold on
plot(AA,xx,'b');
plot(AA,yy,'g');
plot(AA,r,'r');
fprintf('Solution:\n');
fprintf('x: %f\n', x);
fprintf('y: %f\n', y);
fprintf('A: %f\n', A);
fprintf('Time: %f\n', time);
end
function [xnext, ynext] = rkstep(xcur, ycur, h)
kx1 = f_prim_x(xcur,ycur);
ky1 = f_prim_y(xcur,ycur);
kx2 = f_prim_x(xcur+0.5*h,ycur+0.5*h*kx1);
kx3 = f_prim_x(xcur+0.5*h,ycur+0.5*h*kx2);
kx4 = f_prim_x(xcur+h,ycur+h*kx3);
ky2 = f_prim_y(xcur+0.5*h*ky1,ycur+0.5*h);
ky3 = f_prim_y(xcur+0.5*h*ky2,ycur+0.5*h);
ky4 = f_prim_y(xcur+h*ky2,ycur+h);
xnext = xcur + (1/6)*h*(kx1 + 2*kx2 + 2*kx3 + kx4);
ynext = ycur + (1/6)*h*(ky1 + 2*ky2 + 2*ky3 + ky4);
end
function [fx] = f_prim_x(x,y)
fx = 60*x - 0.2*x*y;
end
function [fy] = f_prim_y(x,y)
fy = 0.01*x*y - 100*y;
end
And I'm running it by executing: [xx yy time] = rk4_m(8000,300,10)
The problem is that everything collapses after 2-3 iterations returning useless results. What am I doing wrong? Or is just this method not appropriate for this kind equation?
The semicolons are intentionally omitted.
Looks like I didn't pay attention to actual h size. It works now! Thanks!
Looks like some form of the Lotka-Volterra equation?
I'm not sure if if your initial condition is [300;8000] or [8000;300] (you specify it both ways above), but regardless, you have an oscillatory system that you're trying to integrate with a large fixed time step that is (much) greater than the period of oscillation. This is why your error explodes. If you try increasing n (say, 1e6), you'll find that eventually you'll get a stable solution (assuming that your Runge-Kutta implementation is otherwise correct).
Is there a reason why you're not using Matlab's builtin ODE solvers, e.g. ode45 or ode15s?
function ode45demo
[t,y]=odeode45(#f,[0 15],[300;8000]);
figure;
plot(t,y);
function ydot=f(t,y)
ydot(1,1) = 60*y(1) - 0.2*y(1)*y(2);
ydot(2,1) = 0.01*y(1)*y(2) - 100*y(2);
You'll find that adaptive step size solvers are much more efficient for these types of oscillatory problems. Because your system has such a high frequency and seems rather stiff, I suggest that you also look at what ode15s gives and/or adjust the 'AbsTol' and 'RelTol' options with odeset.
The immediate problem is that the RK4 code was not completely evolved from the scalar case to the case of two coupled equations. Note that there is no time parameter in the derivative funtions. x and y are both dependent variables and thus get the slope update defined by the derivative functions in every step. Then xcur gets the kx updates and ycur gets the ky updates.
function [xnext, ynext] = rkstep(xcur, ycur, h)
kx1 = f_prim_x(xcur,ycur);
ky1 = f_prim_y(xcur,ycur);
kx2 = f_prim_x(xcur+0.5*h*kx1,ycur+0.5*h*ky1);
ky2 = f_prim_y(xcur+0.5*h*kx1,ycur+0.5*h*ky1);
kx3 = f_prim_x(xcur+0.5*h*kx2,ycur+0.5*h*ky2);
ky3 = f_prim_y(xcur+0.5*h*kx2,ycur+0.5*h*ky2);
kx4 = f_prim_x(xcur+h*kx3,ycur+h*ky3);
ky4 = f_prim_y(xcur+h*kx3,ycur+h*ky3);
xnext = xcur + (1/6)*h*(kx1 + 2*kx2 + 2*kx3 + kx4);
ynext = ycur + (1/6)*h*(ky1 + 2*ky2 + 2*ky3 + ky4);
end