This document is the authoritative reference for the syntax and semantics of JSim's Mathematical Modeling Language (MML).

Prerequisites:

Contents:

  • Overview
  • Import statements
  • Unit statements
  • Template definitions
  • Function and procedure definitions
  • Component declarations
  • Component sub-statments
  • Pre-defined component types
  • Algebraic expression syntax
  • Reserved word list
  • Comments or Questions?

Give feedback

Overview

MML is a ASCII text-based language that declares a set of mathematical variables and the relationships that constrain them. MML is case sensitive and extraneous whitespace (space, tab, C/R and N/L) characters are ignored. Characters between /* and */ and those between // and the end of the line are treated as comments. Characters on a single line between double-quote marks (") are interpreted as strings. Multi-line strings, useful for function and procedure code blocks, are delimited by {{ and }}. MML text may be stored in the model source section of a JSim project file, or may be stored as a free-standing text file. In the latter case, it is strongly recommended the file have the .mod extension.

An MML file is a series of top-level statements, which may be import statements, unit statements, template definitions, function or procedure definitions or component declarations. A properly formed MML model must contain exactly one top-level component declaration. All other top level statements are optional. Older MML files may start with the keywords "JSim v1.1", identifying the MML (not JSim) version number. This syntax is still supported, but is not longer recommended.

In all syntactic descriptions that follow, square brackets [] denote optional elements.

Import Statements

Import statements allow importing unit, template, function and procedure definitions from standard libraries. Import statement syntax is:

      import name;

 

If name does not have an extension, .mod is assumed. Name may be placed in quotes to handle spaces and oddball file name characters, such as directory delimiters.

Import statements search directories listed in the property JSIMPATH. See the JSim Environment Variables for details.

Unit Statements

Unit statements may be either unit conversion statements or unit definitions. Unit conversion statements may be one of two forms:

      unit conversion on;
      unit conversion off;

One of the above is required if units are to be assigned to any model components. Unit conversion on implies that the equations should be checked for unit consistency, and any appropriate conversion factors included in the run-time calculations. Unit conversion off implies that the unit declarations are merely for documentation purposes, but that they have no effect on the run-time calculations.

Unit definitions may be fundamental:

      unit name = fundamental [prefixable];

or derived:

      unit name = [factor] expr [prefixable];

where expr is a unit expression of previously defined units and factor is a numeric factor. If factor is missing, one is assumed. The keyword prefixable allows any defined unit prefixes (see below) to be interpreted correctly.

JSim defines two units internally, which are equivalent:

      dimensionless
      radian

Fundamental units form an orthogonal basis for the unit system. Typically this will include units of time, length, mass, etc. All other units must be defined explicitly by the model writer. NSR distributes a standard units file (nsrunit.mod) that, when imported (see Import Statements), provides for most common needs.

Derived units are defined in terms of previously defined units using the MML unit expression syntax. A unit expression may be of any of the following forms:

  • unit
  • expr1*expr2
  • expr1/expr2
  • expr^number
  • 1/expr

where unit is a previously defined unit, and exprX are unit expressions. Standard algebraic order of operations apply. Parentheses may be used to override order of operations, however (due to parsing difficulties) a unit expression may not begin with a parenthesis.

Unit prefixes may be defines as follows:

      unit prefix name = number;

All defined unit prefixes (typically kilo, milli, micro, etc.) apply to all units defined with the prefixable keyword.

Template Definitions

Template statements allow the creation of new component types, beyond the four types that are defined automatically. There are currently two supported template statements, math templates and class templates.

Math templates allow the modeler to define reusable chunks of MML code:

     math template name [ ( arguments ) ] { sub-statements }

 

Arguments to a math template represent variables that are shared between the component and its calling context. See Using Templates within MML for more information.

Class templates access component definitions in previously compiled Java class files:

     class template name { class="classfile"; }

For example, the NSR-distributed BTex BCL defines all its components as class templates. See Using BCL Components within MML for more information.

Function and Procedure Definitions

Functions and procedure (F&P) definitions allow MML models to access code written in procedural languages such as Java, Matlab, Fortran, etc. Functions return a real data value when given some number of input arguments. Procedures return no data value, but may have both input and output arguments. Class F&P access pre-compiled java classes:

     class real function name { class="classfile"; }

     class procedure na/jsim/docs/MML_if_else.htmlme { class="classfile"; }

Native F&P definitions reference pre-compiled native code libraries:

      real native function name ( arguments ) {
        library="somelibrary";
        name="functionname";
      }

      real native procedure name ( arguments ) {
        library="somelibrary";
        name="functionname";
      }

Source F&P definitions incorporate source code that can be compiled at model build or model run time::

real source-type function name ( arguments ) { topcode={{ user-code }}; maincode={{ user-code }}; bottomcode={{ user-code }}; }

source-type procedure name ( arguments ) { topcode={{ user-code }}; maincode={{ user-code }}; bottomcode={{ user-code }}; }

where source-type is a supported source type (currently "java" or "matlab"). Arguments to native and source F&P are placeholder names passed to the compiled code. Scalar placeholders are simple names (following JSim naming conventions). Multi-dimensional placeholders are a series of simple names separated by at (@) symbols. All arguments to functions are inputs, and are separated by commas. Input arguments to procedures are listed first, separated by commas and followed by a semicolon. Output arguments to procedures follow the the semicolon. See Using Functions and Procedures in MML for further information.

Component declarations

A component declaration may be one of in two forms:

      [ access ] type name [ ( arguments ) ] [ unit ];

      [ access ] type name [ ( arguments ) ] [ unit ] { sub-statements }

where

  • "access" may be "public", "private" or "extern", the default being public. This clause determines the visibility of the component to the model user.
  • "type" is the component type. The internally defined MML types are "math", "real", "int" and "realDomain". All but the first are considered variable types. Additional types may be create via the top-level template definition statements. Details for built-in component declarations are provided within this document.
  • "name" the (case sensitive) component name. It must be unique within its parent component's context. The name must begin with a letter and may contain any number of letters, numbers, underscores (_) or periods (.) so long as it does not contain two consecutive underscores or periods. Names must not start with the letter sequence "JS" in any capitalization and must not be found within JSim's list of reserved words .
  • "arguments" is a comma separated list of one or more components, algebraic expressions or strings that help to define a component. For example, the arguments to a "real" component declaration are the relevant realDomains over which it varies.
  • "unit" is the physical unit associated with the component. See the Unit Statements section for more information on units.
  • "sub-statements" serve to qualify relationships within the component. The sub-statements may be additional component declarations, equations, combined declaration/equations, void function calls or access redefinition statements. Declared (child) sub-components may be accessed in the parent's context via a dot-separated name (parent-name.child-name).

Component sub-statements

Component sub-statements are of the same form as top-level component declarations described above. This allows arbitrary nesting of components.

Equations are exact numerical relationships between variables in one of the following forms:

      expr2 = expr3;

      when (expr1) expr2 = expr3;

      when (expr1) {
        expr2 = expr3;
        expr4 = expr5;
        ...
      }      

      event (expr1) stateVar = expr;

      event (expr1) {
        stateVar2 = expr2;
        stateVar3 = expr3;
        ...
      }

where exprX are algebraic expression of variables, with expr1 being of the boolean type. See Algebraic Expression Syntax for further information.

Combined declaration/equations are of the form:

      [access] type name [(arguments)] = expr;

which is equivalent to the two statements:

      [access] type name [(arguments)];
      name = expr;

With unit conversion on, name is given the same units as expr.

Relations describe inexact numerical relationships between variables using the <, <=, >, >= and ~= relations in place of the equals sign. This feature is not completely supported at this time.

Procedure calls are of the form:

      proc1(arg1, arg2, ... , argN);

where proc1 has been previously defined using a top-level procedure definition statement and argX are function arguments.

Access redefinition statements redefine a previously defined component's access. This is most useful when a component predefines sub-variables that may not be of the proper access (e.g. realDomain). The syntax is:

      [access] type name;

Predefined Components

The following components are internally defined within MML, and do not need to be defined by the modeler.

Math Components

The built-in "math" component serves mearly as a wrapper for a mathematical system. It requires no arguments and accepts no unit clause. To be useful, it is always declared with sub-statements. No sub-components are automatically created. Only real, int, realState, intState and realDomain sub-components are supported.

Real and Integer Components

The built-in real, realState, int and intState components represent dependant real and integer variables that may be scalars, or of one or more dimensions. The arguments denote those dimensions, and must be realDomains. If no arguments are specified, the variable is a scalar. The variables may be declared within any higher lever component, making them useful not only in MML models, but in many BCL models as well. Units are supported, but not required for these components. No sub-components are automatically declared. MML is neutral on the precision for these variables. The JSim compiler currently implements both reals and integers as 64-bit floating-point numbers.

Choice Components

The built-in choice component is a scalar integer variable whose value is associated with a set of String labels. The arguments, which may be integers or Strings define the associations. The number of labels corresponds to the number of String arguments. The values start at 1, and increment with each successive label. The next label value may be reset with a preceeding integer argument. The labels only have force when the variable is an input. If the variable is an output, it is treated the same as any other integer variable. Characteristics not mentioned here are inherited from integers (above).

RealDomain Components

The built-in realDomain component represents a one-dimensional independent variable, as specified by a fixed, evenly spaced grid. No arguments are required. Units are supported but not required. Four sub-components are automatically declared:

        real min;       // minimum value
        real max;       // maximum value
        real delta;     // grid spacing
        int ct; // # of grid points (at least 2, min and max)

Algebraic expression syntax

Algebraic expressions in JSim may involve numeric constants with or without units, variables, standard binary operations, built-in or model defined functions, or interpolated variable values. Expressions may be of the numeric or boolean type.

Numberic constants may be expressed as positive or negative integers (e.g. 0, 123, -123), decimals (e.g. 12.3, -0.123) or floating point numbers using either e or E (e.g. 1e-12, -5.3E4). Unary plus is not allowed and numbers must have a digit to both the left and right of any decimal point.

Constants with physical units are enclosed in parentheses:

      (number unitexpr)

where unitexpr is a unit expression as described previously.

Variables are normally listed in equations without their domains. When a variable name in an expression is followed by a parenthesis, the number of arguments within the parenthesis must match the variables' dimension and the returned value is the interpolated value at the domain values in the arguments. See Miscellaneous Short Topics in MML for more information.

Numeric Binary Operations:

  • + addition
  • - subtraction (also unary minus)
  • * multiplication
  • / division
  • ^ exponentiation (right-associative, e.g. a^b^c=a^(b^c))
  • : derivative or partial derivative (more on this later)

Built-in Numeric Constants/Functions:

  • PI 3.14159...
  • abs(x) absolute value
  • ceil(x) round upward to next integer
  • floor(x) round downward to next integer
  • round(x) round to nearest integer
  • rem(x,y) remainder of x when divided by y
  • sqrt(x) square root
  • ln(x) natural log, x must be dimensionless if unit correction is on
  • log(x) log base 10, x must be dimensionless if unit correction is on
  • exp(x) inverse natural log (e^x), x must be dimensionless if unit correction is on

  • sin(x) trigonometric sine (x in radians)
  • cos(x) trigonometric cosine (x in radians)
  • tan(x) trigonometric tangent (x in radians)
  • asin(x) trigonometric inverse sine, x must be dimensionless if unit correction is on
  • acos(x) trigonometric inverse cosine, x must be dimensionless if unit correction is on
  • atan(x,y) trigonometric inverse tangent, where (x,y) represent vector coordinates in the standard XY plane. x/y must be dimensionless if unit correction is on

  • sinh(x) hyperbolic sine, x must be dimensionless if unit correction is on
  • cosh(x) hyperbolic cosine, x must be dimensionless if unit correction is on
  • tanh(x) hyperbolic tangent, x must be dimensionless if unit correction is on
  • asinh(x) inverse hyperbolic sine, x must be dimensionless if unit correction is on
  • acosh(x) inverse hyperbolic cosine (positive branch), x must be dimensionless if unit correction is on
  • atanh(x) inverse hyperbolic tangent, x must be dimensionless if unit correction is on

  • besseli0(x) modified Bessel function of the 1st kind, order zero, x must be dimensionless if unit correction is on
  • besseli1(x) modified Bessel function of the 1st kind, order one, x must be dimensionless if unit correction is on
  • besselkn(n,x) modified Bessel function of the 2nd kind, integer order round(n), negative x returns NaN, n and x must be dimensionless if unit correction is on
  • besseljn(n,x) Bessel function of the 1st kind, integer order round(n), n and x must be dimensionless if unit correction is on
  • besselyn(n,x) Bessel function of the 2nd kind, integer order round(n), negative x returns NaN, n and x must be dimensionless if unit correction is on

  • erf(x) error function, x must be dimensionless if unit correction is on
  • erfc(x) complementary error function, x must be dimensionless if unit correction is on

  • integral(x@t) integral of x over domain t
  • integral(t=a to b, x) integral of x for values of domain t from a to b
  • sum(x@t) sum of x for all values of domain t
  • sum(t=a to b, x) sum of x for values of domain t from a to b

  • random() pseudo-random number from a uniform distribution between 0 and 1 inclusive
  • randomg() pseudo-random number from a Gaussian (normal) distribution of mean 0 and standard deviation 1

Comparison Operators:

  • < less than
  • <= less than or equals
  • = equals
  • > greater than
  • >= greater than or equals

Boolean Operators:

Boolean Constants:

  • true boolean true
  • false boolean false

Reserved word list

The following words have special meanings within MML and thus cannot be used as component, template, function or unit names:

  • and
  • assign
  • class
  • conversion
  • else
  • event
  • extern
  • false
  • function
  • fundamental
  • if
  • import
  • integral
  • JSim
  • or
  • override
  • PI
  • private
  • procedure
  • public
  • solver
  • source
  • sum
  • template
  • to
  • true
  • unit
  • when

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.