How to include a Piecewise
2 views (last 30 days)
Show older comments
syms t f(t) g(t)
p= piecewise (0<=t<=1,5, 1<t<=2, 10, 2<t<=3, 15, 3<t<=4, 20, 4<t<=5, 25);
Eqs =[diff(f,1) == (p)*(1-f*g)*g, diff(g,1) == ((f^2)*((g)/(1-g)))];
g = odeToVectorField(Eqs);
Sys = matlabFunction(g);
tspan=[0 25];
Y0=[11 23];
[t,y] = ode45(@(t,Y) Sys(Y),tspan, Y0);
I am trying to include a piecewise function into the differential equation and I tried to use if, elseif, else loops. When I run this code it says "Error using symengine Unable to generate code for piecewise for use in anonymous functions."
0 Comments
Answers (1)
Walter Roberson
on 2 Jul 2018
You could use the 'File' option to matlabFunction. When you tell it to write to a file, then it is able to generate code for piecewise()
clearvars
syms f(t) g(t) Y
p = piecewise(0<=t<=1,5, 1<t<=2, 10, 2<t<=3, 15, 3<t<=4, 20, 4<t<=5, 25);
Eqs = [diff(f,1) == (p)*(1-f*g)*g, diff(g,1) == ((f^2)*((g)/(1-g)))];
[gfunc, vars] = odeToVectorField(Eqs);
Sys = matlabFunction(gfunc, 'vars', [t, Y], 'file', 'gfunc.m');
tspan=[0 25];
Y0=[11 23];
[t,y] = ode45(Sys, tspan, Y0);
If you plot(t,y) you will notice that the plot stops after t = 5. You did not define any value for p for t < 0 or t > 5 so piecewise will assign nan for those values.
You need to be careful about the order of your initial bounds. There is an optional second output to odeToVectorField that shows the substitutions that have been made. When I use that, I see that the order is [g; f], implying that Y0 needs to be in the order [g(0); f(0)] which might not be the case for your Y0. I do not know how it chooses the order for the variables.
However, you have a worse problem: you can never use ode*() with discontinuous functions. If you are lucky it will detect the discontinuity and complain; if you are not lucky (as is the case here) it will simply give you the wrong answer.
If you have discontinuities in your functions, then you need to control tspan to only handle one condition at a time if the conditions are time based; if the conditions are not time based then you need to use event functions to terminate at the boundaries. Each time you terminate, you would start another ode45() call using the last y outputs of the previous call as the y0 value for the new call, and having adjusted the function to the new piecewise condition. If you use an event function for this control then there is no fixed number of times that you will need to call ode45() again: you might find that after only another 3 to 5 iterations that the value of the variable has crossed the boundary in the other direction.
(I notice that there there is no closed form solution for your system.)
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!