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:

abcdefghijklmnopqrstuvwxyz (symbols between U+0061 and U+007A) ABCDEFGHIJKLMNOPQRSTUVWXYZ (symbols between U+0041 and U+005A)

These characters are referred to in CellML as the “Basic Latin alphabetical characters”.

The “digits” are the Unicode characters:

0123456789 (symbols between U+0030 and U+0039)

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

  1. Every CellML infoset SHALL be represented in an XML information set which conforms with the well-formedness requirements of XML 1.1 [5].

  2. 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

  1. 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):

    1. A document information item;

    2. An element information item;

    3. An attribute information item;

    4. A processing instruction information item;

    5. An unexpanded entity reference information item;

    6. A document type declaration information item;

    7. An unparsed entity information item; or

    8. A notational information item.

  2. 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.

  3. 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 and food_ideas have element contents, because they have child elements inside them,

  • category is an attribute of the recipe element, and name and units are attributes of the ingredient element, and

  • the 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

  1. 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):

    1. A comment information item;

    2. A namespace information item; or

    3. A character information item.

  2. 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>
  1. 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:

    1. Adding, removing, and/or modifying comment information items.

    2. 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.

    3. 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

  1. Element information items in a CellML infoset MUST belong to one of the following namespaces, unless explicitly indicated otherwise:

    1. The CellML namespace; or

    2. The MathML namespace.

  2. Attribute information items in a CellML element MUST NOT be prefixed with a namespace, unless explicitly indicated otherwise.

XML ID Attributes

  1. 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 and variable), so this remains valid.

  • There is repetition of the id attribute “p” in the CarbohydrateIdeas.cellml document, between the variable named “Peanutbutter” and the component named “Porridge”. This is not valid.

Data representation formats in CellML

The following data representation formats are defined for use in this specification:

  1. A CellML identifier:

    1. 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.

    1. 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.

  1. An integer string:

    1. SHALL be a base 10 representation of an integer.

    1. MAY begin with a single Basic Latin plus character U+002B or a single Basic Latin hyphen-minus character U+002D as the sign indicator.

    1. 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, +.

  1. A basic real number string:

    1. SHALL be a base 10 representation of a real number.

    1. MAY begin with a single Basic Latin plus character U+002B or a single Basic Latin hyphen-minus character U+002D as the sign indicator.

    1. MAY contain a single decimal point separator, which SHALL be the Basic Latin full stop character U+002E.

    1. 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).

  1. A real number string:

    1. 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.

    1. The representation of the number SHALL be the representation of the significand, optionally followed by a representation of the exponent.

    1. The significand SHALL be represented as a basic real number string.

    1. 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.

    1. 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.

  1. Every model element MUST contain a name 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).

  1. A model element MAY contain one or more additional specific element children, each of which MUST be of one of the following types:

    1. A component element;

    2. A connection element;

    3. An encapsulation element;

    4. An import element; or

    5. A 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>
  1. A model element MUST NOT contain more than one encapsulation 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.

  1. Every import element MUST contain an attribute in the namespace http://www.w3.org/1999/xlink, with a local name equal to href.

    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 the href 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>
  1. Every import element MAY contain one or more specific element children, each of which MUST be of one of the following types:

    1. An import component element; or

    2. An 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.

  1. 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.

  1. Every import units element MUST contain a name 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 the name attribute of any other units or import 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 called smallPotOfPaint in the example below).

  • A file to import from, specified using the xlink:href attribute of the parent import block. This is discussed in more detail in The import element information item. In the example below this is the paint_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 the units_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>
  1. Every import units element MUST contain a units_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 the name attribute on a units or import 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.

  1. Every import component element MUST contain a name 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 the name attribute of any other component or import component element in the CellML infoset.

  1. Every import component element MUST contain a component_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 the name attribute on a component or import 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 called pi_calculator in the example below),

  • A file to import from, specified using the xlink:href attribute of the parent import block. This is discussed in more detail in The import element information item. In the example below this is the pi_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 the component_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:

  1. 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.

  2. 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>
  1. 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 given href 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.

  1. Every units element MUST contain a name 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 the name attribute of any other units element or import units element in the CellML infoset.

  1. 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).

  1. A units element MAY contain one or more unit 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.

  1. Every unit element MUST contain a units attribute.

    The value of the units attribute MUST be a valid units reference, as defined in 3.2 Units references.

    1. 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 every units element in the CellML model.

      The units element inclusion digraph SHALL contain an arc from units element A to units element B if and only if units element A contains a unit element with a units attribute value that is identical to the name attribute value of units element B.

    1. 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>
  1. A unit element MAY contain any of the following attributes:

    1. The prefix attribute. If present, the value of the attribute MUST meet the constraints specified in 3.3 Interpretation of units elements.

    1. The multiplier attribute. If present, the value of the attribute MUST be a real number string.

    1. 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.

  1. Every component element MUST contain a name 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 the name attribute on any other component element or import 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>
  1. A component element MAY contain one or more specific element children, each of which MUST be of one of the following types:

    1. A math element;

    2. A reset element; or

    3. A 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.

  1. Every variable element MUST have exactly one of each of the following attributes:

    1. The name 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 the name attribute on any sibling variable element.

    1. The units attribute. The value of the units attribute MUST be a valid units reference, as defined in 3.2 Units references.

  2. Every variable element MAY contain one or more of the following attributes:

    1. The interface attribute. If the attribute is present, it MUST have value of public, private, public_and_private, or none.

    1. 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.

  1. Every reset element MUST have exactly one of each of the following attributes:

    1. The variable attribute. The value of the variable attribute MUST be a valid variable reference, as defined in 3.5 Variable references.

    1. The test_variable attribute. The value of the test_variable attribute MUST be a valid variable reference, as defined in 3.5 Variable references.

    1. The order attribute. The value of the order attribute MUST be an integer string.

      The value of the order attribute MUST be unique for all reset elements with variable attributes that reference variables in the same equivalent variable set (see 3.10 Interpretation of map_variables elements).

  1. A reset element MUST contain exactly two element children, which MUST be one of each of the following types:

    1. A reset_value element; and

    1. 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.

  1. A test_value element MUST contain exactly one math 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.

  1. A reset_value element MUST contain exactly one math 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.

  1. 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.

  1. 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>
  1. 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>
  1. A MathML cn element MUST have an attribute in the CellML namespace, with a local name equal to units.

    The value of the units attribute MUST be a valid units reference, as defined in 3.2 Units references.

  1. 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.

Supported MathML elements

Element Category

Element List

Simple Operands

ci, cn, sep

Basic Structural

apply, piecewise, piece, otherwise

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

diff

Qualifier Elements

bvar, logbase, degree *

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.

  1. An encapsulation element MAY contain one or more component_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.

  1. Every component_ref element MUST contain a component 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 the component attribute on any other component_ref element in the CellML infoset.

  1. Every component_ref element MAY in turn contain one or more component_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.

  1. Each connection element MUST contain a component_1 attribute.

    The value of the component_1 attribute MUST be a valid component reference, as defined in 3.4 Component references.

  1. Each connection element MUST contain a component_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>
  1. The value of the component_1 attribute MUST NOT be identical to the value of the component_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>
  1. A CellML infoset MUST NOT contain more than one connection element with a given pair of components referenced by the component_1 and component_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>
  1. A connection element MAY contain one or more map_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.

  1. Each map_variables element MUST contain a variable_1 attribute.

    The value of the variable_1 attribute MUST be a valid variable reference, as defined in 3.5 Variable references.

  1. Each map_variables element MUST contain a variable_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>
  1. A connection element MUST NOT contain more than one map_variables element with a given variable_1 attribute value and variable_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

  1. Each import units or import 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 parent import element’s href attribute.

  2. A units reference occurring within an imported element, SHALL be resolved with respect to the imported infoset.

  3. When determining the equivalent variable set of a variable in an imported component:

    1. Connections defined in the importing infoset SHALL be handled as described in 3.10 Interpretation of map_variables elements.

    2. Connections defined in the imported infoset SHALL be handled as follows:

      1. Connections to components in the encapsulated set of the imported component SHALL be maintained, and this rule SHALL be applied recursively; and

      2. 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.

  1. A units reference SHALL be a CellML identifier.

  2. The units identified by a units reference SHALL be determined as follows:

    1. 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.

    2. If the units reference is identical to the value of the name attribute of a units element in the same infoset, then it SHALL refer to the units specified by that element.

    3. If the units reference is identical to the value of the name attribute of an import units element in the same infoset, then it SHALL refer to units from the infoset defined by the import units element (see 3.1 Interpretation of import elements`). The units specified SHALL then be determined by treating the value of the units_ref attribute on the import units element as a units reference within the imported infoset. If necessary, this rule SHALL be applied recursively.

  3. 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.

Built-in units
Name

Unit reduction tuple
multiplier⋅(base, exponent)

ampere

-

becquerel

(second, -1)

candela

-

coulomb

(second, 1), (ampere, 1)

dimensionless

-

farad

(kilogram, -1), (metre, -2), (second, 4), (ampere, 2)

gram

0.001⋅(kilogram, 1)

gray

(metre, 2), (second, -2)

henry

(kilogram, 1), (metre, 2), (second, -2), (ampere, -2)

hertz

(second, -1)

joule

(kilogram, 1), (metre, 2), (second, -2)

katal

(second, -1), (mole, 1)

kelvin

-

kilogram

-

litre

0.001⋅(metre, 3)

lumen

(candela, 1)

lux

(metre, -2), (candela, 1)

metre

-

mole

-

newton

(kilogram, 1), (metre, 1), (second, -2)

ohm

(kilogram, 1), (metre, 2), (second, -3), (ampere, -2)

pascal

(kilogram, 1), (metre, -1), (second, -2)

radian

(dimensionless, 1)

second

-

siemens

(kilogram, -1), (metre, -2), (second, 3), (ampere, 2)

sievert

(metre, 2), (second, -2)

steradian

(dimensionless, 1)

tesla

(kilogram, 1), (second, -2), (ampere, -1)

volt

(kilogram, 1), (metre, 2), (second, -3), (ampere, -1)

watt

(kilogram, 1), (metre, 2), (second, -3)

weber

(kilogram, 1), (metre, 2), (second, -2), (ampere, -1)

Interpretation of units elements

  1. The units element SHALL be interpreted as the product of its unit element children, according to the following rules:

    1. The prefix term is a conceptual property of unit elements. If the unit element does not have a prefix attribute, the prefix term SHALL have value 0. If the prefix 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, the prefix 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.

    2. The exponent term is a conceptual property of unit elements. If a unit element has no exponent attribute, the exponent term SHALL have value 1.0. Otherwise, the value of the exponent attribute MUST be a real number string, and the value of the exponent term SHALL be the numerical value of that string.

    3. The multiplier term is a conceptual property of unit elements. If a unit element has no multiplier attribute, the multiplier term SHALL have value 1.0. Otherwise, the value of the multiplier attribute MUST be a real number string, and the value of the multiplier term SHALL be the numerical value of that string.

    4. The relationship between the product, \(P\), of numerical values given in each and every child unit element’s units attribute, to a numerical value, \(x\), with units given by the encompassing units 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).

  1. For the purposes of this specification, the “irreducible units” of a model SHALL consist of:

    1. 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 no unit child elements).

    2. 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.

  1. 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:

    1. If the units element has no unit child elements, then the set of tuples SHALL have a single member, which SHALL consist of the name of the units element and the exponent 1.0.

    2. If the units element has one or more unit child elements, then the set of tuples SHALL consist of the entire collection of tuples given by all unit child elements.

      Tuples for each unit child element SHALL be determined as follows:

      1. 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.

      1. 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.

      1. 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 the units element so referenced.

      2. 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.

    3. 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.

    4. 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: joules 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 to apple, and

  • the 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 the cider_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>
Prefix values

Name

Value

yotta

24

zetta

21

exa

18

peta

15

tera

12

giga

9

mega

6

kilo

3

hecto

2

deca

1

deci

−1

centi

−2

milli

−3

micro

−6

nano

−9

pico

−12

femto

−15

atto

−18

zepto

−21

yocto

−24

Component references

A “component reference” is an attribute value that specifies a CellML component.

  1. A component reference SHALL be a CellML identifier.

  2. The component identified by a component reference SHALL be determined as follows:

    1. If the component reference is identical to the value of the name attribute of a component element in the same infoset, then it SHALL refer to the component specified by that element.

    2. If the component reference is identical to the value of the name attribute of an import component element in the same infoset, then it SHALL refer to a component from the infoset defined by the import component element (see 3.1 Interpretation of import elements). The component specified SHALL then be determined by treating the value of the component_ref attribute on the import component element as a component reference within the imported infoset. If necessary, this rule SHALL be applied recursively.

  3. 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.

  1. A variable reference SHALL be a CellML identifier.

  2. The variable identified by a variable reference SHALL be determined as follows:

    1. When present in a descendant of a component element, it SHALL refer to the variable of the same name within that component.

    2. When present in the variable_1 attribute of a map_variables element, it SHALL refer to the variable of the same name in the component identified by the component_1 attribute in the same map_variables element.

    3. When present in the variable_2 attribute of a map_variables element, it SHALL refer to the variable of the same name in the component identified by the component_2 attribute in the same map_variables element.

  3. 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

  1. The initial_value attribute of a variable element MUST either be a real number string, or a variable reference.

  2. The conditions under which initial values hold are (by design) not defined in a CellML model.

  3. 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.

  4. 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 the initial_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 the math block, rather than via the initial_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 a math 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

  1. 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

  1. The following component elements SHALL, for the purposes of this specification, be “pertinent component elements”:

    1. All component elements in the top-level CellML infoset for the CellML model;

    2. All component elements referenced by import component elements (see 3.1 Interpretation of import elements) in the top-level CellML infoset; and

    3. All component elements which are descendants in the encapsulation digraph (see 3.9 Interpretation of encapsulation elements) of a pertinent component element.

  2. 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 pertinent component element, SHALL be treated, in terms of the semantics of the mathematical model, as a statement which holds true unconditionally.

  3. Units referenced by a units attribute SHALL NOT affect the mathematical interpretation of the CellML model.

Interpretation of encapsulation elements

  1. 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.

  2. Where a component_ref element appears as a child of another component_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 parent component_ref element, and to the node corresponding to the component referenced by the child component_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>
  1. 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.

  1. 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.

  1. 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.

  1. The “hidden set” for a component A SHALL be the set of all components B where component B is not in the encapsulated set for component A, and component B is not the encapsulation parent of component A, and component B is not in the sibling set for component A.

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 a component element or the model element itself.

  • 3.9.6 defines the “hidden set” of any component as those other component elements which are neither the parent, the children, nor the siblings of that current component 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 and JethrineBodine,

  • LukeClampett and AmosClampett, and

  • MyrtleClampett and JedClampett.

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 from EllyMayClampett (grandfather/grandchild)

  • AmosClampett is hidden from MyrtleClampett (uncle/niece)

  • PearlBodine is hidden from JedClampett (cousins)

  • GrannyMoses is hidden from LukeClampett (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

  1. 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.

  1. 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:

    1. Variable A SHALL be the variable referenced by the encompassing connection element’s component_1 and this map_variables element’s variable_1 attribute; and

    2. Variable B SHALL be the variable referenced by the encompassing connection element’s component_2 and this map_variables element’s variable_2 attribute.

  2. For every map_variables element present in the CellML model, there SHALL be an arc in the variable equivalence network.

    1. One endpoint of the arc in the variable equivalence network SHALL be the node corresponding to variable A; and

    2. 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.

  1. CellML models MUST NOT contain any pair of map_variables elements which duplicates an existing arc in the variable equivalence network.

  2. 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>
  1. 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>
  1. 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>
  1. For a given variable, the “available interfaces” SHALL be determined by the value of the interface attribute on the corresponding variable element as follows:

    1. A value of public specifies that the variable has a public interface;

    2. A value of private specifies that the variable has a private interface;

    3. A value of public_and_private specifies that the variable has both a public and a private interface;

    4. A value of none specifies that the variable has no interface; or

    5. If the interface attribute is absent, then the variable has no interface.

  2. The “applicable interfaces” for variables A and B in components AA and BB respectively SHALL be defined as follows:

    1. 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.

    2. 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.

    3. 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.

  3. 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.

  1. 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.

  2. 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 and ChristopherRobin have public interfaces between their mood and poohs_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 the mood variable in component Eeyore does not specify one, no mappings are permitted. For that connection to exist, the mood variable must have an interface type public.

  • Mapping C is not valid. The variable kangas_mood has explicitly specified that no mappings are possible by using the none interface type. For this mapping to be valid, the type needs to be public.

  • Mapping D is not valid. Because they are sibling components, the variables in ChristopherRobin and Kanga must both have the interface type of public 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 component Roo with a private interface. But if Mapping D is to be made valid, that same variable must maintain a public interface in order to access variables in its sibling component ChristopherRobin. It is for this reason that the public_and_private interface type exists. For Mappings D and E to be valid, the variable roos_mood in component Kanga must have an interface type of public_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>
  1. 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 all variable 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

  1. For the purposes of this section, we define the “reset variable” to be the variable referenced by a reset element’s variable attribute, and the “test variable” to be the variable referenced by its test_variable attribute.

  2. Each reset element describes a change to be applied to the reset variable when specified conditions are met during the simulation of the model.

  3. 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’s order attribute, lowest (least positive / most negative) having priority.

  4. 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.

  5. When a reset occurs, the reset variable SHALL be set to the result of evaluating the MathML expression encoded in the reset_value.

References

  1. RFC 2119: Key words for use in RFCs to Indicate Requirement Levels https://www.ietf.org/rfc/rfc2119.txt

  1. XML Information Set (Second Edition) https://www.w3.org/TR/2004/REC-xml-infoset-20040204/

  1. Namespaces in XML 1.1 (Second Edition) https://www.w3.org/TR/xml-names11/

  1. Unicode® 13.0.0 https://www.unicode.org/versions/Unicode13.0.0/

  1. Extensible Markup Language (XML) 1.1 (Second Edition) https://www.w3.org/TR/xml11/

  1. 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