Skip to content

MKX Language

This chapter documents the core language used inside MKX input files. It is organized from simple values up to larger composition features such as conditional blocks and local bindings.

Overview

MKX language features appear in places such as:

  • let bindings
  • component attributes
  • reaction model arguments
  • simulation settings
  • output settings

The language is easiest to understand in four layers:

  1. scalar values
  2. collection values
  3. expressions
  4. structural composition features

1. Scalar Values

Numbers

1
1.0
1e-8
120e3

Strings

"results"
"key"

Identifiers

Identifiers are used for names and symbolic values.

thermal
arr_base
cvode_bdf

Boolean Values

Boolean values are written as identifiers.

true
false

2. Collection Values

Lists

Lists use square brackets.

[tabdelim, hdf5]
["A*", "B*", "*"]
[{T=600}, {T=650}, {T=700}]

Objects

Objects use braces and store keyed values.

{phase=gas, init=1.0, role=reactant}
{Vf=1e13, Vb=1e13}
{method=cvode_bdf, atol=1e-12, rtol=1e-10, t_end=1e6}

Both = and : are accepted in object-style assignments.

{Vf=1e13, Vb=1e13}
{Vf:1e13, Vb:1e13}

3. Expressions

Expressions are used inside object fields, model arguments, solver settings, conditions, and let bindings.

Supported Expression Forms

MKX currently supports:

  • numeric literals
  • string literals
  • identifiers
  • boolean identifiers
  • unary expressions
  • binary arithmetic expressions
  • parenthesized expressions
  • function calls
  • list literals
  • object literals

Arithmetic Expressions

Supported binary arithmetic operators:

  • +
  • -
  • *
  • /
  • ^

Examples:

50e3 + shift
2 * x
Eaf / 2
x ^ 2

Unary Expressions

Supported unary operators:

  • unary +
  • unary -

Examples:

+1e3
-5e3

Parenthesized Expressions

(50e3 + shift) / 2

Function Calls

Function-call syntax is supported for a small set of built-in numeric functions.

pow(10, 3)
max(2, 5, 4)
sqrt(1e-8)

Supported built-in functions during normalization:

  • exp(x)
  • log(x)
  • sqrt(x)
  • abs(x)
  • pow(x, y)
  • min(x1, x2, ...)
  • max(x1, x2, ...)

Operator Precedence

Expressions are parsed with the following precedence, from highest to lowest:

  1. parenthesized expressions
  2. unary +, -
  3. power ^
  4. multiplication and division
  5. addition and subtraction

Parentheses are encouraged whenever an expression becomes hard to read.

4. Structural Composition

MKX also supports features that help build larger files cleanly.

let Bindings

Use let to define reusable values.

let asite = 1e-20
let arr = {Vf=1e13, Vb=1e13}
let solver_cfg = {method=cvode_bdf, atol=1e-12, rtol=1e-10, t_end=1e6}

Spread Syntax

Object values can be expanded into argument lists using spread syntax.

let arr = {Vf=1e13, Vb=1e13}

{A*}+{B*}=>{AB*}+{*} @ ArrheniusDefault(*arr, Eaf=120e3, Eab=80e3)

The same spread form may also be used inside object-style field lists, such as component attributes:

let s1 = {site="S1", site_density=1.0}

components {
  *S1  {phase=surface, init=1.0, tags=[emptysite], *s1},
  A*S1 {phase=surface, init=0.0, *s1}
}

As with model arguments, later explicit fields override earlier spread values.

where Bindings

Local bindings may be attached to individual entries using where (...).

{A*}+{B*}=>{C*}+{*} @ ArrheniusDefault(*arr, Eaf=50e3 + shift, Eab=55e3)
where (shift=-5e3)

This is useful when a value is local to a single entry and should not become a top-level let.

Block Conditionals

MKX supports structural conditionals inside components { ... } and reactions { ... } blocks.

The syntax is:

if(enabled) {
  ...
} else {
  ...
}

The condition must resolve to a boolean value, typically from a top-level let.

Reaction Example

let enabled = true

reactions {
  if(enabled) {
    {A}+{*}=>{B}+{*} @ ArrheniusDefault(Vf=1e6, Vb=0.0, Eaf=0.0, Eab=1e5)
  } else {
    {A}+{*}=>{B}+{*} @ ArrheniusDefault(Vf=1e6, Vb=1e7, Eaf=30e3, Eab=1e5)
  }
}

This lets you switch entire elementary steps on or off, or choose between two alternative parameterizations, without duplicating the surrounding file.

Component Example

let use_adsorbate = false

components {
  A {phase=gas, init=1.0, role=reactant},
  * {phase=surface, init=1.0, tags=[emptysite]},
  if(use_adsorbate) {
    A* {phase=surface, init=0.0}
  } else {
    B* {phase=surface, init=0.0}
  }
}

Worked Example

The example below combines let, spread syntax, arithmetic, and a block-conditional reaction choice.

let include_conversion_step = true
let arr_fast = {Vf=1e6, Vb=0.0}
let arr_slow = {Vf=1e6, Vb=1e7}

reactions {
  if(include_conversion_step) {
    {A}+{*}=>{B}+{*} @ ArrheniusDefault(*arr_fast, Eaf=0.0, Eab=1e5)
  } else {
    {A}+{*}=>{B}+{*} @ ArrheniusDefault(*arr_slow, Eaf=30e3, Eab=1e5)
  }
}

Read from top to bottom, this does the following:

  1. defines a boolean switch
  2. defines two reusable parameter objects
  3. chooses one full reaction entry or the other inside reactions { ... }

Supported And Unsupported Features

It is important to distinguish between syntax accepted by the parser and features intended for normal use.

Supported

The following are supported and intended for normal use:

  • numeric arithmetic with +, -, *, /, ^
  • grouping with parentheses
  • lists and objects
  • reusable values through let
  • spread syntax
  • local where bindings
  • block conditionals inside components and reactions
  • the built-in functions listed above

Not Supported

The following are not currently supported:

  • comparison operators such as ==, !=, <, <=, >, >=
  • logical operators such as &&, ||, !
  • string concatenation
  • indexing into lists or objects
  • member access syntax
  • arbitrary user-defined functions
  • function names other than the built-in functions listed above
  • nested block conditionals

In particular, generic call syntax such as foo(1, 2) may parse, but it will fail during normalization unless foo is one of the supported built-in functions.

Likewise, a conditional such as if(T > 600) { ... } else { ... } is not yet supported because comparison operators are not yet part of the language.

Comments

Line comments start with #.

# This is a comment