Model structure overview
Models are based on user-defined types that contain parameter declarations, reference declarations and specification of what children an instance of a type can have. Typically they also contain a behavior specification which can contain build-time and run-time declarations. Build-time declarations apply when a simulation is set up, for example to connect cells. Run-time declarations specify the state variables, equations and events that are involved.
An instance of a type is a model component. It specifies a particular set of parameters for a given type. It says nothing about state variables: in a simulation, typically many run-time instances will correspond to a single model component definition, and several model component definitions will use the same type. A run-time instance holds its own set of state variables as defined by the Type definition and a reference to its component for the parameter values specific to that particular model component. The update rules come from the type definition. As such, neither the Type nor the Component is properly a "prototype" for the runtime instance.
Defining types
Types are declared as, for example:
<Type name="myCell">
<Parameter name="threshold" dimension="voltage" />
</Type>
A component based on such a type is expressed as:
<Component type="myCell" threshold="dimensional_quantity" />
A type can contain elements for specifying the following aspects of the structure and parameters of a model component:
- Parameter - dimensional quantities that remain fixed within a model
- Child - a required single sub-component of a given type
- Children - variable number of sub-components of the given type
- ComponentRef - a reference to a top-level component definition.
- Link - a reference to a component definition relative to the referrer
- Attachments - for build-time connections
- EventPort - for run-time discrete event communication
The "EventPort" and "Attachments" declarations don't have any corresponding elements in their model component specification. They only affect how the component can be used when a model is instantiated. EventPorts specify that a model can send or receive events, and should match up with declarations in its behavior specification. An "Attachments" declaration specifies that a run-time instance can have dynamically generated attachments as, for example, when a new synapse run-time instance is added to a cell for each incoming connection.
Inheritance
A type can extend another type, adding new parameters, or supplying values (SetParam) for inherited parameters. As well as reducing duplication, the key application of this is with the Child and Children declarations, where a type can specify that it needs a child or children of a particular supertype, but doesn't care about which particular sub-type is used in a model. This applies, for example, where a cell requires synapses that compute a quantity with dimensions current, but doesn't need access to any other parts of the synapse behavior.
Run-time behaviors
Run time behaviors are included within a Behavior block in a type specification. They include declaration of:
- state variables
- first order differential equations with respect to time of state variables
- inherited quantities - those that must exist in the parent component
- derived quantities - things computed in terms of other local quantities
- external quantities - things accessed from other run-time instances at an xpath-like address
- global quantities
Run time behaviors can be grouped into Regimes, where only one regime is operative at a given time for a particular run-time instance. Regimes have access to all the variables in the parent instance and can define their own local variables.
Behaviors can also contain event blocks:
- OnStart blocks contain any initialization declarations needed when a run-time state is instantiated
- OnEvent blocks specify what happens when an event is received on a specified port
- OnEntry blocks (only within regimes) specify things that should happen each time the system enters that regime.
- OnCondition blocks have a test condition and specify what should happen when it is met.
Build-time behaviors
Build-time behaviors define the structure of a multi-component model. Currently there are:
- MultiInstantiate - for declaring that a component yields multiple run-time instances corresponding to a particular model component. Eg, for defining populations of cells.
- ForEach - for iterating over multiple instances in the run-time structure
- EventConnection - for connecting ports between run-time instances
Other
There are also Run, Show and Record behaviors for creating type definitions that define simulations and what should be recorded or displayed from such a simulation.
Observations
The numerous references to "run-time instances" above is problematic, since the structures do not dictate any particular way of building a simulator or running a model. In particular, there is no requirement that a component or behavior declaration should give rise to any particular collection of state variables that could be interpreted as a run-time instance in the state of a simulator.
So, it is convenient to think of eventual state instances, and that is indeed how the reference interpreter works, but the model specification structure should avoid anything that is specific to this picture.
Type specification examples
Examples of type definitions using the various types of child element:
<Type name="synapse">
<EventPort direction="in" />
</Type>
<Type name="HHChannel">
<Children name="gates" type="HHGate" />
</Type>
<Type name="HHGate">
<Child name="Forward" type="HHRate" />
<Child name="Reverse" type="HHRate" />
</Type>
<Type name="synapseCell">
<Attachments name="synapses" type="synapse" />
</Type>
<Type name="Population">
<ComponentRef name="component" type="Component" />
</Type>
<Type name="EventConnectivity">
<Link name="source" type="Population" />
</Type>
The model component declarations corresponding to the channel and gate types would be:
<Component type="HHChanne">
<Component type="HHGate">
<Component type="some_hh_gate_type" role="Forward" />
<Component type="some_hh_gate_type" role="Reverse" />
</Component>
</Component>
<HHChannel>
<HHGate>
<Forward type="some_hh_gate_type" />
<Reverse type="some_hh_gate_type" />
</HHGate>
</HHChannel>
For the population type it would be:
<Component id="myPopulation" type="population" component="myCellModel" />
<Component type="EventConnectivity" source="myPopulation" />