Descrete events are used to instantaneously change values of model variables when given conditions are met. For example when model time reaches certain value or when boolean expression becomes true. Generally event consists of two parts: trigger - which defines conditions of event and execution - actions which should be performed after event is triggered. In BioUML events are handling according to latest SBML specification.
Events handling is independent from time course simulation and can be used in different types of models including ODE solving, stochastic simulation, algebraic models. Solver should be able to recognize that event was triggered, calculate specific time point at which it happened and stop simulation. Special wrapper solver EventLoopSimulator takes control, processes triggered events changes model variable values, reinits main solver and restarts it. Most solvers which are able to detect events have option Locate event which is set to true by default.
- Trigger specifies conditions for event to occur. It is a mathematicla boolean expression from model variables. If during simulation this expression transits from false to true - event is considered as triggered. It is usually better to formulate trigger in terms of inequalities:
time > 9,
x+y > z.
- Assignments - list of assignments which should be performed when event is executed. Each assignment consists of variable and mathematical expression. When event is executed, expressions are evalueated and results are assigned to variables.
- Priority - defines order of events execution in the case when several events are to be executed at the same time. Prioity is a evaluated expression from model variables and is recalculated each time it is checked. If prioirty is not set - event will have minimal priority (Note: behaviour for this case is not specified by SBML specification and left to particular software to decide).
- Delay - defines time delay between event triggering and execution. Delay should be assgined by numerical value and can not be changed during simulation.
- Use trigger time values - if true then assignment expressions are calculated using values of variables at the time of triggering. If false - at the time of execution. Note: these values may be different due to two reasons:
- trigger and execution are perforemd at different time points
- trigger and execution are perforemd at the same time point but other event with higher priority changed these variables
- Persistent tigger - if true then once event is triggered - it will be executed no matter what happends before execution time. If false and event tigger transits from true to false after event is triggered then event is considered switched off and will not be executed. Note that if then trigger will transit from false to true again - event will be triggered again.
- Trigger initial value - defines whether event may be triggered at the start of the simulation (i.e.
time = 0). If set to true then event can not be triggered at
time = 0even if Trigger expression is true at this
Logic of events can be quite complicated. Time point at which event should be executed may be different totime point at which it is executed due to preset time delay. Events execution may affect other events causing them to trigger or deactivating already triggered events. If several events are to be executed at the same time - order of execution is managed according to their priorities which are represented by mathematical expressions and may also be changed when other events are executed. It should be noted that events may form infinite loop triggering each other, so model creator should be cautious while using events in models.
If trigger is set to inequality of type
A > B and during simulation A transits from
B - eps to
B + eps, where
eps > 0 is some positive number then event is considered to be triggered exactly at the time point when
A = B. The same behaviour may be achieved with trigger
A = B, however this type of triggers should be used with cautious because it will be evaluated to true at one exact moment of time which can be accidentally skipped by solver. Whereas trigger
A > B will be evaluated to true for longer time period and it will be spotted by solver. After that solver will use bisection method to find exact time point at which transition from false to true happened (which is
A = B).
Similarly, sometimes events may be triggered even if model does not assume that A may ever exceed B. For example:
- B(t)= B(0) = 5,
- dA/dt = 5 - A(t), A(0) = 0.
Due to numerical error, there may be point in time when
A will be slightly larger than
B which will trigger event.
When event is executed, for each assignment, right hand side is evaluated and assigned to correspondent variable. Values of variables used in right hand side are fixed before execution and thus order of assignments does not matter. Let's consider example:
- Trigger: x > 1
- Delay: 3
- Priority: y + z
- x = y + 5,
- y = x - 2,
- z = z + 1.
- Before event execution: x = 1, y = 2, z = 3.
- After event execution: x = 7, y = -1, z = 4.
In BioUML each Event is broken into two events:
- preparational event calculates right hand side expressions and stores obtained values. It also calulates time point at which assignments should be performed by taking current time and adding delay value of base event:
DelayedTime = time + Delay. It have the same trigger as base event and priority = Infinity, so it will be executed prior to any actual assignments.
- executional event actually assignes values calculated by preparational event to left hand side variables. If base event has delay then It has trigger
time > DelayedTime. In that case event is triggered and executed in DelayedTime after preparational. Otherwise trigger is the same as for base event and both events will be executed simultaneously, but priority of the executional event is the same as for base event.
Thus each event is executed at the very same time point when it was triggered, all preparational events are executed before any executional and order of executional events is defined by priorities.
Let's consider what happends with event discussed earlier:
- Preparational event
- Trigger: x > 1
- Priority: Infinity
- tempx = y + 5,
- tempy = x - 2,
- tempz = z + 1,
- DelayedTime = time + 7.
- Executional event
- Trigger: time > DelayedTime
- Priority: y + z
- x = tempx,
- y = tempy,
- z = tempz.
Processing of events done by EventLoopSimulator goes as follows:
- Check which events were triggered. Add all these events to the pool of pending events.
- Calculate prioirty for each of triggered events - choose one event with the highest priority, or if there are several events with maximal priority - choose one of them randomly.
- Process chosen event
- Recalculate triggers of all other events.
- If it was not triggered before step 3 but is triggered now (it was switched on by executed event) - add it to the pool of pending events.
- If event has Persistent trigger = false and its trigger expression evaluates to false - remove it from the pool (it was switched off).
- If list of pending events is empty - reinit solver and start it with new values. Else - goto 2.