Anatomy of generated code¶
This page describes the C++ files chaste-sbml emits and how they fit together.
The examples come from the reference model Goldbeter1991, generated as an
srn model.
What gets generated¶
The files produced depend on --model-type. All names are derived from the
model name (the SBML filename with a Sbml suffix, unless you pass one):
Model type |
Files |
Contents |
|---|---|---|
|
|
The ODE system only. |
|
|
The ODE system plus an SRN model that wraps it. |
|
|
The ODE system plus a cell-cycle model that wraps it. |
Pass --tests (or --test-output-dir) to emit a placeholder test
Test<Name>.hpp. It is written alongside the model by default; --test-output-dir
places it elsewhere. All output is formatted with clang-format.
The class hierarchy¶
Generated classes extend the shipped base classes, which in turn extend Chaste’s core classes:
AbstractOdeSystem (Chaste)
└── AbstractSbmlOdeSystem (shipped)
└── <Name>SbmlOdeSystem (generated)
AbstractOdeSrnModel (Chaste)
└── AbstractSbmlSrnModel (shipped)
└── <Name>SbmlSrnModel (generated, srn)
AbstractOdeBasedCellCycleModel (Chaste)
└── AbstractSbmlCellCycleModel (shipped)
└── <Name>SbmlCellCycleModel (generated, cell-cycle)
The ODE system¶
<Name>SbmlOdeSystem is the heart of the output: it turns the SBML model into a
Chaste AbstractOdeSystem. The header groups the model’s quantities into
labelled double members:
class Goldbeter1991SbmlOdeSystem : public AbstractSbmlOdeSystem
{
// PARAMETERS
double VM1; // VM1
// ...
// STATE VARIABLES
double C; // Cyclin
double M; // cdc_2_kinase
double X; // Cyclin Protease
double d_C_dt; // one derivative member per state variable
// ...
// DERIVED QUANTITIES
double cell; // cell
// REACTIONS
double reaction1; // creation of cyclin
// ...
};
The constructor tells the base class how many state variables, parameters, and events the model has, then initialises the system:
Goldbeter1991SbmlOdeSystem::Goldbeter1991SbmlOdeSystem()
: AbstractSbmlOdeSystem(3, 3, 0) // (numStateVars, numParameters, numEvents)
{
mpSystemInfo.reset(new CellwiseOdeSystemInformation<Goldbeter1991SbmlOdeSystem>);
Initialise();
// EVENTS
}
Key methods:
Initialise(double time = 0.0)Sets every parameter, derived quantity, and reaction to its initial value, and seeds the state variables and their default initial conditions.
RunModelEquations(time, rStateVariables)The computational core. It reads the state, recomputes every intermediate equation and reaction, and returns the vector of derivatives.
EvaluateYDerivatives(time, rY, rDY)(override)Called by the ODE solver. It runs the model equations and writes the derivatives into
rDY. When time-unit scaling applies, it multiplies time and each derivative byTIMESCALE_MULTIPLIER, declared on the class so that tests can work in the model’s native units without repeating the value:// in the header static constexpr double TIMESCALE_MULTIPLIER = 3600.0; // seconds per hour // ... rDY[i] = TIMESCALE_MULTIPLIER * derivatives[i];
// in a test double end_time = 100.0 / Goldbeter1991SbmlOdeSystem::TIMESCALE_MULTIPLIER;
ComputeDerivedQuantities(time, rY)(override)Returns the derived quantities, reaction fluxes, and amount/concentration conversions, for post-processing and output.
ProcessModelEvents(time, rY)(override, private)Present for every model. It refreshes the model state and, when the model has events, computes how close each trigger is to firing (used by CVODE root-finding) and records the deferred event assignments. See Events below.
A CellwiseOdeSystemInformation specialization at the bottom of the .cpp
records variable names, units, and initial conditions.
The wrapper (SRN / cell-cycle)¶
For the srn and cell-cycle types, the wrapper class owns an instance of the
ODE system and plugs it into Chaste’s cell-based machinery.
The default constructor forwards to the base class; note the SRN wrapper passes the state-variable count and the cell-cycle wrapper does not:
Goldbeter1991SbmlSrnModel::Goldbeter1991SbmlSrnModel(
boost::shared_ptr<AbstractCellCycleModelOdeSolver> pOdeSolver)
: AbstractSbmlSrnModel(3, pOdeSolver) // cell-cycle: AbstractSbmlCellCycleModel(pOdeSolver)
{
}
Initialise()(override)Creates the ODE system and hands it to the base class. SRN:
AbstractSbmlSrnModel::Initialise(new <Name>SbmlOdeSystem);— cell-cycle:mpOdeSystem = new <Name>SbmlOdeSystem; AbstractSbmlCellCycleModel::Initialise();CreateSrnModel()/CreateCellCycleModel()(override)Called by Chaste at cell division; returns a copy via the protected copy-constructor, which deep-copies the ODE system for the daughter cell:
auto* p_ode_system = static_cast<Goldbeter1991SbmlOdeSystem*>(rModel.GetOdeSystem()); this->SetOdeSystem(new Goldbeter1991SbmlOdeSystem(*p_ode_system));
OutputSrnModelParameters()/OutputCellCycleModelParameters()(override)Chains to the base class.
The solver is chosen implicitly: the wrapper base-class constructor calls
sbmlodesolversetup::SetUpDefaultOdeSolver, which prefers CVODE (with sensible
tolerances) and falls back to RungeKutta4IvpOdeSolver.
Events¶
When the model has events, the ODE system’s constructor sets up per-event state
(the event type and whether its trigger is satisfied at t = 0), and
ProcessModelEvents computes, for each event:
a signed trigger distance (used by CVODE to root-find the exact firing time),
whether the trigger is currently active, and
the deferred state/parameter assignments to apply when it fires.
For a cell-cycle model, an event tagged SbmlEventType::CELL_DIVISION is what
drives division: the base class’s ReadyToDivide() returns true only once such
an event has fired.
The placeholder test¶
Test<Name>.hpp is a CxxTest skeleton, not a real test — it exists so the
generated code compiles and links under Chaste’s test runner. It always contains
a smoke test for the ODE system:
class TestGoldbeter1991SbmlOdeSystem : public CxxTest::TestSuite
{
public:
void TestOdeSystem()
{
TS_ASSERT_THROWS_NOTHING(Goldbeter1991SbmlOdeSystem ode_system);
}
};
For srn and cell-cycle models it adds a second suite, deriving from
AbstractCellBasedTestSuite, that constructs the wrapper. Both suites carry a
// TODO: Add tests marker — fill them in with the assertions your model needs.
The base classes¶
The generated code #includes and subclasses a small, stable set of C++ base
classes that ship with the package. Copy them into your project with
--copy-base-classes:
File |
Role |
|---|---|
|
Base for every generated ODE system; extends Chaste’s |
|
Base for SRN wrappers; extends |
|
Base for cell-cycle wrappers; extends |
|
|
|
The |
|
|
Important
The base classes are versioned with the tool. Re-run --copy-base-classes
whenever you upgrade chaste-sbml, so the copied classes match the code being
generated.
See also
Using generated code walks through wiring these files into a Chaste user project.