The Beatbox Cardiac Simulation Software: A User's Guide


Table of Contents


Introduction

Beatbox is a program that could be compiled for sequential or parallel (MPI) use. Currently it has a small collection of cell models, including FitzHugh-Nagumo, Luo-Rudy I, Courtemanche et al. human atrial (this list will be expanding) and solves reaction diffusion equations with these cell models to simulate wave propagation in idealised and realistic cardiac tissue models. Currently the solvers use finite differencing with regular spatial grid and forward Euler in time with or without operator splitting. Some semi-implicit solvers are now in test exploitation and bidomain solvers are under development.

Figure 1: Conceptual view of a ring of devices.
Conceputal view of a ring of devices.

A special feature of Beatbox is its flexibility in setting various experimental protocols, without the need to recompile the package. A simulation is set up by constructing an input script that spatial model (1D, 2D, box, or geometry) details, and "devices", which perform computations, input/output, and control functions. The simulation script is typically called filename.bbs, where the conventional extension bbs stands for "beatbox script", and filename can be anything you like. The "devices" are chained together in a ring, with an integer counter t, usually corresponding to the time steps in the simulation. The concept of the ring of devices is illustrated in Figure 1. In this example,

k_func
(the first instance) works as a control device that defines when other devices will be active: the second k_func at the start of the computations, ppmout every so often, and stop in the end.
k_func
(the second instance) works as a computational device defining the initial conditions,
diff
is a computational device that performs diffusion substep in the operator-splitting time step,
euler
... performs reaction substep in the operator-splitting time step,
ppmout
is an output device that writes rounded-up simulation results to the disk for subsequent visualization,
stop
is a control device that terminates the run.

Each device has a set of parameters, specific for it, e.g. the list of parameters for k_func is different from that for diff (but there are some "universal" and some "typical" parameters, such as their control variables or the mesh domain on which the device operates). A simulation run can use more than one instance of the given device, each of which may appear anywhere in the ring; in this example k_func has two instances appearing one after the other. All instances of the same device will have the same list of parameters, but the values of parameters are set completely indepently in different instances.

The function of the input script is to define the computational grid and to describe all the devices for the given run together with their parameters.

A simulation will thus typically involve:

  1. The input script being read and the simulation initialised:
    • The simulation grid is created with the specified dimensions, and if realistic geometry is used, then the relevant subset of the simulation grid and the diffusion tensor field are defined,
    • Devices are added to the ring of devices with the specified parameters.
  2. The simulation is run:
    • Each device in the ring is called in turn to perform its part of the simulation task, provided it is commanded to be active at this step by the control device(s),
    • Repeat until the stop condition is met, or an error occurs.
  3. The simulation is terminated.

In this distribution, there are some example scripts provided, which illustrate the format of the input scripts and use of the devices. A more formal description of the bbs script language and of the devices available follow below. A certain stage of Beatbox development is reflected in Ross McFarlane, High-Performance Computing for Computational Biology of the Heart, PhD Dissertation, October 2010, see Chapters 2 and 3 in particular.

Setting-up Beatbox

Prerequisites

The developers tried to make Beatbox self-contained and reduce the number of dependencies to an absolute minimum. You will require:

Getting Beatbox

The recommended way to obtain BeatBox is to download the most recent official release from the BeatBox home page,

An alternative which may be more appropriate for beta-testers, is to obtain the most recent version of BeatBox code from its SVN repository, say by issuing the following commands:

mkdir ~/beatbox
cd ~/beatbox
svn co --username=anonymous --password=beatbox https://beatbox-trac.epcc.ed.ac.uk/svn/trunk/ ./

Note that this will be a read-only copy of the repository, i.e. you will not be able to check any modifications back in. If you would like to become a developer please get in touch with the project team.

Installation instructions

Compiling and installing Beatbox

Assuming that all the components mentioned above are available and in place, the following sequence of commannds

autoreconf -fi
export CC=mpicc
./configure CFLAGS="-g -O0" --prefix=$HOME
make
make install

will compile two versions of the program, Beatbox (parallel) and Beatbox_SEQ (sequential), and install them in $HOME/bin/. A shell script bbx_compile_local.sh is provided in the root distribution directory, to facilitate the installation.

You may wish to change the install location specified in this file: current setting --prefix=$HOME means that the binaries will be installed in $HOME/bin/. This is reasonable in the assumption that that directory exists and is in your $PATH; modify it as appropriate if you prefer to keep your binaries elsewhere.

The options CFLAGS="-g -O0" mean that the code will be prepared for debugging and not optimized; for "production runs" this can be omitted and replaced by CFLAGS="-O3".

If the script, configure or Makefile cannot find the include and library files, the paths may have to be explicitly incorporated into src/Makefile.am and then go through the whole procedure starting from the autoreconf -fi step.

Compiling and installing Beatbox on HECToR

HECToR (www.hector.ac.uk) is the national UK supercomputer service. HECToR is a Cray XE6 based system. In order to install on HECToR, we need to cross compile for back end nodes and make correct settings, so the process is a little bit different (script bbx_compile_hector.sh):

# Create the configure and install scripts
autoreconf -fi

# Load the PGI compiler module
module load pgi

# Tell the configure command what compiler we need to use.
export CC=cc

# Need to explicitly tell the Cray system what X libraries to use
export LIBS="-lm -lX11 -lxcb -lxcb-xlib -ldl -lXau"

# Run configure - note that it will install in $HOME/bin
./configure --prefix=$HOME

# Now make the code
make

# Install the code to the directories specified by the prefix above.
make install

Again, change the prefix flag if you would like it to install elsewhere.

Running Beatbox

General Instructions

The sequential version of the program may be run by using:

   Beatbox_SEQ [<options>] [--] <input_script> [<arguments> | <options> | -- ]

That is: the executable name (with the full path if necessary), followed by the input script and the arguments, if any, with options interpspersed anywhere after the executable name. Similar to many Unix programs, options are those words that start with a minus '-', but a double minus '--' signals an end of all options so a word starting with - after that is interpreted as input script name or argument.

Correspondingly, assuming that you have mpich2, the parallel version on a local computer may be run using

   mpirun -np <num_procs> Beatbox [<options>] [--] <input_script> [<arguments> | <options> | -- ]

The parsing of the input script and the simulations are commented by printing messages to the standard output and duplicating them into a log file.

The possible options are:

CAVEAT: options -debug, -log and -decomp gobble the next word for the name of the debug or log file; failure to appreciate that is a common error leading to weird behaviour. This should be addressed one day, perhaps by making them like -debug=<filename> instead.

The arguments can be used in the input script, where they appear as pre-defined string macros, see below. The parsing is usual for the unix shells, that is each word makes a separate argument, except when quotes are used.

Beatbox on HECToR

This subsection gives a brief description on how to conduct simulations on HECToR or a similar HPC facility. Before starting any simulations, a certain familiarity with HECToR architecture, compilers, modules, and general terms of usage can be gained from the HECToR User Guide.

On HECToR compilation is done through a set of compilation wrappers, cc will always correspond to the actual compilation suite being used. The default version is for the Cray compilers. Other compiler suites may be used (by loading and unloading the appropriate modules), but will still use the same wrapper. The compilation is done for the work nodes - thus we are cross compiling.

HECToR manages production as well as (parallel and serial) debugging runs by using the PBSpro queuing system. A PBS script consists of a set of PBS commands, and other generic shell commands. A sample PBS script that can be used to run Beatbox jobs is shown below. The commands are explained in the comments (text following a ## on any line) - a line that starts with #PBS denotes a PBS command. The following script was used to run the 3D atrium simulation and is called Beatboxrun64.sh. Its contents are:

#!/bin/bash --login

## A PBS command starts with #PBS.
## Start by specifying a name for the job.

#PBS -N Beatbox64

## Specify number of cores requested.

#PBS -l mppwidth=64

## Hector is composed of "nodes", each of which consist of 
## two 16 cores processors - thus one has 32 cores available in a node.
## The number of cores per node controls memory available to the job.
## Use of all cores in a node (assuming mppwidth is more than 32) 
## optimises the use AU charged to your account. 

#PBS -l mppnppn=32

## This is the amount of time requested for the simulation.

#PBS -l walltime=3:00:00

## A project code has to be provided, otherwise the job is usually
## not accepted by a queue.

#PBS -A e203

## Assume this PBS script lies in the same directory as the executable
## file. Note to be seen by the back end nodes this must lie in one of
## the work directories. Change directories to where the job was launched.
## You must make sure that you copied the Beatbox executable, the 
## humanAtrium.bbs and humanAtrium.bbg scripts to this directory for this
## to work.
cd $PBS_O_WORKDIR

## Run the job
## n is the total number of processes
## N is the number of processes per node
## Launch the parallel job using aprun. The stdout is called 
## Beatbox64.o_job_number, and stderr is called Beatbox64.e_job_number
aprun -n 64 -N 32 ./Beatbox humanAtrium_start_crn.bbs

Before submitting any job using such a submission script, it may be worthwhile to run a check on the script using the HECToR provided checkScript:

   checkScript Beatbox64.sh

This will indicate if there are any errors in the script so you can fix these before you submit it to the PBS system. The production job is then submitted to a parallel queue using:

  qsub Beatbox64.sh

Further options are also available, and can be seen in the user guide. Similarly to production, parallel debugging jobs must also be submitted to the queue with the following command added:

#PBS -v DISPLAY

and the appropriate debugger binary name preceding the aprun. For example, the TotalView parallel debugger can be invoked by:

  totalview aprun -a -b -a xt -n 64 -N 32 /work/.../myprog.x 

The detailed submission script for debugging jobs can be found on the relevant HECToR pages.

The status of submitted jobs can be checked using the command:

  qstat -u your_hector_user_name

and the job is deleted using:

  qdel job_number

Beatbox Scripting Guide

A Beatbox simulation is defined by the user in the form of an input script ("Beatbox script" or "bbs script"). A script is a plain text file that specifies the computational grid, the devices that are to be used to do the calculations and input/output, and their parameters. Any script should be able to run on any of Beatbox’s supported hardware platforms; if a sequential-only device is used in a script submitted to parallel execution, the warning message will be output but the script will run nonetheless.

This section introduces Beatbox scripts by first describing the scripting language, before discussing common applications. Unlike interpreted scripting languages such as PHP or Python, Beatbox scripts are not run during the simulation. The script is read once to build the simulation, after which the script code does no longer define the flow of execution, so can be modified or removed with no consequences for the current run.

Similar to other programming languages, Beatbox scripts allow the user to define variables and macros, include external code and make calls to the operating system. The Beatbox scripting language also provides a small library of arithmetic and logical functions. The user may also improve the legibility of their code, or disable portions of the code using comments. Each of these features is discussed below.

For the impatient

If you prefer to learn by example rather than go through formal definitions, you may wish to try and jump ahead to a simple working example and then only if and when necessary go back to check out those formal definitions, or go forward to further, more sophisticated examples.

The Data

Any Beatbox run operates with two sorts of data. One is the computational grid, which is effectively a four-dimensional array of real numbers (of the precision specified at compile time), which is the object of operation of the computational devices. The four dimensions are the three spatial dimensions x,y,z and the "component" dimension v. Slices in the component dimension are called "layers".

Associated with the computational grid could be the geometry array (if complex geometry option is on), which has the same shape as the main grid, and determines which points in it belong to the computational domain and which are "void", and (if anisotropy option is on) contains information about fiber directions.

The other are the arithmetic variables and string macros. The arithmetic variables can be integer or real (with the precision defined at compile time), their names following C convention. The input script interpreter contains a built-in interpreter of arithmetic experession, so parameters of a device can be specified as arithmetic expressions (possibly depending on arithmetic variables) rather than specific values. The script is interpreted from top to bottom, so any arithmetic variable will exist and have a valid value of it was defined and assigned the value above the point at which it is used. The exceptions are the pre-defined variables, such as integer t containing the counter of the device ring loop, and real pi containing the number pi.

The string macros have the form of a string of characters between [ and ]. The strings of characers making the names of the macros also have to obey the C rules. The exception is string macros [1], [2], [3] ..., which cannot be defined within the script, and which contain the values of the command line arguments (see above). There some more pre-defined string macros, e.g. names of colours used in graphical devices. The values of ordinary string macros are assigned at the moment of their definition. Whenever they are used in the script, their values are simply substituted in place of [...] and the result is interpreted as if it was part of the script all along. A string macro may appear e.g. in the expression defining the value of an arithmetic variable, which is one way to convert string macro to an arithmetic expression.

In the parallel version, the computational grid (and the geometry array) are split between the thread: if a particular value belongs to one subdomain it is not accessible to another subdomain (with the exception of halo points, see below). On the contrary, any arithmetic variable or string macro is available in all threads; however depending on its use, they may have different values in different threads.

Need to doublecheck the actual syntatic restrictions on variable and string macro names and bring the code and this manual in correspondence with each other.

The Beatbox Scripting Language

After preprocessing (see below), a Beatbox script consists of a series of commands. A command is a sequence of characters (being part of one line of script or spanning across several lines), beginning with a recognised keyword and ending with a semicolon ';'. The following code excerpt shows examples of three commands:

def int sideLength 26; state xmax=sideLength, ymax=sideLength, zmax=sideLength, vmax=3;
euler
v1=[iext]
ode=lrd
par={ht=ht IV=@24}
;

This script defines sideLength which is the used initialise the state of the system before the euler device is called.

The types of command in a Beatbox script are listed below. Each command describes an action to be taken by Beatbox, with the keyword at the beginning of the command being the verb.

Preprocessing

As each line of the script is parsed, Beatbox preprocesses the code in a manner similar to the C Preprocessor [see Kernighan and Ritchie, 1988, chap. 4]. The Beatbox preprocessor handles four tasks:

  1. skipping comments,
  2. including other Beatbox scripts,
  3. calling system commands and
  4. expanding string macros.

Each of these are discussed below.

Comments

Comments can be added to Beatbox scripts in five ways:


  1. /*
     Multi-line C style comment
    */
    

  2. // Single-line C++ style comment
    

  3. rem ’Remark’ command-style comment , which must end with a semicolon;
    
  4. anything added after an end command,
  5. anything within the body of any command which is not recognized as a valid name=value pair.

MAA: The last type of comment is not clear to me. An example might help.

Text in a comment is ignored by the parser, except undefined macros will cause fatal errors within a body of a rem or another command.

Including Other Beatbox Scripts

Where the relative path to a Beatbox script file is enclosed in in angle brackets (< >), the content of the referenced file will be read and inserted at that location. Unlike in the C programming language, the name of the file in angle brackets is not preceded by an #include command. This can be used to maintain consistency across a number of simulations, or to reduce code redundancy. Beatbox replaces a filename in angle brackets with the file’s entire contents. For example, given a script called useful.bbs:

Listing G.1: Script stored in a useful.bbs script file.
// Here is a lot of useful code...
def real apar=1;
def real bpar=2;

and a script that includes useful.bbs as follows:

Listing G.2: Another script that includes useful.bbs.
// This is my own script
<useful.bbs>
// Here’s some more of my own code.
def real cpar=3;

The result, after preprocessing, is as shown below:

Listing G.3: Effective resultant script, after useful.bbs has been included and comments eliminated.
def real apar=1;
def real bpar=2;
def real cpar=3;

Calling System Commands

Beatbox replaces code in backticks (`...`) with the result of that code when run as a system command, via a system() call (stdlib.h). For example:

   `date '+%Y%m%d-%H:%M:%S'`

will be replaced with the result of the UNIX date command:

   20120710-09:30:55

Expanding String Macros

String macros allow the user to define reusable strings that can be pasted throughout a script. String macros are distinct from variables in that they are expanded once, prior to the script being interpreted and cannot therefore be assigned values other than when they are defined. A string macro is defined as follows:

def str <macro name> <value>;

where <macro name> is a string using letters, numbers, underscores (_) or hyphens (-) and <value> is any string not including a semicolon.

Need to doublecheck the actual syntatic restrictions on variable and string macro names and bring the code and this manual in correspondence with each other.

After a macro is defined, its name, wrapped in square brackets ( [ ] ) is associated with its value. When Beatbox input script parser finds a macro’s name in square brackets, it replaces them with the value.

In the following excerpt, the variable hat is assigned the value porkpie. The variable headware is assigned the value hat.

def str snack porkpie; // Assigned string ’porkpie’.
def str hat [snack];   // Assigned string ’porkpie’.
def str headware hat;  // Assigned string ’hat’, not value of hat macro.

A macro can expand to anything that could be typed in the script. For example, a string macro can be used in place of an int, long or real:

def str ninetynine 99;       // Assigned string value ’99’.
def int number [ninetynine]; // Assigned integer value 99.

A number variable cannot, however, be used to define a macro:

def int number 99;         // Assigned integer value 99.
def str ninetynine number; // Assigned string value ’number’.

It is possible to assign several lines of code (excluding semicolons) to a string macro, so this:

def str instruction ppmout
when=out file="ppm/%04d.ppm" mode="w"
r=[u] r0=umin r1=umax
g=[v] g0=vmin g1=vmax
b=[i] b0=0 b1=255;
[instruction];

is equivalent to:

ppmout 
when=out file="ppm/%04d.ppm" mode="w"
r=[u] r0=umin r1=umax
g=[v] g0=vmin g1=vmax
b=[i] b0=0 b1=255;

Defining Arithmetic Variables with the def Command

Arithmetic variables defined in the script are distinct from the C language variables used in Beatbox’s implementation. For clarity, variables defined in the script, using def may be referred to as "k-variables".

A k-variable is defined using the def command, like this:

def <type> <name> [=] <value>;

where <type> is one of:

so k-variables and arithmetic expressions only have two data types, real and integer, and their actual precision (int or long int, float or double) is determined at the compile time by the settings in k_.h; typically long and double respectively.

A <variable name> can consist of letters, numbers, underscores (_) or hyphens (-).

Variables defined in this way are accessible in the script during the input script parsing, as well as at run-time by some devices, e.g. k_func.

The <value> (optional) is an expression that may be evaluated to the correct type and is assigned as the initial value of the variable just defined. Expressions are discussed in greater detail below. If no initial value is given, the variable is assigned the initial value of 0 or 0.0 as appropriate.

Beatbox stores the names of macros wrapped in their square brackets ([...]), therefore it is possible for a script to define macros and variables with the same name.

Predefined k-variables and string macros

Some variables and macros exist without being defined in the input script. All of them are read-only, i.e. cannot be modified in the input script. These are: Apart from these, some devices have their own predefined variables with the scope restricted to the body of that device.

Expressions

Any numerical value in a Beatbox script, be it initial value in a variable definition or the value of a device parameter, may be specified as a mathematical expression. An expression may be a literal value, such as 5.0, or the result of some computation, such as 6*5 or count/2.

Beatbox expressions can use the standard infix arithmetic operators: addition (+), subtraction (-), multiplication (*), division (/) and exponentiation (** or ^), as well unary plus and minus. For more complex operations Beatbox provides a collection of functions:

The last three functions are not thread-safe or would be too communicationally expensive to implement in the parallel mode, so are only allowed in the sequential mode.

The arithmetic operators distinguish between real and integer numbers, so 5/2 produces 2 while 5.0/2.0 gives 2.5. The usual type casting rules apply, e.g. sum of a real and an integer is a real, etc. All functions take real arguments and return real values. Calling a function with a wrong number of arguments is an error. The built-in "k-compiler" of arithmetic expressions is not optimizing, and any intellectual work is expected to be done by the user. E.g. calling function with an integer argument, say 0, will generate the conversion of the integer 0 into the real 0.0 in the compiled code; where as putting 0.0 as the argument will not require that so will generate a slightly shorter and more efficient "k-executable".

Briefly about Device-Defining Commands

The simplified syntax of a device-defining command is

<device> [<name>=<value> [...]] ;

The <name>=<value> pairs define the device parameters and are separated from each other by spaces (including '\t', '\b', '\r' and '\n' characters). Each device has its own set of parameters, whose names will be checked for in the body of the command. The pairs <name>=<value> with parameter names not known to the given device, or something that is not a <name>=<value> pair, are silently ignored. If there is more than one <name>=<value> pair with the same name, only the first occurrence matters and the rest is/are ignored. If no <name>=<value> pair corresponding to a parameter is found, the default value is assigned, or an error message is output and parsing terminates if there is no default value for this parameter.

The parameters could be arithmetic, string, or blocks.

For the arithmetic parameters, which could be any valid arithmetic C type, the <value> is taken as the string of characters after the = sign until the first blank character, is intepreted as an arithmetic expression, it is evaluated to the appropriate k-type (integer or real), cast to the required C type, and assigned to the parameter. A parameter in a device may have a default value and maximal and minimal allowed values. If a calculated value goes beyond the prescribed limits, and error message is printed and parsing is terminated.

For the string parameters, the value (subject to preprocessing) is intepreted as the literal value of the parameter. A string containing blank spaces or one of the special characters \n, \b, \f, \t, \r, \a and \0 can be used as a value by enclosing it in double quotes "...". Any other character within the double quotes, preceded by the backslash \ (including the double quote and the backslash itself) evaluates to that character. String parameters may have default values, but obviosuly not minimal or maximal values.

The block parameters expect the values in the form of text enclosed by curly brackets, {...}. Such block text may span several lines of the script and will usually contain its own set of <name>=<value> pairs. There are no defaults for block parameters, i.e. they are always compulsory.

Defining the Computational Grid with the state Command

General description

The first functional task of a script is to define the mesh. The mesh is stored as a four-dimensional array, corresponding to a three-dimensional, regular Cartesian mesh with an array of dynamic variables at each point. Dynamic variables hold space-dependent values, local to each point in the mesh. The majority of dynamic variables are commonly employed to hold variables of the cell model. The dimensions of the mesh and number of dynamic variables (i.e. the size of the four-dimensional array) are set using the state command.

The syntax of the state command is the same as that of a device-defining command, only it does not add any devices into the device ring.

The required set of parameters depends on whether geometry file is used, which is determined by the string parameter geometry. If this parameter is assigned to a non-empty string, then it is understood to be the name of the geometry file. This case is described in more detail below.

If parameter geometry is absent or is assigned to an empty string, no geometry file is read, the computations are done in a parallelepiped, and its sizes xmax, ymax (compulsory) and zmax (optional, default=1) will be checked for. Parameter vmax is still required.

The integer coordinates (index) x runs from 0 through to xmax-1 (so the name xmax is a bit of a misnomer, but stuck for historical reasons). If zmax≥3, the calculations will be three-dimensional (3D). Otherwise, if ymax≥3, the calculations will be two-dimensional (2D). Otherwise, if xmax≥3, the calculations will be one-dimensional (1D). Otherwise, it is zero-dimensional case (0D), that is, no spatial extent (ODE model). At least three points in a particular direction are needed to make that direction "extended", because in that case the marginal values of the coordinates need to be kept free, for technical reasons related to implementation of boundary conditions. The cases of xmax=2 etc are syntactically allowed but hardly ever used in practice.

In any case, parameter vmax is accepted. It is optional and defaults to 2 (a tribute to the FitzHugh-Nagumo model). It defines the number of dynamic variables per node of the computational grid, i.e. the number of computational layers. Note that this number may and ofter is larger that the number of equations in the model, as extra layers may be required as working arrays for computational purposes (more detail below).

The mesh defined in the example below has 300 points along the x-axis and 400 points along the y-axis. Since zmax is equal to 1, there is one point along the z-axis, making the medium flat on the xy-plane. The variable vmax specifies the number of dynamic variables stored at every point in the mesh.

Listing G.4: Defining a two-dimensional mesh with the state command.
state xmax=300 ymax=400 zmax=1 vmax=3;

Beatbox assumes that the simulation medium will follow a hierarchy of axes; x before y before z, i.e. one-dimensional simulations must use the x-axis and two-dimensional simulations must use the x and y axes.

Any Beatbox input script must contain exactly one state command, and it should precede any device-defining commands.

Anatomically Realistic Tissue Geometry

If you would like to use an anatomically realistic mesh for your simulation, you can specify it in the geometry parameter of the state module. For example, geometry=ffr.bbg will select the ffr.bbg geometry file.

When using a geometry file, there is no need to specify the dimensions of the mesh, in fact Beatbox will complain if you do. You do still need to define vmax, however, to suit your chosen RHS module and any other dynamic variables your simulation needs. Beatbox will also complain if the fibre directions specified in your geometry file are not unit vectors. If you like, Beatbox will normalise the fibre directions for you, if you set the normaliseVectors parameter to 1. If you would like to model anisotropy, set the ansiotropy parameter to 1. This only works when a geometry is specified. When the anisotropy=1, the behaviour and required parameters of some devices may change. In particular, the diff device, performing the diffusion substep, will require two diffusion coefficients, Dpar and Dtrans for the diffusivity along and across the fibres, instead of the isotropic D.

Geometry File Format

The Beatbox geometry file will typically have the extension .bbg and is a plain text file, each line of which describes a point belonging to the tissue. Any such line will have four numbers or seven numbers: integers for x, y and z coordinates of a node and its tissue type, and three reals for the fibre orientation data. The de-facto limits of the x-, y- and z-components of all points in the file will be used to define the circumscribed box. The file does not have to describe every point in the box; the points that are not mentioned will simply be assumed to belong to the void. A zero tissue type designates the void, so such lines can be omitted without any loss of information. The three reals of the fibre orientation data for any nonzero tissue type will be the directional cosines of the fibres. If no true fibre data are available in the source of the geometry, and/or no anisotropy is used in simulations, then any triple can be put as the fibre orientation data, say 1,0,0.

More about Device-Definining Commands

Following the state declaration, a script can add to the ring of devices by invoking or ‘calling’ Beatbox devices. A device call takes the form of the device name, followed by parameters as key-value pairs, separated by spaces. The excerpt below shows the euler device being called with some parameters.

euler v1=[iext] ht=ht ode=lrd pars={IV=@24} name=Geoff;

Each device call will add an instance of the device to the ring of devices. It is possible to instantiate the same device, e.g. euler, multiple times and the parameters of each instance will remain independent. The different instances can be distinguished from each other (say, in the debugging or profiling listings) by the values of their optional name parameter, "Geoff" in the above example.

Assigning Device Parameters

Device parameters are assigned following the device name as key-value pairs with the syntax <key>=<value>. Since spaces separate device parameters, an str parameter value that includes spaces, should be enclosed in quotes (" "). Expressions assigned to int, long and real parameters will be reduced to literal values when read. An example is shown in Listing G.5.

Some devices may request parameters formatted as a codestring or a block.

Example uses of a codestring and a block are shown below.

Listing G.5 shows the assignment of a parameter, bar to an imaginary foo device. Although the value of hat may change throughout the simulation, the value of the bar parameter will be set only once, when the device is called. In this case, bar will be assigned the value 40.

Listing G.5: Assigning a device parameter.
def real hat 10.0;
foo bar = min(hat ,60)*4;

Listing G.6 illustrate usage of block parameters in real devices k_func and euler. device.

Listing G.6: Assigning block parameters to the k_func and euler devices.
k_func nowhere=1 pgm={
    stim = eq(t,stimTime);
};
def int neqn 24;
def str iext neqn;
euler v0=0 v1=neqn-1 ht=ht ode=crn par={ht=ht, IV=@[iext]};

In the k_func, the block parameter pgm is assigned the string enclosed between the {...} brackets. This will be compiled and result in a k-executable, which will be stored among other internal parameters of this instance of k_func device for future use. Then at each time step (but only once per thread, as defined by the nowhere=1 parameter), this k-executable will be evaluated using the then current, run-time values of k-variables t and stimTime, and the result will be assigned to the k-variable stim.

In euler, parameter ode, which is a string defining the kinetic model used by the forward Euler timestepper, is assigned crn which stands for the Courtemanche-Ramirez-Nattel 1998 human atrial model. It uses layers from 0 through to neqn-1=23 so k-variable neqn must be equal to the number of dynamic variables in the model (24), at the parsing time, otherwise program will stop with an error message. Parameter ht, which designates the time step of the forward Euler scheme, will be assigned to the current (parse-time) value of the k-variable ht. Parameter par will be assigned the whole contents within the {...} brackets, and passed for further parse-time processing by the ode-specific parser of the euler device. On this occasion, the CRN model requires the time step ht again, since it calculates new values of some of the variables rather than calculating their time derivatives. Note that using a different value of ht parameter in euler device and in its crn kinetic model would be syntactically correct, but would probably not do what you want. This kinetic model also uses parameter IV which corresponds to inter-cellular current. Its value is given as @[iext]. In this example, string macro [iext] expands to 24, the value of IV will be different for every point, and it will be the value taken from the layer 24 at that point (more about the layer substitution below).

So the difference between the parse-time and run-time execution of k-code within block parameters is not syntactical, but device-specific. In other words, the only way to find out how it will be interpreted is to look into the description of the particular device.

Generic Device Parameters

A set of generic parameters, listed below, is applicable to all device types. All of the generic parameters listed below are optional - if no value is given for them, a default will be provided by Beatbox. Generic parameters and their defaults are described below.

(str) name

Given name for the device. If the script specifies two instances of a device, giving one of the devices a name will disambiguate the devices in any output messages. Also, some devices refer to another device in the simulation using its name parameter. The default for name is the device name.

(real) when

The device's condition. The value given for when must be a real k-variable. The device will be run only on timesteps (loops of the device ring) when the value of this variable is nonzero. A literal value cannot be used for this parameter (think of this parameter as a codestring, where the code is restricted to just one real variable; allowing here a generic k-expression would be more consistent but also more expensive). For devices that should run on every timestep, Beatbox provides the predefined read-only variable always, whose value is 1, and when=always is the default.

Space Parameters

These specify the points of the mesh on which the device will operate:

  • (int) nowhere: if nonzero, the device is not associated with any part of the computational grid, and its execution does not involve any loops through x,y,z coordinates on the grid. The other space parameters have effect only if nowhere=0, which is the default.
  • (int)x0 Lower x bound. Allowed values from 0 to xmax-1, defaults to 1.
  • (int) x1 Upper x bound. Allowed values from x0 to xmax-1, defaults to xmax-2.
  • (int) y0 Lower y bound. Allowed values from 0 to ymax-1, defaults to 0 for one-dimensional calculations and to 1 otherwise.
  • (int) y1 Upper y bound. Allowed values from y0 to ymax-1, defaults to ymax-1 for one-dimensional calculations and to ymax-2 otherwise.
  • (int) z0 Lower z bound. Allowed values from to zmax-1, defaults to 1 for three-dimensional calculations and to 0 otherwise.
  • (int) z1 Upper z bound. Allowed values from z0 to zmax-1, defaults to zmax-2 for three-dimensional calculations and zmax-1 otherwise.
  • (int) v0 Lower v (layer number) bound. Allowed values from 0 to vmax-1, defaults to 0.
  • (int) v1 Upper v (layer number) bound. Allowed values from 0 to vmax-1, defaults to v0.

In general, a device will operate on points from, e.g. x0 ≤ x ≤ x1. In some devices, the v0,v1 parameters do not define a range of v coordinate, but identify separate layers each having its own function. For example, Beatbox’s diff* devices use v0 to indicate the dynamic variable containing transmembrane potential or another diffusing field, and v1 to indicate where the Laplacian of that field should be stored. For devices that have no effect on the computational grid, the nowhere parameter should be set to 1 to indicate this. The operation of some devices, in particular k_func is strongly affected by the nowhere parameter.

Window Parameters

These specify the placement and colouring of the area associated with the device within the graphical screen when run-time graphics is on.

  • int row0 Lower row.
  • int row1 Upper row.
  • int col0 Left column.
  • int col1 Right column.
  • int color Colour.

The k_func Device

All the standard devices (with the exception of ad-hoc, experimental ones) are described in detail in the Beatbox Device Reference below. However the k_func device is so important for understanding of the Beatbox control flow that it some consideration immediately. This device takes block parameter pgm which is expected to be a "k-program", that is a set of one or more "assignment operators", separated by semicolons. An assignment operator is a string of the form <k-variable>=<k-expression>. The expressions are compiled at parse-time, but evaluated and assigned at run-time using the then current values of k-variables.

The functioning of the k_func device somewhat differs depending on the value of its nowhere parameter. If nowhere is nonzero, then the "k-program" is executed exactly once per per time step, and it can only use the usual "global" k-variables both in the right-hand sides and in the left-hand sides of the assignments.

If, however, nowhere=0 and the device has space, then at every time step the k-program is executed at every point of the space. In this case, the k-programs may use the device's "local" real variables:

All the local variables can be used in the left-hand sides as well as the right-hand sides. The resulting values of u0, u1, ... variables are stored back into the computational grid. The resulting values of all other local variables will be lost after the device instance finishes its work at the given time step. In this mode, k_func can be used to fill the computational grid with values according to given formulas or other algorithms.

A common and very important application of k_func device in the nowhere mode is in updating variables used for devices’ when parameters. For example, to run another device at timestep 200 only, the k_func device called below will assign the value 1.0 to stim when the current timestep, t equals stimTime, and the value of 0.0 otherwise:

def real stimTime 200;
k_func nowhere=1 pgm={
  stim = eq(t,stimTime);
};

The following device call adds a line to the pgm parameter to set k-variable print to 1.0 on timesteps 0, 50, 100, ... and to 0.0 otherwise:

def real stimTime 200;
def real printInterval 50;
k_func nowhere=1 pgm={
  stim = eq(t,stimTime);
  print = ifeq0(mod(t,printInterval));
};

The example below illustrates use of k_func with a space (nowhere=0 mode). It models stimulation of the excitable medium by raising the transmebrane voltage (allocated in the layer whose number is encoded by string macro [V]), in the left half of the box. The value of the stimulus linearly depends on the y coordinate and varies linearly between 0 at y=0 and and 1.5 at y=ymax-1:

def str V 0;
k_func when=stim x0=1 x1=(xmax-1.0)/2 pgm={
  u[V] = u[V] + 1.5*y/(ymax-1);
};

Phase Distribution

Device k_func implements a method that is very specific for cardiac, and generically excitable media simulations. This is a "phase distribution" method, particularly suitable for creating initial conditions. The method was described e.g. in V.N. Biktashev et al., Phil. Trans. Roy. Soc. London, ser A 347: 611-630, 1994. The idea of the method is that the user a scalar field, the phase, defined up to an integer multiple of 2π, and Beatbox then automatically fills the space of the k_func device with corresponding values of the dynamic variables, where what values of dynamic variables correspond to what values of the phase is defined by a "profile", provided in an input file. For this purpose, k_func takes parameter file, which will be the name of a text file, containing space-separated columns of real numbers. Each column corresponds to values of one dynamic variable, and the number of rows represents the whole circle [0,2π) of the phase.

Figure 2: Conceptual arrangement of file for use with phase distribution.
Conceputal arrangement of file for use with phase distribution.

For example, the following data file contains a 2×10 table of values:

Listing G.7: Sample k_func profile file.
2.378  5.111
5.768  8.860
5.609  7.777
1.493  6.545
5.609  7.777
1.347  7.346
4.256  7.423
4.167  6.245
1.234  7.987
3.245  5.222

Conceptually, the values are arranged in a circle, as shown in Figure 2.


Figure 3: k_func interpolation. The value of phaseu is interpolated between ip and ip1 using p and q.
k_func interpolation

If parameter file is given and correponds to a valid profile, phase distribution is initiated by assigning a value to local variable phaseu in the k_func program. The value assigned to phaseu, taken to be in radians, indicates a point on the circle, and consequently the line of the input file to be read. Since phaseu is a real number, linear interpolation is used to calculate values from two neighbouring rows of array, as illustrated in Figure 3. The calculated value is then assigned to the corresponding layer of u: the values interpolated from the first column of the profile to u0, from the second to u1 etc until the last column available on the profile. Note that if the number of u* is more than the number of layers allocated to this k_func instance by its vmin,vmax parameters, then the trailing values will be lost.

An alternative version of the phase distribution method is with assignment to phasep local variable instead of phaseu. In this case, instead of calculating the values of u0, u1, ... local variables, the same algorithm is used to calculate the values of local variables p0, p1, .... Those local variables can then be used later in the same k-program to calculate the u0,u1,... variables. Such indirect assignment may be required if the columns in the profile go in a wrong order etc.

Putting it all together: a simple example

We now consider a simple working example of a Beatbox script, minimal.bbs. It corresponds to Figure 1 above, and solves a standard initial/boundary-value problem for the FitzHugh-Nagumo model, as defined in A.T.Winfree, Chaos 1:305,1991:

u/∂t  =  ε-1(u-u3/3-v)  +  D2u,   ∂v/∂t  = ε(u+β-γv),   (x,y,z)  ∈ Ω  = [0,Lx]× [0,Ly] ;
u/∂n =  0,   (x,y,z)  ∈ ∂Ω ;
u(x,y,0)={-1.7,   xLx;   1.7,   otherwise},
v(x,y,0)={-0.7,   yLy;   0.7,   otherwise}.

It may be executed, say, in the sequential mode by using the following command:

Beatbox_SEQ minimal.bbs
File minimal.bbs.
state xmax=102 ymax=102 vmax=3;

/* device control variables */
def real begin;
def real output;
def real end;	

/* Schedule */
k_func name=schedule nowhere=1 pgm={
  begin =eq(t,0);
  output=eq(mod(t,100),0);
  end   =ge(t,2000);
};

/* Initial conditions */
k_func name=ic when=begin
  x0=1 x1=100 y0=1 y1=100 pgm={
  u0=-1.7+3.4*gt(x,50);
  u1=-0.7+1.4*gt(y,50);
};

/* Diffusion substep */
diff v0=0 v1=2 D=1.0 hx=0.5;

/* Reaction substep */
euler v0=0 v1=1 ht=0.03
  ode=fhncub par={
  eps=0.2
  bet=0.8
  gam=0.5
  Iu=@2
};

/* Output image files */
ppmout when=output
  file=%04d.ppm
  r=0 r0=-1.7 r1=1.7
  g=1 g0=-0.7 g1=0.7
  b=2 b0=0.0  b1=1.0;

stop when=end;

end;

The expected results of the run are described below, and for now we consider the script itself, which is shown on the right.

The script starts with a space command, which the 2D computational grid of 100×100 internal nodes (zmax defaults to 1), and three layers, they will have numbers 0,1,2. Layers 0 and 1 will be used for variables u and v, and layer 2 will keep the values of the diffusion term D2u.

The "device control variables" begin,output,end are required to define which devices work when. They are defined by the three def commands, their values are updated by the first k_func device and used as values of the when parameters of other devices.

The first k_func device does not have a when parameter, so its value defaults to always and it is executed at each step. It has nowhere=1 so its k-program is not iterated over any grid points, but only executed once. The k-program assigns value 1 to k-variables begin at the very first loop of the device ring, when the loop counter t is zero, otherwise begin is assigned zero. Variable output will be 1 at every 100th step, and 0 otherwise. And variable end will be zero until the step 2000, from which on it will be assigned 1.

The second k_func device calculates the initial conditions in accordance with the formula above. It only works during the very first loop (when=begin), and iterates over all internal points, as specified by x0,x1,y0,y1. Its k-program assigns the values to the u0 local k-variable (which means layer 0 value, i.e. u variable of the model) and u1 local variable (layer 1, v variable), according to the formulas for the initial conditions above. The k-expressions depend on local k-variables x,y each of which runs from 1 through to 100, and the ranges 1..50 and 51..100 represent two halves of the computational box.

Notice that the two k_func devices use the optional name parameter. This is used to tell them from each other in the output.

The diff device calculates the diffusion term using values in layer zero (v0=0) and puts the results into layer two (v1=2). It uses the diffusion coefficient value of 1.0, and hx=0.5 is the spatial discretization step. The device applies every step (no when parameter), at all the inner points of the grid (no space parameters, so the defaults are used).

The euler device makes the forward Euler timestep. It also applies at every step and at all the inner points of the grid. This device uses layers 0 and 1, as v0=0, v1=1. It uses time discretization step ht=0.03, and the right-hand sides of the FitzHugh-Nagumo model are selected by ode=fhncub. The parameters of the model are defined by the name-value pairs within the block parameter pgm, namely ε=0.2, β=0.8, γ=0.5. The parameter Iu stands for the extra term in the right-hand side for the u variable, which is defined here, through the layer substitution call @2, as the value of layer 2 at the same point, i.e. the value of the diffusion term as computed by the previous diff device.

The ppmout device make the results of calculations usable. Every time it is active, i.e. at every 100th time step, it outputs a file in the ppm format. The space for this device is not specified so it defaults to all inner points.

The discretization of the floating point data from the computational grid to the one-byte unsigned integers in the PPM file is defined by the following parameters. Integer r=0 says that the red-component will be made from the values in layer 0, i.e. values of the u variable. Its values below r0=-1.7 will be mapped to "0" bytes (zero intensity of the red component), the values above r1=1.7 will be mapped to the maximal "255" bytes (maximal intensity of the red component), with a linear interpolation of values in between. Similarly, the (g)reen component is made out of v values in layer 1, and the (b)lue component out of values of the diffusion term in layer 2. Thus the head of the excitation wave is red, its back is yellow and the refractory tail is green. The blue component, represents the Laplacian but shows only the positive part of it (as b0=0.0). This shows as a dark blue stripe ahead of the front of the excitation wave, and a cyan stripe around its back (the images can be seen below).

The names of the output files are encoded by the string parameter file. The value of this parameter is treated as a file mask, where resulting file names will have the form of the four digits representing the file's ordinal number, followed by .ppm, so the filenames will be 0000.ppm, 0001.ppm, ..., 0020.ppm.

The last device is stop, which does what it says on the tin. Its only one parameter when=end means, according to the assignment for k-variable end above, that this device would work at every timestep, starting from 2000 and above. But it only works once as after that Beatbox terminates.

The script is terminated by the end command, which is purely syntactical, to signal that the script file is complete and the rest of it, if any, should be ignored.

A sequential run of this script may produce standard output like this:

525 $ Beatbox_SEQ minimal.bbs
Beatbox v1.0
------------------------------------------------------------------------------------
Sequential version compiled Aug 31 2012 19:10:55 $
Execution begin at Tue Sep 25 18:24:11 2012 $
Input file minimal.bbs without additional arguments $
with options: noappend nodebug noverbose graph noprofile logname=minimal.log
state   /* grid 102 x 102 x 1 x 3 */ $
k_func $
k_func $
diff $
euler $
ppmout $
stop $
end $
Ring of 6 devices created: (0)schedule (1)ic (2)diff (3)euler (4)ppmout (5)stop $
STOP AT 2000[0]                                                                

BEATBOX_0.1 finished at t=2000 by device 5 "stop"
Tue Sep 25 18:24:14 2012
======================================================
526 $ 

and the file minimal.log with a bit more detail, such as values of the device parameters read, and k-variables assigned. First the standard output and the log file show the commands being read in; so if an error happens at parse time, it is clear which device has caused it. Then the whole device ring is described again, now giving devices' ordinal numbers in the ring, and using their proper names where given. After that there would be output from devices produced during their work, or debug information if it was specified, but in this example the only message is from the stop device. The final message is a signal of normal termination: stopping by any other device would probably happen due to a fatal run-time error. Wall-clock times are printed before and after the execution, so we see that this run took about 3 second.

If ppm format is not convenient, the output files can be converted to another using e.g. an appropriate netpbm utility, say (in bash):

 for (( i=0 ; $i<=20 ; i=$i+1 )); do n=`printf %04d $i`; pnmtopng $n.ppm > $n.png; done

Here are the resulting figures:

figure 0000 figure 0001 figure 0002 figure 0003 figure 0004 figure 0005 figure 0006
figure 0007 figure 0008 figure 0009 figure 0010 figure 0011 figure 0012 figure 0013
figure 0014 figure 0015 figure 0016 figure 0017 figure 0018 figure 0019 figure 0020

The example we have considered is "minimal" and this sort of task is routinely done by any cardiac simulation packages. However, Beatbox's flexibility allows you to do much more than that. To discover Beatbox's capabilities, do look at further sample scripts provided.

Some more advanced scripts

Here we describe a few sample scripts that illustrate some typical uses of BeatBox and can be used as templates for your specific tasks. These scripts are located under:

These scripts are designed to introduce BeatBox devices in an informal, "how-to" way; a more formal description of devices is given later in the Beatbox Device Reference.

Sequential

fhn0.bbs

This script generates action potentials using single cell with FitzHugh-Nagumo kinetics. See:

The APs are initiated repeatedly: a stimulating pulse is issued every time that the two dynamic variables satisfy certain inequalities, meaning the system comes back close enough to the resting state. The solution corresponding to the n-th action potential, n=4, is output to file:

This file will be used in the next example. This example illustrates use of:

Inputs to this script:

Output of this script: To run this script with run-time graphics, call it by

Beatbox_SEQ fhn0.bbs

and without graphics,

Beatbox_SEQ fhn0.bbs -nograph

The same applies to all examples with run-time graphics.

fhn1.bbs

This script simulates propagation of excitation pulses in a one-dimensional cable with FitzHugh-Nagumo kinetics. See:

The pulses are initiated by non-stationary non-homogeneous Dirichlet conditions on the left boundary, where u-variable is made time-dependent according to the record in the fhn0.rec (the file obtained in the previous example). The input is included in the fhn1.bbs script code and need not be given at command line. It outputs a point record during n-th front, n=5, into file: fhn1.rec. This record file will be used in the next example. This example illustrates use of

Inputs to this script:

Output of this script: To run this script with run-time graphics, call it by

Beatbox_SEQ fhn1.bbs

and without graphics,

Beatbox_SEQ fhn1.bbs -nograph

fhn2.bbs

This script simulates a spiral wave in a two-dimensional square sheet with FitzHugh-Nagumo kinetics, and periodically outputs the solution. See:

Essentially, this is a variant of the minimal.bbs script discussed above. Some new things that this script illustrates:

Note that this script will create file fhn2.trj containing the records of the detected spiral tips, and directory fhn2.dir which will contain several png image files created by imgout and k_imgout devices.

Inputs to this script are: Outputs from this script are: Before running this script, make sure that a correct fhn1.rec has been created by running fhn1.bbs. To run this bbs script with graphics, use the following command:
Beatbox_SEQ fhn2.bbs
and to run without graphics, use the following command:
Beatbox_SEQ fhn2.bbs -nograph

b02.bbs

This script simulates propagation and destruction of a critical solution in the model of INa-driven excitation front described in V.N. Biktashev, "Dissipation of the excitation wavefronts", Phys. Rev. Lett., 89(16): 168102, 2002, and reproduces figure 5 from that paper. See:

This script reproduces both panels of the figure, and it is placed in a separate subdirectory in which some post-processing is done as well. The new things that this script illustrates are:

The directory ../data/scripts/sequential/b02/ also contains Makefile which describes the workflow leading to creation of the final product, fig5a.png and fig5b.png files. For this to work, netpbm has to be installed on your computer.

The following steps can be done to reproduce the workflow:

Command line inputs to this script are: The outputs from this script are: Before running this script, please read sec 4.1.4 of beatbox.html. This script comes with a Makefile that will allow you to do the simulation. To use this Makefile for the simulations, type at the command line:
make all
Alternatively, to run this bbs script from command line with graphics, use one of the following commands::
Beatbox_SEQ fig5.bbs 0.624 output_dir   or
Beatbox_SEQ fig5.bbs 0.625 output_dir
and to run without graphics, use the following command:
Beatbox_SEQ fig5.bbs 0.624 output_dir -nograph or
Beatbox_SEQ fig5.bbs 0.625 output_dir -nograph

Parallel

scroll.bbs

This script simulates a scroll waves in a cuboidal 3D domain with Barkley kinetics and explicit Euler approximation of diffusion. It is a short crude model of actual simulations used in H. Dierckx et al., ``Buckling of scroll waves'' Phys. Rev. Lett., 109(17):174102, 2012 (that paper also used an alternating-direction semi-implicit approximation of diffusion, but it is still to be documented). See:

The script uses phase-distribution method to create initial conditions in the form of a slightly twisted scroll wave, using a pre-recorded file bkl1.rec in the same directory. Further things to note in this script are:

The directory ../data/scripts/parallel/Barkley/ also contains Makefile which describes the workflow leading to creation of the final product, bkl1.rec pre-recorded file used for the initial conditions, and report.dat which contains the table of run time in seconds vs number of processors used when this script was tested by the developers on a MacPro workstation. As in b02.bbs example above, you can use make --dry all to see the workflow involved, or just make all to do it all automatically.

The report.dat obtained by the developers for BeatBox version 1.2.484 on a MacPro with 2 x 2.4 GHz 6-Core Intel Xeon processor contained

1	 207.352903 
2	 105.242710 
4	 55.027358 
8	 31.047070 
16	 30.074329 

which indicates that parallelization is effective only up to about 8 processes and further increase of number of processes does not offer any speed-up. Presumably this is due to the relatively small size of the box, so communication cost start dominating after np=8.

Exercise: Increase the size of the box twice in each direction and repeat the scaling test.

Answer: On the same computer as above, the resulting report.dat contained

TBD

Visualization of the resulting "3D ppm" files can be done using EZView. To this end, the ../data/scripts/parallel/Barkley/ directory contains Perl script view.pl. As can be seen from the Makefile, to view the result of simultion on 8 processors, you say

make view-8
on the command line, etc. The Perl script creates an appropriate "task file" in the relevant directory, and then calls ezscroll binary which thus has to be already installed on your computer and visible in your $PATH. See http://empslocal.ex.ac.uk/people/staff/vnb262/software/EZView/ for the EZView source code and instruction; this particular scroll will work with version 1.1 (beware, different versions of EZView use different format of task files).

Command line inputs The outputs from this bbs script are: Before running this script, make sure that the bkl1.rec is in your working directory. You will also need the provided view.pl (a perl script) in your working directory. To run this script in parallel and do the exercise, you can edit the scroll.bbs file and then type:
make all
to do all the tasks in the simulation. To do the tasks individually, see the Makefile.

bbg (geometry) data and cell models

bbg (geometry)

There is an extensive repository (and ever growing) of cardiac anatomical models in Beatbox. These models are provided as ASCII text files with an extension .bbg (e.g. ffr.bbg). The way to include any of the following geometries into a simulation is by means of a state device call in the bbs program as follows:
state file=name_of_your_geometry.bbg normaliseVectors=1 anisotropy=1 vmax=neqn+1;
The bbs program can then work out the bounding box xmax, ymax, and zmax. If you have isotropic simulation, the normaliseVectors and anisotropy parameters should not be included in the state call. A brief description of the geometries, and asssociated bbs programs is below. The space step is usually obtained from the authors of the geometry, as is the species type (human, rabbit,...).

ffr.bbg

This is a rabbit ventricle geometry. The space step in this geometry is 0.1 mm. There is 1 tissue type in this geomtry. The bbs program that can initiate a spiral wave and gives all other optimised simulation paramters using LRD kineitcs is: The purpose of this script is to allow 3D simulation using the ffr.bbg rabbit geometry. This bbs script also demonstrated the use of the anisotropic diff device.
The inputs to this script are: The outputs of this script are: To run this simulation, make sure you have ppm/ and out/ sub-directories. To run this simulation in serial, use the command:
Beatbox_SEQ LRD_ffr.bbs -verbose
To run this in parallel using np number of processors, use the command:
mpirun -n np Beatbox LRD_ffr.bbs -verbose -profile

ffr_slice.bbg

This is a slice of the above rabbit ventricle geometry. The space step in this geometry is 0.1 mm. There is 1 tissue type in this geometry. The bbs program that can initiate a spiral wave and gives all other optimised simulation paramters using LRD kineitcs is: The purpose of this script is to allow 2D simulation using an uneven geomtry. The inputs to this file are the geometry, i.e. ffr_slice.bbg. The 2D geometry has fibre orientation and this file demonstrates the use of the anisotropic diff device. The output from this script are 2D ppm files (in the sub-dir ppm/). To run this simulation in serial, use the command: To run this in parallel using np number of processors, use the command: h2 class="numbered">Cell models There is an extensive repository (and every growing) of electrophysiological and electro-mechanical cardiac cell models in Beatbox. These cell models are provided as modules and are assigned a name that can be used in the bbs programs. The cell model module is accessed in a call to the ode solver, i.e. euler device. The euler device's generic syntax is:
euler v0=0 v1=neqn-1 ht=ht ode=my_cell_model_name rest=100 par={
ht=ht;
Iu=@[iext];
par1=val1;
par2=val2;
};
where neqn is the number of ODEs in the cell model, and par1 and par2 are cell model specific parameters that you may want to modify (e.g. increase gCaL). Assuming that your diffusing variable is voltage, the layer of voltage is explained in the sub-sections below. See Beatbox Cell Model Reference below for several cell model available in the package.

Beatbox Developer's Guide

Hello Beatbox!

Devices are the primary building block of a Beatbox simulation. A simulation consists of two or more devices that are called in turn, at most once for each simulation timestep. When called, the device can perform a task, with optional access to the simulation medium, New.

In this tutorial, we’ll build a device to output the text “Hello, Beatbox !” in the simulation’s standard output file. We won’t go into much detail in this section, rather we’ll just look at the absolute minimum one has to do to build a working device.

The Device Skeleton

The template below shows the a .c file containing the basic outline of a minimal device.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "system.h"
#include "beatbox.h"
#include "device.h"
#include "state.h"
#include "bikt.h"
#include "qpp.h"

typedef struct {
int dummy;  // Add your own device -specific storage here.
} STR;

RUN_HEAD(myDevice)
/* Put code to perform the device ’s task here. */
RUN_TAIL(myDevice)

DESTROY_HEAD(myDevice)
/* Free any allocated resources here. */
DESTROY_TAIL(myDevice)

CREATE_HEAD(myDevice)
/* Add any initialisation code here. */
CREATE_TAIL(myDevice ,1)

There are four key parts to a device:

  1. The first is the definition of the STR datatype. Every device in Beatbox defines STR to meet its specific storage requirements. Usually, STR is used to define a structure for any constants required by the device. For our “Hello, Beatbox !” device, we won’t need any persistent storage, so we’ll just use the minimal implementation that’s given in the template. We’ll see how to use STR in more detail in Section I.2.

  2. The second part of interest is the function used to run our device. Code between the RUN_HEAD and RUN_TAIL macros defines what the device does. This is where whatever computation or output tasks to be performed by the device will happen. For our “Hello, Beatbox!” device, this is where we want to output our message. We’ll use the MESSAGE macro, defined in beatbox.h, which will print to both stdout and the simulation’s .res file.

    RUN_HEAD(hello)
    MESSAGE("Hello , Beatbox!\n");
    RUN_TAIL(hello)
    

    We’ll also have to change the name in the parentheses of the RUN_HEAD and RUN_TAIL macros from myDevice to hello. hello will be the name of our device, and we’ll need to use it wherever we refer to the device. Device names cannot use spaces and are, by convention, all lower-case, without punctuation. If you really need to separate words, use an underscore (_).

  3. The function defined by expanding the DESTROY_HEAD and DESTROY_TAIL macros is called only once, at the end of a simulation, and should be used to free any allocated resources. Since our device won’t allocate anything, we don’t have anything to free, so we can leave this function empty and just put the device name in the parentheses:

    DESTROY_HEAD(hello)
    /* Nothing to do here. */
    DESTROY_TAIL(hello)
    
  4. The fourth and final part prepares the device to be run. The function defined by expanding the CREATE_HEAD and CREATE_TAIL macros will be called only once, at the start of the simulation and should be used to perform any initialisation tasks required by the device. This is discussed in much more detail in Section I.2. For our “Hello, Beatbox!” device, we needn’t add any code here, so just put the device name in the parentheses.

    CREATE_HEAD(hello)
    /* Nothing to do here. Quite boring , actually. */
    CREATE_TAIL(hello ,1)
    

    Although we’ve not put any code between the HEAD and TAIL macros, it’s important not to remove them altogether, as they are all referred to elsewhere in Beatbox. Also, be sure not to change the order of the macros, since CREATE_TAIL defines code dependent upon the RUN_HEAD and DESTROY_HEAD macros. We can now save our device file. By convention, the device’s .c file should have the same name as the device, so ours will be hello.c.

Registering our Device

Now that we have a new device, we need to inform Beatbox that it’s available for use in a simulation. We do this by listing our device’s name in devlist.h. The name listed here must match exactly (case matters) the name we used in our device code.

Open devlist.h and add the following line:

D(hello)

It’s good practice to add your device in alphabetical order. You’ll see a few devices in there that are listed as S(somedevice). These devices will only work in sequential mode, and will be disabled in parallel. They’re naughty devices. Since we don’t want our new device to fall in with this rough crowd, we’re going to use D(), ok?

Building Beatbox with our Device

Beatbox is built using the GNU Autotools. To include our new device in the build, we must add it to Makefile.am, which, like your hello.c file, should be in the src directory. Makefile.am contains a simple description of what’s required to build the software. When we’re done changing it, we’ll use automake to generate a new Makefile, from which the code will actually be built. Open Makefile.am. Scroll down the file, past the flags and other stuff until you find the line:

common_sources = \

followed by a long list of .c and .h files. In correct alphabetical order, add the following line to the list:

hello.c\

We can now build Beatbox with our new device. First, we need to generate a new Makefile by invoking automake from the beatbox directory.

$ pwd
$ /Users/rossmcf/Working/beatbox
$ automake

With automake, no news is good news. We can now compile our new version of Beatbox containing the hello device. We’ll run the local configure script to set up the build system for our machine, and then make to actually build the code.

$ pwd
$ /Users/rossmcf/Working/beatbox
$ ./configure
... (Lots of stuff)
$ make
... (Lots more stuff , hopefully no errors.)

This will compile the code. Assuming all is well, you can now install the binary wherever you want it.

$ make install
... (Even more stuff.)

Don’t be too worried about all the text whizzing by. If anything goes amiss, the last line usually tells you all you need to know.

Running our Device

To include our new device in a simulation, we use the device’s name in the script. So, to print our “Hello, Beatbox!” at each timestep, we include the following line, making sure to leave a space between the device name and the semicolon: hello ; You can try using the following simple script, let’s call it basic.bbs, to test it:

// The medium
state xmax=1 ymax=1 zmax=1 vmax=4;

// Schedule and display parameters
def real begin;
def real end;
k_func nowhere=1 pgm={
begin =eq(t,0);
end =ge(t,20);
};

// Our new device!
hello ;

stop when=end;
end;

Running the script with the following command:

$ <mpirun commands> Beatbox basic.bbs <-options>

should produce something like:

Beatbox 
------------------------------------------------------------------------------------
BEATBOX_1.0 -- MPI version date Oct 26 2010 22:11:47 $
execution begin at Tue Oct 26 22:14:12 2010 $
Input file basic.bbs without additional arguments $
with options: noappend nodebug noverbose nograph noprofile resname=basic.res
state  Simulation medium (1 x 1 x 1)
Domain decomposed as (001,001,001).
0 processors of 1 remain idle.
$
k_func $
hello $
stop $
end of input file $
Loop of 3 devices created: (0)k_func (1)hello (2)stop $
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
Hello , Beatbox!
TIMING INFO
-------------------------
This run took 0.000266 seconds.
BEATBOX_0.1 finished at t=20 by device 2 "stop"

So, now that you’ve built your first device, you might want to make one that actually does something. For that, you’ll need to read Section I.2.

Anatomy of a Device

This section assumes that you’ve read Section I.1 and have built a Beatbox device using the method described therein. We’re now going to go a little more slowly, taking the time to see how and why things work they way they do in Beatbox. Much of the generic code required of a device is provided as a collection of macros and type definitions in device.h, which must be included by all devices.

The Parameter Structure

For the persistent storage of data, devices must declare a parameter structure using the STR datatype. STR is a marker type that should be defined, using typedef , as a struct. Typically, the STR struct has fields for one or more user-specified parameters and any other constants required by an instance of the device. A minimal implementation, as shown in hello.c, above, should define STR as a struct with at least one field. Commonly, the parameter structure is used to hold values of parameters read from the script. This process is described in Section I.2.5.

The Device Datatype

The Device datatype (device.h) represents an instance of a device, as called in the user script. One Device structure is allocated for each of the device calls in the script, such that if the same type of device (e.g. k_func) is called multiple times, there will be multiple Device structures. For the most part, the Device structure is only used ‘behind the scenes’. One field of the Device structure that you will see a lot, however, is the Space structure.

Your device’s space determines the points and dynamic variables of the simulation medium on which it should operate. A device’s implementation code should not interact directly with the Device structure, so we won’t look at it any longer. Forget you even saw it. Some minimal interaction with the Device structure is provided in the function template macros defined in device.h. Using these is the best way to get the job done without wandering into any dangerous territory.

Device Function Templates

As we saw in Section I.1, your device needs to define three functions, referred to as Create, Run and Destroy. device.h defines three template macros that will wrap around your function implementations. Using these templates is strongly recommended since they ensure reliable operation of devices, keep code concise and reduce redundancy. Each template takes the form of a HEAD and TAIL macro. These open and close the function respectively, and throw in some standard functionality for good measure.

The head macros take at least one argument, the name of the device. This is included into the function’s name when the macro is expanded, so that, for example, the euler device will have functions called create_euler(), run_euler() and destroy_euler(). Your chosen device name must be unique and used consistently throughout all macros and in devlist.h.

CREATE_HEAD and CREATE_TAIL

You device’s Create function performs any initialisation required for the device. The function is run once only, before the simulation begins. The CREATE_HEAD macro declares and allocates memory for the device’s parameter structure, S, a local variable of type STR. You can use the body of the function to assign values to the parameter structure.

The defined function will have the name of create_<name>, where <name> is the argument to theCREATE_HEAD macro. To avoid name collisions, it is strongly recommended that <name> correspond to the name of the device.

The create_<name> function has two parameters, dev and w. dev is a pointer to the Device structure and is used by the CREATE_TAIL macro to assign values to its fields. w is a pointer to the parameter string taken from the device call in the user script. This can be used in combination with the functions defined in qpp.h to acquire values from the user script. For more details on how to do this, see Section I.2.5.

The CREATE_TAIL macro assigns the address of S and pointers to functions named run_<name> and destroy_<name> to the par, p and d fields of the Device structure respectively.

Although the Create function has access to the Device structure at this point, it is perilous to tamper with the device structure, so just don’t.

RUN_HEAD and RUN_TAIL

Your device’s Run function describes the task it will perform. The function will be called run_<name> where <name> is the argument to the RUN_HEAD macro. The Run function is pointed to by the p field of the Device structure, with the s, w and par fields of the same structure passed as arguments.

The RUN_HEAD macro contains code that assigns par to a local variable, S, of type STR. Fields of the parameter structure can then be accessed using S->fieldName. Commonly, the Run function begins by retrieving values from the parameter structure to local variables. This can be done using shortcut macros defined in device.h. We discuss this in more detail in Section I.2.5.

The RUN_TAIL macro closes the function, returning 1 to indicate success. If the Run function of any device returns, 0 Beatbox will stop the simulation immediately.

DESTROY_HEAD and DESTROY_TAIL

In your device’s Destroy function, it should put its toys away; it’s time for bed. Specifically, the Destroy function should free any memory allocated for the device and close any open files. If you use the provided template macros, there is no need to free par/S. The function is pointed to by the d field of the Device structure, with the s, w and par fields of the same structure passed as arguments.

The DESTROY_HEAD macro will again point local variable S to your device’s parameter structure. The DESTROY_TAIL macro frees par and returns 1 to indicate success.

Accessing New

Beatbox’s simulation medium is a four-dimensional data set - multiple dynamic variables or layers at points in three-dimensional space. Beatbox represents the simulation medium with a one-dimensional array called New, defined in state.h. In addition to exporting New, state.h provides a collection of variables and macros with which to navigate it. These are listed in Table I.1.

Table I.1: Public state Variables.
NameDescription
t The current time step.
New The simulation medium.
vmax Number of layers.
xmax Number of points in the x-axis.
ymax Number of points in the y-axis.
zmax Number of points in the z-axis.
vmax_xmax Number of variables in the v/x plane.
vmax_xmax_ymax Number of variables in the v/x/y plane.
DX The number of array locations between neighbouring points on the x-axis. (See Figure 2.8)
DY The number of array locations between neighbouring points on the y-axis. (See Figure 2.8)
DZ The number of array locations between neighbouring points on the z-axis.
DV The number of array locations between neighbouring points on the v (variable) axis.
dim The dimensionality of the mesh, from 0 (single cell) to 3.
ONE 1 if the dimensionality is greater than or equal to 1. 0 otherwise.
TWO 1 if the dimensionality is greater than or equal to 2. 0 otherwise.
TRI 1 if the dimensionality is greater than or equal to 3. 0 otherwise.

To access a point in New, use the ind() function to obtain the index of the desired location. ind() takes 4 coordinates, {x,y,z,v}. For a pointer, you will commonly use New+ind(x,y,z,v), and for an absolute value New[ind(x,y,z,v)].

When accessing New, your device MUST only alter values at points within its space, i.e. i0 <= i <= i1. When iterating over the medium, it is advised that the space structure’s fields be used as loop bounds. Not doing so will produce inconsistent behaviour for users.

RUN_HEAD(example)
int x, y, z;
real HUGE *u;
for(z=s.z0;z<=s.z1;z++){
    for(y=s.y0;y<=s.y1;y++){
        for(x=s.x0;x<=s.x1;x++){

            u=New+ind(x,y,z,s.v0);
            /* do something to u here */

        }
     }
}
RUN_TAIL(example)

Accessing points immediately (x ± 1,y ± 1,z ± 1) outside of the device’s space is acceptable, provided such access is read-only. If your device does reference neighbouring points in this fashion, it MUST include the DEVICE_REQUIRES_SYNC macro in its Create function. This will ensure that the device continues to operate correctly in parallel.

Great care should also be exercised when writing to locations in New. Since New may hold values relating to more than one timestep, the mathematical procedure may be corrupted if values required by other devices are overwritten. In general, operations on New MUST be commutative — the device MUST NOT assume a particular order of execution. In addition, devices that are not explicitly parallelised MUST NOT assign values derived from New to their parameter structure, or any other global variable. This will stop terrible things from happening when the device is run in parallel.

To keep users happy, layers accessed by your device should be specified via the Space structure. In most cases, v0 and v1 describe a range, but some devices use them separately, e.g. s.v0 as ‘source’ and s.v1 as ‘destination’.

Tissue Geometry

If your device is interested in accessing data about the underlying tissue geometry, you’ll find it in Geom. Geom is organised in much the same way as New, and we use geom_ind(x,y,z,v) to access it. The v variable can have one of four values:

To test if a point is tissue, use isTissue(x,y,z). The same rules apply to Geom as to New, in particular, stick to your Space structure and don’t reference any further away than ( x ± 1,y ± 1,z ± 1).

Reading Parameters

Commonly, a device will take some parameters from the user via the script. We call this process ‘accepting’ a parameter. There are two steps to this process:

  1. Firstly, the parameter is read by the script preprocessor, and assigned to the device’s parameter structure.
  2. Later, in order to use the parameter, the device will retrieve the value from the parameter structure. Both of these steps are greatly simplified by some handy macros defined in qpp.h.

Parameter Accept Macros

Parameter accept macros provide a quick way to pull a parameter value from the script and assign it to its namesake field in the device’s parameter structure. The first thing to consider is the type of parameter you’d like to accept. There are four common types:

The corresponding parameter accept macros are listed below. They each have a default argument that, if given the corresponding null value, will require that the user supplies a value, rather than merely making it optional.

ACCEPTI(name,deflt,minv,maxv);
  • name Name of the parameter whose value is to be read.
  • deflt Default value, in case no parameter called name is found. If INONE, a script parameter MUST be found.
  • minv Minimum allowed value. If INONE, no minimum is prescribed.
  • maxv Maximum allowed value. If INONE, no maximum is prescribed.
ACCEPTR(name,deflt,minv,maxv);
  • name Name of the parameter whose value is to be read.
  • deflt Default value, in case no parameter called name is found. If RNONE, a script parameter MUST be found.
  • minv Minimum allowed value. If RNONE, no minimum is prescribed.
  • maxv Maximum allowed value. If RNONE, no maximum is prescribed.
ACCEPTS(name,deflt);
  • name Name of the parameter whose value is to be read.
  • deflt Default value, in case no parameter called name is found. If NULL, a script parameter MUST be found.
ACCEPTF(name,mode,deflt);
  • name Name of the parameter whose value is to be read.
  • mode Access mode in which the file is to be opened. Syntax is identical to a fopen() call:
    • r or rb Open existing le for reading.
    • w or wb Create le or wipe existing le before writing.
    • a or ab Append to end of existing le, creating if necessary.
    • rt or rbt or rtb Open existing le for updatereading and writing.
    • wt or wbt or wtb Create le or wipe existing le before updating.
    • at or abt or atb AppendOpen or create le for update, writing at end of le.
  • deflt Default filename, in case no parameter called name is found. If NULL, a filename MUST be found in the script.

Parameter Shortcut Macros

To aid access to fields of the parameter structure, device.h provides shortcut macros to declare local variables and initialise them with values from their namesake fields in the parameter structure.

The Laws of Devices

Beatbox allows simulations to be run on distributed-memory parallel machines using MPI. Many devices can be run in parallel without special adaptation, but it’s difficult to tell exactly what will and won’t work in parallel. The ‘Laws of Devices’ below describe how a device should behave in order to ensure its safety in parallel. If these rules aren’t followed, there is a very real chance that your device will crash horribly in parallel, or worse, quietly produce incorrect results. Please read and stick to them.

  1. A device must only alter layers of New in its space, at points in its space.
  2. All operations on New must be commutative — the order of operation cannot be assumed.
  3. Aside from the permitted regions of New, a device may only alter the values of local variables or those in its parameter structure.
  4. Assignments made to a device’s parameter structure must not be derived from data in New.
  5. Assignments made to a device’s parameter structure must not be derived from data in its Space structure.
  6. Assignments made to a device’s parameter structure must not be derived from local minima or maxima (e.g. local_xmax).
  7. Assignments made to a device’s parameter structure must not be derived from a random number generator.
  8. From any point in its space, a device may not reference points in New beyond {x ± 1 ,y ± 1 ,z ± 1}.
  9. A device that references neighbouring points in New must put the DEVICE_REQUIRES_SYNC macro in its Create function.
  10. From any point in its space, a device may not reference points in Geom beyond {x ± 1 ,y ± 1 ,z ± 1}.
  11. Files accessed from a device must only be read.

If you’re planning on making a device that needs to do something forbidden by the laws above, it will need to be explicitly parallelised to run in parallel. Please consult your local MPI expert. In the meantime, you can enable the device as sequential only, by going to devlist.h and changing the D before your device’s name to an S. It’s now one of the naughty devices.

Visualisation

Beatbox has the functionality to output ppm files which allow easy visualisation, especially of large data sets. The visualisation can be further improved using BBXVIEW package.

To convert ppm to jpg/png, use something like this in a shell script from netpbm and usually 0. If voltage is being output to the ppm files, then the:

for (( i = $start; i <= $finish; i++))
do
   ppmtojpeg out/ord2_${i}.ppm > jpegs/ord2_${i}.jpg
done

Further, to make an animation, use ImageMagick using the convert command:

    convert -delay 20 -loop 0  sphere*.gif animatespheres.gif 

A shell script to handle these tasks will have the following contents:

#!/bin/bash for (( i = $start; i <= $finish; i++)) do ppmtojpeg out/ord2_${i}.ppm > jpegs/ord2_${i}.jpg done # convert -delay 20 -loop 0 sphere*.gif animatespheres.gif

You will need to make this shell script executable. For example, if you save it as myscript.sh, then you need to do the following:
chmod 766 myscript.sh
After this, you can run your script like any other program from the command line as:
./myscript.sh

ParaView can be used to make animations using the 3D ppm data. To do this, first run the script ppm_2_paraview. This perl script needs the inputs bgr bgg bgb channel threshold filename.ppm where the rgb values are from the bbs file, or default values (255 255 255). The channel is again from the bbs file threshold is usually around 127. Once the vtk files are produced in this manner, use paraview to prepare the visualisation interactively using the first file. An output to animation will then produce the desired jpegs / tiffs / pngs. Use convert from ImagemMagick to make a low maintainence animated gif that can be put into powerpoint or web pages.

Advanced

call graphs to show how the code works for developer's.

How to implement a CellML cell model into Beatbox

Following is a method involving minimal manipulation of CellML cell model code to incorporate it into Beatbox format. We use the OHara-Rudy 2011 model as an example to illustrate the method.

Step 1: Get the CellML file

Published cardiac and other simulation models are distributed by means of the CellML Project website, that can be found here: CellML Project. In particular, the cell models are listed in the repository: CellML Repository. The desired CellML file should be downloaded from the repository. The file that we are looking for is usually has an extension of .cellml. As an example, the OHara-Rudy (ORd) cell model file looks like this: ORd CellML file. There are other formats in which the cell model may be provided (C, C++, MATLAB,...) and the best location to get the CellML file is from the provided tar.gz download all files section.

Step 2: Convert the CellML file to C code

The information in the CellML file obtained as in Step 1 needs to be converted into suitable C format. In principle, the converted codes as delivered by the CellML website may be sufficient. However, to obtain all the information required to construct the cell model in Beatbox format (i.e. initial conditions and the algebraic-differential equations for the model dynamics) is ideally obtained by means of COR software. COR (Cellular Open Resource) is primarily a Windows software, but may be installed on Linux and MAC-OS if the operating system is 32 bit or if there are 32 bit emulators available. As of the date of this document, a Linux variant is also being developed. So the next thing to do is download and install COR. Once it is installed, open the CellML file that you downloaded in Step 1 and export it to C. The exported files are a .c and a .h with the same name as the CellML file. For example, the ORd exported files are:Ohara_Rudy_2011.c and Ohara_Rudy_2011.h.

Step 3: Define the constant modelling default parameters

The header file as exported in Step 2 simply declares all constants and variables. The format that the declarations appear in the header file depend on the original CellML file and how the model authors provided the original codes to CellML. In the C file (Ohara_Rudy_2011.c in our case), there is hopefully an annotated section (called "Constants" or similar) that shows the model constants and this section should be identified. It should be borne in mind that these constants should be simply numerical assignments to place holders, i.e. a formula should not appear on the right hand side of these assignments. Further, due to the Beatbox format, these modelling constants should all be real (i.e. float or double) numbers. All derived constants and integer constants are handled otherwise (see below).

Take this list of constants and put them in a file called, say ord_par.h. The format of the list of constants should be further manipulated such that Beatbox macro's can do what they should do. The final ord_par.h should look like this: ord_par.h.

Step 4: Define the initial conditions to the model

A void init(void) (or similarly named function) is provide in the exported C file. Contents of this function without any alterations should be copied to another file. In the ORd example, we choose to call this file ord_init.h. Note that none of the contents of the initialisation have been altered. The exported C file probably (hopefully) uses a vector to maintain values of dynamic variables, and that should also be retained to reduce manipulation of original code. The prepared ord_init.c file can be found here: ord_init.h. Note that unlike in the parameter file of Step 3, the code in the initialisation has not been manipulated at all.

Step 5: Define the actual model calculation

After having defined the constant real parameters and assigned initial values to the dynamic variables vector, we now construct the code that will be used for the actual cell model integration. This step starts with identifying the function called void compute(double t) or similar in the exported C file. The contents of this function should be imported into another header file, say called ord_step.h. You may notice that in this code, there are several derived variables (e.g. currents, fluxes,...), integer constants, etc. These derived variables are typically declared as "Computed Variables" or with similar annotation. These declarations should be put at the top before the model code. The final ord_step.h look like this: ord_step.h. Note that no integration (forward Euler or otherwise) is included in this ord_step.h - this is simply the code for computing the next time step increment. A vector called dY[] may also be found in this code. We will deal with this in a bit.

Step 6: Define a variable to deal with the device in ord.on

A constant variable needs to be defined to tell several of Beatbox macros about the new cell model. For example, in case of the ORd, create a file ord.on with the following line of code:

#define ORD 1

You can see the file: ord.on.

Step 7: Update rhslist.h

The list of RHS of cell models needs to be updated. This list is in:

of the package. Code, similar to what is shown below, should be added to this file:

#if ORD
   D(ord)
#endif

Explanations on the meaning of the macro D, the choice of names etc. are to be found in the developers guide.

Step 8: Define the wrapper for the model simulation

The main C wrapper that initialises, declares local placeholders, and provides the cell model code to the Euler solver is given a consistent name. For example, in case of ORd, it is simply called ord.c. This wrapper contains headers, macros, and basically includes the code from the above files.

Step 9: Update the Makefile.am

There is a Makefile.am in the Beatbox/src directory. Add entries for .on, _step.h, _init.h, _par.h, and .c files that you have just created. Save, do a distclean, configure, and make again. Hopefully, it all compiles. To start using the cell model, make a bbs file as shown in the template below.

Step 10: Make a bbs file to simulate the AP

A bbs file template: ord0.bbs:

A Practical Guide for Automake if you add new modules

Bash / perl scripting for increased Beatbox functionality

Beatbox Device Reference

activation

Overview

This is a computational device, which computes and stores activation times at all points in the grid, within its space. The activation time at a point of the grid is defined as the most recent moment when the value of a certain field at that point has crossed a given value in a given direction. The typical intended use is that the "certain field" is the transmembrane voltage. The activation times are in terms of the integer counter t, but their values are real, and defined by linear interpolation between the current and the previous value of the selected field at the given point. If activation times in terms of the model time are required, these values should be properly interpreted, typically just multiplied by the time step. Since the device needs the current and the immediately preceding values of the given field, it should be run at continuous time intervals for correct work.

Parameters

Type Name Description
intv0 The layer containing the field used for definining the activation time, e.g. the transmembrane voltage layer.
intv1 The layer used for storing the computed activation times. Must be different from v0.
intvd An auxiliary layer, used for storing previous values of the field. Must be different from both v0 and v1, and must not be modified by any other devices. In particular, it should be outside the range of layers used by the cell model(s).
realthresholdActivation is the event when the selected field crosses this value, in the direction defined by the next parameter, sign.
intsignOnly the sign of this parameter matters. If positive, activation is defined when the selected field value crosses the threshold value upwards; if negative, activation is when the value crosses the threshold downwards; if zero, then crossing in either direction will be counted as activation.
All parameters are mandatory.

Typical Syntax

activation v0=[Volt] vd=[p] v1=[a] threshold=Vact sign=1;
where string macro [Volt] contains the number of the layer used for storing transmembrane voltage, [p] and [a] are layers outside the kinetic model, where layer [a] will contain the most recent activation times in all points through which the excitation wave passed at least once. Excitation wave is considered to have passed through a point when the voltage at that point crossed the value given by the previously assigned k-variable Vact upwards.

Instances in Example Scripts

beatbox/data/scripts/sequential/TenTusscherPanfilov_modelS/ttp06/benchmark.bbs
This script can be run e.g. using the following command:
Beatbox_SEQ benchmark.bbs 0.5.bbg 0.5 0.05 0.5_0.05.dat
where 0.5.bbg is the geometry file, 0.5 and 0.05 are space and time discretization steps, and 0.5_0.05.dat is the output file where the results of the benchmark will be stored. More results will be also stored in files in the subdirectory 0.5_0.05.dat.dir. See the Makefile and eport.pdf in that directory for more details.

clock

Overview

Prints the current integer timestep to stdout.

Parameters

Type Name Description
intwhenrate of output
intcol0 starting column of graphics.
introw0 starting row of graphics.
intcolor Color code of line graphics.

Typical Syntax

The clock device is mainly used during run time graphics simulations. The typical syntax of clock device is as follows. The clock device is mainly used during run time graphics simulations. The typical syntax of clock device is as follows.
clock when=often color=WHITE row0=10 col0=20; 

Instances of clock in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0.bbs
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn1.bbs
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn2.bbs
The inputs, outputs, and methods of running for fhn0-fhn2.bbs have been described in previous sections.

ctlpoint

Overview

Saves the entire simulation state for disaster recovery, or to facilitate a branching point in long simulations.

Parameters

Type Name Description
strfile Control point file to be restored from / saved to.
intenrich Can the restored control point define k variables not present in the script.

d_dt

Overview

Computes the time derivative of a layer (dynamical variable) at a given location.

Parameters

Type Name Description
realht time step
intvdDynamical variable for which derivative is sought.

Typical Syntax

d_dt ht=ht vd=1;

Instances in Example Scripts

beatbox/data/sequential/FitzHughNagumo_model/fhn2.bbs
The inputs, outputs, and method of simulation for fhn2.bbs have been described above.

diff

Overview

Computes the Laplacian, with implicit Neumann boundary conditions.

Parameters

diff must be used with the default space. The v0 space parameter is used to indicate the diffused variable, usually the transmembrane voltage. The v1 space parameter is used to indicate the layer in which the Laplacian should be stored.

Type Name Description Isotropic or Anisotropic
realhx Space step.Isotropic Only
realD Isotropic diffusion coefficient.Anisotropic Only
realDpar Anisotropic diffusion coefficient parallel to the fibres.Isotropic
realDtrans Anisotropic diffusion coefficient in the transverse direction, perpendicular to the fibres.Anisotropic

Typical Syntax

The typical syntax of diff device is as follows. Assuming that the diffusing layer is diff_layer (a number) and the layer in which the Laplacian is to be stored is lap_layer, the syntax for the isotropic diffusion is
diff v0=diff_layer v1=lap_layer hx=hx D=D;
where uniform diffusion is used throughout the tissue. In case of anisotropic diffusion, the syntax changes to account for diffusion parallel to the fibres (signified by Dpar) and transverse to the fibres (signified by Dtrans) and is
diff v0=diff_layer v1=lap_layer Dpar=D Dtrans=D/4 hx=hx;

Instances of diff in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of isotropic diffusion can be found in the following:
beatbox/data/scripts/sequential/fhn1.bbs
beatbox/data/scripts/sequential/fhn2.bbs
and for the anisotropic case can be found in
beatbox/data/scripts/sequential/LRD_model/LRD_ffr.bbs
The inputs, outputs, and method of simulation for fhn1.bbs, fhn2.bbs, and LRD_ffr.bbs have been described above.

dump

Overview

Writes the contents of the simulation medium within its space to a binary file.

Parameters

TypeNameDescription
strfile Relative path to the dump file.
intappend Should the file be appended to?

Typical Syntax

The typical syntax of dump device is as follows. Assuming that the dynamical layers are between ode_layer0 (a number) and the layer ode_layer1 the syntax for the dump device is
dump when=end v0=ode_layer0 v1=ode_layer1 append=0 file=my_dump_file.dmp;

Instances of dump in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of dump device can be found in the following:
beatbox/data/scripts/sequential/LRD_model/LRD_ffr.bbs
The simulation state saved in such a manner may be used to continue the simulation using the load device. The inputs, outputs, and method of simulation for LRD_ffr.bbs have been described above.

euler

Overview

General pointwise ODE stepper.

Parameters

TypeNameDescription
realhtTimestep duration.
strode Name of the RHS module to use.
intrest Number of timesteps of the RHS module to run before starting simulation. Can be useful for finding resting initial conditions.

Typical Syntax

The typical syntax of euler device is as follows. Assuming that the ODE layers are between ode_layer0 (a number) and the layer ode_layer1, the ODE module (i.e. cell model) that you are using od ode_module, and the user defined model parameters are defined in bbs parameters p1, and p2, the syntax is
euler name=name_to_device_call v0=ode_layer0 v1=ode_later1 ht=ht ode=ode_module rest=100 par={par1=p1; par2=p2;};
You can given the device call a convinient name, name_to_device_call in this case, to refer to your device elsewhere in the bbs script.

Instances of euler in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of euler device can be found in the following:
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0.bbs
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn1.bbs
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn2.bbs
Indeed, all bbs scripts in the examples use the euler device.

grad2d

Overview

Computes the 2D gradient at a given x,y,z location.

Parameters

The only parameter is the space step.

Typical Syntax

grad2d hx=hx;

Instances in Example Scripts

beatbox/data/sequential/FitzHughNagumo_model/fhn2.bbs
The input, output, and simulation method of fhn2.bbs has been described previously.

imgout

Overview

Produces png images of the space. Values from specified layers of the simulation medium are mapped to colour channels by linear interpolation using specified minima and maxima. imgout produces a new, sequentially numbered file every time it is run.

Parameters

TypeNameDescription
SequencefilterOn the fly producing png images.
intr Layer of the simulation medium from which the red colour channel should be mapped.
realr0 Value of the layer assigned to r that should map to 0.
real r1 Value of the layer assigned to r that should map to 255.
intg Layer of the simulation medium from which the blue colour channel should be mapped.
realg0 Value of the layer assigned to g that should map to 0.
realg1 Value of the layer assigned to g that should map to 255.
intb Layer of the simulation medium from which the green colour channel should be mapped.
realb0 Value of the layer assigned to b that should map to 0.
realb1 Value of the layer assigned to b that should map to 255.

Typical Syntax

The typical syntax of imgout device is as follows.
imgout filter="pnmflip -tb | pnmtopng > [outdir]/uvi%07.0f.png" mode="w" r=[u] r0=umin r1=umax g=[v] g0=vmin g1=vmax b=[i] b0=-1 b1=1;

Instances of ppmout in Example Scripts

Examples of ppmout device can be found in the following:
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn2.bbs

k_clock

Overview

Prints the current time to stdout.

Parameters

Type Name Description
intwhenrate of output
intcol0 starting column of graphics.
introw0 starting row of graphics.
intcolor Color code of line graphics.
realcode usually set to t*dt
stringformatstring defining format of output real

Typical Syntax

The k_clock device is mainly used during run time graphics simulations. The typical syntax of k_clock device is as follows.
k_clock when=often color=WHITE row0=1 col0=21 code=t*ht format="T=%4.1f ms"; 

Instances of k_clock in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0.bbs
The inputs, outputs, and methods of running for fhn0.bbs have been described in previous sections.

k_draw

Overview

Draws the visualisation window.

Parameters

Type Name Description
intcol0 starting column of graphics.
intcol1 end column of graphics.
introw0 starting row of graphics.
intcol1 end column of graphics.
intcolor Color code of line graphics.

Typical Syntax

The typical syntax of k_draw device is as follows.
def str win1 col0=col0 col1=col1 row0=row0 row1=row1 color=15*16+15;
k_draw when=always [win1] color=BLUE*16;

Instances in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0.bbs

k func

Overview

Allows the user to specify user defined functions to be executed as part of the simulation run.

Parameters

TypeNameDescription
strfile Relative path to file for phase distribution. See Beatbox Scripting Guide.
strdebugRelative path to output file for debugging purposes. If stdout, will print to screen.
CodeblockpgmThe function to be executed when the device is run. Beatbox script statements, separated by semicolons. Users should note that the behaviour of k_func changes significantly in relation to the nowhere parameter.When nowhere=1, assignments can be made to k variables only. Assignments from the simulation medium or random number generators are disallowed. When nowhere=0, assignments can be made to the simulation medium only. It is possible to define intermediate variables in k_func programs, using the def keyword. Variables must be initialised before they are used, and are reinitialised on each iteration of the k_func program.

Typical Syntax

The typical syntax of k_func device is as follows.
k_func name=timing nowhere=1 pgm={
  begin = eq(t,0);          // 1 when t is equal to zero, 0 otherwise. 
  often = eq(mod(t,10),0);  // 1 if t is divisible by 10, 0 otherwise.
  end   = ge(t,100000);	    // 1 if t is greater or equal than 100000, 
                            // 0 otherwise.
};

Instances in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0.bbs

k_paint

Overview

k_paint is a device for run-time graphics to paint the field using VGA colour palette.

Parameters

Type Name Description
intwhenOutput rate
intcol0 starting column of graphics.
intcol1 end column of graphics.
introw0 starting row of graphics.
intcol1 end column of graphics.
intcolor Color code of line graphics.

Typical Syntax

The typical syntax of k_paint device is as follows.
k_paint when=out nabs=nx nord=ny          // how many abscissa and ordinate values
  col0=col0 col1=col1 row0=row0 row1=row1 // output it into the left panel
  color=WHITE*16+WHITE                    // white borders for the panel
  pgm={                                   // program should calculate colour for given (abs,ord)
                                          // and we take abs=x and ord=y
  col=ifge0(u(abs,ord,0,[u]),LIGHTRED,0)  // red component there if u field is above 0
  + ifge0(u(abs,ord,0,[v]),GREEN,0)};     // and green if [v] field is above 0

Instances in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn2.bbs

k_plot

Overview

Plots the visualised variables.

Parameters

Type Name Description
intcol0 starting column of graphics.
intcol1 end column of graphics.
introw0 starting row of graphics.
introw1 end column of graphics.
intcolor Color code of line graphics.
intlinewidth Width of line.
intabsmin Minimum value of variable.
intabsmax Maximum value of variable.
intcleanClean or not.

Typical Syntax

The typical syntax of k_paint device is as follows.
k_plot name=uplot when=often 
  col0=col0 col1=col1 row0=row0 row1=row1 // defines the part of the graph window for this output
  color=WHITE*16+WHITE			  // colour of the "window" border	
  lines=1 				  // connect the dots
  clean=1                                 // clean window before drawing this graph
  ordmin=umin ordmax=umax		  // limits for the ordinate of the plot
  N=nx					  // the abscissa will be integer running from 1 to nx
  pgm={ord=u(abs,0,0,[u]);col=LIGHTRED};  // ordinate is value of u variable at the point, plot in light red

Instances in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn1.bbs

load

Overview

Loads data from a file saved by dump into the simulation medium.

Parameters

TypeNameDescription
strfileRelative path to the file to be read.
intrewindShould the file be rewound before reading?

Typical Syntax

The typical syntax of load device is as follows. Assuming that the dynamical layers are between ode_layer0 (a number) and the layer ode_layer1 the syntax for the dump device is, and that the dump file (see above) has been saved to a file called my_dump_file.dmp, then the syntax is
load when=begin v0=ode_layer0 v1=ode_layer1 append=0 file=my_dump_file.dmp;

Instances of load in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of dump device can be found in the following:
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn1_load.bbs
The purpose of this file is to give an example of the use of load device. The input that this file expects is the dump file "fhn1.dmp". The output of this script is a dump file at the end of the run. To run this script, use the following command:
Beatbox_SEQ fhn1_load.bbs

k_poincare

Overview

Samples a dynamic variable at a single point in the mesh, to detect a crossing in time of a specified value.

Parameters

The k_poincare device must be run on a single point. Upper space parameters x1, y1, z1 and v1 are unused by this device. The v0 space parameter is the dynamic variable to be sampled at point (x0,y0,z0).

TypeNameDescription
k variableresultName of the k variable into which the result should be stored — 1 if a crossing has been detected on this timestep, 0 otherwise. k variable timestep Name of the k variable into which the timestep of the last crossing should be stored. An assignment will only be made to this variable on the timestep when a, crossing is detected.
realcrossThe crossing threshold. If previous and current values of the sampled dynamic variable straddle cross, a crossing is detected.
intsignThe sign of the crossings to be detected:
  • 1 indicates positive crossings only,
  • -1 indicates negative crossings only,
  • 0 indicates that crossings in either direction will be accepted.

Typical Syntax

The typical syntax of k_poincare device is as follows.
k_poincare nowhere=1 sign=1 pgm={front1=U1-umid;tfront1=t};
In this syntax, front1 will become 1 when the variable U1 is increasing (slope sign 1). Additionally, the value of the integer time counter t will be stored tfront1.

Instances of k_poincare in Example Scripts

beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn1.bbs

ppmout

Overview

Produces PPM images of the space. Values from specified layers of the simulation medium are mapped to colour channels by linear interpolation using specified minima and maxima. ppmout produces a new, sequentially numbered file every time it is run. In three-dimensional meshes, ppmout produces non-standard PPM files, in which multiple z-layers are stacked into a single file.

Parameters

TypeNameDescription
SequencefileFormat specifier for the sequence of files produced.
intr Layer of the simulation medium from which the red colour channel should be mapped.
realr0 Value of the layer assigned to r that should map to 0.
real r1 Value of the layer assigned to r that should map to 255.
intg Layer of the simulation medium from which the blue colour channel should be mapped.
realg0 Value of the layer assigned to g that should map to 0.
realg1 Value of the layer assigned to g that should map to 255.
intb Layer of the simulation medium from which the green colour channel should be mapped.
realb0 Value of the layer assigned to b that should map to 0.
realb1 Value of the layer assigned to b that should map to 255.
Geometry Only
intbgr Red value of the background colour, to be displayed at void points.
intbgg Green value of the background colour, to be displayed at void points.
intbgb Blue value of the background colour, to be displayed at void points.

Typical Syntax

The typical syntax of ppmout device is as follows.
ppmout file="ppm/%04d.ppm" mode="w" r=[u] r0=umin r1=umax g=[v] g0=vmin g1=vmax b=[i] b0=0 b1=255;
where the red, green, and blue channel are defined by maximum, minumum, and mid-point values of user defined dynamical variables.

Instances of ppmout in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of dump device can be found in the following:
beatbox/data/scripts/sequential/fhn2.bbs

record

Overview

record writes values from the simulation medium to file in ASCII format. A hierarchical set of separators — vsep, xsep, ysep and zsep — are used between values. recordsep is used between records, i.e. separate runs of the record device.

Parameters

TypeNameDescription
strfile Relative path to the file to be written.
intappend Should the file be appended to?
strfilehead Data to be placed at the top of the record file.
strvsep v-axis separator. Must be at most 2 characters in length.
strxsep x-axis separator. Must be at most 2 characters in length.
strysep y-axis separator. Must be at most 2 characters in length.
strzsep z-axis separator. Must be at most 2 characters in length.
strrecordsep Record separator. Must be at most 2 characters in length.

Typical Syntax

The typical syntax of record device is as follows.
record when=often file=output_record_file_name.rec append=0 x0=1 x1=xmax-1 y0=1 y1=ymax-1 z0=1 z1=zmax-1 v0=ode_layer0 v1=ode_layer1;

Instances of record in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of record device can be found in the following:
beatbox/data/scripts/sequential/fhn0.bbs

reduce

Overview

Reduce performs a reduction operation — sum, product, minimum or maximum — over its space. The result of the operation is assigned to a specified k variable.

Parameters

Type Name Description
k variableresultName of the k variable into which the result should be stored.
strtimestepName of the operation to perform. Accepted values are “ sum ”, “ product ”, “ min ” and “ max ”.

Typical Syntax

The typical syntax of reduce device is as follows.
reduce name=U_sample operation=max v0=[u] result=U;

Instances of reduce in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of record device can be found in the following:
beatbox/data/scripts/sequential/fhn0.bbs
beatbox/data/scripts/sequential/fhn1.bbs

sample

Overview

Assigns a dynamic variable value from a specified point in the mesh to a k variable.

Parameters

The sample device must be run on a single point. Upper space parameters, x1, y1, z1 and v1 are unused by this device. The v0 space parameter is the dynamic variable to be sampled at point (x0, y0, z0).

Type Name Description
k variableresultName of the k variable into which the sampled value should be stored.

Typical Syntax

The typical syntax of sample device is as follows.
sample x0=x_loc y0=y_loc z0=z_loc v0=ode_layer result=name_of_place_holder;

Instances of sample in Example Scripts

All example scripts can be found in data/scripts of the package distribution. Examples of record device can be found in the following:
beatbox/data/scripts/sequential/fhn0.bbs
beatbox/data/scripts/sequential/fhn1.bbs

stop

Overview

Stops the simulation run.

Parameters

None.

Typical Syntax

The typical syntax of stop device is as follows. Assuming that the variable for end has been defined in the variable end, the syntax is
stop when=end;

Instances of stop in Example Scripts

All bbs scripts must have a call to the stop device. The stop devices occurs in all the example bbs scripts.

update

update updates the run time visualisation.

Parameters

Type Name Description
intwhen Frequency of updating

Typical Syntax

update when=often; // run time graphics are updated when often is true.

Instances in Example Scripts

beatbox/data/sequential/pd/scripts_crn0.bbs
beatbox/data/sequential/pd/scripts_crn1.bbs

vtkout2

Overview

Outputs legacy VTK file for 2D model. The header is in ASCII, and the data are in double binary format.

Parameters

Type Name Description
intrDynamical layer to output
intr0, r1minimum and maximum of the expected values in later r

Typical Syntax

/* Note: the g and b layers are there to allow vtkout2 syntax to be similar to the ppmout syntax */
vtkout2 when=often file="vtk/fk2%06d.bin.vtk" mode="w" r=[u] r0=umin r1=umax g=[v] g0=vmin g1=vmax b=[i] b0=0 b1=255;

Instances in Example Scripts

data/scripts/sequential/FentonKarma_model/fk2_san.bbs

Beatbox Cell Model Reference

Fitz-Hugh Nagumo Cell Model

The Fitz-Hugh Nagumo model (FHN) consists of 2 variables. The voltage is in layer 0. The name of the module is fhncubpar and fhncub. The example of FHN cell model AP is in
beatbox/data/scripts/sequential/FitzHughNagumo_model/fhn0_ap.bbs
This bbs script has no inputs, and its output is a record file called fhn_ap.vtg. To run, use the command:
Beatbox_SEQ fhn0_ap.bbs
After running this bbs script, you can produce an AP profile as shown in the figure below. FHN AP profile.

Fenton Karma Cell Model

The Fenton Karma model (FK) consists of 3 variables. The voltage is in layer 0. The name of the module is fk. The example of FK cell model AP is in
beatbox/data/scripts/sequential/FentonKarma_model/fk0_ap.bbs
This bbs script has no inputs, and its output is a record file called fk0_ap.vtg. To run, use the command:
Beatbox_SEQ fk0_ap.bbs
After running this bbs script, you can produce an AP profile as shown in the figure below. FHN AP profile.

Fenton Karma Modified Cell Model

The FK model (previous subsection) was modified and developed to produce mouse sinoatrial node and atrial action potentials. The name of the module is called fkmod/ The examples of the cell model are in
beatbox/data/scripts/sequential/FentonKarma_model/fk0_atrial.bbs
beatbox/data/scripts/sequential/FentonKarma_model/fk0_san.bbs
where a Makefile detailing the SAN and atrial command line inputs is give. To run the atrial cell, type:
make atrial
and to run the SAN cell, type:
make san
We get this figure for SAN AP: FKMOD SAN AP profile. and atrial AP profile as shown below. FKMOD SAN AP profile.

LRD

The Luo-Rudy (LRd) model was published in 1994 by Luo and Rudy to simulate the guinea pig ventricular action potential. It consists of XYZ variables. The voltage is in layer 0. The name of the module is lrd. The example of LRd cell model AP is in
beatbox/data/scripts/sequential/LRD_model/lrd0_ap.bbs
This script requires no input and outputs a vtg file with the AP data. It can be run using
Beatbox_SEQ lrd0_ap.bbs
You can produce an AP profile as shown in the figure below. LRD AP profile.

CRN

The Courtemanche et al. (CRN) cell model was published in 1998 and simulates the human atrial action potential. It consists of 21 variables. The voltage is in layer 0. The name of the module is crn. The example of CRN cell model AP is in
beatbox/data/scripts/sequential/CRN_model/crn0_ap.bbs
This script requires no input and outputs a vtg file with the AP data. It can be run using
Beatbox_SEQ crn0_ap.bbs
You can produce an AP profile as shown in the figure below. CRN AP profile.

TTNNP04 Human Ventricle Model from author source code

This model was published in "A model for human ventricular tissue", by K. H. W. J. ten Tusscher, D. Noble, P. J. Noble and A. V. Panfilov, Am J Physiol Heart Circ Physiol 286: H1573-H1589, 2004, and simulates the human ventricular action potential. It consists of 17 variables. The voltage is in layer 0. The name of the module is ttnnp04. This implementation is based on author's code retrieved 2013/02/02. It does not provide the true ODE right-hand sides, instead it performs the timestep, using Rush-Larsen formula for all gating variables and explicit Euler for all other variables. Hence it requires the time step as parameter ht.
beatbox/data/scripts/sequential/TenTusscherPanfilov_modelS/ttnnp04_ap.bbs
Beatbox program to demonstrate the ten Tusscher et al. 2004 human ventricle AP. There are no inputs,and the output is ttnnp04_ap.vtg. To run,
Beatbox_SEQ ttnnp04_ap.bbs
You can produce an AP profile as shown in the figure below. TTNP AP profile.

TTP Human Ventricle Model from author source code

This model was published in "Alternans and spiral breakup in a human ventricular tissue model", by K. H. W. J. ten Tusscher and A. V. Panfilov, J Physiol Heart Circ Physiol 291: H1088 –H1100, 2006, and simulates the human ventricular action potential. It consists of 19 variables. The voltage is in layer 0. The name of the module is ttnp. This implementation is based on CELLML version and provides true ODE right-hand sides, unlike TTP06 implementation described below. Note that the resulting ODEs are very stiff and require very small time steps. The example of TTNP cell model AP is in
beatbox/data/scripts/sequential/TenTusscherPanfilov_modelS/ttp06_ap.bbs
Beatbox program to demonstrate the ten Tusscher et al. 2006 human ventricle AP. There are no inputs,and the output is ttp06_ap.vtg. To run,
Beatbox_SEQ ttp06_ap.bbs
You can produce an AP profile as shown in the figure below. TTNP AP profile.

TTP06

This model was published in "Alternans and spiral breakup in a human ventricular tissue model", by K. H. W. J. ten Tusscher and A. V. Panfilov, J Physiol Heart Circ Physiol 291: H1088 –H1100, 2006, and simulates the human ventricular action potential. It consists of 19 variables. The voltage is in layer 0. The name of the module is ttp06. This implementation is based on author's code retrieved 2013/02/08. Unlike implementation TTNP described above, this one does not provide the true ODE right-hand sides, instead it performs the timestep, using Rush-Larsen formula for all gating variables and explicit Euler for all other variables. Hence it requires the time step as parameter ht.

beatbox/data/scripts/sequential/TenTusscherPanfilov_modelS/ttp06.bbs
TTNP AP profile.

A slightly more advanced example of this model can be found in the directory:

beatbox/data/scripts/sequential/TenTusscherPanfilov_modelS/ttp06/

The bbs.benchmark script there does the computational job, Makefile describes the workflow leading to the final report and report.pdf is the report itself.


Copyright © (2010-2012) Vadim Biktashev, Alexander Karpov,Irina Biktasheva, Ross McFarlane;
Copyright © 2012Sanjay Kharche
This file is part of the Beatbox distribution.