Skip to content

simulator.executor_amici

The executor of AMICI runs a plan on a model of AMICI.

AMICI is the integrator (CVODES) and the root finder, the executor fires the events of the model: the model AMICI compiles keeps the trigger of every event and records, instead of its assignments, that the event fired in an integration and the time of its first execution, see sbmlsim.model.model_amici. An integration from a time runs on the model without the assignments of its events, so its rows up to the first root of a trigger are the ones of the model; there the executor applies the semantics of SBML, see sbmlsim.simulator.changes.fire_events (the order of the priorities, the persistence of the triggers, the values of the assignments at the trigger or at the execution, the events an assignment triggers, the events of one time one after the other), and integrates on from the state after the events (_Course._advance), so no row of the output is past an event without its assignments.

It has the semantics of the executor of roadrunner, see sbmlsim.simulator.executor, so the results of the engines are comparable:

  1. The model is initialized with the pre-initialization values, see AmiciSBMLModel.initialize, from the free parameters as loaded, so nothing of an earlier simulation is left.
  2. The events whose trigger is false before the time 0 (AmiciSBMLModel.start_events) and true in the initial state fire at the start, in the initial state before a change at the start, with the events they trigger, as in roadrunner (_Course.start_events); AMICI fires no event at the start of an integration, see sbmlsim.model.model_amici. With a presimulation they fire at its start, the time 0.
  3. A presimulation integrates from the time 0 until the rates of change vanish, see steady_state.
  4. The segments between the changes are the ones of sbmlsim.simulator.segments.simulate_segments, with the events a change triggers fired by the executor, the stop of a segment just before a change and the events at the end. AMICI integrates in absolute time, every segment from the state the one before it ended in.
  5. AMICI evaluates a comparison which is exactly at its threshold at the start of an integration as written and keeps the value for the whole integration, since CVODES reports no root at the start and the root function does not change its sign afterwards, see sbmlsim.model.model_amici: a comparison of a trigger as true, also a strict one, e.g. time > 1 from the time 1 after a change there or X > 2 after a change which sets X = 2, and does not find the crossing when the comparison becomes true. Every strict comparison of a trigger is compiled shifted by a parameter, a > b + shift, which is 0 but at the start of an integration at which the comparison is exactly at its threshold (_Course._arm): there the executor integrates the resolution of the time ahead (_Course._probe) to tell the events whose trigger is true right after the start. Such an event which did not fire at the start fires there, after the row of the start, as in roadrunner, which fires it in its first step (the steps of the integrator have it as two rows at the start); one which fired at the start, e.g. time > 10 at the end of a horizon of a steady state, stays true for AMICI and does not fire again. Every other comparison at its threshold is shifted by THRESHOLD_ULPS units in the last place of the largest term of its operands (_Course._shift), so AMICI finds the crossing when it comes: an event which sets its own trigger back to its threshold, Y > 2 by Y = 2, fires again when Y rises above 2 later, as in roadrunner. A comparison of a math of the model, e.g. the condition of a piecewise in a rate, piecewise(2, time <= tend, 0), is compiled shifted as well (AmiciSBMLModel.switches); before every integration from a time at which it is exactly at its threshold, e.g. from the time tend after an event or a change there, the executor shifts it the same way (_Course._arm_switches, for a comparison of the time by at least its change over the resolution of the time, so the explicit root of AMICI at the shifted time is after the start, also time > tlag with tlag = 0 at the start 0, and the comparison turns at most about the resolution late whatever its scale, time/86400 > tlag), so it keeps its value until the operands move by the shift in the direction which changes it, time <= tend false right after tend, as roadrunner evaluates it at every step. An output row exactly at the threshold of such a comparison, e.g. at tend, has the rates and the assignment rules evaluated with the comparison as written, the value of the SBML, as roadrunner and COPASI have it (Rate = Ri at tend); AMICI evaluates the expressions of the row after the root (_Course._switch_rows).
  6. AMICI finds the root of a trigger where it crosses its threshold, so the event is at its time; a strict trigger of the time is at its time exactly. The events of a root within the resolution of the time of a grid time are at the grid time, whose state the integration gave. An output time at the root has the state before the events there unless the trigger is true at the time, every comparison within the tolerance of the integrator of its threshold taken at it (_Course._visible): a comparison which is not strict is true there, a strict one false, so the output has the state after X >= 2 and before X > 2 at the time X reaches 2, as in roadrunner, where a strict trigger fires in the first step after the time. A root AMICI finds again at the start of the next integration within the resolution of the time, the crossing fired for, is no event: the integration starts again from it (_Course._advance). A trigger which an integration makes true within the rounding of its stop, without a root reported by AMICI, fires at the stop, where the next integration would start with the trigger true.
  7. The output of OutputMode.TIMES are the plan times of a segment. AMICI outputs the states at given times only, so the steps of the integrator (OutputMode.INTEGRATOR) are a substitute: a grid of STEPS intervals of the same length per segment, refined where the linear interpolation between two rows misses the solution at their midpoint by more than the square root of the relative tolerance of the integrator times the largest magnitude of the selection in the segment, so the rows interpolate as accurately as the steps of roadrunner, whose density CVODE chose (_Course.steps, _Course._refine: 1e-5 of the largest value at the default tolerances, 6e-6 on the HCTZ model against 3e-5 with the steps of roadrunner, at about twice the rows of roadrunner and one integration per round of the refinement and piece between two events, three to four times the cost of the grid alone), and every event of the model as two rows at its time, the states before and after it; the rows at the changes, at the events and at the end correspond to the ones of roadrunner.
  8. The integration from a time runs to the end of the segment, after an event over the distance between the last two events, doubled after every integration without an event (_Course._advance): the integration past the first root, which is discarded, is at most as long as the one before it, so the cost of a simulation is linear in the number of its events.

Known differences to roadrunner:

  • roadrunner evaluates the triggers of the events when the model is initialized, at the time 0, also for a simulation from a negative start; AMICI evaluates them at the start.
  • An event whose trigger is false before the time 0 and which a pre-initialization makes true, e.g. a dose dose > 0 with dose set before the initialization, fires at the start in AMICI and COPASI, as in libroadrunner after resetAll and in the SBML Test Suite; the executor of roadrunner does not fire it (#439).
  • roadrunner integrates a model which does not read the time in local time, every segment from its time 0; AMICI integrates every model in absolute time.
  • The steps of the integrator are the refined grid with the events, see 7.; the steps of CVODES in AMICI are not exposed.
  • AMICI has one absolute tolerance for every state, a concentration species in its concentration, see AmiciSBMLModel.set_integrator_settings; the steps differ between the engines, the rows at the changes, at the events and at the end correspond.
  • The rows of an event of the model in the steps are the states before and after it at its time, the ones of roadrunner a little before and after it, at a distance which depends on the last step of CVODE.
  • Simultaneous events of the same priority execute in the order of the document, roadrunner orders them at random.
  • The output row at the exact time of a root of a strict trigger of the time shows the state before the event (the trigger is false at the time, see 6.); the row of roadrunner depends on where CVODE lands its root, e.g. the state before at time > 0.1, time > 0.7 and time > 12 and the state after at time > 1/3.
  • A trigger which compares for equality, a == b or a != b, raises when the model is loaded, see sbmlsim.model.model_amici.
  • AMICI 1.2 computes the time of a trigger of the time with a precision of about eight digits (time >= 1 + 1e-8 triggers at 1 in AMICI, with time >= 1): the executor fires the event when AMICI finds it, after the events of the roots before it, so its assignments see the state after them, as in roadrunner, at a time a little before the one of roadrunner.
  • AMICI 1.2 does not import a trigger with a negation of a comparison (!(X <= 3)), the model raises when it is loaded.

The absolute tolerance of AMICI is the one of roadrunner times sbmlsim.model.model_amici.AMICI_ATOL_FACTOR, so AMICI integrates the HCTZ model at least as accurately as roadrunner at the defaults of Simulator (the largest relative error 1.1e-7 against 1.5e-7 of roadrunner, see the measurement there).

The delays of events, the delay csymbol and the other features AMICI does not simulate as roadrunner are refused when the model is loaded, see AmiciSBMLModel.

execute

execute(plan, model, selections)

Run a plan on a model of AMICI.

The contract of sbmlsim.simulator.executor.execute: the output has two rows at the time of a change after the start, the state before the change and the state after it, and the steps of the integrator have two at an event of the model, see the module.

Parameters:

Name Type Description Default
plan Plan

the plan, compiled against the model.

required
model AmiciSBMLModel

the model.

required
selections Sequence[str]

the columns of the result, time is added as the first column if it is missing.

required

Returns:

Type Description
TimecourseResult

The result, with the time shifted by plan.time_shift.

Raises:

Type Description
SteadyStateError

if the presimulation does not reach a steady state.

RuntimeError

if AMICI fails to integrate, with its message.

NotImplementedError

for a plan AMICI does not simulate, see check_supported.

check_supported

check_supported(plan, model)

Refuse a plan which sets a compartment AMICI keeps out of its states.

execute checks every plan, and Simulator.run the plan of the first point of every simulation and model before it runs a point, see sbmlsim.simulator.engines.check_plan. A compartment whose size in the SBML is not a number and which has no initial assignment is a number of AMICI, which integrates no state which is not finite, see sbmlsim.model.model_amici.

Raises:

Type Description
UnsupportedModelError

a NotImplementedError, for a plan which sets such a compartment.

steady_state

steady_state(model, plan, start=0.0)

Integrate a model until its rates of change vanish, see sbmlsim.simulator.segments.steady_state.

Every horizon fires the events of the model, see _Course.

Parameters:

Name Type Description Default
model AmiciSBMLModel

the model in the state the integration starts from.

required
plan SteadyStatePlan

the steady state.

required
start float

the time the integration starts at.

0.0

Returns:

Type Description
float

The time the steady state was reached at.

Raises:

Type Description
SteadyStateError

if the steady state is not reached by max_time.

RuntimeError

if AMICI fails to integrate, with its message.