Tracking max value during simulation
9 views (last 30 days)
Show older comments
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
0 Comments
Accepted Answer
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
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.
More Answers (0)
Communities
More Answers in the SimBiology Community
See Also
Categories
Find more on Scan Parameter Ranges in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!