3.9. Interpretation of encapsulation
elements¶
For the purposes of this specification, there SHALL be a conceptual “encapsulation digraph” in which there is exactly one node for every component in the CellML model.
If a
component_ref
element appears as a child of anothercomponent_ref
element, then there SHALL be an arc in the encapsulation digraph, and that arc SHALL be from the node corresponding to the component referenced by the parentcomponent_ref
element, and to the node corresponding to the component referenced by the childcomponent_ref
element.
See more
You can think of an encapsulation structure as a tree. The model is the tree’s trunk, and each component at the top-level of the model is a branch. Subsequent generations of branches can stem from any component, but no two branches can recombine or belong to more than one parent, as this would create a loop. Any component not listed inside the encapsulation is a top-level component (a branch off the trunk).
An encapsulation hierarchy is specified using a single encapsulation
element, and any number of generations of component_ref
children.
Where no encapsulation
element is present, all component
elements have the same level; they branch off the model
-trunk.
Some examples of valid and invalid encapsulation structures are shown below.
<!-- Valid encapsulation structure. This will give the arrangement of:
- grandad
- father
- child
- aunt
- orphan
Because the component named "orphan" is not included in the encapsulation
it will stay at the top level of the model. -->
<model name="I_am_a_valid_model">
<component name="grandad"/>
<component name="aunt"/>
<component name="father"/>
<component name="child"/>
<component name="orphan">
<encapsulation>
<component_ref component="grandad">
<component_ref component="aunt"/>
<component_ref component="father">
<component_ref component="child"/>
</component_ref>
</component_ref>
</encapsulation>
</model>
<!-- Invalid: More than one encapsulation is not permitted. -->
<model name="too_many_encapsulations">
<component name="parent1"/>
<component name="child1"/>
<component name="parent2"/>
<component name="child2"/>
<encapsulation>
<component_ref component="parent1">
<component_ref component="child2"/>
</component_ref>
</encapsulation>
<encapsulation>
<component_ref component="parent2">
<component_ref component="child2"/>
</component_ref>
</encapsulation>
</model>
<!-- Invalid: A component cannot appear more than once in an encapsulation. -->
<model name="duplicated_component_ref">
<component name="parent"/>
<component name="child"/>
<encapsulation>
<component_ref component="parent">
<component_ref component="child">
<component_ref component="parent"/>
</component_ref>
</component_ref>
</encapsulation>
</model>
<!-- Valid, but redundant: An encapsulation can be empty, but this is the default
condition so its inclusion alters nothing. -->
<model name="empty_encapsulation">
<component name="parent"/>
<component name="child"/>
<encapsulation>
</encapsulation>
</model>
<!-- Valid, but redundant: An encapsulation must have a minimum of two levels of children
to affect the model's structure. This still represents the default condition. -->
<model name="duplicated_component_ref">
<component name="parent"/>
<component name="child"/>
<encapsulation>
<component_ref component="parent">
<!-- There has to be a child here or the parent is not a parent. -->
</component_ref>
</encapsulation>
</model>
The “encapsulated set” for a component A SHALL be the set of all components B such that there exists an arc in the encapsulation digraph from the node corresponding to A to the node corresponding to B.
The “encapsulation parent” for a component A SHALL be the component corresponding to the node which is the parent node in the encapsulation digraph of the node corresponding to A. A component SHALL NOT appear as child of more than one encapsulation parent.
The “sibling set” for a component A SHALL be the set of all components which have the same encapsulation parent as A, or in the case that A has no encapsulation parent, SHALL be the set of all components which do not have an encapsulation parent.
See more
In the informative block above we used the analogy of a tree to describe the encapsulation structure, but the language around it is closer to a family tree in which there are only single parents allowed. With this in mind, the points above become clear.
3.9.3 defines the “encapsulation set” of a component as its direct component children.
3.9.4 makes clear that there can only be single parents in this family tree.
3.9.5 defines siblings as those
component
elements which share a parent, be that parent acomponent
element or themodel
element itself.3.9.6 defines the “hidden set” of any
component
as those othercomponent
elements which are neither the parent, the children, nor the siblings of that currentcomponent
element.
These distinctions become important when considering the kind of connection
elements which may be formed, and in determining the interface_type
attribute values which are available to a component’s variable
children.
The example below illustrates the extended family tree from the 1980s TV show, The Beverly Hillbillies.
model: TheBeverlyHillbillies
├─ component: GrannyMoses
├─ component: MissJane
└─ component: ClampettFamily
├─ component: LukeClampett
│ ├─ component: MyrtleClampett
│ └─ component: JedClampett
│ └─ component: EllyMayClampett
└─ component: AmosClampett
└─ component: PearlBodine
├─ component: JethroBodine
└─ component: JethrineBodine
See CellML syntax
<model name="TheBeverlyHillbillies">
<!-- Note that the first two components here are not listed inside the
encapsulation. They are, by default, siblings of each other,
as well as of the root component (ClampettFamily) of the
encapsulation structure. -->
<component name="GrannyMoses" />
<component name="MissJane" />
<component name="ClampettFamily" />
<component name="LukeClampett" />
<component name="AmosClampett" />
<component name="MyrtleClampett" />
<component name="JedClampett" />
<component name="EllyMayClampett" />
<component name="PearlBodine" />
<component name="JethroBodine" />
<component name="JethrineBodine" />
<encapsulation>
<component_ref component="ClampettFamily">
<component_ref component="LukeClampett">
<component_ref component="MyrtleClampett">
</component_ref>
<component_ref component="JedClampett">
<component_ref component="EllyMayClampett"/>
</component_ref>
</component_ref>
<component_ref component="AmosClampett">
<component_ref component="PearlBodine">
<component_ref component="JethroBodine"/>
<component_ref component="JethrineBodine"/>
</component_ref>
</component_ref>
</encapsulation>
</model>
In this example, we can see that the encapsulation set (or direct children) of component PearlBodine
are the twins JethroBodine
and JethrineBodine
.
Similarly, LukeClampett
is the parent of MyrtleClampett
and JedClampett
.
Several sets of siblings are fairly easy to spot:
JethroBodine
andJethrineBodine
,LukeClampett
andAmosClampett
, andMyrtleClampett
andJedClampett
.
Other siblings that are not as clear at first glance are GrannyMoses
, MissJane
, and the placeholder ClampettFamily
, by virtue of their common parent, TheBeverlyHillbillies
model itself.
See more
Before two variable
elements can be connected or mapped to one another, two set of rules must be followed.
The first rule is that the variables’ parent component
elements must not be hidden from one another (as stated in 3.9.7), and the second (found in 3.10.9-10) is that the interface_type
attributes of the variables must not exclude their connection either.
Understanding hidden sets and connections
It’s easier to define hidden components by defining those which are not hidden first.
Basically, one degree of separation is all that is “seen” by any component.
This means that parent components can see their children, and children their parents.
Sibling components (including those who are top-level children of the model
element) are visible to one another as well.
Components in any other relationships are too distant to be visible, and are therefore hidden from each other.
Reusing the same example as earlier, we can see that:
LukeClampett
is hidden fromEllyMayClampett
(grandfather/grandchild)AmosClampett
is hidden fromMyrtleClampett
(uncle/niece)PearlBodine
is hidden fromJedClampett
(cousins)GrannyMoses
is hidden fromLukeClampett
(great-aunt/great-nephew)
model: TheBeverlyHillbillies
├─ component: GrannyMoses
├─ component: MissJane
└─ component: ClampettFamily
├─ component: LukeClampett
│ ├─ component: MyrtleClampett
│ └─ component: JedClampett
│ └─ component: EllyMayClampett
└─ component: AmosClampett
└─ component: PearlBodine
├─ component: JethroBodine
└─ component: JethrineBodine
<!-- None of the following connections are possible as their
components are hidden from one another. -->
<!-- Grandfather and grandchild. -->
<connection component_1="LukeClampett" component_2="EllyMayClampett" />
<!-- Uncle and niece. -->
<connection component_1="AmosClampett" component_2="MyrtleClampett" />
<!-- Cousin and cousin. -->
<connection component_1="PearlBodine" component_2="JedClampett" />
<!-- Great-aunt and great-nephew. -->
<connection component_1="GrannyMoses" component_2="LukeClampett" />
The second rule above addresses the restrictions around which variable
elements are able to access one another.
This is a little more complicated, and explained in more detail in the informative block in 3.10 Interpretation of map_variables elements.