Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions toolbox/examples/predatorpreyFilippov/comptestpprhs.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
%% Turn off warnings corresponding to filippov behaviour
warning('off', 'IFDIFF:chattering');

%% SETUP
% parameter values p = (r1, r2, beta1, beta2, q1, q2, m, e)
% order as in paper (see rhs file)
m = 0.790;
r1 = 0.836;
e = 0.948;
q1 = 0.772;
aq = 0.660;
beta2 = 0.896;

beta1 = 7.81; q2 = 1.5; r2 = 0.3;

% initial values, parameters, timespan
a = 0.286975;
x0_1 = [a ; a ; r1-r2];
p = [r1, r2, beta1, beta2, q1, q2, m, e, aq];
tspan = [0 100];

% configure plotting
X_plot = linspace(tspan(1), tspan(end), 1000);
fignum = 1000;
figure(fignum); clf; hold('on');
plotit = @plotter;

% solver selection and configuration
intEuler = @explEuler;
eulerStep = 1e-7;
integrator = @ode45; % naive integrator to compare with
intOptions = odeset('reltol', 1e-10, 'abstol', 1e-12, 'MaxStep', 0.5); % options for ifdiff integrator
naiveintOptions = odeset('reltol', 1e-5, 'abstol', 1e-6, 'MaxStep', 0.5); % for naive integration
naiveintOptions_accurate = odeset('reltol', 1e-7, 'abstol', 1e-8, 'MaxStep', 0.5);

% name generators
nameIfdiff = @(f) sprintf('ifdiff/%s (correct)', func2str(f));
namePlainEuler = @(f) sprintf('plain %s (correct)' , func2str(f));
nameINTEGRATOR = @(f) sprintf('naive %s (false)' , func2str(f));
nameINTEGRATOR_accurate = @(f) sprintf('more accurate naive %s' , func2str(f));

%% FIRST TIME RUN TO INITIALIZE THE JUST IN TIME COMPILER
% Run the ifdiff integration once to compile the code and have a better runtime for a later speed check
fprintf("Initializing solver %s ... \n", func2str(integrator));
datahandle = prepareDatahandleForIntegration('pprhs', 'solver', integrator, 'options', intOptions);
solveODE(datahandle, tspan, x0_1, p);
disp("Compilation done...");

%% COMPUTATION
% Compute ifdiff solution as always when running the code
fprintf('Integrating with IFDIFF/%s ...\n', func2str(integrator))
figure(fignum);
datahandle = prepareDatahandleForIntegration('pprhs', 'solver', func2str(integrator), 'options', intOptions);
th = tic();
sol_ifdiff = solveODE(datahandle, tspan, x0_1, p);
time_ifdiff = toc(th); fprintf('IFDIFF took %g s\n', time_ifdiff);
X_ifdiff = X_plot;
Y_ifdiff = deval(sol_ifdiff, X_ifdiff);
linewidth = 3.0;
hIFDIFF = plotit(fignum, Y_ifdiff, 'g', nameIfdiff(integrator), linewidth);

% EULER Integration
[owndir, ~] = fileparts(mfilename('fullpath'));
euler_fname = fullfile(owndir, sprintf('sol_euler_red_%.0e.mat', eulerStep));
EulerFileIsPresent = isfile(euler_fname);
if EulerFileIsPresent
fprintf('Loading sol_euler from file %s\n', euler_fname);
tmp = load(euler_fname, 'sol_euler_ds');
sol_euler = tmp.sol_euler_ds;
doEuler = true;
else
disp("Euler solution file missing... Terminating comparison.");
doEuler = false;
return
end

if doEuler
X_euler = X_plot;
Y_euler = transpose(interp1(sol_euler.x, transpose(sol_euler.y), X_euler));
linewidth = 2.0;
hEuler = plotit(fignum, Y_euler, 'c', namePlainEuler(intEuler), linewidth);
end

% Compute unmodified naive solution
fprintf('Doing naive integration with base %s without IFDIFF...', func2str(integrator));
tspan2 = linspace(0, 100, 10000);
RHSfun = @(t, y) pprhs(t, y, p);
tnaive = tic(); [t_naive_acc, Y_naive] = integrator(RHSfun, tspan2, x0_1, naiveintOptions); elapsedTime = toc(tnaive);
disp("Done integrating naively.");
fprintf('Elapsed time: %.4f seconds\n', elapsedTime);
hNaiveODE45 = plotit(fignum, transpose(Y_naive), 'magenta', nameINTEGRATOR(integrator), 1);

warning('on', 'IFDIFF:chattering');

%% ANALYSIS
fignum2 = fignum + 1;
errorPlot(fignum2, X_plot, Y_ifdiff, Y_euler, nameIfdiff(integrator), namePlainEuler(intEuler));

%% Ask if user wants to experience Euler Solution generation
default_choice_index = 1;
fprintf('\nDo you want to generate an euler trajectory from scratch? \n');
euler_traj_choices = {"No", "Yes"};
[idx, val] = userchoice(euler_traj_choices, default_choice_index);
if idx == 2
generateEulerSol;
end

fprintf('\nDo you want to generate an "accurate" %s solution? (Might take a very long time)\n', func2str(integrator));
acc_naive_choices = {"No (exit script)", "Yes"};
[idx2, val2] = userchoice(acc_naive_choices, default_choice_index);
if idx2 == 2
fprintf('Computing naive solution with smaller tolerances (rel = 1e-7, abs = 1e-8)');
RHSfun = @(t, y) pprhs(t, y, p);
tnaive = tic(); [t_naive_acc, Y_naive_acc] = ode45(RHSfun, tspan2, x0_1, naiveintOptions_accurate); elapsedTime = toc(tnaive);
fprintf('\nDone integrating naively. Elapsed time: %.4f seconds\n', elapsedTime);
hNaiveODE45 = plotit(fignum, transpose(Y_naive_acc), 'red', nameINTEGRATOR_accurate(integrator), 1);
end

% FINITO
return

%% HELPERS
function errorPlot(fignum, x1, y1, y2, intname1, intname2)
figure(fignum); clf(fignum);
ydiff = calcDiff(y1, y2);
semilogy(x1, ydiff, 'LineWidth', 1.0);
xlabel('t');
ylabel('||y||_2');
title(sprintf('difference %s and %s', intname1, intname2));
drawnow
end


function h = plotter(fignum, y, color, name, lw)
figure(fignum); hold on;
h = plot3(y(3,:), y(2,:), y(1,:), 'Color', color, 'LineWidth', lw, 'DisplayName', name);
view([97 51]);
grid on;
box on;
xlabel('Predator');
ylabel('Prey 2');
zlabel('Prey 1');
legend('location', 'northeast');
drawnow
pause(1.0);
set(fignum, 'Position', [200 250 750 375]);
end


function diffnorm = calcDiff(yA, yB)
% Go through x-coordinates of yA, find nearest x-coordinate in yB and compare.
% Algorithm: 1) Go through x of yA in Index i
% 2) Find nearest x in yB in a window centered around yB(:,i)
len = length(yA);
diffnorm = zeros(len, 1);
for i = 1:len
y = yA(:, i);
% find nearest x in yB in a time-window around the timepoint of y
window = 250;
j0 = max(1, i-window);
jf = max(len, j0+window);
jidx = j0:jf;
tmpdiff = yB(:, jidx) - repmat(y, [1, length(jidx)]);
tmpdiff = vecnorm(tmpdiff,2,1);
diffnorm(i) = min(tmpdiff);
diffnorm(i) = diffnorm(i) / norm(y);
end
end
99 changes: 99 additions & 0 deletions toolbox/examples/predatorpreyFilippov/generateEulerSol.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
%% SETUP
% parameter values p = (r1, r2, beta1, beta2, q1, q2, m, e)
% order as in paper (see rhs file)
m = 0.790;
r1 = 0.836;
e = 0.948;
q1 = 0.772;
aq = 0.660;
beta2 = 0.896;

beta1 = 7.81; q2 = 1.5; r2 = 0.3;

% initial values, parameters, timespan
a = 0.286975;
x0_1 = [a ; a ; r1-r2];
p = [r1, r2, beta1, beta2, q1, q2, m, e, aq];
tspan = [0 100];

% configure plotting
X_plot = linspace(tspan(1), tspan(end), 1000);
fignum = 1002;
figure(fignum); clf; hold('on');
plotit = @plotter;

% solver selection and configuration
intEuler = @explEuler;
eulerStep = 1e-7;
namePlainEuler = @(f) sprintf('plain %s' , func2str(f));

%% COMPUTATION
% Now let the user decide if an euler solution is generated or loaded
fprintf('\nThis is the Euler solution generation script. Proceed with generation?\n');
choices = {"no (load from .mat file)", "yes (can take up to 20 minutes)"};
default_choice_index = 1;
[idx, val] = userchoice(choices, default_choice_index);
doEuler = false;
if idx == 2
doEuler = true;
end

% EULER Integration
[owndir, ~] = fileparts(mfilename('fullpath'));
euler_fname = fullfile(owndir, sprintf('sol_euler_red_%.0e.mat', eulerStep));
EulerFileIsPresent = isfile(euler_fname);
if EulerFileIsPresent && ~doEuler
fprintf('Loading sol_euler from file %s\n', euler_fname);
tmp = load(euler_fname, 'sol_euler_ds');
sol_euler = tmp.sol_euler_ds;
doEuler = true;
else
if ~EulerFileIsPresent
disp("Euler solution file missing... Generating file");
else
disp("Computing Euler solution");
end
% Generate euler solution
fprintf('Integrating with integrator %s (might take a while) ...\n', func2str(intEuler))
figure(fignum);
th = tic();
sol_euler = intEuler(@(t,x) pprhs(t,x,p), tspan, x0_1, eulerStep);
time_euler = toc(th); fprintf('Euler took %g s\n', time_euler);
fprintf('Saving result to %s for later reuse.\n', euler_fname);
% reduce euler solution to make file smaller and save it
ds = 100;
idx = 1:ds:numel(sol_euler.x);
sol_euler_ds.x = sol_euler.x(idx);
sol_euler_ds.y = sol_euler.y(:, idx);
save(euler_fname, "sol_euler_ds");
doEuler = true; % in case we ended up here because the file did not exist
end

if doEuler
X_euler = X_plot;
Y_euler = transpose(interp1(sol_euler.x, transpose(sol_euler.y), X_euler));
linewidth = 2.0;
hEuler = plotit(fignum, Y_euler, 'c', namePlainEuler(intEuler), linewidth);
end



% FINITO
return

%% HELPERS

function h = plotter(fignum, y, color, name, lw)
figure(fignum); hold on;
h = plot3(y(3,:), y(2,:), y(1,:), 'Color', color, 'LineWidth', lw, 'DisplayName', name);
view([97 51]);
grid on;
box on;
xlabel('Predator');
ylabel('Prey 2');
zlabel('Prey 1');
legend('location', 'northeast');
drawnow
pause(1.0);
set(fignum, 'Position', [200 250 750 375]);
end
Binary file not shown.
Loading