Implementation
Processing in pseudocode
this is now updated according to the discussion in Heidelberg, sept 2008
- generate list of algebraic trigger functions from boolean expressions and map them to the assignments
- initialize integration
- Reporting
- Add events with the prior flag set to
FALSE
which fire at t = 0
to the process queue.
- Process queue until no steps are left for which
t = 0
- calculate nextReportTime
- while nextReportTime <= endTime
- Call integration method to proceed to
min(nextReportTime, firstProcessQueueTime)
. The integration method stops when the end time is reached or when an event is triggered.
- if at least one event was triggered loop over all triggered events:
e = triggered event
addToQueue(currentTime + (e.delayAfterCalculation ? 0 : e.delay), e.isPrior, CALC, &e)
//add the calculation to the event queue
addToQueue(currentTime + e.delay, e.isPrior, ASSIGN, &e)
//add the assignment to the event queue
- Process queue until no steps are left for which
t = currentTime
and prior is TRUE
- if (currentTime == nextReportTime)
- Reporting
- calculate nextReportTime
- Process queue until no steps are left for which
t = currentTime
Adding Events to the process queue
Each event has to be added twice to the process queue:
- for calculation
- for assignment
Processing the event queue
Processing of the queue is usually called with
current_time
equal to the topmost time in the queue. The first run should then process all items with the
PRIOR
flag and
item.time == current_time
, the second run the remaining items with
item.time == current_time
.
The sorting of the event queue should ensure that the items with the
PRIOR
flag are on top, and that, on the next sorting level, calculation items are handled before assignment items with the same
time
and
PRIOR
flag.
Pseudocode
- while
current_time == queue.topmostTime
item=queue.topmostItem
if item.isCalculation
- evaluate the assignment expressions and store the result(s). The result should be stored (or mapped to) the corresponding assignment item in the queue.
else if item.isAssignment
- assign the stored value (from the corresponding calculation item) to the proper object in the model.
- Check if a new event was triggered by the assignments (
a
). If yes, loop over all newly triggered events:
e = triggered event
addToQueue(currentTime + (e.delayAfterCalculation ? 0 : e.delay), a.PRIOR, CALC, &e)
//add the calculation to the event queue
addToQueue(currentTime + e.delay, a.PRIOR, ASSIGN, &e)
//add the assignment to the event queue
- drop top item from queue
Note: When an event is triggered by another event, it inherits the
isPrior
property from the triggering event, not from its own trigger expression.
Update Simulated Values
The values used in each trigger expression must be handled in the same way as reaction fluxes and the right hand side of ODEs, i.e., they need to be updated in CModel::updateSimulatedValues.
Moieties
When performing the event assignment, potentially we need to also recalculate the values of the moieties.