MML (for "Mathematical Modeling Language") is a concise, ASCII text description of model calculations that is used by JSim. This document is an introductory survey of MML, with pointers to further information.
Prerequisites:
- JSim Overview (recommended)
- Introduction to the JSim GUI (recommended)
Contents:
- A Simple MML Model
- Ordinary Differential Equations (ODEs)
- Physical Units
- Driving Data and Signals
- Parameters and Parameter Sets
- Understanding Constraints
- Further topics
- Comments or Questions?
A Simple MML Model
Below is a simple model using trig functions:
// introductory algebraic model math main { realDomain t; t.min=0; t.max=2*PI; t.delta=0.1; real amp = 1; real phase = 0; real u(t), v(t), w(t); u = amp*sin(t-phase); v = amp*cos(t-phase); w = u + v; }
Items of note:
- An MML model is a set of nested components. There must be one top-level component, in this case of type "math". This document will consider only top-level components of type math (for details, see templates). The name given the math component (here "main") is inconsequential to JSim operation. Content of the math component is delimited by curly braces {}.
- Inside the math component are variable declarations and equations. A variable must be declared before it is used in an equation. Variables types used here are of type "realDomain" and "real".
- A realDomain represents an independent variable, typically time or space. Each realDomain (here "t") contains subvariables "min" (minimum value), "max" (maximum value), "delta" (grid point separation) and "ct" (number of grid points). When this model runs, "t" will be calculated as a regularly spaced grid. To be calculable, the model writer must constrain 3 of the 4 subvariables. Note that subvariables are separated by a period (e.g. "t.min").
- A "real" variable represents a either constant or a dependent variable (dependent upon realDomains), whose value during a single model run varies over its declared realDomains. Here "amp" and "period" are declared without realDomains so they have a unique value during a single model run, while "u", "v" and "w" are declared with realDomain "t" so their values will vary with those of "t". See Variable constants for more information concerning variables with no domain dependencies such as "amp" an "period".
- Variable names must be alpha-numeric (including underscore) and start with a letter. For technical reasons, they may not start with the letters "JS" in any capitalization or contain two successive underscores. Variables names are case-sensitive, as is MML in general.
- MML algebraic syntax is largely intuitive. The constant "PI" and the functions "sin()" and "cos()" are built into JSim. See here for more information, including a complete list of built-in functions.
- Spacing (spaces, tabs and new-lines) does not affect MML semantics. Single line commentary may be added after double-slashes (//). Extended C-style comments (/* */) are also supported.
- Many older models contain the first line "JSim v1.1". This syntax is still supported, but not longer recommended.
Ordinary Differential Equations (ODEs)
ODEs are used in research and education for models ranging from very simple to exceedingly complex. A simple MML model of exponential decay using an ODE is as follows:
// introductory ODE model math main { realDomain t; t.min=0; t.max=4; t.delta=0.1; real rate = 1; real u(t); // declaration of u when (t=t.min) u=1; // initial condition for u u:t = -rate*u; // ODE state equation for u }
To be solvable by JSim, an ODE variable must have two constraints:
- an initial condition (IC) that sets the initial value of the variable using the "when" clause;
- an ODE state equation relating the variable's derivative to the variable itself or other model varibles.
Note that MML uses the colon (:) operator to represent differentiation. See Using ODEs in MML for more information.
Physical Units
MML allows (but does not require) defining physical units (e.g. m/sec^2) for variables. Along with making the model easier to read, this allows JSim to perform integrity checks that catch common errors, thus reducing debugging time. Two related issues are involved:
- Inserting conversion factors. For example, when adding centimeters to millimeters, one variable must be adjusted by a factor of 10;
- Detecting illegal constructs. For example, adding meters/second to meters/second^2 is fundamentally incorrect.
When JSim compiles a model containing the optional "unit correction on" clause, appropriate conversion factors are inserted into constructs of the 1st sort, while constructs of the 2nd sort generate a compilation error. Consider the model:
// introduction to MML unit conversion unit conversion on; // enable unit checking import nsrunit; // standard units file math main { real s1 = 50 cm; // s1 in centimeters real s2 = 100 mm; // s2 in millimeters real t = 5 sec; // t in seconds real v1 = s1/t; // v1 will be 10 cm/sec real v2 = s2/t; // v2 will be 20 mm/sec real s3 = (v1+2*v2)*t; // s3 will be 70 cm }
Items of note:
- The "unit conversion on" clause enables JSim unit checking. "nsrunit" is JSim's distributed unit file that is recommended, and sufficient for most purposes. Model writers may define additional units, if desired, or even use an entirely separate file of unit definitions.
- In this simple case, the conversion factor inserted for the "s3" equation is fairly easy to see. However in large models, conversion factors are tedious and difficult to keep track of. They also clutter up the code, for example 1 faraday = 96485.341 coulomb.
- The formulation above discourages some common typos. For example, if the parentheses in the "s3" equation were mistakenly omitted, JSim would reject the model due to unit imbalance. Our experience is that errors of this general form (although more subtle) are disturbingly common in papers submitted to professional journals, presumably due to a lack of automated unit checking tools such as JSim.
- See Using Physical Units in MML for further infomation.
Driving Data and Test Signals
Many scientific analyses require driving model inputs with experimentally measured data or idealized external test signals. JSim's approach is to provide these at run-time, rather than to encode them directly in MML. This allows easy switching back and forth between various driving functions at run-time. In MML, the "extern" declaration is used to label variables that will be supplied externally via the run-time environment. The following MML models the concentration in a stirred tank whose inflow is supplied externally:
// extern variable to provide input to model unit conversion on; import nsrunit; math main { realDomain t sec; t.min=0; t.max=30; t.delta=0.1; real F = 1 ml/sec; // inflow rate real V = 20 ml; // tank volume extern real Cin(t) mM; // inflow concentration (millimolar) real C(t) mM; // current tank concentration (millimolar) when (t=t.min) C = 35; // initial conc = 35 millimolar V*C:t = F*(Cin-C); // ODE state equation }
Parameters and Parameter Sets
When JSim compiles an MML model, it classifies variables as either "input" or "output":
- Variables set equal to numeric constants in MML (e.g. t.min, t.max, t.delta, F and V in the above model) are classified as inputs;
- Variables declared "extern" (e.g. Cin in the above model) are classified as inputs;
- All other variables are classified as outputs.
JSim model "parameters" are values that affect model calculations that the user may alter without model recompilation. There are 3 types of parameters:
- MML variables classified as "inputs" above;
- numeric solver controls, e.g. which ODE solver algorithm to use (more info);
- function generator controls, e.g. the amplitude of a test signal (more info).
A collection of values for all the parameters in a JSim model is called a "parameter set". The values generated during a model run reflect both the model's MML code (which provides default parameter values) and the model's "current parameter set". The JSim GUI allows users to save and restore distinct parameter sets for modeling varying experimental conditions (e.g. "baseline", "elevated heart rate"). See JSim Parameter Sets for further info.
New User Warning: Values in the current parameter set are preserved between compiles. This usually saves modelers work, because most editing is the fine-tuning of model calculations, however it can cause a confusing scenario for new users. When an MML model is first compiled, the default values (e.g. V=20 in the above model) are loaded into the current parameter set. If you were to modify the MML to V=25 and recompile, the value shown in the JSim GUI after recompilation would still be 20, a value restored from the current parameter set. The compilation has altered V's default value to 25 (which you can see by selecting "Revert to model defaults" from the ParSet menu), but not its current value. This behaviour is somewhat controversial and is further discussed here.
Understanding Constraints
MML is a declarative language, not a procedural one. MML models primarily consist of
- declarations of physical units;
- declarations of variables;
- declarations of constraints on those variables.
The most common type of constraints are mathematical equations. Consider the following:
// constraint example math main { real a, b, c; a = b + 1; // eqn 1 c = a + b; // eqn 2 a = 5; // eqn 3 }
Notes:
- This model will calculate a=5, b=4, c=9.
- The order equations are declared in MML does not affect the results. Any reordering of eqns 1, 2 and 3 would produce the same results.
- Equations do not necessarily imply calculation of the left-hand side from the right-hand side (as they do in procedural languages such as Fortran, C, Java).
"extern" is another type of constraint. Substituting the following for eqn 3 in the above model would require the JSim user to specify a value for "a" before the model can run:
extern a;
Understanding constraints is important because JSim requires all model variables to be completely constrained, that is, it ensures there is no ambiguity in the model calculations. If any one of the 3 equations in the above model were omitted, compilation would abort with a "model underconstrained" error message. Alternatively, adding a 4th equation such as
b=6 // eqn 4
would cause compilation abort with a "model overconstrained" error message. This may seem needlessly picky, but it is actually an advantage. This approach guarantees that model equations are complete and consistent, ultimately clarifying thinking, reducing debugging and improving scientific communication.
For simple, equation-based models, a fully constrained model will have as many variables as equations. The current JSim compiler is not smart enough to detect consistent systems with more equations that variables, as might occur in the above model with the added relation "b=4". In this case, the compile would abort with a "model overconstrained" error message. Modelers can avoid this situation by matching the number of equations with the number of variables to be solved.
Some exceptions to the #variables = #constraints include the following (follow links for details):
- ODE variables require 2 equations - an initial condition and a state equation;
- 1D PDE variables (more info)require 4 equations - an initial condition, two boundary conditions and a state equation;
- Event variables (more info)require an initial condition and one or more event statements;
- MML procedures (more info) may constrain multiple variables with a single statment.
By framing models in terms of constraints, MML can easily intermix mathematics (explicit & implicit equations, ODEs, PDEs), discrete events and procedural code (e.g. Java, C, Fortran). This allows modelers to naturally mix computational methods as required by the science, rather than by shoehorning all model calculations into a single computational framework.
Further Topics
Most MML modeler writers will need to be familiar with the previous topics. Other features of MML are usually best learned as need arises, to wit:
- Implicit equations(more info) - JSim supports both linear and non-linear implicit (sometimes called simultaneous) equations.
- Partial differential equations (PDEs) (more info) - JSim currently supports a variety of 1-dimensional PDEs. Entended 1D support and some 2D support is under development.
- Integrals and Summations (more info) - MML constructs for integration and summation.
- Events (more info) - MML constructs appropriate for discrete state changes, such as gate openings and closings. Event also support some recursive function definitions.
- Functions and procedures (more info) are mechanisms for embedding code from procedural languages such as Java, C and Fortran as constraints within MML models.
- Templates (more info) are MML's mechanism for structuring model code and writing reusable model components.
Comments or Questions?
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.