Tracking max value during simulation

12 views (last 30 days)
Hello,
I'm trying to keep track of the max value of a variable during simulation. I'm currently doing this using an event, as follows:
mdl.addevent('A > maxA',{'maxA = A'})
However, this isn't working. I believe the reason it's not working is because events are only trigerred on rising edges, and thus maxA doesn't track A as A rises gradually.
Is there a way to accomplish tracking of the maximum value of a variable during a simulation? Since I am using maxA during the simulation, I cannot calculate it post-hoc (i.e., can't use an observable).
Thank you!
Abed

Accepted Answer

Jeremy Huard
Jeremy Huard on 27 Jan 2023
Edited: Jeremy Huard on 27 Jan 2023
Hi Abed,
the easiest way to keep track of the max of a species during a simulation might be to use an external function (see attachment) with a persistent variable that stores the current maximal value:
function out = getmax(time,s)
persistent maxS
if time==0 || isempty(maxS)
maxS = -Inf;
end
maxS = max(maxS,s);
out = maxS;
end
You can then use this function in a repeated assignment:
% Create model.
m1 = sbiomodel('test');
% Add compartment
c1 = addcompartment(m1,'comp',1);
% Add species to compartment.
addspecies(c1, 's');
% Add rule to model.
addrule(m1, 's = sin(time*2*pi + 2) + 2', 'repeatedAssignment');
% Add dummy ODE to model
addspecies(c1, 's2',10);
addrule(m1, 's2 = -s2', 'rate');
% Add parameter to model.
addparameter(m1, 'maxS',Constant=false);
addrule(m1,'maxS = getmax(time,s)','repeatedAssignment');
% Modify settings
cs = getconfigset(m1);
cs.SolverOptions.MaxStep = 0.01;
% Simulate
simfun = createSimFunction(m1,{},{'maxS','s'},[],[],AutoAccelerate=false);
stopTime = 1.5;
results = simfun([],stopTime);
sbioplot(results);
I hope this helps.
Best regards,
Jérémy
  3 Comments
Arthur Goldsipe
Arthur Goldsipe on 27 Jan 2023
The persistent variable was my first thought, too. But it makes me a little nervous. (I'll say why in a moment.) So I suggest usin git with caution.
At the very least, I would validate that the solution makes sense after the fact. For example, make sure the calculated maximum approximates the real maximum of the state. And ideally check that the differential equations still seemed to be solved accurately. One relatively simple approach for doing this would be to perform repeated simulatations until your answer converges. For the first simulation and only the first simulation, use the persistent variable to calculate the maximum. From then on, replace the persistent variable calculation with a function that calculates the maximum by interpolating using the data from the previous simulation. Keep updating the data used for interpolation until it doesn't change signficantly. (If anything about that doesn't make sense, let me know.)
Here's why I'm concerned about the persistent variable approach: First, the persistent variable might end up storing trial state values that were ultimately rejected because they didn't meet error tolerances. So the "maximum" might not be the "real maximum." Second, this function now has "memory" and could return a different result for the same inputs, depending on how the function is called in between. This probably breaks some core assumptions of the ODE solver, which could in turn lead to unexpected errors or an inability to control the solution within the specified error tolerance.
Abed Alnaif
Abed Alnaif on 27 Jan 2023
Thanks for these insights Arthur. These make sense and I hadn’t considered these issues. Maybe the best approach is to devise a small ODE system which will have memory for Cmax, at least approximately, although nothing comes to mind immediately.

Sign in to comment.

More Answers (0)

Communities

More Answers in the  SimBiology Community

Categories

Find more on Scan Parameter Ranges in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!