Using Physical Units in MML

Introduction

This document describes using physical units in MML models. This feature is useful both for documenting models and for insuring they are dimensionally correct.

Prerequisites:

Contents:

  • Physical Units
  • Some Examples with Units
  • More About Units
  • Defining Additional Units
  • JSim Standard Units file
  • Comments or Questions?
    Give feedback

Physical Units

MML variables may be assigned physical units (e.g. meter/sec) for either documentation or calculation purposes. Using MML units requires three steps:

  1. defining the system of units to be used;
  2. deciding on a unit conversion policy;
  3. declaring variables with units clauses.

(1) JSim has no predefined units policy. The unit system is flexible enough to allow intermixing of e.g. CGS, MKS, English and user custom units as needed. The radian unit is predefined, but all other units must be declared in the model file. Most users will wish to import the NSR unit library (nsrunit.mod) that is distributed with JSim. A subsequent section describes how model files may define additional units.

You may examine the NSR unit library definition file (nsrunit.mod) to see what units are predefined in that file. This file may be found in common/nsrunit.mod within the JSim distribution directory. A single unit may have multiple names. For example, meters may be written either as "meter" or as "m", but not as "meters". Also, unit name space is separate from variable name space, so there is no problem defining a variable with name "m", even though this is also the name of a physical unit.

(2) To use JSim units, a model file must declare either "unit conversion on" or "unit conversion off". With unit conversion on, variable constraints are checked for unit consistency and conversion factors are calculated internally. Any constraint that is not consistent will generate an error. With unit conversion off, a variable may still be declared with units, but the declaration is merely documentation and has no effect on the run-time calculations.

(3) Declaring variables with units simply requires a unit expression following the variable name. The unit expression may combine any of the previously defined units using the operators * (multiply), / (divide), ^ (exponentiation), and 1/ (inverse). Examples:

      realDomain t sec;         // time in seconds
      real area m^2;            // area in square meters
      real f(t) kg*m/sec^2;     // force in newtons
      real h(t) 1/sec;          // frequency in Hertz

Some examples with units

A simple, complete example follows. Note that the import and unit conversion directives come before the math block.:

// 1st unit conversion example
import nsrunit;
unit conversion on;
math example6a {
  real dist1 m, dist2 m;// dist1 and dist2 in meters
  real dist3 cm;        // dist3 in centimeters
  dist1 = 3;
  dist2 = 2;     
  dist3 = dist1 + dist2; 
}
 

The run-time output of this model is as follows:

      dist1 = 3 m
      dist2 = 2 m
      dist3 = 500 cm    

To obtain the same results from a model with unit conversion off, the explicit conversion of meters to centimeters must be written into the MML:

// equivalent to example6a, but with unit conversion off
import nsrunit;
unit conversion off;
math example6b {
  real dist1 m, dist2 m;  // dist1 and dist2 in meters
  real dist3 cm;  // dist3 in centimeters
  dist1 = 3;
  dist2 = 2;
  dist3 = 100*(dist1 + dist2);
}
 

The run-time output of this model is as follows:

      dist1 = 3 m
      dist2 = 2 m
      dist3 = 500 cm

With unit conversion on, JSim rejects unit-inconsistent models. This can be a handy debugging tool when complicated equations are involved. The "c=a+b" constraint below will generate a unit inconsistency error since kilograms and seconds are incompatible.:

import nsrunit;
unit conversion on;
math example6c {
  real a kg, b sec, c sec;  
  a = 3;
  b = 2;
  c = a + b;
}

More About Units

Combined variable declaration and constraints assign variable units as might be expected:

      real a = 4 kg/sec;   //  a will be in kg/sec

Some formulas require numeric constants with units to be dimensionally correct. Such expressions usually require enclosing parentheses:

      real dt = 10 sec;
      real dist km;
      dist = dt * (12 km/sec);  // distance = elapsed time * speed

With unit conversion on, variables declared without units will be assigned units that are compatible with its constraints:

      real a km;
      real b sec;
      real c = a/b;     // c will be in km/sec

The automatically assigned unit will almost always be dimensionally consistent, but it may not be the unit the MML author has in mind. Authors particular about the desired unit should assign it to the variable explicitly. In (usually rare) cases no reasonable guess can be made for a variable's unit, so it will be set dimensionless. If this assignment results in inconsistencies, the model writer should add an explicit unit declaration.

Dimensionless variables should so declared:

      real a km, b cm;
      real c dimensionless;
      b = c*a;

The predefined radian unit is equivalent to "dimensionless". Note that built-in trigonometric and logarithmic functions require arguments in radians, so appropriate conversion constants may be required. For example:

// transcendental functions require dimensionless args
import nsrunit;
unit conversion on;
math sinewave {
  realDomain t sec;   // time in seconds
  t.min=0; t.max=2*PI; t.ct=33;
  real u(t) = sin(t/(1 sec));  // dimensionless u has period 2*PI seconds
}
 

The "import nsrunit", unit declaration and unit conversion statements may appear in any order so long as any unit declaration(s) follow the "import nsrunit" statement.

Defining Additional Units

You may define additional units for a model using the "unit" clause:

// adding user-defined units
import nsrunit;
unit teaspoon = 0.203 cm^3 prefixable,
furlong = 201 m,
grosdik = 77 furlong/sec;
unit degree = 3.14159/180 radian;
unit mySpecialOne = fundamental;
unit conversion on;
math example7 {
  real vol = 15 microteaspoon;
  real len = 8 furlong;
  real rate = vol/len;
  real car = 2 mySpecialOne/furlong;

  real angle_rad = PI radian;
  real angle_degree degree;
       angle_degree = angle_rad;
}
 

The "prefixable" declaration above, enables the standard SI prefixes (milli, kilo, micro, etc.) for the unit "teaspoon". "furlongs" is not declared as prefixable in this example, so the declaration "megafurlong" would result in an error. A unit defined as "fundamental" is a new unit that cannot be expressed as any other defined units. The variable "car" has units of mySpecialOne/furlong.

Comments or Questions?

Give feedback

 

Model development and archiving support at https://www.imagwiki.nibib.nih.gov/physiome provided by the following grants: NIH U01HL122199 Analyzing the Cardiac Power Grid, 09/15/2015 - 05/31/2020, NIH/NIBIB BE08407 Software Integration, JSim and SBW 6/1/09-5/31/13; NIH/NHLBI T15 HL88516-01 Modeling for Heart, Lung and Blood: From Cell to Organ, 4/1/07-3/31/11; NSF BES-0506477 Adaptive Multi-Scale Model Simulation, 8/15/05-7/31/08; NIH/NHLBI R01 HL073598 Core 3: 3D Imaging and Computer Modeling of the Respiratory Tract, 9/1/04-8/31/09; as well as prior support from NIH/NCRR P41 RR01243 Simulation Resource in Circulatory Mass Transport and Exchange, 12/1/1980-11/30/01 and NIH/NIBIB R01 EB001973 JSim: A Simulation Analysis Platform, 3/1/02-2/28/07.