This document specifies the syntax, core functionality, and extensions for defining and working with units in the Heta language. The units
property is available for components of the following classes: @Const
, @Record
, @Species
, @Reaction
, @TimeScale
, and any other class referring to the @_Size
parent class.
Refer to examples in the Using Units section for practical implementations.
The Heta language includes a default set of core units based on the SBML specifications. These core units are as follows:
Core Units |
---|
mole, litre, second, kilogram, katal, item, joule, metre, dimensionless, watt, |
volt, ampere, newton, becquerel, candela, coulomb, farad, gram, gray, henry, |
hertz, kelvin, lumen, lux, ohm, pascal, radian, siemens, sievert, steradian, |
tesla, weber, year, day, hour, minute, avogadro |
Complex units, formed by combining predefined units (e.g., mole/litre
, m^2
, joule/second
), can be expressed using UnitsExpr
string format.
This format is a set of declared units separated by /
or *
operators. The ^
operator is used to specify exponents.
Examples:
s1 @Species { units: mole/litre };
k1 @Const { units: mole^2/(litre)^2/second };
k2 @Const { units: 1/second };
x1 @Record { units: metre^2*joule/second };
Parentheses may be used to enclose a single unit for clarity or emphasis; however, they cannot be used to group multiple units together, and nesting of parentheses is not allowed.
Examples:
s1 @Species { units: (mole/litre) }; // error in syntax: grouping
x2 @Record { units: ((mole)*litre) }; // errror in syntax: nesting
You can specify a multiplier for units using number before the unit. When multiplier is used the parentheses are mandatory.
Example:
s2 @Species { units: (1e-9 mole)/litre } .= 10;
c1 @Compartment { units: (1e-9 metre)^3 };
As an alternative to UnitsExpr
, complex units can be specified as an array of UnitsComponent
objects. This format allows explicit specification of multipliers, exponents, and base units.
Example:
s3 @Species {
units: [
{ kind: mole, multiplier: 1e-9 },
{ kind: litre, exponent: -1 }
]
};
Users can define custom units using the #defineUnit
action. Custom units can be specified in either UnitsExpr
or UnitsComponent[]
format.
Example:
pM #defineUnit {
units: [
{ kind: mole, multiplier: 1e-12 },
{ kind: litre, multiplier: 1, exponent: -1 }
]
};
fM #defineUnit { units: (1e-15 mole)/litre };
s1 @Species { units: pM };
Dimensionless units can be represented in the following ways:
- Direct Use: Specify the
dimensionless
base unit. - Literal Representation: Use the symbol
1
instead ofdimensionless
. - Synonym Declaration: Define a synonym of
dimensionless
using the#defineUnit
action.
Examples:
x1 @Const { units: dimensionless } = 1.1;
x2 @Const { units: 1 } = 2.2;
#defineUnit DL { units: dimensionless };
x3 @Const { units: DL } = 3.3;
During compilation, the Heta compiler may perform units consistency checks to validate compatibility and correctness of unit definitions. The availability and implementation of this feature depend on the compiler being used.
For more information, refer to the Compilation chapter.
This example demonstrates a simple units inconsistency resulting in a compilation error.
c1 @Compartment { units: litre } .= 1;
s1 @Species { units: mole/litre, compartment: c1 } .= 10;
r1 @Reaction { units: mole/second } := k1 * s1;
k1 @Const { units: 1/second } = 1e-3;
The reaction rate r1
is calculated using k1
and s1
and has derived units of mole/litre/second
. But the stated units of r1
is mole/second
and incompatible. Correcting such mismatches ensures the model's mathematical and dimensional integrity.