Informative CellML 2.0 Specification¶
Definitions¶
Terminology¶
The keywords “MUST”, “MUST NOT”, “SHALL”, “SHALL NOT”, and “MAY” in this document are to be interpreted as described in RFC 2119 [1].
The key phrase “information item”, as well as any specific type of information item such as an “element information item”, are to be interpreted as described in XML Information Set [2].
CellML infoset: An XML information set containing a hierarchy of information items conforming to the rules described in this document. In this specification, such infosets are assumed to be CellML 2.0 infosets.
CellML model: A mathematical model represented by a hierarchy of one or more CellML infosets, according to the rules described in this document. In this specification, the topmost CellML infoset in a hierarchy is referred to as the top-level CellML infoset.
Namespace: An XML namespace, as defined in Namespaces in XML 1.1 [3].
CellML namespace: The CellML 2.0 namespace.
CellML 2.0 namespace: The namespace http://www.cellml.org/cellml/2.0#.
MathML namespace: The namespace http://www.w3.org/1998/Math/MathML.
CellML information item: Any information item in the CellML namespace.
Basic Latin alphabetical character: A Unicode [4] character in the range U+0041 to U+005A or in the range U+0061 to U+007A.
Digit: A Unicode character in the range U+0030 to U+0039.
Basic Latin alphanumerical character: A Unicode character which is either a Basic Latin alphabetical character or a digit.
Basic Latin underscore: The Unicode character U+005F.
Basic Latin plus: The Unicode character U+002B.
Basic Latin minus: The Unicode character U+002D.
Basic Latin full stop: The Unicode character U+002E.
Whitespace character: Any one of the Unicode characters U+0009, U+000A, U+000D, or U+0020.
See more
Namespaces
Namespaces are a way of making sure that names and definitions are interpreted within the right frame of reference.
In CellML, two namespaces are used.
These are the CellML namespace itself (which helps to define the units
elements as distinct from the XML default units system) and the MathML namespace used to interpret the math
elements.
For more information on namespaces in general, please refer to the W3 schools namespace page, or for the MathML namespace please refer to the W3 MathML namespace page.
Unicode, Basic Latin alphabetical characters, and digits
The Unicode project is an attempt to codify all of the symbols - alphabets, writings, even emojis - of all the languages of the world so that they can be interchangeable and interpreted by computers. Since computers understand numbers rather than symbols, each character in each language is given a unique numerical code. The codes themselves are arranged into blocks representing sets of characters, and the Basic Latin block is one of these. It contains, amongst other things, the upper and lowercase alphabet without decoration:
These characters are referred to in CellML as the “Basic Latin alphabetical characters”.
The “digits” are the Unicode characters:
Together with the Basic Latin alphabetical characters, they form the “Basic Latin alphanumerical characters”.
In addition, CellML recognises four special characters:
+
the plus sign (U+002B),-
the minus sign (U+002D),.
the full stop or decimal point (U+002E),_
the underscore (U+005F),
and the following whitespace characters:
These symbols and character sets will be used throughout the CellML definition to define allowed content of attributes and elements.
CellML information sets¶
CellML and XML¶
Every CellML infoset SHALL be represented in an XML information set which conforms with the well-formedness requirements of XML 1.1 [5].
In this document, the remaining provisions relating to CellML infosets SHALL be interpreted as additional constraints on the XML information set represented by a CellML infoset.
Specific information items¶
For the purposes of this specification, a specific information item is one of the following (see https://www.w3.org/TR/2004/REC-xml-infoset-20040204/ for definitions):
A document information item;
An element information item;
An attribute information item;
A processing instruction information item;
An unexpanded entity reference information item;
A document type declaration information item;
An unparsed entity information item; or
A notational information item.
Specific information items MUST NOT appear in a CellML infoset except where explicitly allowed by this specification, or where allowed by a normative specification referenced by this specification.
The order in which specific information items appear, as children of an element information item defined in this specification, SHALL NOT affect the semantic interpretation of the CellML model.
See more
Specific information items
There are different kinds of information stored in XML elements.
In the example below, the food_ideas
element has:
title
,instructions
,ingredient
have text content (note that numbers like 1.0 are treated as text),ingredients
andfood_ideas
have element contents, because they have child elements inside them,category
is an attribute of therecipe
element, andname
andunits
are attributes of theingredient
element, andthe note within
<!-- ... -->
comment tags is of an unparsed type and is ignored.
<food_ideas>
<recipe category="easy">
<title>Three ingredient scones</title>
<!-- These are so easy ... and if you're clever you'll save a little cream for whipping on the top! -->
<ingredients>
<ingredient name="cream" units="cup">1.0</ingredient>
<ingredient name="lemonade" units="cup">1</ingredient>
<ingredient name="selfraising_flour" units="cup">4</ingredient>
</ingredients>
<instructions>
Mix them all together using your hands.
You can use extra flour if you need to.
Bake at 220C for about 12 minutes or until golden.
</instructions>
</recipe>
</food_ideas>
Using CellML this could be written:
<model name="recipes">
<units name="cup">
<unit units="litre" prefix="milli" multiplier="250.0" />
</units>
<component name="Three_ingredient_scones">
<!-- Sigh ... if only it were possible for my computer to make me tea ... -->
<variable name="cream" cellml:units="cup" initial_value="1" />
<variable name="lemonade" cellml:units="cup" initial_value="1" />
<variable name="selfraising_flour" cellml:units="cup" initial_value="5" />
<variable name="mixture" cellml:units="cup" />
<math>
<apply><eq/>
<ci>mixture</ci>
<apply><plus/>
<ci>cream</ci>
<ci>lemonade</ci>
<ci>selfraising_flour</ci>
</apply>
</apply>
</math>
</component>
<!-- BUT THIS IS NOT VALID! -->
<extra type="Danger_Will_Robinson">
Even though this looks like a valid XML text block, it's not allowed here. Only those
elements which are explicitly specified as types of children are allowed!
</extra>
</model>
Non-specific information items¶
For the purposes of this specification, a non-specific information item is one of the following (see https://www.w3.org/TR/2004/REC-xml-infoset-20040204/ for definitions):
A comment information item;
A namespace information item; or
A character information item.
An element information item in the CellML namespace MUST NOT contain any character information items, except for whitespace characters.
See more
<!-- This is not valid! -->
<model name="myInvalidCellML">
... because it has stuff here that shouldn't be here.
</model>
Two CellML infosets SHALL be deemed semantically equivalent if one can be transformed into the other by making zero or more of the following changes:
Adding, removing, and/or modifying comment information items.
Changing (inserting, removing, and/or modifying) one or more namespace information items, and/or modifying the prefix of one or more information items, without changing the namespace that any information item is in.
The following paragraph applies to character information items which are the direct child of an element information item in the CellML namespace, or in the MathML namespace: inserting or removing character information items that consist entirely of whitespace characters, changing the number of whitespace characters in such an information item, or changing the number of whitespace characters at the beginning or end of any character information item.
See more
Semantic equivalence
The example below is identical to that in the previous “See more” block because:
newlines, tabs, whitespace do not affect equivalence (except as part of text or attribute content),
the order of element definition does not affect equivalence,
the order of attribute definition does not affect equivalence, and
comments do not affect equivalence.
<model name="recipes">
<component name="Three_ingredient_scones">
<!--
Comments are ignored ...
so here's a really long one about how much I now
feel like yummy scones and jam and cream and tea ...
-->
<!-- The order of child elements is ignored -->
<math>
<apply><eq/>
<ci>mixture</ci>
<apply><plus/>
<ci>cream</ci>
<ci>lemonade</ci>
<ci>selfraising_flour</ci>
</apply>
</apply>
</math>
<!-- Whitespace (including tab, new line, and space) between attributes is ignored. -->
<variable
name="selfraising_flour"
cellml:units="cup"
/>
<variable name="cream" cellml:units="cup" />
<!-- Whitespace (including tab, new line, and space) between elements is ignored. -->
<variable cellml:units="dimensionless" name="mixture" /><variable name="lemonade" cellml:units="cup" />
</component>
<units name="cup">
<!-- The order of attributes within an element is ignored. -->
<unit multiplier="250.0" prefix="milli" units="litre" />
</units>
</model>
Use of namespaces¶
Element information items in a CellML infoset MUST belong to one of the following namespaces, unless explicitly indicated otherwise:
The CellML namespace; or
The MathML namespace.
Attribute information items in a CellML element MUST NOT be prefixed with a namespace, unless explicitly indicated otherwise.
XML ID Attributes¶
Any element information item in the CellML namespace MAY contain an attribute with local name
id.
This attribute SHALL be treated as having attribute type ID, as defined in Section 3.3.1 of XML 1.1 [5].
See more
Understanding element IDs
In order to understand how the XML id
attribute is used in CellML models, we need to understand four things.
Firstly, in CellML the elements are identified by uniqueness over the model scope of their name
attribute, their type (eg: variable
), and in some cases, by their parent element too.
Secondly, the CellML model
might exist over several different documents, and make use of import
functionality to connect these documents into one model.
Thirdly, the uniqueness of the XML id
attribute value extends only to the document scope, not the CellML model scope.
Finally, there are aspects of the written XML which do not contribute to the conceptual model as represented by the CellML; simple examples are things like whitespace between elements, comments, quotation and angle bracket markers.
These are all parts of the written language which guide interpretation into the conceptual model.
The id
attribute is likewise an XML attribute which falls into the same category: it may be read when a document is parsed, but as it doesn’t form a part of any CellML element, it doesn’t exist in the constructed conceptual representation.
Having said this, the syntax of CellML is a subset of XML (as specified in CellML information sets), so the rules of XML id
attributes must be followed, where present.
Consider the example below.
# In the document "BreakfastMenu.cellml".
# All id attributes are unique within this document.
model: name = "BreakfastOfChampions", id = "b"
├─ component: name = "Protein", id = "p"
├─ component: name = "Carbohydrates", id = "c" <╴╴╴╴╴╴╴╴╴┐
└─ component: name = "FunStuff", id = "f" ╷
└─ variable: name = "FunStuff", id = "fs" ╷
╷
Valid: A CellML component named "Porridge" is
imported, but its XML id attribute "p" is not
a part of that import.
╵
# In the document "CarbohydrateIdeas.cellml". ╵
# All id attributes should be unique within this document. ╵
model: name = "Carbs" id = none specified ╵
├─ component: name = "Chocolate", id = "c" ╵
├─ component: name = "Porridge", id = "p" ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
└─ component: name = "Toast", id = "t"
└─ variable: name = "Peanutbutter", id = "p"
# Invalid: The variable Peanutbutter is not allowed to have an id of "p"
# as this conflicts with the component Porridge id "p" in the same document.
See CellML syntax
<!-- In the file BreakfastMenu.cellml: -->
<model name="BreakfastOfChampions" id="b">
<component name="Protein" id="p" />
<import href="CarbohydrateIdeas.cellml">
<!-- Valid: The id attribute value is set here to be "c"
rather than that of the import, "p" -->
<component name="Carbohydrates" id="c" component_ref="Porridge" />
</import>
<!-- Valid: The name attributes are repeated, but in different element types.
The id attributes are distinct. -->
<component name="FunStuff" id="f" />
<variable name="FunStuff" id="fs" units="sprinkles" />
</component>
</model>
<!-- In the file CarbohydrateIdeas.cellml: -->
<model name="Carbs">
<!-- The id attribute "c" here does not clash with the Carbohydrates
component above as they are unknown to each other,
and in different documents. -->
<component name="Chocolate" id="c" />
<!-- Valid: The id attribute "p" here does not clash with the Protein
component id above because even though they are in the same model,
they are in different documents. -->
<component name="Porridge" id="p" />
<component name="Toast" id="t">
<!-- Invalid: The id attribute "p" here does clash with the component
Porridge above because they are in the same document. -->
<variable name="Peanutbutter" id="p" units="smooth" />
</component>
</model>
Some points to note:
Here we have two separate documents which are partially combined to make one model.
There is no repetition of
id
attribute values within the BreakfastMenu.cellml document.There is repetition of the
name
attribute “FunStuff”, but the elements have different types (component
andvariable
), so this remains valid.There is repetition of the
id
attribute “p” in the CarbohydrateIdeas.cellml document, between thevariable
named “Peanutbutter” and thecomponent
named “Porridge”. This is not valid.
Data representation formats in CellML¶
The following data representation formats are defined for use in this specification:
A CellML identifier:
SHALL consist of a single Basic Latin alphabetical character, which MAY be followed by any combination of Basic Latin alphanumerical characters and/or Basic Latin underscores.
SHALL, when comparing two identifiers, be considered identical to another identifier if and only if both identifiers are identical sequences of characters.
See more
Names and identifiers need to be a single word, and without any special characters other than an underscore. For example, these are allowed:
myName
,
my_name
,
myName1
,
… but these are not permitted:
my Name
has a space,
myName!
contains a special character, and
1myName
starts with a numerical character.
Note that CellML identifiers are case-sensitive, and empty strings are not allowed.
An integer string:
SHALL be a base 10 representation of an integer.
SHALL, other than the sign indicator, consist of one or more digits.
See more
An integer string is simply a string containing only the numerical characters between 0 and 9.
If it’s a negative then it should begin with the minus sign, -
, if it’s positive it may begin with the plus sign, +
.
A basic real number string:
SHALL be a base 10 representation of a real number.
MAY contain a single decimal point separator, which SHALL be the Basic Latin full stop character U+002E.
SHALL, other than the sign indicator and the decimal point separator, consist of one or more digits.
See more
Note that the basic real number string is distinct from the real number string in that it does not include real numbers in scientific notation (also called scientific form, standard index form, or standard form).
For example:
"-123.4567"
is a valid basic real number string,
"-1.234567E03"
is not (but it is a valid real number string),
"+123.4567"
is not valid (must not contain the plus sign+
),
"1234567"
is valid (it’s ok to not use a decimal point.
),
"123,4567"
is not valid (the decimal signifier must be a full-stop symbol.
),
"123,456.7"
is not valid (you may not use a comma,
or a space :code:` ` as a thousands separator),
"12.34.56"
is not valid (maximum of one decimal point.
is permitted), and
"0x123abc"
is not valid (base 10 numbers only).
A real number string:
SHALL be a base 10 representation of a real number \(r=s \times 10^e\) where \(s\) is the significand, a real number, and \(e\) is the exponent, an integer.
The representation of the number SHALL be the representation of the significand, optionally followed by a representation of the exponent.
The significand SHALL be represented as a basic real number string.
An exponent SHALL be represented by an exponent separator character, followed by the integer string representation of the value of the exponent. The exponent separator character SHALL be either the Basic Latin “E” character U+0045 or the Basic Latin “e” character U+0065.
If the exponent representation is omitted, the exponent shall be zero.
See more
Note that the real number string is distinct from the basic real number string in that it includes numbers in scientific notation (also called scientific form, standard index form, or standard form).
Where it does not contain an exponent term, the number is interpreted as if it was a basic real number string: the exponent term is effectively zero.
For example:
"1.234E03"
is a valid real number string,
"+1.234E03"
is not valid (must not contain the plus sign+
in the significand),
"1.234E+03"
is valid (a plus sign+
sign is permitted in the exponent),
"1.234E+3.0"
is not valid (the exponent must be an integer),
"1.234e3"
is valid (either case of E or e is permitted),
"123,45E03"
is not valid (the decimal signifier must be a full-stop symbol.
),
"123.45"
is valid, and is treated as if it were a basic real number string: the exponent term is effectivly zero,
"123.45E"
is not valid (if the exponent is present it may not be blank),
"123,456.7e89"
is not valid (you may not use a thousands separator), and
"0x123abc"
is not valid (base 10 numbers only).
Element information items¶
The model
element¶
The top-level element information item in a CellML infoset MUST be an element in the CellML namespace with a local name equal to model
.
In this specification, the top-level element is referred to as the model
element.
Every
model
element MUST contain aname
attribute.The value of the
name
attribute MUST be a CellML identifier.
See more
The model
is the highest level in the CellML file, not including the opening xml
tags.
And, just like the Highlander, there can be only one.
These are valid CellML name attributes:
myValidName
is valid (both cases are permitted),
my_other_valid_name
is valid (underscores are permitted), and
this1too
is valid (numerals 0-9 are permitted).
These are not valid CellML name attributes:
my invalid name
is not valid (spaces are not permitted),
thisIsInvalidToo!
is not valid (special characters other than the underscore_
are not permitted),
1amNotValidEither
is not valid (must not begin with a number), and
" "
empty string is not valid (a name must be present).
A
model
element MAY contain one or more additional specific element children, each of which MUST be of one of the following types:A
component
element;A
connection
element;An
encapsulation
element;An
import
element; orA
units
element.
See more
<model name="myModel">
<component name="myFirstComponent"> ... </component>
<component name="aDuplicatedComponentName"> ... </component>
<!-- INVALID: This component is not valid because it has the same name as an existing one. -->
<component name="aDuplicatedComponentName"> ... </component>
<units name="myUnits"> ... </units>
<units name="myOtherUnits"> ... </units>
<units name="aDuplicatedUnitName"> ... </units>
<!-- INVALID This units item is not valid because it has the same name as an existing units item. -->
<units name="aDuplicatedUnitName"> ... </units>
<!-- A model can contain any number of import items. -->
<import />
<import />
<!-- A model can contain any number of connection items, as long as the things they connect are unique. -->
<connection />
<connection />
<encapsulation>...</encapsulation>
<!-- INVALID: A model must contain only ONE encapsulation item. -->
<encapsulation>...</encapsulation>
<!-- INVALID: The only child elements of the model are those stated. -->
<apples> ... </apples>
</model>
A
model
element MUST NOT contain more than oneencapsulation
elements.
See more
The encapsulation of a model defines the nested structure of its components.
This in turn affects which variables have access to which other variables, and allows the modular behaviour to happen at any level.
For this reason, there can be only one encapsulation
item in any model.
For more information about encapsulation, please refer to The encapsulation element information item.
The import
element¶
An import
element information item (referred to in this specification as an import
element) is an element in the CellML namespace with a local name equal to import
, which appears as a child of a model
element.
Every
import
element MUST contain an attribute in the namespacehttp://www.w3.org/1999/xlink
, with a local name equal tohref
.The value of this attribute SHALL be a valid locator
href
, as defined in Section 5.4 of the XLink specification [6].The
href
attribute SHALL be treated according to the XLink specification [6], by applying the rules for simple-type elements.When describing an
import
element or one of its children, the phrase “imported CellML infoset” SHALL refer to the CellML infoset obtained by parsing the document referenced by thehref
attribute.
See more
At present the location specified by the href
attribute must be a locally available file (not online).
The path may either be absolute from the root directory, or relative to the importing model’s location.
For example, here’s a model based around casting for The Wizard of Oz.
In the main model (the one doing the importing), the component used to play Dorothy is defined by importing a component
named judy_garland
from the file called role_of_dorothy.cellml
and setting its reference in the main file to be the component named dorothy
.
Note the file structure: the path to the imported file is specified relative to the importing file, in this case role_of_dorothy.cellml
sits inside a folder called characters
.
oz_model.cellml
<model name="oz">
<import xlink:href="characters/role_of_dorothy.cellml">
<component name="dorothy" component_ref="judy_garland" />
</import>
...
</model>
characters/dorothy.cellml
<model name="candidates_for_dorothy">
<component name="judy_garland"> ... </component>
...
<import xlink:href="toto.cellml">
<component name="judy_garlands_dog" component_ref="a_terrier_called_terry"/>
</import>
</model>
characters/role_of_toto.cellml
<model name="candidates_for_toto">
<component name="a_terrier_called_terry"> ... </component>
<component name="scooby_doo"> ... </component>
</model>
The component representing Toto could be imported in one of two ways, both giving identical model representations.
Either directly from the role_of_toto.cellml
file, or indirectly via the role_of_dorothy.cellml
file:
<model name="oz">
<import xlink:href="characters/role_of_dorothy.cellml">
<component name="dorothy" component_ref="judy_garland" />
</import>
<!-- Either directly from the "role_of_toto.cellml" file ... -->
<import xlink:href="characters/role_of_toto.cellml">
<component name="toto" component_ref="a_terrier_called_terry" />
</import>
<!-- ... OR indirectly through the role_of_dorothy.cellml" file. -->
<import xlink:href="characters/role_of_dorothy.cellml">
<component name="toto" component_ref="judy_garlands_dog" />
</import>
</model>
Every
import
element MAY contain one or more specific element children, each of which MUST be of one of the following types:An
import component
element; orAn
import units
element.
See more
The only items which can be imported directly are component
and units
items.
The intention is that these are modular building blocks, able to be passed between models easily through this import functionality.
When you import a component
, all its variables
and encapsulated child component
items are imported too, along with any its governing math
block and any units
items it uses.
When you import a units
item, the child unit
items which it contain are imported as well.
Any CellML infoset imported, directly or indirectly, by the imported CellML infoset MUST NOT be semantically equivalent to the importing CellML infoset (see 1.2.3.3 regarding semantic equivalence).
See more
The intention behind this restriction is to prevent circular import definitions from occurring.
Models are able to import twins, that is, component
or units
items which are identical in content but under different names.
Models may not import themselves, because this would create an infinite loop of dependence.
For example, the first Olsen twins model below is permitted: the same component is imported twice under different names.
<model name="olsen_twins">
<import xlink:href="twin_sister.cellml">
<component name="mary_kate" component_ref="sister"/>
</import>
<import xlink:href="twin_sister.cellml">
<component name="ashley" component_ref="sister"/>
</import>
<model>
This recursive import is not permitted because a component cannot import itself:
<!-- In a file called "multiplicity.cellml": -->
<model name="multiplicity">
<import xlink:href="multiplicity.cellml">
<component name="doug" component_ref="doug"/>
</import>
<model>
The sames applies for “indirect” imports, where recursion is created over several files:
<!-- In a file called "multiplicity.cellml": -->
<model name="multiplicity">
<import xlink:href="clone.cellml">
<component name="doug" component_ref="clone"/>
</import>
<model>
<!-- In a file called "clone.cellml": -->
<model name="first_clone">
<import xlink:href="clone_of_clone.cellml">
<component name="clone" component_ref="another_clone"/>
</import>
</model>
<!-- In a file called "clone_of_clone.cellml": -->
<model name="repeating_cloning">
<import xlink:href="multiplicity.cellml">
<component name="another_clone" component_ref="doug"/>
</import>
</model>
The import units
element¶
An import units
element information item (referred to in this specification as an import units
element) is an element in the CellML namespace with a local name equal to units
, which appears as a child of an import
element.
Every
import units
element MUST contain aname
attribute.The value of the
name
attribute MUST be a CellML identifier.The value of the
name
attribute MUST NOT be identical to the value of thename
attribute of any otherunits
orimport units
element in the CellML infoset.
Read more
Importing units means that you’re assured of consistency between your models, and allows for a more modular reuse of the components which use them. There are three ingredients required in importing any item:
A destination item in the importing model (this is the
units
item calledsmallPotOfPaint
in the example below).A file to import from, specified using the
xlink:href
attribute of the parentimport
block. This is discussed in more detail in The import element information item. In the example below this is thepaint_pot_sizes.cellml
file.The specific item name to retrieve from the imported file. In the example below this is the
twoLitrePot
value passed to theunits_ref
attribute.
Thus we can read the import statement below as: “retrieve the units
named twoLitrePot
from the file paint_pot_sizes.cellml
, and store it here in this model under the name potOfPaint
”.
<import xlink:href="paint_pot_sizes.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<units units_ref="twoLitrePot" name="potOfPaint"/>
</import>
Note that if you’ve already defined the namespace inside the <model>
tags then you would not need to repeat it here.
Imported items have the same restrictions as concrete items regarding the uniqueness of their names.
In the example below, the name potOfPaint
is used for the locally defined units in line 2, but the same name is used as the name for the imported units in line 6.
This is not permitted as it violates the uniqueness requirement for unit names.
<model name="paintingTheHouse">
<units name="potOfPaint">
<unit units="metre" exponent="3" multiplier="0.002">
</units>
<!-- This destination name conflicts with the locally defined name above -->
<import xlink:href="paint_pot_sizes.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<units units_ref="twoLitrePot" name="potOfPaint"/>
</import>
<component name="paintCalculator">
...
</component>
</model>
Every
import units
element MUST contain aunits_ref
attribute.The value of the
units_ref
attribute MUST be a CellML identifier.The value of the
units_ref
attribute MUST be identical to the value of thename
attribute on aunits
orimport units
element in the imported CellML infoset.
The import component
element¶
An import component
element information item (referred to in this specification as an import component
element) is an element in the CellML namespace with a local name equal to component
, which appears as a child of an import
element.
Every
import component
element MUST contain aname
attribute.The value of the
name
attribute MUST be a CellML identifier.The value of the
name
attribute MUST NOT be identical to the value of thename
attribute of any othercomponent
orimport component
element in the CellML infoset.
Every
import component
element MUST contain acomponent_ref
attribute.The value of the
component_ref
attribute MUST be a CellML identifier.The value of the
component_ref
attribute MUST be identical to the value of thename
attribute on acomponent
orimport component
element in the imported CellML infoset.
See more
The ablility to import and reuse component
items is one of the most powerful features in CellML, as it allows modellers to easily plug-n-play different variations and model parts.
There are three ingredients required in importing any item:
A destination in the importing model (this is the
component
item calledpi_calculator
in the example below),A file to import from, specified using the
xlink:href
attribute of the parentimport
block. This is discussed in more detail in The import element information item. In the example below this is thepi_approximators.cellml
file.The specific item name to retrieve from the imported file. In the example below this is the
circumference_over_diameter
value passed to thecomponent_ref
attribute.
Thus we can read the import statement below as: “retrieve the component
named circumference_over_diameter
from the file pi_approximators.cellml
, and store it here in this model under the name pi_calculator
”.
<import xlink:href="pi_approximators.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<component component_ref="circumference_over_diameter" name="pi_calculator"/>
</import>
Things to watch out for:
The namespace. Note that if you’ve already defined the
xmlns:xlink
namespace inside the<model>
tags then you would not need to repeat it here.The name attribute. Imported items have the same restrictions as locally defined items regarding the uniqueness of their names and their format. In the example below, the name
pi_calculator
is used for the locally defined component in line 2, but the same name is used as the name for the imported component in line 6. This is not permitted as it violates the uniqueness requirement for names specified above. The second imported component uses an invalid name attribute (see Data representation formats in CellML) so is not permitted either.
<model name="circle">
<component name="pi_calculator">
...
</component>
<!-- This destination name conflicts with the locally defined name above: -->
<import xlink:href="series_approx_of_pi.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<component component_ref="GregoryLeibnizApproximator" name="pi_calculator"/>
</import>
<!-- This destination name is not valid CellML as it contains whitespace and special characters: -->
<import xlink:href="series_approx_of_pi.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<component component_ref="GregoryLeibnizApproximator" name="pi calculator!"/>
</import>
</model>
The component_ref attribute. This must be a valid CellML identifier (see Data representation formats in CellML). It also has to actually exist as a
component
in the givenhref
location! Neither of the imports below are permitted:
<model name="circle">
<!-- This component_ref name does not exist at in the file specified: -->
<import xlink:href="series_approx_of_pi.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<component component_ref="I_dont_exist" name="pi_calculator"/>
</import>
<!-- This component_ref name is not a valid CellML identifier: -->
<import xlink:href="series_approx_of_pi.cellml" xmlns:xlink="http://www.w3.org/1999/xlink">
<component component_ref="I have spaces so am not a valid ID" name="pi_calculator"/>
</import>
</model>
The units
element¶
A units
element information item (referred to in this specification as a units
element) is an element in the CellML namespace with a local name equal to units
, which appears as a child of a model
element.
Every
units
element MUST contain aname
attribute.The value of the
name
attribute MUST be a CellML identifier.The value of the
name
attribute MUST NOT be identical to the value of thename
attribute of any otherunits
element orimport units
element in the CellML infoset.
The value of the
name
attribute MUST NOT be identical to the name of any of the units listed in Table 3.1: Built-in units (see 3.2 Units references).
A
units
element MAY contain one or moreunit
element children.
See more
The best way to understand how units
work is to read the informative sections within the Unit element section in the next section, which defines their child unit
items.
The following examples show examples of what is not permitted when defining units
items.
<!-- The units name attribute is not a valid CellML identifier. -->
<units name="I'm not valid!"> ... </units>
<!-- Duplicted local units names are not allowed. -->
<units name="duplicatedName"> ... </units>
<units name="duplicatedName"> ... </units>
<!-- Duplicated name of an imported units item is not allowed. -->
<import xlink:href="handyUnitsForImport.cellml">
<units units_ref="myCustomUnits" name="duplicatedName">
</import>
<!-- Duplicating the name of built-in units is not allowed. -->
<units name="metre"> ... </units>
The unit
element¶
A unit
element information item (referred to in this specification as a unit
element) is an element in the CellML namespace with a local name equal to unit
, which appears as a child of a units
element.
Every
unit
element MUST contain aunits
attribute.The value of the
units
attribute MUST be a valid units reference, as defined in 3.2 Units references.For the purpose of the constraint in the next paragraph, the
units
element inclusion digraph SHALL be defined as a conceptual digraph which SHALL contain one node for everyunits
element in the CellML model.The
units
element inclusion digraph SHALL contain an arc fromunits
element A tounits
element B if and only ifunits
element A contains aunit
element with aunits
attribute value that is identical to thename
attribute value ofunits
element B.
The element inclusion digraph MUST NOT contain any cycles.
See more
A Units
item is simply a collection of Unit
items, each with a prefix
, multiplier
, and exponent
.
They can be nested and contain multiple generations of inheritance, which means that there’s always a possibility of circular definitions: these are not permitted.
For example, the first definition is valid:
<!-- Defining new base units called A: -->
<units name="A"/>
<!-- Defining new units called B, equivalent to 1000.A^2 -->
<units name="B">
<unit units="A" prefix="kilo" exponent="2"/>
</units>
<!-- Defining new units called C, equivalent to B^3/ms or (1000)^3.A^6/ms -->
<units name="C">
<unit units="B" exponent="3"/>
<unit units="second" prefix="milli" exponent="-1"/>
</units>
The second definition creates a circular dependency, and is not valid:
<!-- Defining units called A which depend on units B: -->
<units name="A">
<unit units="B" exponent="2"/>
</units>
<!-- Defining units called B which depend on units C: -->
<units name="B">
<unit units="C" prefix="kilo" exponent="-2"/>
</units>
<!-- Defining units called C which depend on A: -->
<units name="C">
<unit units="A" prefix="mega"/>
<unit units="second" prefix="milli" exponent="-1"/>
</units>
A
unit
element MAY contain any of the following attributes:The
prefix
attribute. If present, the value of the attribute MUST meet the constraints specified in 3.3 Interpretation of units elements.
The
multiplier
attribute. If present, the value of the attribute MUST be a real number string.
The
exponent
attribute. If present, the value of the attribute MUST be a real number string.
See more
There are two items related to units in CellML, and their naming can be confusing!
The plural form, units
, represents the units to be used in the model by being assigned to variable
and cn
elements.
A units
item is a collection of smaller unit
items which transform the base dimensionality into the form required by the final units by way of prefixes, multipliers, and exponents.
In the example, we’ll need to use two of the built-in base units, metre
and second
, and manipulate them to form cm3/s.
This is done by including child unit
items.
First, we need to change the base units of metre
into cm3/s:
<units name="cm3_per_second">
<unit units="metre" prefix="centi" exponent="3"> <!-- The default multiplier is 1. -->
...
</units>
Next, we include the time dependency, changing the built-in units second
into s-1.
Note that sibling unit
items within a parent units
item are simply multplied together to form the final representation:
<units name="cm3_per_second">
<unit units="metre" prefix="centi" exponent="3"> <!-- Note default multiplier of 1. -->
<unit units="second" exponent="-1"> <!-- Note default prefix of 0, default multiplier of 1. -->
</units>
This is exactly equivalent to the alterantives below:
<units name="cm3_per_second">
<unit units="metre" prefix="-2" exponent="3"> <!-- A prefix can be specified as a power of 10. -->
<unit units="second" exponent="-1">
</units>
<!-- or ... -->
<units name="cm3_per_second">
<unit units="metre" exponent="3" multiplier="0.01"> <!-- A multiplier is specified instead of a prefix. -->
<unit units="second" exponent="-1">
</units>
<!-- or ... -->
<units name="cm3_per_second">
<unit units="metre" prefix="centi"> <!-- Note default exponent of 1 ... -->
<unit units="metre" prefix="-1"> <!-- ... is repeated ... -->
<unit units="metre" multiplier="0.01"> <!-- ... to give the equivalent power of 3. -->
<unit units="second" exponent="-1">
</units>
For more information on units
items please refer to the previous section.
The component
element¶
A component
element information item (referred to in this specification as a component
element) is an element in the CellML namespace with a local name equal to component
, which appears as a child of a model
element.
See more
Components are a convenient way to modularise a model, and allow parts to be removed, replaced, and reused easily. They define the scope of their contents, meaning that the items within a component need only be uniquely named in that local scope. Commonly needed variables (like time, for example) can be given the same name in multiple components without triggering an error.
Components are the largest building blocks of the model, and have three important parts to them.
The first is their naming and contents, similar to all the other CellML items, and described below.
The second relates to their structure in relation to other component
items: this structure is called their encapsulation and is described in The encapsulation item.
The third relates to the import component
item, as described in The import_component item.
Every
component
element MUST contain aname
attribute.The value of the
name
attribute MUST be a CellML identifier.The value of the
name
attribute MUST NOT be identical to the value of thename
attribute on any othercomponent
element orimport component
element in the CellML infoset.
See more
A component
item, as with every other part of CellML, must use a name unique to its scope, and obey the format definitions outlined in Data representation formats.
For example:
<!-- This is valid: -->
<component name="myValidName"> ... </component>
<!-- Not valid: the units name attribute is not a valid CellML identifier. -->
<component name="I'm not valid!"> ... </component>
<!-- Not valid: duplicted component names are not allowed. -->
<component name="duplicatedName"> ... </component>
<component name="duplicatedName"> ... </component>
<!-- Not valid: duplicating the name of an imported component item is not allowed. -->
<import xlink:href="handyComponentsForImport.cellml">
<component component_ref="myComponentRef" name="duplicatedName">
</import>
A
component
element MAY contain one or more specific element children, each of which MUST be of one of the following types:A
math
element;A
reset
element; orA
variable
element.
See more
The mathematics of a component
Perhaps the most important part of a component
item is the mathematics it contains.
This is stored inside a collection of <math>
blocks as described in The math element.
The math
then defines the operation of the local variable
items and how they relate to each other mathematically.
For example, a component to calculate Einstein’s \(E=mc^2\) could be represented by:
<component name="mass_into_energy">
<math>
<apply><eq/>
<ci>E</ci>
<apply><times/>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<cn cellml:units="dimensionless">2</cn>
</apply>
</apply>
</apply>
</math>
...
</component>
Please refer to the math element section for information on the math
items and MathML format.
The variables of a component
The MathML block above refers to three variables named E
, m
and c
.
These variable names must be the same as the name
attributes of the child variable
items in this component.
<component name="mass_into_energy">
...
<variable name="E" units="joule" />
<variable name="m" units="kilogram" />
<variable name="c" units="metres_per_second" />
</component>
Please refer to the variable element section for information on variable
items.
The reset items of a component
Please refer to the reset element section for more information on reset
items.
The variable
element¶
A variable
element information item (referred to in this specification as a variable
element) is an element in the CellML namespace with a local name equal to variable
, which appears as a child of a component
element.
Every
variable
element MUST have exactly one of each of the following attributes:The
name
attribute. The value of thename
attribute MUST be a CellML identifier.The value of the
name
attribute MUST NOT be identical to the value of thename
attribute on any siblingvariable
element.
The
units
attribute. The value of theunits
attribute MUST be a valid units reference, as defined in 3.2 Units references.
Every
variable
element MAY contain one or more of the following attributes:The
interface
attribute. If the attribute is present, it MUST have value ofpublic
,private
,public_and_private
, ornone
.
The
initial_value
attribute. If the attribute is present, it MUST meet the requirements described by 3.6 Interpretation of initial_value attributes.
See more
In addition to the standard name
attribute, each variable
must also define a units
attribute too.
Reusing Einstein’s example from the component item section we can give the three variables their fuller definitions:
<component name="mass_into_energy">
<math>
...
</math>
<variable name="E" units="joule"/>
<variable name="m" units="kilogram"/>
<variable name="c" units="metre_per_second"/>
</component>
Extra attributes that can be used as needed include the initial_value
, which will either set a constant value for a variable, or set its initial conditions if it’s being solved for.
More information about initialisation can be found in the Interpretation of initial values section.
Finally, where one variable
(A) has been mapped to another (B) in a different component (BB), both A and B must specify interface
attributes.
These prescribe the relative positions in the encapsulation that the components AA and BB must have in order for their respective variables A and B to access one another.
This is outlined in more detail in the encapsulation element section.
The reset
element¶
A reset
element information item (referred to in this specification as a reset
element) is an element in the CellML namespace with a local name equal to reset
, which appears as a child of a component
element.
Every
reset
element MUST have exactly one of each of the following attributes:The
variable
attribute. The value of thevariable
attribute MUST be a valid variable reference, as defined in 3.5 Variable references.
The
test_variable
attribute. The value of thetest_variable
attribute MUST be a valid variable reference, as defined in 3.5 Variable references.
The
order
attribute. The value of theorder
attribute MUST be an integer string.The value of the
order
attribute MUST be unique for allreset
elements withvariable
attributes that reference variables in the same equivalent variable set (see 3.10 Interpretation of map_variables elements).
A
reset
element MUST contain exactly two element children, which MUST be one of each of the following types:A
reset_value
element; and
A
test_value
element.
The test_value
element¶
A test_value
element information item (referred to in this specification as a test_value
element) is an element in the CellML namespace with a local name equal to test_value
, which appears as a child of a reset
element.
A
test_value
element MUST contain exactly onemath
element child.
See more
The test_value
(like the reset_value
) block takes a slightly different kind of MathML statement to those in the component
elements.
Because the the left hand side of the equation has already been effectively defined by specifying the test_variable
, the math
child of a test_value
needs only to specify the right hand side.
This means that the normal opening block of <apply><eq/><ci>left_hand_side_variable</ci> ... </apply>
is omitted:
<reset variable="position" test_variable="height_above_the_floor_in_metres" order="1"/>
<test_value>
<math>
<cn cellml:units="metre">1.0</cn>
</apply>
</math>
</test_value>
<reset_value>
<math>
<apply><plus/>
<apply><abs/>
<apply><minus/>
<cn cellml:units="metre">1</cn>
<ci>position</ci>
</apply>
</apply>
<cn cellml:units="metre">1.0</cn>
</apply>
</math>
</reset_value>
</reset>
In the above example, the position of a ball above a 1 metre high table is maintained, as every time it appears to drop below the table-level datum of position=1.0
it is reset to a “bounced” value greater than 1.0 instead.
For the reset
to be useful, the equations it contains need to make sense.
Be sure to check that the units that you’re using within the test_value
block match those of the test_variable
against which it will be compared.
In this example the reset_value
(the new position of the ball over the table) must be in metres to match the variable
’s units, as with the test_value
which must match the units of the test_variable
.
A mismatch of units here doesn’t mean you have an invalid CellML 2.0 model, but it does mean that it may not behave in the way you are expecting!
The reset_value
element¶
A reset_value
element information item (referred to in this specification as a reset_value
element) is an element in the CellML namespace with a local name equal to reset_value
, which appears as a child of a reset
element.
A
reset_value
element MUST contain exactly onemath
element child.
See more
The test_value
(like the reset_value
) block takes a slightly different kind of MathML statement to those in the component
elements.
Because the the left hand side of the equation has already been effectively defined by specifying the test_variable
, the math
child of a test_value
needs only to specify the right hand side.
This means that the normal opening block of <apply><eq/><ci>left_hand_side_variable</ci> ... </apply>
is omitted:
<reset variable="position" test_variable="height_above_the_floor_in_metres" order="1"/>
<test_value>
<math>
<cn cellml:units="metre">1.0</cn>
</apply>
</math>
</test_value>
<reset_value>
<math>
<apply><plus/>
<apply><abs/>
<apply><minus/>
<cn cellml:units="metre">1</cn>
<ci>position</ci>
</apply>
</apply>
<cn cellml:units="metre">1.0</cn>
</apply>
</math>
</reset_value>
</reset>
In the above example, the position of a ball above a 1 metre high table is maintained, as every time it appears to drop below the table-level datum of position=1.0
it is reset to a “bounced” value greater than 1.0 instead.
For the reset
to be useful, the equations it contains need to make sense.
Be sure to check that the units that you’re using within the test_value
block match those of the test_variable
against which it will be compared.
In this example the reset_value
(the new position of the ball over the table) must be in metres to match the variable
’s units, as with the test_value
which must match the units of the test_variable
.
A mismatch of units here doesn’t mean you have an invalid CellML 2.0 model, but it does mean that it may not behave in the way you are expecting!
The math
element¶
A math
element information item (referred to in this specification as a math
element) is an element in the MathML namespace, which appears as a child of a component
element, a test_value
element, or a reset_value
element.
A
math
element MUST be the top-level element of a Content MathML tree, as described in MathML 2.0 [7].
See more
Because MathML is an entire language in its own right, we just don’t have the ability to go through all its general aspects here. Some great general resources are available on the MathML 2.0 site, and we’ll discuss below the more CellML specific restrictions in the other “See more” sections.
Please note that MathML 2 content markup is the only syntax used in CellML, even though more recent versions (MathML 3 and MathML 4) are available.
Each element child of a
math
element MUST have an element-type name that is listed in Table 2.1: Supported MathML elements.
See more
Probably the biggest aspect of CellML’s restrictions of MathML is that it is confined to using only MathML2 content markup. No form of presentation markup is permitted, and only the version MathML2 is allowed (i.e.: not MathML 3 or greater).
The basics
The types of block can be divided into two broad categories: operation items and information items. For example, the calculation of Einstein’s \(E=mc^2\) could be represented by:
<math>
<apply><eq/>
<ci>E</ci>
<apply><times/>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<cn cellml:units="dimensionless">2</cn>
</apply>
</apply>
</apply>
</math>
The code below is similar, but with the mistakes as listed:
<math>
<apply><eq/>
<!-- The line below is not valid because <ci> elements cannot specify units;
their units are taken from the units of the variable
(even though in this case, E really does have units Joules). -->
<ci cellml:units="joule">E</ci>
<!-- The <apply> operation below is missing an operation argument (it should be <times/>) -->
<apply>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<!-- The contents of a <cn> block below must be a real number, not a variable. -->
<!-- It must also define units in the cellml namespace, i.e.: units:cellml="myUnits". -->
<cn>variable_with_value_of_two</cn>
</apply>
</apply>
</apply>
</math>
The contents of a MathML
ci
element MUST be a valid variable reference, as defined in 3.5 Variable references.
See more
Consider the same \(E=mc^2\) formula as earlier, but now the value of mass m
is calculated in another component:
<component name="mass_into_energy">
<!-- The local variables for energy E and speed of light c are listed here ... -->
<variable name="E" units="joule"/>
<variable name="c" units="metres_per_second"/>
<!-- ... but the variable for mass calculated in another component. -->
<math>
<apply><eq/>
<ci>E</ci>
<apply><times/>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<cn cellml:units="dimensionless">2</cn>
</apply>
</apply>
</apply>
</math>
</component>
<component name="calculate_mass">
<variable name="m" units="kilograms" initial_value="54" />
</component>
This situation is not valid, as the math
block in component mass_into_energy
doesn’t have access to the variable m
in the component calculate_mass
.
To get around this, you would need to create a new local variable within the mass_into_energy
component, and use a connection
element to link it to the mass variable m
in the other component.
The valid form of the model is shown below. You can read more about connections
in The connection element, and the interface_type
attribute in The variable element.
<component name="mass_into_energy">
<variable name="E" units="joule"/>
<variable name="c" units="metres_per_second"/>
<!-- A new local variable named m is created here with a public interface type. -->
<variable name="m" units="kilograms" interface_type="public"/>
<math>
<apply><eq/>
<ci>E</ci>
<apply><times/>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<cn cellml:units="dimensionless">2</cn>
</apply>
</apply>
</apply>
</math>
</component>
<component name="calculate_mass">
<variable name="mass" units="kilograms" initial_value="54" />
</component>
<!-- A connection element is created which links components "calculate_mass" and "mass_into_energy". -->
<connection component_1="mass_into_energy" component_2="calculate_mass">
<!-- A map_variable pair is created which links the "m" variables in each of the connected components. -->
<map_variables variable_1="m" variable_2="m" />
</connection>
A MathML
cn
element MUST have an attribute in the CellML namespace, with a local name equal tounits
.The value of the
units
attribute MUST be a valid units reference, as defined in 3.2 Units references.
A
cn
element MUST be base 10, and MUST be of the following types: real or e-notation.
See more
Constants using the <cn>
tags
When specifying a constant with <cn>
, its real number value is given between the tags, and its units are specified as an attribute.
<!-- These are valid: Note the cellml namespace for the units. -->
<cn cellml:units="customUnitsDefinedInTheModel">35.3</cn> <!-- Units which exist in the model are permitted. -->
<cn cellml:units="litre">10</cn> <!-- Built-in units (with UK spelling) are permitted. -->
<cn cellml:units="dimensionless">3.14159e+03</cn> <!-- Scientific or e-notation is permitted. -->
Please note that the units name specified must refer to a units
element that exists in the model
element, or be one from the Built-in Units table.
<!-- These are not valid: -->
<cn cellml:units="unitsThatDontExist">35.3</cn> <!-- The units reference must exist in the model. -->
<cn>42</cn> <!-- Units must be specified. -->
<cn some_other_namespace:units="some_units">502.642</cn> <!-- Units must be in the cellml namespace. -->
<cn cellml:units="meter">26.6</cn> <!-- Built-in unit names must be in UK spelling, i.e.: metre, litre. -->
<cn cellml:units="dimensionless">3,000</cn> <!-- Must be a valid real number string, the comma separator is not permitted. -->
<cn cellml:units="dimensionless">+4.0</cn> <!-- The plus sign indicator is not permitted except in e-notation exponents. -->
<cn cellml:units="dimensionless">0x235abc</cn> <!-- The value must be in base 10. -->
<cn cellml:units="dimensionless">i_am_a_variable</cn> <!-- Only real number values are permitted in <cn> blocks. -->
Dimensional consistency (or, how to write nonsense maths)
For a model to have a valid CellML syntax, it needs to follow the MathML rules outlined above. But it’s still possible to create nonsense (should you so desire … ), and one great way to create nonsense is to have MathML statements which have inconsistent units. Consider again Einstein’s equation \(E=mc^2\). Now imagine that encode it into CellML like this:
<variable name="E" units="joule"/>
<variable name="c" units="lumen"/>
<variable name="m" units="weber"/>
<math>
<apply><eq/>
<!-- Nonsense alert! Left hand side units of joules ... -->
<ci>E</ci>
<!-- ... but right hand side units of (weber).(lumen)^(volt)! -->
<apply><times/>
<ci>m</ci>
<apply><power/>
<ci>c</ci>
<!-- Nonesense alert! Units in an exponent? -->
<cn cellml:units="volt">2</cn>
</apply>
</apply>
</apply>
</math>
Believe it or not, this is valid! (Perhaps it’s better to say it’s not invalid).
It’s clearly nonsense, but it doesn’t actually violate any syntax rules.
The only instance where you will create an invalid model by assigning units
to variables
is when you need to form a map_variables
pair with a variable
in another component
.
In this case, each variable
must have an equivalent unit reduction or it won’t be valid CellML.
Element Category |
Element List |
Simple Operands |
|
Basic Structural |
|
Relational and Logical Operators |
eq , neq , gt , lt , geq ,leq , and , or , xor , not |
Arithmetic Operators |
plus , minus , times , divide ,power , root , abs ,exp , ln , log ,floor , ceiling ,min , max , rem |
Calculus Elements |
|
Qualifier Elements |
|
Trigonometric Operators |
sin , cos , tan , sec ,
csc , cot ,sinh , cosh , tanh , sech ,
csch , coth ,arcsin , arccos , arctan ,arcsec , arccsc , arccot ,arcsinh , arccosh , arctanh ,arcsech , arccsch , arccoth |
Mathematical and Logical Constants |
pi , exponentiale ,
notanumber ,infinity , true , false |
* degree
MUST be a child of root
or diff
The encapsulation
element¶
An encapsulation
element information item (referred to in this specification as an encapsulation
element) is an element in the CellML namespace with a local name equal to encapsulation
, which appears as a child of a model
element.
An
encapsulation
element MAY contain one or morecomponent_ref
element children.
See more
Encapsulation is the way that CellML manages the hierarchy of components and keeps their modularity.
This is why there can be only one encapsulation
element within a model
: you can think of it as a table of contents for components in the whole model.
Encapsulations don’t have to include all of the model’s components; only the ones which need to sit within another component.
Components which are not listed within the encapsulation are top-level children of the model
.
<!-- 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 component_ref
element¶
A component_ref
element information item (referred to in this specification as a component_ref
element) is an element in the CellML namespace with a local name equal to component_ref
, which appears as a child of an encapsulation
element.
Every
component_ref
element MUST contain acomponent
attribute.The value of the
component
attribute MUST be a valid component reference, as defined in 3.4 Component references.The value of the
component
attribute MUST NOT be identical to the value of thecomponent
attribute on any othercomponent_ref
element in the CellML infoset.
Every
component_ref
element MAY in turn contain one or morecomponent_ref
element children.
See more
Please see the notes about the component_ref
usage under the “See more” link on the encapsulation element page.
The connection
element¶
A connection
element information item (referred to in this specification as a connection
element) is an element in the CellML namespace with a local name equal to connection
, which appears as a child of a model
element.
Each
connection
element MUST contain acomponent_1
attribute.The value of the
component_1
attribute MUST be a valid component reference, as defined in 3.4 Component references.
Each
connection
element MUST contain acomponent_2
attribute.The value of the
component_2
attribute MUST be a valid component reference, as defined in 3.4 Component references.
See more
Creating connection
items allows variable
values to be passed between eligible components
.
There are both syntactic (i.e.: format) and semantic (i.e.: meaning) rules about how these must be specified, including what “eligible” means.
Syntax will be discussed below and in the other “See more” blocks on this page.
For more on the semantic rules, please see Interpretation of map_variables.
Both points above are really saying the same thing.
The way in which you specify the component_1
and component_2
items must follow the general CellML 2.0 format for a valid identifier, and must point to a component
which exists under that name (note that this could be either an intantiated component
, or an import component
item).
<!-- This is a valid CellML 2.0 connection: -->
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="romeo" variable_2="juliet">
</connection>
</model>
<!-- This is not valid: -->
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<!-- The component_2 attribute does not exist as a component or import component name.-->
<connection component_1="house_of_montague" component_2="CapuletWhanau">
<!-- The variable_1 name is not a valid CellML identifier. -->
<map_variables variable_1="Romeo, Romeo ..." variable_2="juliet">
</connection>
</model>
The value of the
component_1
attribute MUST NOT be identical to the value of thecomponent_2
attribute.
See more
All this means is that equivalent variables
(i.e.: those specified by connection
and map_variables
items) must be in different components
.
Since the only reason you’d need to use these connections is in order to access a variable
in another component
, this restriction does kinda make sense!
<model>
<component name="happily_ever_after">
<variable name="juliet" interface_type="public">
<variable name="romeo" interface_type="public">
</component>
<!-- This is not valid because component_1 and component_2 are the same. -->
<connection component_1="happily_ever_after" component_2="happily_ever_after">
<map_variables variable_1="romeo" variable_2="juliet">
</connection>
</model>
A CellML infoset MUST NOT contain more than one
connection
element with a given pair of components referenced by thecomponent_1
andcomponent_2
attribute values, in any order.
See more
You may only have one connection
any two components
, regardless of which is specified as component_1
and which is specified as component_2
.
If you have found duplicate connection
elements, simply merge their contents - a connection
can contain any number of map_variables
children.
Make sure that the order in which you specify the component
attributes matches the order in which you specify their child variable
items too: ie, all variable_1
items must be within the component_1
component and vice versa.
<!-- This is not valid CellML: -->
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
<variable name="rosaline" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="romeo" variable_2="juliet">
</connection>
<!-- This connection duplicates the one above, even though
component_1 and component_2 are swapped. -->
<connection component_1="capulet" component_2="montague">
<map_variables variable_1="rosaline" variable_2="romeo">
</connection>
</model>
<!-- This is now valid: The contents were merged to create a valid model. -->
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
<variable name="rosaline" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<!-- The contents have been merged. Note that the order of variables
must match the order of the parent component, i.e.: all variable_1s
must be within component_1 etc. -->
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="romeo" variable_2="juliet">
<map_variables variable_1="romeo" variable_2="rosaline">
</connection>
</model>
A
connection
element MAY contain one or moremap_variables
element children.
See more
The point of creating a connection
item is in order to connect variables
between eligible components
.
You are allowed to have an empty connection
, but it is meaningless.
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<!-- Valid but redundant: an empty connection is meaningless. -->
<connection component_1="montague" component_2="capulet">
</connection>
</model>
The map_variables
element¶
A map_variables
element information item (referred to in this specification as a map_variables
element) is an element in the CellML namespace with a local name equal to map_variables
, which appears as a child of a connection
element.
Each
map_variables
element MUST contain avariable_1
attribute.The value of the
variable_1
attribute MUST be a valid variable reference, as defined in 3.5 Variable references.
Each
map_variables
element MUST contain avariable_2
attribute.The value of the
variable_2
attribute MUST be a valid variable reference, as defined in 3.5 Variable references.
See more
The points above are both saying the same thing for their variable_1
and variable_2
attributes respectively:
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<!-- Valid: -->
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="romeo" variable_2="juliet">
</connection>
<!-- Invalid: the variable_1 value is not a valid CellML identifier (special characters and spaces). -->
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="Romeo, Romeo ..." variable_2="juliet">
</connection>
<!-- Invalid: the variable_2 value does not exist in component_2. -->
<connection component_1="montague" component_2="capulet">
<map_variables variable_1="romeo" variable_2="juliet_is_the_sun">
</connection>
</model>
A
connection
element MUST NOT contain more than onemap_variables
element with a givenvariable_1
attribute value andvariable_2
attribute value pair.
See more
Just as you can have only one connection
between any two components
, within that connection
you can have only one map_variables
item between any two variables
:
<model>
<component name="house_of_capulet">
<variable name="juliet" interface_type="public">
</component>
<component name="house_of_montague">
<variable name="romeo" interface_type="public">
</component>
<connection component_1="montague" component_2="capulet">
<!-- Invalid: Duplicate map_variables are not allowed. -->
<map_variables variable_1="romeo" variable_2="juliet">
<map_variables variable_1="romeo" variable_2="juliet">
</connection>
</model>
Interpretation¶
Interpretation of import
elements¶
Each
import units
orimport component
element present in a CellML infoset (the importing infoset) SHALL define a new and distinct instance of the CellML infoset (the imported infoset) that is specified by the parentimport
element’shref
attribute.A units reference occurring within an imported element, SHALL be resolved with respect to the imported infoset.
When determining the equivalent variable set of a variable in an imported component:
Connections defined in the importing infoset SHALL be handled as described in 3.10 Interpretation of map_variables elements.
Connections defined in the imported infoset SHALL be handled as follows:
Connections to components in the encapsulated set of the imported component SHALL be maintained, and this rule SHALL be applied recursively; and
Connections to components in the sibling set, or to the encapsulation parent of the imported component SHALL NOT be maintained.
See more
Please see the informative sections on Units reference and Component reference pages for examples specific to importing units
and component
elements.
Units references¶
A “units reference” is an attribute value that specifies the physical units a variable or number is in.
A units reference SHALL be a CellML identifier.
The units identified by a units reference SHALL be determined as follows:
If the units reference is identical to a value in the “Name” column of Table 3.1: Built-in units, then it SHALL refer to the built-in units from the same row of the table.
If the units reference is identical to the value of the
name
attribute of aunits
element in the same infoset, then it SHALL refer to the units specified by that element.If the units reference is identical to the value of the
name
attribute of animport units
element in the same infoset, then it SHALL refer to units from the infoset defined by theimport units
element (see 3.1 Interpretation of import elements`). The units specified SHALL then be determined by treating the value of theunits_ref
attribute on theimport units
element as a units reference within the imported infoset. If necessary, this rule SHALL be applied recursively.
If no units can be identified using the rules above, the attribute value SHALL NOT be a valid units reference.
See more
Understanding units references
Units references are different from other reference types in that their value refers either to other units which you’ve imported or created in your model, or to one of the list of built-in units.
The trickier part is understanding them during an import process, where the scope or domain in which named units exist becomes important, as alluded to in points 3.2.1 and 3.2.2.2.
Consider the example below.
The first model BlueberryPieRecipe
simply combines two pre-made component ingredients; one for the crust and one for the filling.
model: BlueberryPieRecipe
├─ component: crust <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
└─ component: filling <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷
╷ ╷
imported components
╵ ╵
# In filling_recipes.cellml: ╵ ╵
model: PieFillingRecipes ╵ ╵
├─ component: BlueberryCinnamonFilling ╶┘ ╵
└─ component: AppleAndPearFilling ╵
╵
# In crust_recipes.cellml: ╵
model: PieCrustRecipes ╵
├─ component: HazelnutLavenderCrust ╴╴╴╴╴╴┘
└─ component: CheeseAndAlmondCrust
See CellML syntax
<!-- Inside the file "how_to_make_blueberry_pie.cellml": -->
<model name="BlueberryPieRecipe">
<import xlink:href="relative/path/to/my/crust_recipes.cellml">
<component name="crust" component_ref="HazelnutLavenderCrust" />
</import>
<import xlink:href="relative/path/to/my/filling_recipe.cellml">
<component name="filling" component_ref="BlueberryCinnamonFilling" />
</import>
</model>
The components are imported from separate files, each of which defines and uses its own local definitions of the custom measurement units spoon
, dash
, and smidgen
.
model: BlueberryPieRecipe
├─ component: crust <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
└─ component: filling <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷
╷ ╷
imported components and
the units they need
╵ ╵
# In filling_recipes.cellml: ╵ ╵
model: PieFillingRecipes ╵ ╵
├─ component: BlueberryCinnamonFilling ╴╴╴┬┬┘ ╵
│ ├─ variable: blueberries (gram) ╷╷ ╵
│ ├─ variable: sugar (dimensionless) units are implicitly
│ ├─ variable: cornflour (gram) imported by the component
│ ├─ variable: cinnamon ╵╵ ╵
┌╴╴╴╴╴╴╴╴╴> └─ units: smidgen ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╵ ╵
╷ | └─ variable: water ╵ ╵
╷┌╴╴╴╴╴╴╴╴╴> └─ units: spoonful ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵
╷╷ | ╵
╷╷ ├─ component: AppleAndPearFilling ╵
╷╷ | ╵
local custom units ╵
╵╵ | ╵
╵└╴╴├─ units: spoonful ╵
└╴╴╴└─ units: smidgen ╵
╵
# In crust_recipes.cellml: ╵
model: PieCrustRecipes ╵
├─ component: HazelnutLavenderCrust ╴╴╴╴╴╴╴┬┬┬┘
│ ├─ variable: ground_hazelnut (gram) ╷╷╷
│ ├─ variable: egg (dimensionless) ╷╷╷
│ ├─ variable: flour (gram) units are implicitly
│ ├─ variable: sugar (gram) imported by the component
│ ├─ variable: water ╵╵╵
┌╴╴╴╴╴╴╴╴╴╴> └─ units: spoonful ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╵╵
╷ │ ├─ variable: salt ╵╵
╷┌╴╴╴╴╴╴╴╴╴> └─ units: dash ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╵
╷╷ │ └─ variable: lavender_flowers ╵
╷╷┌╴╴╴╴╴╴╴╴> └─ units: smidgen ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
╷╷╷ │
local custom units
╵╵╵ │
╵╵╵ ├─ component: CheeseAndAlmondCrust
╵╵╵ │
╵╵└╴├─ units: smidgen
╵└╴╴├─ units: dash
└╴╴╴├─ units: spoonful
└─ units: dollop
See CellML syntax
<!-- Inside the file "crust_recipes.cellml": -->
<model name="PieCrustRecipes">
<component name="HazelnutLavenderCrust">
<!-- These units are built-in so do not change. -->
<variables name="ground_hazelnut" units="gram" />
<variables name="egg" units="dimensionless" />
<variables name="flour" units="gram" />
<variables name="sugar" units="gram" />
<!-- These units are defined for this, their local scope, below. -->
<variables name="water" units="spoonful" />
<variables name="salt" units="dash" />
<variables name="lavender_flowers" units="smidgen" />
...
</component>
<component name="CheeseAndAlmondCrust">
...
</component>
<!-- Local units definitions for spoonful, dash, and smidgen. -->
<units name="spoonful">
<unit units="litre" prefix="milli" multiplier="15" />
</units>
<units name="dash">
<unit units="gram" multiplier="5" />
</units>
<units name="smidgen">
<unit units="gram" multiplier="1" />
</units>
<units name="dollop">
<unit units="litre" prefix="milli" multiplier="20" />
</units>
</model>
<!-- Inside the file "filling_recipes.cellml": -->
<model name="PieFillingRecipes">
<component name="BlueberryCinnamonFilling">
<!-- These units are built-in, so do not change. -->
<variables name="blueberries" units="gram" />
<variables name="sugar" units="dimensionless" />
<variables name="cornflour" units="gram" />
<!-- These units are defined for use in this, their local scope, below. -->
<variables name="cinnamon" units="smidgen" />
<variables name="water" units="spoonful" />
<math>
...
</math>
</component>
<component name="AppleAndPearFilling">
...
</component>
<!-- Local units definitions for spoonful and smidgen. -->
<units name="spoonful">
<unit units="litre" prefix="milli" multiplier="5" />
</units>
<units name="smidgen">
<unit units="gram" multiplier="20" />
</units>
</model>
This is where the idea of scope becomes important.
As it stands, there is no conflict between the two different definitions of spoonful
and smidgen
, because each of the components refers to its own definition of these units.
The components do not “know” that there is any other definition out there, because they cannot “see” up into the importing model.
Now let’s consider that the cook wants to alter the recipe a little after these two main ingredients have been imported, by adding a spoonful of brandy to some custard. The top-level model becomes:
model: BlueberryPieRecipe
├─ component: BrandyCustard
│ ├─ variable: custard (litre)
│ └─ variable: brandy
│ └─ units: spoonful # These units are not defined in a scope
│ which this component can access:
│ the model is invalid.
├─ component: crust <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
└─ component: filling <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷
╷ ╷
imported components
╵ ╵
# In filling_recipes.cellml: ╵ ╵
model: PieFillingRecipes ╵ ╵
├─ component: BlueberryCinnamonFilling ╶┘ ╵
└─ component: AppleAndPearFilling ╵
╵
# In crust_recipes.cellml: ╵
model: PieCrustRecipes ╵
├─ component: HazelnutLavenderCrust ╴╴╴╴╴╴┘
└─ component: CheeseAndAlmondCrust
See CellML syntax
<!-- Inside the file "how_to_make_blueberry_pie.cellml": -->
<model name="BlueberryPieRecipe">
<import xlink:href="relative/path/to/my/crust_recipes.cellml">
<component name="premade_crust" component_ref="HazelnutLavenderCrust" />
</import>
<import xlink:href="relative/path/to/my/filling_recipe.cellml">
<component name="yummy_filling" component_ref="BlueberryCinnamonFilling" />
</import>
<!-- Defining a new component, brandy custard -->
<component name="BrandyCustard">
<variable name="custard" units="litre" />
<variable name="brandy" units="spoonful" />
...
</component>
</model>
At this stage the model is invalid because the units spoonful
in the top-level model are not defined. Just as the imported models cannot “see” up into the importing model, neither can the importing model “see” down into the imported models beyond those items which it has explicitly imported.
In order to reuse the spoonful
units from either of the imported models, they must be explicitly imported. The top-level model becomes:
model: BlueberryPieRecipe
├─ component: BrandyCustard
│ ├─ variable: custard (litre)
│ └─ variable: brandy
┌╴╴╴╴╴╴╴╴> └─ units: spoonful
╷ ├─ component: crust <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
╷ ├─ component: filling <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷
╷ │ ╷ ╷
└╴╴╴└─ units: spoonful <╴╴╴╴╴╴╴┐ imported components and
╷ the units they need
explicitly imported units ╵ ╵
are available to all components ╵ ╵
╵ ╵ ╵
# In filling_recipes.cellml: ╵ ╵ ╵
model: FillingRecipeCollection ╵ ╵ ╵
├─ units: spoonful ╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵
├─ component: BlueberryCinnamonFilling ╶┘ ╵
└─ component: AppleAndPearFilling ╵
╵
# In crust_recipes.cellml: ╵
model: PieCrustRecipes ╵
├─ component: HazelnutLavenderCrust ╴╴╴╴╴╴┘
└─ component: CheeseAndAlmondCrust
See CellML syntax
<!-- Inside the file "how_to_make_blueberry_pie.cellml": -->
<model name="BlueberryPieRecipe">
<import xlink:href="relative/path/to/my/crust_recipes.cellml">
<component name="premade_crust" component_ref="HazelnutLavenderCrust" />
</import>
<import xlink:href="relative/path/to/my/filling_recipe.cellml">
<component name="yummy_filling" component_ref="BlueberryCinnamonFilling" />
</import>
<!-- Defining a new component, brandy custard -->
<component name="BrandyCustard">
<variable name="custard" units="litre" />
<variable name="brandy" units="spoonful" />
...
</component>
<!-- Explicitly importing the "spoonful" units from the "filling_recipes.cellml" file: -->
<import xlink:href="relative/path/to/my/filling_recipe.cellml">
<!-- The units are also called "spoonful" in this top-level scope. -->
<units name="spoonful" component_ref="spoonful" />
</import>
</model>
At this stage we have three sets of units all named “spoonful”.
Since each is only accessible to its local components there is no conflict of definition or interpretation.
Now that the units required in the new BrandyCustard
component are defined within the same scope, the model becomes valid, and our dessert needs are satisfied once more.
Name
|
Unit reduction tuple
multiplier⋅(base, exponent)
|
|
- |
|
( |
|
- |
|
( |
|
- |
|
( |
|
0.001⋅( |
|
( |
|
( |
|
( |
|
( |
|
( |
|
- |
|
- |
|
0.001⋅( |
|
( |
|
( |
|
- |
|
- |
|
( |
|
( |
|
( |
|
( |
|
- |
|
( |
|
( |
|
( |
|
( |
|
( |
|
( |
|
( |
Interpretation of units
elements¶
The
units
element SHALL be interpreted as the product of itsunit
element children, according to the following rules:The prefix term is a conceptual property of
unit
elements. If theunit
element does not have aprefix
attribute, the prefix term SHALL have value 0. If theprefix
attribute has a value which is an integer string, then the value of the prefix term SHALL be the numerical value of that string. Otherwise, theprefix
attribute MUST have a value taken from the “Name” column of Table 3.2: Prefix values, and the prefix term SHALL have the value taken from the “Value” column of the same row.The exponent term is a conceptual property of
unit
elements. If aunit
element has noexponent
attribute, the exponent term SHALL have value 1.0. Otherwise, the value of theexponent
attribute MUST be a real number string, and the value of the exponent term SHALL be the numerical value of that string.The multiplier term is a conceptual property of
unit
elements. If aunit
element has nomultiplier
attribute, the multiplier term SHALL have value 1.0. Otherwise, the value of themultiplier
attribute MUST be a real number string, and the value of the multiplier term SHALL be the numerical value of that string.The relationship between the product, \(P\), of numerical values given in each and every child
unit
element’sunits
attribute, to a numerical value, \(x\), with units given by the encompassingunits
element, SHALL be\[x[u_x] = {\dfrac {1} {m_1 \dotsm m_n(10^{p_1})^{e_1} \dotsm (10^{p_1})^{e_n}}} { \left[ \dfrac {u_x}{u^{e_1} \dotsm u^{e_n}} \right ] }P \left[ u^{e_1} \dotsm u^{e_n} \right]\]where \(u_x\) denotes the units of the
units
element; \(p_i\), \(e_i\), \(m_i\) and \(u_i\) refer to the prefix, exponent and multiplier terms and units of the \(i^{th}\)unit
child element, respectively. Square brackets encompass the units of numerical values.
See more
Prefixes
The prefix
term is different from the other attributes of a unit
element in that it can accept both a string (the name of the prefix from the Prefix table) or an integer (the base 10 log equivalent to the prefix).
It’s also different because it will become invalid if a non-integer real number is used.
For example, these are equivalent:
<!-- This is valid ... -->
<unit units="myOtherUnits" prefix="3">
<!-- ... is the same as ... -->
<unit units="myOtherUnits" prefix="kilo">
<!-- ... and the same as this. -->
<unit units="myOtherUnits" multiplier="1000.0">
<!-- BUT this is not valid, the prefix MUST be an integer or prefix name only! -->
<unit units="myOtherUnits" prefix="3.">
Note: These examples are only equivalent because the exponent
in each case is 1.
Multipliers and exponents
As you might expect, both the exponent
and multiplier
attributes must be valid real numbers, which could include an integers.
(This is in contrast to the prefix
which must be an integer or a named prefix.)
All three attributes can be combined in different ways to give the same effective outcome.
The examples below all define a units
item equivalent to a 330 mL bottle of beer.
<!-- The prefix can be an integer or a named prefix: -->
<units name="bottle_of_beer">
<unit units="metre" prefix="-2" exponent="3.0" multiplier="330" />
</units>
<units name="bottle_of_beer">
<unit units="metre" prefix="centi" exponent="3.0" multiplier="330" />
</units>
<!-- Note that exponents are added to the combination of prefix and units terms
only, not to the muptiplier:
i.e.: this is (0.33)*((deci)(metre))^3
-->
<units name="bottle_of_beer">
<unit units="metre" prefix="deci" exponent="3.0" multiplier="0.33"/>
</units>
<!-- A missing prefix has no effect: -->
<units name="bottle_of_beer">
<unit units="metre" exponent="3.0" multiplier="3.3e-4"/>
</units>
<!-- Repeated unit items can be included:
- the three centimetres together give 1 mL, and
- the dimensionless multiplier makes them 330 mL.
-->
<units name="bottle_of_beer">
<unit units="metre" prefix="centi"/>
<unit units="metre" prefix="centi"/>
<unit units="metre" prefix="centi"/>
<unit units="dimensionless" multiplier="330.0"/>
</units>
Note: All spellings of built-in units and prefixes must be UK (not US) English, i.e.: metre
(not meter), litre
(not liter), and deca
(not deka).
Combinations
Once you’ve read above how single unit
items can be combined to form a units
item, you’ll also need to define how units
items can be used to form generations of units.
Using the same example of the 330mL beer bottle as before, here are alternative, but equivalent, definitions.
<units name="bottle_of_beer">
<unit units="millilitre" multiplier="330">
</units>
<!-- Of course, we need to define the "millilitre" unit before the above is valid: -->
<units name="millilitre">
<unit units="litre" prefix="milli" /> <!-- Note UK spelling! -->
</units>
<!-- The above is equivalent to: -->
<units name="millilitre">
<unit units="metre" prefix="centi" exponent="3.0" /> <!-- Note UK spelling! -->
</units>
But we can also use child units
in conjunction with exponents
too.
In this situation you’ll need to understand the equation above. Let’s start by defining a centimeter:
<units name="centimeter">
<unit units="metre" multiplier="0.01"/>
</units>
<!-- ... or ... -->
<units name="centimeter">
<unit units="metre" prefix="centi"/>
</units>
<!-- ... or ... -->
<units name="centimeter">
<unit units="metre" prefix="-2"/>
</units>
Now cube it to get the units of millilitres:
<units name="millilitre">
<unit units="centimetre" exponent="3.0"/>
</units>
This is equivalent to creating the units of (10-6)(metre
)3, because the effect of the exponent
is applied to the combination of units
and prefix
, but not to the multiplier
. For example:
<!-- So this ... -->
<units name="millilitre">
<unit units="metre" exponent="3.0" multiplier="1e-6" />
</units>
<!-- ... is equivalent to this: -->
<units name="millilitre">
<units units="metre" exponent="3.0" prefix="-2" />
</units>
It’s good to get your head around the difference between how the multiplier
and prefix
terms work, or your scaling might not be quite what you expect (and your beer disappointing).
For the purposes of this specification, the “irreducible units” of a model SHALL consist of:
The units defined in a model that are not defined in terms of other units (i.e. the set of
units
elements in the CellML model which have nounit
child elements).The built-in irreducible units (those built-in units with “-” in the “Unit reduction tuple” column of Table 3.1: Built-in units) referenced by variables or other units in the model.
See more
The terms “irreducible units” and “unit reduction” really need to be understood together, but before either make sense we need to explain the concept of “base units”. In the physical world there are seven base units defined in the SI (Système International d’Unités) system. These are:
Symbol |
Name |
Base quantity |
s |
second |
time |
m |
metre |
length |
kg |
kilogram |
mass |
A |
ampere |
electric current |
K |
kelvin |
thermodynamic temperature |
mol |
mole |
amount of substance |
cd |
candela |
luminous intensity |
Some of the units listed in the Built-in Units table are these base units, but others are combinations of them included for convenience. Only those rows in the table which have no entries in the “Unit reduction” column are “irreducible” or base units.
In the CellML 2.0 world you are able to also define your own base units.
These are units
items which you create which do not reference any child unit
items (thus rendering them “irreducible”).
For example:
<!-- Define a new base unit called "egg".
It's a base unit because it has no child unit items. -->
<units name="egg">
</units>
<!-- Define other units which use this new base unit. -->
<units name="dozen_eggs">
<unit units="egg" multiplier="12" />
</units>
<!-- Combine the new base unit with existing built-in units: eggs/m^2. -->
<units name="eggs_per_square_metre">
<unit units="egg" />
<unit units="metre" exponent="-2" />
</units>
The terms “irreducible units” and “unit reduction” are used when discussing situations where the units of two variables must be equivalent. It makes no sense to equate a variable with units of seconds to another with units of kilograms, for example. The same is true for more complicated versions of units, as outlined in the next section.
The “unit reduction” is a conceptual property of
units
elements. It consists of a set of tuples where each tuple is composed of a “unit name” and a real-valued “exponent”. The set of tuples SHALL be determined as follows:If the
units
element has nounit
child elements, then the set of tuples SHALL have a single member, which SHALL consist of the name of theunits
element and the exponent 1.0.If the
units
element has one or moreunit
child elements, then the set of tuples SHALL consist of the entire collection of tuples given by allunit
child elements.Tuples for each
unit
child element SHALL be determined as follows:If the units reference of the
unit
child element is to a single unit which is an irreducible unit, then the set of tuples SHALL have a single member, which SHALL consist of the name of the irreducible unit being referenced and the exponent 1.0.
If the units reference of the
unit
child element is to built-in units other than an irreducible unit, then the tuples SHALL be derived directly from Table 3.1: Built-in units. Specifically, the set of tuples SHALL consist of the tuples given in the “Unit reduction tuple” column of the row for which the value in the “Name” column is identical to the name of the units reference.
If the units reference of the
unit
child element is to a unit which is neither built-in, nor an irreducible unit, then the set of tuples SHALL be defined recursively as the set of tuples for theunits
element so referenced.The exponents of each tuple in the set for the current
unit
element, as derived by following rules 3.3.3.2.1, 3.3.3.2.2 or 3.3.3.2.3 above, SHALL be multiplied by the exponent term of the current, referencing,unit
element.
Tuples which have the unit name of “dimensionless” SHALL be removed from the set of tuples. Note that this can result in the set of tuples being empty.
If the set of tuples contains tuples which have the same unit name, then those tuples SHALL be combined into a single tuple with that unit name and an exponent being the sum of those tuples’ exponents. If the resulting tuple’s exponent is zero, then the tuple SHALL be removed from the set of tuples. Note that this can result in the set of tuples being empty.
See more
Unit reduction
As discussed in the previous “See more” block, “irreducible” or “base” units are those fundamental quantities which cannot be expressed in any other way.
This includes user-defined base units too.
The “unit reduction” of any units
item is simply a recipe for how any units item is constructed from these “base unit” ingredients.
For example, the units “metres per second” could be written:
m/s,
m⋅s-1,
product[ (metre)^1 , (second)^-1 ]
, or
product[ power(metre, 1) , power(second, -2) ]
.
This final list of tuples - representing the base unit and its exponent - is referred to as the unit reduction tuples for the units
element.
Some other examples are given below.
Related to 3.3.3.2.1:
<!-- Unit reduction: [ (metre, 1), (second, -1) ] -->
<units name="metres_per_second">
<unit units="metre">
<unit units="second" exponent="-1>
</units>
Related to 3.3.3.2.2: joule
s are equivalent to kg⋅m2⋅s:sup:−2, and the extra “per second” takes the effective exponent for second
to -3.
<!-- Unit reduction: [ (kilogram, 1), (metre, 2), (second, -3) ] -->
<units name="joules_per_second">
<unit units="joule" />
<unit units="second" exponent="-1" />
</units>
Related to 3.3.3.2.3 and 4: The concentration of apples per litre of cider is expressed using the custom base units apple
, the custom derived units bushell_of_apples
and the built-in convenience units of litre
, the last being equivalent to 0.001m3.
Note that:
scaling does not affect the unit reduction tuples,
the custom derived units
bushell_of_apples
do not appear because it can be further reduced toapple
, andthe final exponent of the
metre
base unit comes from applying 3.3.3.2.4 and multiplying the exponent of the litre reduction tuple (metre, 3) with the exponent given in thecider_concentration
tuple (litre, -1) to give a (metre, -3) in the final unit reduction tuple set.
<!-- Unit reduction: [ (apple, 1), (metre, -3) ] -->
<units name="apple" />
<units name="bushell_of_apples">
<unit units="apple" multiplier="1000" />
</units>
<units name="cider_concentration">
<unit units="bushell_of_apples" multiplier="0.5" />
<unit units="litre" exponent="-1" />
</units>
Dimensionless base units
You may have noticed in the Built-in Units that there is an entry labelled dimensionless
.
This is provided for convenience, and doesn’t take part in determining the unit reduction for any units
items.
Together with the next point, this means that the all unit reduction tuples represent the minimum possible description of a units
item.
For example, this units
item has the unit reduction of (metre, 1)
:
<!-- The "dimensionless" base units do not appear in the unit reduction. -->
<units name="metres_by_dimensionless">
<unit units="metre">
<unit units="dimensionless" exponent="3">
</units>
Combining unit reductions
As outlined above, the built-in base units dimensionless
do not contribute to the unit reduction tuple set.
This holds for built-in units which are effectively dimensionless (like radian
and steradian
) but also for situations in which base units’ exponents could be simplified or cancelled.
For example, all of the units
items below have identical unit reduction tuples of (metre, 1), (second, -1)
:
<units name="metres_per_second">
<unit units="metre">
<unit units="second" exponent="-1">
</units>
Here the metre
exponents of 3 and -4 reduce to 1:
<units name="metres_per_second_too">
<unit units="metre" exponent="4">
<unit units="second" exponent="-1">
<unit units="metre" exponent="-3">
</units>
Here the steradian
inclusion has no effect on the final unit reduction as its own units cancel out:
<units name="metres_per_second_too">
<unit units="metre" exponent="1">
<unit units="second" exponent="-1">
<unit units="steradian" exponent="-3">
</units>
Finally a complicated one with the same outcome.
Note that even though there are some irreducible units used, they end up with an exponent of 0 in the tuple, and are therefore removed from the final unit reduction.
Note that a volt
V is equivalent to m2·kg·s-3·A-1.
<units name="orange" />
<units name="cubed_oranges">
<unit units="orange" exponent="3" />
</units>
<units name="mega_amps_per_gram">
<unit units="ampere" prefix="mega" exponent="1" />
<unit units="gram" exponent="-1" />
</units>
<units name="acceleration_units">
<unit units="metre" prefix="milli" />
<unit units="second" exponent="-2" />
</units>
<!-- Finally, combining these gives a units item with the same reduction as above -->
<units name="believe_it_or_not">
<unit units="orange" exponent="-3" />
<unit units="cubed_oranges" prefix="mega" />
<unit units="volt" prefix="zepto" />
<unit units="acceleration_units" exponent="-1" />
<unit units="mega_amps_per_gram" multiplier="3.14159" />
</units>
Name |
Value |
|
24 |
|
21 |
|
18 |
|
15 |
|
12 |
|
9 |
|
6 |
|
3 |
|
2 |
|
1 |
|
−1 |
|
−2 |
|
−3 |
|
−6 |
|
−9 |
|
−12 |
|
−15 |
|
−18 |
|
−21 |
|
−24 |
Component references¶
A “component reference” is an attribute value that specifies a CellML component.
A component reference SHALL be a CellML identifier.
The component identified by a component reference SHALL be determined as follows:
If the component reference is identical to the value of the
name
attribute of acomponent
element in the same infoset, then it SHALL refer to the component specified by that element.If the component reference is identical to the value of the
name
attribute of animport component
element in the same infoset, then it SHALL refer to a component from the infoset defined by theimport component
element (see 3.1 Interpretation of import elements). The component specified SHALL then be determined by treating the value of thecomponent_ref
attribute on theimport component
element as a component reference within the imported infoset. If necessary, this rule SHALL be applied recursively.
If no component can be identified using the rules above, the attribute value SHALL NOT be a valid component reference.
See more
Understanding component references
As with references to units and variables, the term “component reference” refers to places where you need to refer to a component using its name.
This is done through the component_ref
attribute found in import component
and encapsulation
elements, as well as the component_1
and component_2
attributes of connection
elements.
The complicated part occurs during imports, and involves understanding the scope of a component’s reference. This is really just the appropriate name by which to call it depending on who is doing the calling.
Consider the following example.
Here, two families live next door to one another, and within each family use the terms “husband” and “wife” to refer to their own component members.
In the local “LeadbetterFamilyModel” and “GoodFamilyModel” model
contexts, “husband” and “wife” are the name
attributes of the local components
.
In the wider neighbourhood, however, each person must be referred to by their real-world name: “BarbaraGood”, “TomGood”, “JerryLeadbetter”, and “MargotLeadbetter”.
In the “SurbitonNeighbourhood” model
context, the real-world names of “BarbaraGood” etc. are treated as name
attributes of local component
elements (even though they’re imported), but now the “husband” and “wife” terms are component_ref
elements, as they are not the context providing the name.
model: SurbitonNeighbourhood
├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴┐ ╷
├─ component: MargotLeadbetter <╴╴╷ ╷ ╷
└─ component: JerryLeadbetter <╴┐ ╷ ╷ ╷
╷ ╷ ╷ ╷
imported components
╵ ╵ ╵ ╵
# In LeadbetterFamily.cellml: ╵ ╵ ╵ ╵
model: LeadbetterFamilyModel ╵ ╵ ╵ ╵
├─ component: husband ╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵ ╵
└─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵
╵ ╵
# In GoodFamily.cellml: ╵ ╵
model: GoodFamilyModel ╵ ╵
├─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵
└─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
See CellML syntax
<model name="SurbitonNeighbourhood">
<!-- Importing two families into the neighbourhood. -->
<import xlink:href="GoodFamily.cellml">
<!-- Within the family, the members are called "wife" and "husband", but after
importing into the neighbourhood, these same components are now referred
to by the names "BarbaraGood" and "TomGood". -->
<component name="BarbaraGood" component_ref="wife" />
<component name="TomGood" component_ref="husband" />
</import>
<import xlink:href="LeadbetterFamily.cellml">
<!-- Even though the component_ref attributes here are the same as above
(i.e.: "wife" and "husband") they are interpreted within the context
of the imported model (i.e.: the "TheLeadbetterFamilyUnit" model imported
from the "LeadbetterFamily.cellml" file), and so refer to separate things.
-->
<component name="MargotLeadbetter" component_ref="wife" />
<component name="JerryLeadbetter" component_ref="husband" />
</import>
</model>
<!-- Inside the GoodFamily.cellml file: -->
<model name="TheGoodFamilyUnit">
<component name="husband" />
<component name="wife" />
</model>
<!-- Inside the LeadbetterFamily.cellml file: -->
<model name="TheLeadbetterFamilyUnit">
<component name="husband" />
<component name="wife" />
</model>
Now let’s make things more interesting by adding an encapsulation hierarchy:
model: SurbitonNeighbourhood
├─ component: WomenInTheNeighbourhood
│ ├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴╴╴┐
│ └─ component: MargotLeadbetter <╴╴╴╴┐ ╷
└─ component: MenInTheNeighbourhood ╷ ╷
├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴┐ ╷ ╷
└─ component: JerryLeadbetter <╴┐ ╷ ╷ ╷
╷ ╷ ╷ ╷
imported components
╵ ╵ ╵ ╵
# In LeadbetterFamily.cellml: ╵ ╵ ╵ ╵
model: LeadbetterFamilyModel ╵ ╵ ╵ ╵
├─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵ ╵
└─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴┘ ╵
╵ ╵
# In GoodFamily.cellml: ╵ ╵
model: GoodFamilyModel ╵ ╵
├─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵
└─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
See CellML syntax
<model name="SurbitonNeighbourhood">
...
<component name="WomenInTheNeighbourhood" />
<component name="MenInTheNeighbourhood" />
<!-- Throughout the importing model (i.e.: this model), the imported
items are referred to by their local name attribute ("BarbaraGood" etc),
not the name they are called within their imported family units ("wife"). -->
<encapsulation>
<component_ref component="WomenInTheNeighbourhood">
<component_ref component="BarbaraGood" />
<component_ref component="MargotLeadbetter" />
</component_ref>
<component_ref component="MenInTheNeighbourhood">
<component_ref component="TomGood" />
<component_ref component="JerryLeadbetter" />
</component_ref>
</encapsulation>
</model>
This particular encapsulation structure means that the women (Barbara and Margot) are essentially unable to have any contact with the men (Tom and Jerry) even though their original components in the models from which they were imported were able to access one another.
Note also that these locality-based naming-calling rules will be applied through multiple generations of importing. Since The Good Life is a TV show, there are actors who play the roles of each of the characters. This could be reflected by using another generation of imports within the two family files like this:
model: SurbitonNeighbourhood
├─ component: WomenInTheNeighbourhood
│ ├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴╴╴╴╴┐
│ └─ component: MargotLeadbetter <╴╴╴╴╴╴┐ ╷
└─ component: MenInTheNeighbourhood ╷ ╷
├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷ ╷
└─ component: JerryLeadbetter <╴╴╴┐ ╷ ╷ ╷
╷ ╷ ╷ ╷
imported components
╵ ╵ ╵ ╵
# In LeadbetterFamily.cellml: ╵ ╵ ╵ ╵
model: TheLeadbetterFamilyUnit ╵ ╵ ╵ ╵
┌╴╴╴╴╴╴╴╴> ├─ component: husband ╴╴╴╴╴╴╴┘ ╵ ╵ ╵
╷ ┌ ╴╴╴╴╴> └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴┼╴┘ ╵
╷ ╷ ╵ ╵
╷ ╷ # In GoodFamily.cellml: ╵ ╵
╷ ╷ model: TheGoodFamilyUnit ╵ ╵
╷ ╷ ┌╴╴╴> ├─ component: husband ╴╴╴╴╴╴╴╴╴╴┘ ╵
╷ ╷ ╷ ┌╴> └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
╷ ╷ ╷ ╷
imported components
╵ ╵ ╵ ╵
╵ ╵ ╵ ╵ # In CastOfCharacters.cellml:
╵ ╵ ╵ ╵ model:
╵ ╵ ╵ └╴╴╴├─ component: FelicityKendal
╵ ╵ └╴╴╴╴╴├─ component: RichardBriers
╵ └╴╴╴╴╴╴╴├─ component: PenelopeKeith
└╴╴╴╴╴╴╴╴╴└─ component: PaulEddington
See CellML syntax
<!-- Inside the GoodFamily.cellml file: -->
<model name="TheGoodFamilyUnit">
<import xlink:href="CastOfCharacters.cellml">
<component name="husband" component_ref="RichardBriers" />
<component name="wife" component_ref="FelicityKendal" />
</import>
</model>
<!-- Inside the LeadbetterFamily.cellml file: -->
<model name="TheLeadbetterFamilyUnit">
<import xlink:href="CastOfCharacters.cellml">
<component name="husband" component_ref="PaulEddington" />
<component name="wife" component_ref="PenelopeKeith" />
</import>
</model>
Note that in this situation, the original SurbitonNeighbourhood
model does not need to change at all.
Each of the component references remains correct, as each is isolated in its own scope.
Variable references¶
A “variable reference” is an attribute value that specifies a CellML variable.
A variable reference SHALL be a CellML identifier.
The variable identified by a variable reference SHALL be determined as follows:
When present in a descendant of a
component
element, it SHALL refer to the variable of the same name within that component.When present in the
variable_1
attribute of amap_variables
element, it SHALL refer to the variable of the same name in the component identified by thecomponent_1
attribute in the samemap_variables
element.When present in the
variable_2
attribute of amap_variables
element, it SHALL refer to the variable of the same name in the component identified by thecomponent_2
attribute in the samemap_variables
element.
If no variable can be identified using the rules above, the attribute value SHALL NOT be a valid variable reference.
See more
Understanding variable references
A variable
item only exists within its parent component
item, but can be connected to others via the map_variables
functionality.
There are two different ways that any variable
could be referenced.
The first and simplest is within its own local scope, the parent component
.
In that situation, the variable
element’s name
attribute is enough to uniquely locate it.
The second situation is when a variable
is referred to from a component
other than its parent, so a reference to the parent component
as well as the variable
’s name
is required.
This is found when creating connection
items using map_variables
.
The example below shows how the pairing of components and variables are required to form a valid connection.
<model name="FamousFreds">
<component name="Flintstone">
<variable name="Fred" units="dimensionless" />
<variable name="Wilma" units="dimensionless" />
</component>
<component name="Astair">
<variable name="Fred" units="dimensionless" />
</component>
<component name="CartoonCharacters">
<variable name="FredFlintstone" units="dimensionless" />
<variable name="DaffyDuck" units="dimensionless" />
</component>
<component name="Dancers">
<variable name="FredAstaire" units="dimensionless" />
<variable name="GingerRogers" units="dimensionless" />
</component>
<!-- Correct: connecting the variable "Fred" in component "Flintstone" into the
variable "FredFlintsone" in the "CartoonCharacters" component. -->
<connection component_1="Flintstone" component_2="CartoonCharacters" >
<map_variables variable_1="Fred" variable_2="FredFlintstone" />
</connection>
<!-- Incorrect: trying to connect variable "Fred" from component "Dancers" into the
variable "FredAstaire" from component "Astair": variable_1 must exist within
component_1, and variable_2 must exist within component_2. -->
<connection component_1="Dancers" component_2="Astaire">
<map_variables variable_1="Fred" variable_2="FredAstaire" />
</connection>
</model>
Interpretation of initial_value
attributes¶
The
initial_value
attribute of avariable
element MUST either be a real number string, or a variable reference.The conditions under which initial values hold are (by design) not defined in a CellML model.
Where the
initial_value
attribute is a real number string, it SHALL be interpreted as a statement that the variable on which the attribute appears is equal to that real number value when the initial values hold.Where the
initial_value
attribute is a variable reference, it SHALL be interpreted as a statement that the variable on which the attribute appears is equal to the referenced variable when the initial values hold.
See more
Cycles within initial values
As with other places, it’s possible to set initial conditions which are valid in syntax but lacking in sense. The examples below are technically valid CellML, but they will not lead to meaningful models.
<component name="cyclical_initialisation" >
<variable name="A" initial_value="B" units="dimensionless"/>
<variable name="B" initial_value="A" units="dimensionless"/>
</component>
<component name="self_initialisation" >
<variable name="C" initial_value="C" units="dimensionless"/>
</component>
Best practice for constants, variables, and initial conditions
A
variable
whose value needs to be set for only the beginning of a simulation is initialised using theinitial_value
attribute.This is most frequently used for state variables (those whose value is found by solving a differential equation).
It’s possible - but not recommended - to use a variable reference with the
initial_value
attribute. This option remains in CellML 2.0 only to provide ease of migration from CellML 1.1 models, and may be discontinued in future versions.
A
variable
whose value is constant throughout the simulation is best set within themath
block, rather than via theinitial_value
attribute. This is so that its value will be held to be true throughout the simulation, rather than only the beginning.A
variable
which is not a state variable, and whose value changes during the simulation does not require initialisation; simply include it in amath
block so it can be evaluated.
The following example shows a model for counting games like hide and seek, where the first section shows an older format and the second section shows a better practice for CellML 2.0 models.
<!-- Childhood games involving counting down. -->
<model name="games">
<component name="hide_and_seek">
<variable name="countdown_start" units="second" initial_value="100"/>
<variable name="counter" units="second" initial_value="countdown_start" />
<variable name="time" units="second" />
<math>
<apply><eq/>
<ci>counter</ci>
<apply><minus/>
<ci>countdown_start</ci>
<ci>time</ci>
</apply>
</apply>
</math>
</component>
<component name="hiding_games">
<variable name="time" units="second" />
</component>
<component name="sardines" />
<!-- Creating a generic component to hold global variables like time. -->
<component name="parameters">
<variable name="time" units="second" initial_value="0" />
</component>
<!-- Encapsulating the games into the hiding_games component. -->
<encapsulation>
<component_ref component="hiding_games">
<component_ref component="hide_and_seek"/>
<component_ref component="sardines"/>
</component_ref>
</encapsulation>
<!-- Connect the time variable into the other components. -->
<connection component_1="parameters" component_2="hiding_games">
<map_variables variable_1="time" variable_2="time" />
</connection>
<connection component_1="hiding_games" component_2="hide_and_seek">
<map_variables variable_1="time" variable_2="time" />
</connection>
</model>
This is valid CellML and will work as expected, but it uses a constant (the initial_value
on the countdown_start
variable) embedded within the deepest level of the encapsulation, which makes it more difficult to restart the game from different countdown points.
A better way to organise the model is shown below, annotated with the differences as appropriate.
<model name="games">
<component name="hide_and_seek">
<!-- Remove the initial_values from encapsulated component, move to the "parameters" component. -->
<variable name="countdown_start" units="second" />
<variable name="counter" units="second" />
<variable name="time" units="second">
<math>
<apply><eq/>
<ci>counter</ci>
<apply><minus/>
<ci>countdown_start</ci>
<ci>time</ci>
</apply>
</apply>
</math>
</component>
<component name="sardines"/>
<!-- Define (or import) a top-level component used for setting all parameters, constants, and initial values. -->
<component name="parameters">
<variable name="time" units="second" />
<!-- Move the initialisation of the countdown initial value into this top-level component. -->
<variable name="hide_and_seek_start" initial_value="100" />
</component>
<!-- Add a new transfer variable throughout the encapsulation hierarchy. -->
<component name="hiding_games">
<variable name="time" units="second" />
<variable name="hide_and_seek_start" units="second" />
</component>
<encapsulation>
<component_ref component="hiding_games">
<component_ref component="hide_and_seek"/>
<component_ref component="sardines"/>
</component_ref>
</encapsulation>
<!-- Connect the initialisation variable thoughout the encapsulation hierarchy. -->
<connection component_1="parameters" component_2="hiding_games">
<map_variables variable_1="time" variable_2="time" />
<map_variables variable_1="hide_and_seek_start" variable_2="hide_and_seek_start">
</connection>
<connection component_1="hiding_games" component_2="hide_and_seek">
<map_variables variable_1="time" variable_2="time" />
<map_variables variable_1="hide_and_seek_start" variable_2="countdown_start" />
</connection>
</model>
Moving the initialisation out of the encapsulation hierarchy and into a top-level component allows us to more easily adjust the parameters of the game, as well as making its use more modular so that it can be shared with others.
Effect of units
on a variable
¶
The target of the
units
attribute on a variable is referred to as the “variable units”, and the corresponding unit reduction (see 3.3 Interpretation of units elements) is referred to as the “variable unit reduction”.
Interpretation of math
elements¶
The following
component
elements SHALL, for the purposes of this specification, be “pertinent component elements”:All
component
elements in the top-level CellML infoset for the CellML model;All
component
elements referenced byimport component
elements (see 3.1 Interpretation of import elements) in the top-level CellML infoset; andAll
component
elements which are descendants in the encapsulation digraph (see 3.9 Interpretation of encapsulation elements) of a pertinentcomponent
element.
Every MathML element in the CellML model which appears as a direct child of a MathML
math
element, which in turn appears as a child of a pertinentcomponent
element, SHALL be treated, in terms of the semantics of the mathematical model, as a statement which holds true unconditionally.Units referenced by a
units
attribute SHALL NOT affect the mathematical interpretation of the CellML model.
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.
Where a
component_ref
element appears as a child of anothercomponent_ref
element, 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 on the interpretation of map_variables section.
Interpretation of map_variables
elements¶
For the purposes of this specification, the conceptual “variable equivalence network” SHALL be an undirected graph with one node for every
variable
element in the CellML model. The arcs of this graph SHALL be equivalences defined in the CellML model.
See more
Understanding the terminology
The idea of component modularity and separateness is helpful in organising models and reusing parts of them, but only if it’s also possible to share information between the distinct components.
This is the goal of “variable equivalence”, and requires the combined mechanisms of connection
elements (to connect components) and map_variables
elements (to connect their variables).
Several different words have been used to describe what is essentially this one process: equivalent variables, the connected variable set, mapped variables, etc.
All of these mean the same thing: that the variables in the set act as a single agent throughout the model.
They may have different local names within a component, but they will have the same value everywhere they exist.
Thus there are two ways in which variables are related to one another.
The first is through the mathematical equations as specified in intra-component math
elements; the second is through variable equivalences as specified in inter-component connection
and map_variables
elements.
Both the connection
and map_variables
elements are undirected.
There is no update direction or hierarchy; they all represent, instantaneously, the same thing.
For each
map_variables
element present in the CellML model, we define variables A and B for use in the rules in this section as follows:Variable A SHALL be the variable referenced by the encompassing
connection
element’scomponent_1
and thismap_variables
element’svariable_1
attribute; andVariable B SHALL be the variable referenced by the encompassing
connection
element’scomponent_2
and thismap_variables
element’svariable_2
attribute.
For every
map_variables
element present in the CellML model, there SHALL be an arc in the variable equivalence network.One endpoint of the arc in the variable equivalence network SHALL be the node corresponding to variable A; and
One endpoint of the arc in the variable equivalence network SHALL be the node corresponding to variable B.
See more
Understanding the players
You can think of the previous two points as defining an address using a street name and number.
Since streets (components) have lots of houses (variables) they all need different numbers (variable names) in that street.
And since lots of streets (components) have houses (variables) with the same number (name), we need both the street name and the house number in order to locate a house properly.
This is the purpose of the component_1
and component_2
attributes of connection
elements (to define the respective street (component) names), and the variable_1
and variable_2
attributes of each connection
element’s map_variables
element (to define the respective house number (variable name)).
Thus the “equivalent variable network” is a collection of unique variables (each specified a component and a variable name), which will be treated as the same variable throughout the model.
Note that we use the term “network” here as it best describes the process by which variable equivalence is constructed, even if its final interpretation is not a network, but rather a set.
CellML models MUST NOT contain any pair of
map_variables
elements which duplicates an existing arc in the variable equivalence network.The variable equivalence network MUST NOT contain any cycles.
See more
Understanding the rules
As well as the syntax definitions above, there are rules regarding which variables are able to be connected to one another too.
Both points 3.10.4 and 3.10.5 address a similar issue: that the “network” of variable equivalence must not contain any cycles (a connection such that A-B-A is just a mini cycle after all).
In the model below there are three sets of variables which have equivalent values, and it is the modeller’s desire that they be able to use them interchangably in each language whilst maintaining their value throughout. There are two situations which would render the model invalid if these variables were mapped incorrectly, as shown below.
model: LearningToCount
├─ component: Dutch
│ ├─ variable: een
│ ├─ variable: twee
│ ├─ variable: drie
│ └─ variable: vier
├─ component: Maori
│ ├─ variable: tahi
│ ├─ variable: rua
│ ├─ variable: toru
│ └─ variable: wha
└─ component: French
├─ variable: un
├─ variable: deux
├─ variable: trois
└─ variable: quatre
See CellML syntax
<model name="LearningToCount">
<component name="Dutch">
<variable name="een" />
<variable name="twee" />
<variable name="drie" />
<variable name="vier" />
</component>
<component name="Maori">
<variable name="tahi" />
<variable name="rua" />
<variable name="toru" />
<variable name="wha" />
</component>
<component name="French">
<variable name="un" />
<variable name="deux" />
<variable name="trois" />
<variable name="quatre" />
</component>
</model>
Firstly, duplicated connections are not permitted because they create a mini-cycle of two variables. If an Anglophone is given a definition of een to mean tahi, and tahi to mean een, they are none the wiser.
model: LearningToCount
├─ component: Dutch
│ ├─ variable: een <╴╴╴┬╴╴╴┐
│ ├─ variable: twee ╷ ╷
│ ├─ variable: drie duplicate mapping
│ └─ variable: vier causes a mini-cycle
├─ component: Maori ╵ ╵
│ ├─ variable: tahi <╴╴┴╴╴╴┘
│ ├─ variable: rua
│ ├─ variable: toru
│ └─ variable: wha
└─ component: French
├─ variable: un
├─ variable: deux
├─ variable: trois
└─ variable: quatre
See CellML syntax
<!-- Valid: First define the two components using a connection ... -->
<connection component_1="Dutch" component_2="Maori">
<!-- ... and then define the mapping between two variables within
those two components. -->
<map_variables variable_1="een" variable_2="tahi" />
...
</connection>
<!-- Invalid: Duplicated mappings are not allowed. -->
<connection component_1="Dutch" component_2="Maori">
<map_variables variable_1="een" variable_2="tahi" />
<map_variables variable_1="een" variable_2="tahi" />
...
</connection>
<!-- Invalid: Duplicated connections are not allowed. -->
<connection component_1="Dutch" component_2="Maori">
<map_variables variable_1="een" variable_2="tahi" />
...
</connection>
<connection component_1="Maori" component_2="Dutch">
<map_variables variable_1="tahi" variable_2="een" />
...
</connection>
Secondly, any form of cyclical definition is invalid, as it leaves the mathematical model underdefined. So our Anglophone could be also told that drie means tois, tois means toru, and toru means drie, but unless one of them is nailed down to an actual value somewhere, the model remains under-defined.
model: LearningToCount
├─ component: Dutch
│ ├─ variable: een <╴╴╴╴┐<╴╴╴╴╴╴╴╴┐
│ ├─ variable: twee ╷ ╷
│ ├─ variable: drie cycle created
│ └─ variable: vier ╷ ╷
├─ component: Maori ╷ ╷
│ ├─ variable: tahi <╴╴╴┘<╴╴╴┐ ╷
│ ├─ variable: rua ╷ ╷
│ ├─ variable: toru ╷ ╷
│ └─ variable: wha ╷ ╷
└─ component: French ╷ ╷
├─ variable: un <╴╴╴╴╴╴╴╴╴╴┘<╴╴╴┘
├─ variable: deux
├─ variable: trois
└─ variable: quatre
See CellML syntax
<!-- Invalid: a cycle is created. -->
<connection component_1="Dutch" component_2="Maori">
<map_variables variable_1="een" variable_2="tahi" />
...
</connection>
<connection component_1="Maori" component_2="French">
<map_variables variable_1="tahi" variable_2="un" />
...
</connection>
<connection component_1="French" component_2="Dutch">
<map_variables variable_1="un" variable_2="een" />
...
</connection>
For a given variable, the “available interfaces” SHALL be determined by the value of the
interface
attribute on the correspondingvariable
element as follows:A value of
public
specifies that the variable has a public interface;A value of
private
specifies that the variable has a private interface;A value of
public_and_private
specifies that the variable has both a public and a private interface;A value of
none
specifies that the variable has no interface; orIf the
interface
attribute is absent, then the variable has no interface.
The “applicable interfaces” for variables A and B in components AA and BB respectively SHALL be defined as follows:
When component AA is in the sibling set of component BB (and vice versa), the applicable interface for both variables A and B SHALL be the public interface.
When component AA is in the encapsulated set of component BB, the applicable interface for variable A SHALL be the public interface, and the applicable interface for variable B SHALL be the private interface.
When component BB is in the encapsulated set of component AA, the applicable interface for variable B SHALL be the public interface, and the applicable interface for variable A SHALL be the private interface.
It is noted, for the avoidance of doubt, that if components AA and BB are in each other’s hidden set, there are no applicable interfaces for the variables A and B.
CellML models MUST only contain
map_variables
elements where the applicable interfaces for both variables are available.
See more
Understanding mappings and units
The only place in which valid units
items can cause a model to be invalid is between mapped variables.
Point 3.10.6 means that each variable within a map_variables
element must have an equivalent unit reduction.
Please see that section for more details.
For each
map_variables
element present in the CellML model, the variable unit reduction (see 3.7 Effect of units on a variable) of variable A MUST have an identical set of tuples to the variable unit reduction of variable B. Two sets of tuples SHALL be considered identical if all of the tuples from each set are present in the other, or if both sets are empty. Two tuples are considered identical if and only if both the unit name and exponent of each tuple are identical.Tuples differing by a multiplying factor in their unit reduction MUST be taken into account when interpreting the numerical values of the variables (see 3.3 Interpretation of units elements).
See more
Understanding interfaces
There are two hurdles to get past before variables can be mapped to one another.
The first is the relative position within the encapsulation hierarchy of the variable
elements’ parent component
elements (as discussed in Interpretation of encapsulation, and the second is the value of the interface_type
attribute given to each variable
itself.
This means that even if two components are sufficiently close relatives that they can be connected, the modeller still has control at the individual variable level as to which of those relatives can have access.
The interface_type
attribute value choices are:
- public
(used by child components to reference their parent, or between siblings),
- private
(used by parent components to reference their children),
- public_and_private
(used when both the public
and private
interfaces are required), or
- none
, which is the default.
Which one(s) of these are deemed applicable for any variable
mapping is determined by the relationship between the their parent component
elements.
In the example below, Christopher Robin must assemble an average score of the mood of all of his friends in the Hundred Acre Wood.
He does not have access to all of their mood
scores directly, so must use mapped variables in order to create the average.
model: TheHouseAtPoohCorner
├─ component: ChristopherRobin
│ ├─ variable: my_mood
│ ├─ variable: average_mood_of_everyone
│ ├─ variable: roos_mood
│ ├─ variable: kangas_mood <╴╴╴╴╴┐
│ ├─ variable: eeyores_mood <╴╴╴┐╷
│ └─ variable: poohs_mood <╴╴╴╴┐╷╷
│ ╷╷╷
│ connections between these
│ components are possible, depending
│ on the variables' interfaces
│ ╵╵╵
├─ component: WinnieThePooh ╵╵╵
│ └─ variable: mood ╴╴╴╴╴╴╴╴╴╴╴┘╵╵
├─ component: Eeyore ╵╵
│ └─ variable: mood ╴╴╴╴╴╴╴╴╴╴╴╴┘╵
└─ component: Kanga ╵
│ ├─ variable: mood ╴╴╴╴╴╴╴╴╴╴┘
└─ component: Roo
└─ variable: mood ╴╴╴╴╴╴╴╴╴╴> This variable cannot be connected to
anything within the ChristopherRobin
component as its component is too distant.
At present, the connections above in dashed lines are possible, as long as the variables have interface types which support them.
One connection is not possible (yet): Christopher Robin doesn’t know Roo’s mood, because their components are too distant (grandparent/grandchild) to be directly connected.
We can add a utility variable roos_mood
to the Kanga
component in order to pass along its value to the ChristopherRobin
component.
We’ll also add interface types to the variables, and discuss their effects below.
model: TheHouseAtPoohCorner
├─ component: ChristopherRobin
│ ├─ variable: my_mood
│ ├─ variable: average_mood_of_everyone
│ ├─ variable: roos_mood (interface: public) <╴╴╴╴╴ D ╴╴╴╴╴╴╴╴╴╴╴╴┐
│ ├─ variable: kangas_mood (interface: none) <╴╴╴╴╴ C ╴╴╴╴┐ ╷
│ ├─ variable: eeyores_mood (interface: public) <╴╴ B ╴╴╴┐╷ ╷
│ └─ variable: poohs_mood (interface: public) <╴╴╴╴ A ╴╴┐╷╷ ╷
│ ╷╷╷ utility variable added so
├─ component: WinnieThePooh ╷╷╷ that Roo's mood can be passed
│ └─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╷╷ down to Christopher Robin
├─ component: Eeyore ╷╷ ╵
│ └─ variable: mood ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╷ ╵
└─ component: Kanga ╷ ╵
│ ├─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵
│ └─ variable: roos_mood (interface: private) <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┤
└─ component: Roo ╷
└─ variable: mood (interface: public) ╴╴╴╴╴╴ E ╴╴╴╴╴╴╴╴╴╴╴╴╴┘
See CellML syntax
<model name="TheHouseAtPoohCorner">
<!-- Defining the components and local variables. -->
<component name="ChristopherRobin">
<variable name="my_mood" interface_type="none" units="mood_score" />
<variable name="average_mood_of_everyone" interface_type="none" units="mood_score" />
<variable name="roos_mood" interface_type="public" units="mood_score" />
<variable name="kangas_mood" interface_type="none" units="mood_score" />
<variable name="eeyores_mood" interface_type="public" units="mood_score" />
<variable name="poohs_mood" interface_type="public" units="mood_score" />
</component>
<component name="WinnieThePooh">
<variable name="mood" interface_type="public" units="mood_score" />
</component>
<component name="Eeyore">
<variable name="mood" units="mood_score" />
</component>
<component name="Kanga">
<variable name="mood" interface_type="public" units="mood_score" />
<!-- The utility variable roos_mood is included here so that it can pass
the value of mood in component Roo to roos_mood in component ChristopherRobin. -->
<variable name="roos_mood" interface_type="private" units="mood_score" />
</component>
<component name="Roo">
<variable name="mood" interface_type="public" units="mood_score" />
</component>
<!-- Defining connections and mapped variables. -->
<connection component_1="ChristopherRobin" component_2="WinnieThePooh">
<!-- Mapping A -->
<map_variables variable_1="poohs_mood" variable_2="mood" />
</connection>
<connection component_1="ChristopherRobin" component_2="Eeyore">
<!-- Mapping B -->
<map_variables variable_1="eeyores_mood" variable_2="mood" />
</connection>
<connection component_1="ChristopherRobin" component_2="Kanga">
<!-- Mapping C -->
<map_variables variable_1="kangas_mood" variable_2="mood" />
<!-- Mapping D -->
<map_variables variable_1="roos_mood" variable_2="roos_mood" />
</connection>
<connection component_1="Kanga" component_2="Roo">
<!-- Mapping E -->
<map_variables variable_1="roos_mood" variable_2="mood" />
</connection>
</model>
Mapping A is valid. The sibling components
WinnieThePooh
andChristopherRobin
havepublic
interfaces between theirmood
andpoohs_mood
variables respectively. This follows point 3.10.9.1 and is valid.Mapping B is not valid. By default an interface type is
none
, and since themood
variable in componentEeyore
does not specify one, no mappings are permitted. For that connection to exist, themood
variable must have an interface typepublic
.Mapping C is not valid. The variable
kangas_mood
has explicitly specified that no mappings are possible by using thenone
interface type. For this mapping to be valid, the type needs to bepublic
.Mapping D is not valid. Because they are sibling components, the variables in
ChristopherRobin
andKanga
must both have the interface type ofpublic
in order to be valid … but there’s a twist.Mapping E is currently valid, because variables in component
Kanga
can only access variables in its child componentRoo
with aprivate
interface. But if Mapping D is to be made valid, that same variable must maintain apublic
interface in order to access variables in its sibling componentChristopherRobin
. It is for this reason that thepublic_and_private
interface type exists. For Mappings D and E to be valid, the variableroos_mood
in componentKanga
must have an interface type ofpublic_and_private
.
The corrected model is shown below.
model: TheHouseAtPoohCorner
├─ component: ChristopherRobin
│ ├─ variable: my_mood (interface: none)
│ ├─ variable: average_mood_of_everyone (interface: none)
│ ├─ variable: roos_mood (interface: public) <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
│ ├─ variable: kangas_mood (interface: public) <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐╷
│ ├─ variable: eeyores_mood (interface: public) <╴╴╴╴╴╴╴╴╴╴╴╴╴┐╷╷
│ └─ variable: poohs_mood (interface: public) <╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐╷╷╷
│ ╷╷╷╷
├─ component: WinnieThePooh ╷╷╷╷
│ └─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╷╷╷
├─ component: Eeyore ╷╷╷
│ └─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘╷╷
└─ component: Kanga ╷╷
│ ├─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴ ╴╴╴╴┘╷
│ └─ variable: roos_mood (interface: public_and_private) <╴╴╴┤
└─ component: Roo ╷
└─ variable: mood (interface: public) ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
See CellML syntax
<model name="TheHouseAtPoohCorner">
<!-- Defining the components and local variables. -->
<component name="ChristopherRobin">
<variable name="my_mood" interface_type="none" units="mood_score" />
<variable name="average_mood_of_everyone" interface_type="none" units="mood_score" />
<variable name="roos_mood" interface_type="public" units="mood_score" />
<variable name="kangas_mood" interface_type="public" units="mood_score" />
<variable name="eeyores_mood" interface_type="public" units="mood_score" />
<variable name="poohs_mood" interface_type="public" units="mood_score" />
</component>
<component name="WinnieThePooh">
<variable name="mood" interface_type="public" units="mood_score" />
</component>
<component name="Eeyore">
<variable name="mood" interface_type="public" units="mood_score" />
</component>
<component name="Kanga">
<variable name="mood" interface_type="public" units="mood_score" />
<!-- The utility variable roos_mood is included here so that it can pass
the value of mood in component Roo to roos_mood in component ChristopherRobin. -->
<variable name="roos_mood" interface_type="public_and_private" units="mood_score" />
</component>
<component name="Roo">
<variable name="mood" interface_type="public" units="mood_score" />
</component>
<!-- Defining connections and mapped variables. -->
<connection component_1="ChristopherRobin" component_2="WinnieThePooh">
<map_variables variable_1="poohs_mood" variable_2="mood" />
</connection>
<connection component_1="ChristopherRobin" component_2="Kanga">
<map_variables variable_1="kangas_mood" variable_2="mood" />
<map_variables variable_1="roos_mood" variable_2="roos_mood" />
</connection>
<connection component_1="ChristopherRobin" component_2="Eeyore">
<map_variables variable_1="eeyores_mood" variable_2="mood" />
</connection>
<connection component_1="Kanga" component_2="Roo">
<map_variables variable_1="roos_mood" variable_2="mood" />
</connection>
</model>
The
variable
elements in a CellML model SHALL be treated as belonging to a single “equivalent variable set”. Each set of equivalent variables is the set of allvariable
elements for which the corresponding nodes in the variable equivalence network form a connected subgraph. Each set of equivalent variables represents one variable in the underlying mathematical model.
See more
Understanding mathematics
In an episode of Bill Watterson’s comic, Calvin and Hobbes, Calvin builds a duplicator machine and clones himself several times so that the clones can do his chores in different rooms of the house.
This is essentially the purpose of creating map_variables
elements: to enable the “clones” (the mapped variables) to be used in separate “rooms” (components) whilst really representing the same thing.
The first sentence in 3.10.11 explains this: Each variable
element in a CellML model SHALL be treated as belonging to a single “connected variable set”; or, while there are many “connected variable sets” in a model, any one variable
may belong to only one of them.
In a CellML model there are two mechanisms by which variables can relate to one another: through the mathematics in the math
elements, and through the mapping in the map_variables
elements.
In a mathematical model, there is only one mechanism: the maths itself.
There are no clones, no duplicates, no mappings.
Thus, the purely mathematical model is found by collapsing each set of mapped variables (cloned characters) onto a single unique variable (character), until the relationships between these unique variables no longer involve mapping (cloning) but only mathematics. In the end, Calvin does the same, and the world returns to (roughly) normal.
Interpretation of reset
elements¶
For the purposes of this section, we define the “reset variable” to be the variable referenced by a
reset
element’svariable
attribute, and the “test variable” to be the variable referenced by itstest_variable
attribute.Each
reset
element describes a change to be applied to the reset variable when specified conditions are met during the simulation of the model.All
reset
elements SHALL be considered sequentially for the equivalent variable set (see 3.10 Interpretation of map_variables elements) to which the reset variable belongs. The sequence SHALL be determined by the value of the reset element’sorder
attribute, lowest (least positive / most negative) having priority.The condition under which a reset occurs SHALL be defined by the equality of evaluation of the test variable and the evaluation of the MathML expression encoded in the
test_value
.When a reset occurs, the reset variable SHALL be set to the result of evaluating the MathML expression encoded in the
reset_value
.
References¶
RFC 2119: Key words for use in RFCs to Indicate Requirement Levels https://www.ietf.org/rfc/rfc2119.txt
XML Information Set (Second Edition) https://www.w3.org/TR/2004/REC-xml-infoset-20040204/
Namespaces in XML 1.1 (Second Edition) https://www.w3.org/TR/xml-names11/
Unicode® 13.0.0 https://www.unicode.org/versions/Unicode13.0.0/
Extensible Markup Language (XML) 1.1 (Second Edition) https://www.w3.org/TR/xml11/
XML Linking Language (XLink) Version 1.1 https://www.w3.org/TR/xlink11/
Mathematical Markup Language (MathML) Version 2.0 (Second Edition) https://www.w3.org/TR/MathML2/
This document is the normative version of the CellML Specification, defining the CellML syntax and the rules by which it should be used. It is intended primarily for the developers of software tools which directly consume CellML syntax. Users of CellML models may expand the “See more” blocks throughout this document to access the informative version and see examples. Software-specific information is also available under their respective names or icons throughout the text.
Authors:
Michael Clerx, Michael T. Cooling, Jonathan Cooper, Alan Garny, Keri Moyle, David P. Nickerson, Poul Nielsen, and Hugh Sorby.
Contributors:
Koray Atalag, David Brooks, Edmund J. Crampin, Jesús Carro Fernández, Peter J. Hunter, Gary R. Mirams, and Maxwell L. Neal.
The authors also wish to acknowledge the significant contribution of the (discontinued) CellML 1.2 draft specification, much of the text of which was incorporated into this specification, although the semantics have changed considerably. The CellML 1.2 draft specification was itself the result of a collaborative effort by a number of researchers during 2008-2011:
Andrew K. Miller (who wrote the text reused here), Randall Britten, Jonathan Cooper, Alan Garny, Peter J. Hunter, Justin Marsh, Poul Nielsen, David P. Nickerson, and Hugh Sorby.
Contact: editors@cellml.org