Input File: Base

Little Language Quick Start

TurboWAVE input files are written using an intuitive “little language” which provides three basic functions:

  1. Create objects

  2. Associate objects

  3. Set parameters

There are only four keywords, new, get, generate, and for. You can often get by with only new. The following short example illustrates almost the full range of little language syntax:

// For illustration only, do not try to run
#define $dens 1.0e18 [/cm3] // (1) variables and units
timestep = .01 // (2) floating point assignment

new plane wave 'pw1' // (3) creating a tool with name given in quotes
{
        // Several parameter assignments for the plane wave go here.
        // Some parameters are required, some are optional.
}

new coulomb field solver 'coul' // (4) creating a module
{
        dipole center = ( 0.0 , 0.0 , 0.0 ) // (5) tuple assignment
        get 'pw1' // (6) attach the previously defined plane wave tool to this field solver
        new hermite gauss // (7) adding a tool in nested fashion
        {
                // several parameter assignments go here
        }
}

new plane wave 'pw2' for 'coul' // (8) simulataneously create and attach a tool
{
        // several parameter assignments go here
}

new species 'electrons'
{
        // several parameter assignments go here
}

generate uniform 'electrons' // (9) create a tool and attach to named module
{
        density = $dens // (10) using the C-style macro as a numerical constant
}

If you are familiar with C++ syntax you will recognize comments as preceded by //. The C-style /* and */ comment delimiters are supported also. Numbered highlights in the above example are as follows:

  1. C-style preprocessor macros are used to gain the effect of user defined constants. Numbers can be given physical units with a postfix.

  2. Simple assignment to a floating point parameter. Since no units are given, it is assumed in native units (usually normalized to plasma parameters).

  3. Creating a plane wave tool with the user assigned name ‘pw1’. This name can be used later in the input file.

  4. Creating a field solver module; modules do the high level management of data.

  5. Assignment to a tuple, in this case a spatial 3-vector. The strict syntax requires parenthesis, although the current parser ignores them.

  6. Attaching the previously defined plane wave to the field solver by name.

  7. Attaching a Hermite-Gauss wave tool to the field solver. Since the tool is nested inside the module, the association is established automatically. The user-assigned name is optional in this case.

  8. Create another plane wave tool and use the for keyword to attach it to the previously defined module.

  9. Create a uniform profile tool and associate with the species ‘electrons’. This illustrates the generate keyword, which is merely syntactic sugar that can be used in place of the new-for combination.

  10. The macro key $dens is used to achieve the effect of a user-defined constant.

A Little More Little Language

The input file is a sequence of directives. The directives are one of the following: preprocessor-directives, statements, or assignments.

Preprocessor directives are a subset of C language preprocessor directives. Preprocessor directives occupy a single line, while statements or assignments can be spread over any number of lines. Indentation is never significant.

Statements start with new, get, or generate. The new and generate statements are usually terminated by a curly-brace delimited block that may contain a further sequence of directives. Blocks of directives can be nested in this way with arbitrary depth.

Assignments copy a value in the input file to a simulation parameter. These values can be decimal numbers, physical quantities with units, or identifiers. Identifiers are used to select from choices, for example, periodic is an identifier corresponding to a boundary condition.

To allow for chemistry-friendly notation, identifiers are relaxed compared to other languages. In particular, ., [, ], +, and - are allowed. Thus, Ar[18+] and O2[+].H2O are valid little language identifiers.

There is a Tree-Sitter parser available for turboWAVE input files. For details see the tree-sitter-turbowave Node.js package. The strict language definition is the grammar.js file therein.

Input Preprocessor

The turboWAVE input file is run through a preprocessor. The features provided are as follows.

File Substitution

While preprocessing the input file, the contents of another file can be inserted. The format is similar to that used by the C preprocessor. For example,

#include "myfile.tw"

would substitute the contents of myfile.tw at the point in the file where the #include directive appears. This can be done recursively. The #include directive may appear anywhere in the input file, except where it would interrupt another directive.

The file can be specified using a path. If no path is given, the file should be in the working directory, or the directory of the input file. Using quotes is optional. The angle-brackets used in C for system headers have no meaning and should not be used.

Macro Substitution

The effect of user variables can be achieved via macro substitution. The format is the same as that used by the C preprocessor. For example,

#define $r0 2.5 [cm]

causes every occurrence of $r0 to be replaced with 2.5 [cm]. The substitution value is terminated by a new line. The use of the $ prefix is optional, but highly recommended, as it helps prevent unintended substitutions, and improves readability (including syntax highlights in supported editors).

The keys are matched only to whole words, i.e. $r would not match $r0. You can use macros within other macros, e.g.

#define $r ( $r0 , $r0 )

would be expanded as ( 2.5 [cm] , 2.5 [cm] ) assuming $r0 is defined as above. Macros can be defined at any point in an input file, except where they would interrupt another directive. Unlike C, macros are scoped by file, and redefinition in the same scope throws an error.

Function-like macros are not supported. Line continuation using \ is not allowed, as of this writing.

Conditional Blocks

You can use #define constants to control the inclusion of blocks of code. This works the same as in C. For example,

#define $3D
#ifdef $3D
        #define $cells ( 128 , 128 , 128 )
        // ... other settings sensitive to dimensionality
#else
        #define $cells ( 128 , 1 , 128 )
        // ... other settings sensitive to dimensionality
#endif

allows the user to select from two or three dimensional settings by changing one constant. TurboWAVE supports #ifdef, #ifndef, #else, and #endif. Value comparisons using #if or #elif are not supported at present.

Specifying Units

When a number is given without dimensions, it is assumed to be in native units. As of this writing, native units must be set globally (see Top Level Directives). Dimensional numbers can be specified using the form n u, where n is a number and u is a string identifying the unit. An example is 10 [ps], which means 10 picoseconds. White space between the number and unit is optional. Supported units and identifier string are:

Unit Specifiers.

Quantity

Identifier

Dimension

Spatiotemporal Category

Femtoseconds

[fs]

Time

Picoseconds

[ps]

Time

Nanoseconds

[ns]

Time

Microseconds

[us]

Time

Seconds

[s]

Time

Micrometers

[um]

Length

Millimeters

[mm]

Length

Centimeters

[cm]

Length

Meters

[m]

Length

Degrees

[deg]

Angle

Radians

[rad]

Angle

Milliradians

[mrad]

Angle

Microradians

[urad]

Angle

Thermodynamics Category

Particles per Cubic Meter

[/m3]

Density

Particles per Cubic Centimeter

[/cm3]

Density

Kilograms per Cubic Meter

[kg/m3]

Mass Density

Grams per Cubic Centimeter

[g/cm3]

Mass Density

Joules per Cubic Meter

[J/m3]

Energy Density

Joules per Cubic Centimeter

[J/cm3]

Energy Density

Electron Volts

[eV]

Temperature

Kelvin

[K]

Temperature

Pascals

[Pa]

Pressure

Dynes per Square Centimeter

[dynes/cm2]

Pressure

Bars

[bar]

Pressure

Ergs per Gram

[ergs/g]

Specific Energy

Joules per Kilogram

[J/kg]

Specific Energy

Transport Category

Centimeters Squared

[cm2]

Cross Section

Meters Squared

[m2]

Cross section

Centimeters Squared per Second

[cm2/s]

Diffusivity

Meters Squared per Second

[m2/s]

Diffusivity

Electrodynamics Category

Volts

[V]

Scalar Potential

Webers per Meter

[webers/m]

Vector Potential

Gauss Centimeters

[G*cm]

Vector Potential

Volts per Meter

[V/m]

Electric Field

Volts per Centimeter

[V/cm]

Electric Field

Tesla

[T]

Magnetic Field

Gauss

[G]

Magnetic Field

Top Level Directives

Top level directives may include statements to create modules or tools, as well as assignments to parameters that are associated with the root Simulation object. The Simulation parameter assignments are as follows.

native units = nu
Parameters:

nu (str) – the system of units native to the input file, can be mks, cgs, plasma, atomic, or natural. Modules are allowed to veto the choice of native units by throwing an error. As of this writing, most modules will veto any choice other than plasma.

unit density = CGS_density

Select the density that fixes the plasma normalization to a particular scale.

Parameters:

CGS_density (float) – the density in particles per cubic centimeter. Dimensional numbers must not be used.

dtmin = dtm
Parameters:

dtm (float) – if adaptive timestep in use, don’t let it become less than this

dtmax = dtx
Parameters:

dtx (float) – if adaptive timestep in use, don’t let it become greater than this

dtcrit = dtc
Parameters:

dtc (float) – if adaptive timestep falls below this value, switch to a fixed timestep. The fixed timestep is taken from the timestep directive.

maxtime = tm
Parameters:

tm (float) – stop simulation after this much simulated time (useful with adaptive timestep)

neutralize = n
Parameters:

n (bool) – if yes, this causes an equal and opposite fixed charge to be added to the grid for every particle created.

window speed = v
Parameters:

v (float) – If moving window = yes, speed that lab frame quantities move back. If moving window = no, speed that light frame quantities move forward.

moving window = mv
Parameters:

mv (bool) – Whether or not to move the lab frame quantities backward at the window speed. If no, light frame quantities are moved forward at the window speed.

dump period = dp
Parameters:

dp (int) – Write out checkpoint data every dp steps. If zero do not save any checkpoints.

xboundary = ( b1 , b2 )

Boundary conditions for whole simulation at the extremities in the x-coordinate. Can be overridden by individual modules. Parameters take values absorbing, periodic, emitting, reflecting, axisymmetric, ejecting.

Parameters:
  • b1 (enum) – Boundary condition of the low side.

  • b2 (enum) – Boundary condition on the high side.

yboundary = ( b1 , b2 )

Boundary conditions for whole simulation at the extremities in the y-coordinate, see xboundary.

zboundary = ( b1 , b2 )

Boundary conditions for whole simulation at the extremities in the z-coordinate, see xboundary.

Object Creation

Objects (modules and tools) can be created using the following syntax:

new <key1> [<key2> <key3> ...] [<name>] [for <name>] { <directives> }
generate <key1> [<key2> <key3> ...] [for] <name> { <directives> }

Each form has a preamble followed by a curly-brace delimited block. The start of the preamble is signaled by a keyword, either new or generate. The next several words are ordered keys. The keys are used to identify the type of object requested. The user is free to add any number of trailing keys. In the first form, the first optional name is the user-defined name of the new object, and the second is the name of a previously defined parent object. Giving a parent object is optional.

The second form allows the new object to be associated with a parent object without using the for keyword. This can be more suggestive in some cases, e.g., generate uniform 'electrons' is perhaps more suggestive than new uniform 'profile' for 'electrons'.

When optional names are not given, the turboWAVE parser will automatically choose a unique name for the object.

Quoting user assigned names is not required, but helps with readability, particularly if syntax highlights are used. Quoting chemical names in SPARC reactions and collisions is discouraged due to the potential for high multiplicity.

Objects which may have a high multiplicity use a more compact form with ordered directives. The form is typically

new <key1> [<key2> <key3> ...] = <directives>

In this case the directives are all required and must be in the right order.

Associating Objects

Objects may be related by a containment hierarchy. There are three ways to express this.

Nested Declarations

To use nested declarations, simply create the new object using the new command from within the directives block of the higher level object:

new direct field solver 'em'
{
        new hermite gauss 'HG00'
        {
                // fill in directives defining the mode
        }
}

Pre-declaration

To use a predeclaration, create a named low level object. Then add it to a higher level object with a directive:

new hermite gauss 'HG00'
{
        // fill in directives defining the mode
}
new direct field solver 'em'
{
        get 'HG00'
}

Post-declaration

To use a post-declaration first create the high level object, then use one of the two associative forms of object creation:

new species 'ions'
{
        // fill in directives defining the species
}
generate uniform 'ions' // creates an anonymous profile for 'ions'
{
        // fill in directives defining the profile
}

Numerical Grid

TurboWAVE uses only structured grids, at present. Some of the effect of unstructured grids can be obtained by using grid warps.

TurboWAVE axes are labeled as t, x, y, or z regardless of coordinate system. Index-wise these are mapped as t=0, x=1, y=2, and z=3. In cylindrical coordinates, x is radial, y is azimuthal, and z is axial. In spherical coordinates, x is radial, y is azimuthal, and z is polar.

new grid { directives }

There must be exactly one grid block, which defines the numerical grid for all modules.

Parameters:

directives (block) –

The following directives are supported:

geometry = g
Parameters:

g (enum) – can be cartesian, cylindrical, spherical.

origin = ( tfrac, xfrac, yfrac, zfrac )

Position of the origin relative to the simulation box

Parameters:
  • tfrac (float) – t origin relative to simulation duration, 0 = beginning, 1 = end

  • xfrac (float) – x origin relative to x size of box, 0 = low side, 1 = high side

  • yfrac (float) – y origin relative to y size of box, 0 = low side, 1 = high side

  • zfrac (float) – z origin relative to z size of box, 0 = low side, 1 = high side

shift = ( t0, x0, y0, z0 )

Translate the box in the given units

Parameters:
  • t0 (float) – shift in t

  • x0 (float) – shift in x

  • y0 (float) – shift in y

  • z0 (float) – shift in z

dimensions = ( Nt, Nx, Ny, Nz )

Dimensions of the grid in numbers of cells

Parameters:
  • Nt (int) – time levels

  • Nx (int) – cells along the first coordinate

  • Ny (int) – cells along the second coordinate

  • Nz (int) – cells along the third coordinate

cell size = ( dt, dx, dy, dz )

The cell size is given in parameter space, i.e., it could be an arc length or an angular sweep.

Parameters:
  • dt (float) – time step

  • dx (float) – length of cell edge along first coordinate

  • dy (float) – length of cell edge along second coordinate

  • dz (float) – length of cell edge along third coordinate

decomposition = ( Dt, Dx, Dy, Dz )

Number of cuts of the domain along each coordinate. This determines how the domain is split across parallel tasks. The number of MPI tasks should be set to the product of all three parameters.

Parameters:
  • Dx (int) – cuts along the first coordinate

  • Dy (int) – cuts along the second coordinate

  • Dz (int) – cuts along the third coordinate

adaptive timestep = at
Parameters:

at (bool) – whether or not to use an adaptive time stepping scheme.

Grid Warps

Grid warps allow the user to ramp the cell size up or down, along a given axis, and through a given range of cell indices. Any number of grid warps can be declared as follows:

new warp { <directives> }

Ramp the cell sizes along a given axis through the given range of cell indices. The form of the ramp is a quintic polynomial that can be matched to either a constant or another quintic polynomial, such that the overall function is {\cal C}^2 continuous.

Parameters:

directives (block) –

The following directives are supported:

axis = ax
Parameters:

ax (enum) – The axis along which to create the warp, one of x, y, or z. As usual these are merely labels for whatever coordinate system is in use.

increasing = inc
Parameters:

inc (bool) – If affirmative, the cell size increases with increasing coordinate, otherwise the cell size decreases.

index range = ( i0 , i1 )
Parameters:
  • i0 (int) – cell index where the ramp begins

  • i1 (int) – cell index where the ramp ends

length = L
Parameters:

L (float) – the length of the ramp