Skip to content

A framework for setting up numerical simulation runs in a fool-proof and reproducible fashion.

Notifications You must be signed in to change notification settings

DeltaBoyBZ/simpsim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SIMPSIM

Introduction

Simpsim is a framework for generating simulation runs in a way which is reproducable and avoids human error. It abstracts the workflow into three stages:

  1. Exporting data necessary to do runs e.g. executables and standard parameter files
  2. Importing data by means of querying what has been exported
  3. Producing (many) runs by means of modifying templates

The third stage is further segmented into templating, modifying, and instancing.

Simpsim grew out of the desire to quickly generate runs for testing minor variations of the same program. It allowed similarly-named builds to be tested in a consistent way, while maintaining information about each build so that there can be little doubt about the results of testing.

Get Started

Dependencies

Simpsim is written in Guile Scheme, so it is recommended the user install the latest stable version. For information, visit https://www.gnu.org/software/guile/.

Simpsim produces shell scripts. These should run in any POSIX-compliant shell, but most testing has used Bash.

As Simpsim is extensible, it is possible that produced scripts use commands which are not on the host system. Standard scripts however only use standard tools such as grep and sed, which the user is very likely to have if they are using any GNU/Linux disro.

System Setup

In order to use Simpsim, we need two things:

  1. For Guile to recognise the Simpsim modules
  2. For Simpsim scripts to be callable

Guile Modules

The simplest way to make Guile recognise Simpsim, is to add the repo root to your GUILE_LOAD_PATH,

export GUILE_LOAD_PATH="/path/to/simpsim:$GUILE_LOAD_PATH"

To check that this has worked, start a guile REPL and run,

(use-modules (simpsim)
			   (simpsim formats)
			   (simpsim edits)
			   (simpsim metas))

It should execute without issue.

Shell Scripts

Add the Simpsim root to your PATH,

export PATH="/path/to/simpsim:$PATH"

Tutorial

Exporting

Exporting can be used in many contexts e.g.

  • exporting a build of a project
  • exporting a set up scripts which make up a workflow
  • exporting a significant run

Many exports are similar in the sense that they belong to the same project and contain similar files with small changes. The problem of managing these becomes worse when we consider differences in compiled binaries.

Thus, when exporting, it is useful to have metadata. For example, the date of export, or the Git branch we happen to have checked out. It is convenient to have these computed automatically on export.

The `simpsim` Guile module provides the function `make-export`, which takes as input a data structure representing the exported bundle. The function returns a Bash script in string form.

Here is an example of a simple export script.

 (use-modules (simpsim)
			   (simpsim metas))

 (define my-export
	`("project"
	  (files . "exe/compiled-code")
	  (dirs  . "par")
	  (meta (branch . ,(meta-git-current-branch))
			(commit . ,(meta-git-head-commit))
			(date   . "$(date)")
			(seconds . "$(date +%s)"))))

 (display (make-export "$HOME/simpsim-data" my-export))

The final line constructs the script which exports the desired data and metadata, then prints it to standard output.

Observer that the script does not execute the commands in the script. Simpsim itself does not interact with the file system. Rather, it produces scripts which do, and the user should pipe this script into a shell (upon reviewing of course).

$ guile -s export.scm | sh

A subdirectory of $HOME/simpsim-data called project-<uuid> is created and the given files and directories are copied to it. The <uuid> guarantee no name clashes in the root. There is then a meta subdirectory which contains information distinguishing exports under the same project name.

Importing

A list of exports under the name project are listed by running:

$ getsim project

All listed directories will be subdirectories of the directory specified in environment variable SIMPSIM_ROOT. In general, we expect many subdirectories to be listed. The can be filtered according to the value of their metadata. For example, if we want a version of our code which was built on the experimental branch we might run:

$ getsim project | simmeta branch experimental

Furthermore, if there are still multiple exports, we can select the one which was built most recently with:

$ getsim project | simmeta branch experimental | simrecent

When we have a single directory, we can then copy that directory to our working directory as data.

$ getsim project | simmeta branch experimental | simrecent | simfetch data 

Instancing

There are many scenarios in which we want to set up many runs from identical or similar data. Identical data might be in the form of compiled binaries or data tables. Similar data could be for example parameter files which we would like to modify slightly for each run.

Instancing comprises three steps:

  • define a basic template
  • define a set of modifications to the template
  • define an instance

Here is a simple template:

(use-modules (simpsim edits)
			 (simpsim formats))

(define (less-than a)
  (lambda (x) (< x a))))

(define template
`((data-dir . "data")
  (carbons "compiled-code")
  (editables (parfile (src . "par/basic.par")
					  (dst . "input.par")
					  (edits (grid-spacing . ,(generic-c "dx" c-double-format))
							 (time-step    . ,(generic-c "dt" c-double-format))
							 (output-steps . ,(generic-c "Nout" int-format)))))))

Templates consist of two parts: carbons and editables. The carbons are carbon copies of files in the data directory. The editables are files which are modified in some way for our instance. The edits are handles to functions which, given some value, return a script for making the necessary edit to the file.

The c-double-format is a formatting function which converts values in Scheme to an appropariately formatted string. The generic-c function returns a function whose argument corresponds to a particular value of the declared parameter. Upon evaulation, this function in turn accepts a specific filename to which the edit applies.

Once a template is defined, we define modifications e.g.

 (define (calculate-dt dx cfl dt0)
	(if (< (/ dt0 dx) cfl) dt0
		(calculate-dt dx cfl (/ dt0 2))))

 (define setup-grid (dx cfl dt0)
	`((editable . parfile)
	  (vars (grid-spacting . ,dx)
			(time-step     . ,(calculate-dt dx cfl dt0)))))

 (define setup-output (dx cfl t-plt t-chk)
	(let (dt (calculate-dt dx cfl t-chk))
	  `((editable . parfile)
		(vars (checkpoint-steps . ,(/ t-chk dt))
			  (plot-steps       . ,(/ t-plt dt))))))

Then the instance, which typically defines a single run of our simulation,

 (define (sim-run dx cfl t-plt t-chk)
	`((run-dir . (format #f "run-dr=~,4f" dr))
	  (template . ,template)
	  (ammendments ,(setup-grid dx cfl t-chk)
				   ,(setup-output dx cfl t-plt t-chk))))

With all this, we can obtain the Bash script generating a desired run with e.g.

(use-modules (simpsim))

(display (make-script (sim-run 0.001 0.4 0.1 5.0)))

Creating Many (related) Runs

For single runs, using a tool like Simpsim is likely unnecessary. However, if we wish to created many related runs, Simpsim helps us to systematically generate the correct parameters in a way which evades human error.

The example which was the inspiration for Simpsim is creating a set of runs for a convergence test. With the framework above,

(use-modules (simpsim))

(define (res-pair dx)
  (list dx (/ dx 3.0)))

(display (string-concatenate (map make-script
								  (map (lambda (dx) (sim-run dx 0.4 0.1 5.0))
									   (delete-duplicates
										(apply append
											   (map res-pair
													'(0.3 0.27 0.24 0.21 0.18
														  0.15 0.12 0.09 0.06
														  0.03 0.027 0.024 0.021 0.018
														  0.015 0.012 0.009 0.006
														  0.003))))))))

The produced script creates many runs over a range of spatial resolutions. The time steps are selected automatically such that:

  • They satisfy the CFL condition
  • They evenly divide (to double precision) the checkpoint time T = 5.0

The data produced by these simulations is then ideal for studying the convergence of a numerical scheme impelemented by the simulation.

Goals

Add More Edit Methods

The existing edit methods are specifically designed for editting parameter files of the form,

var = value

of of the form,

foo {
  bar {
    baz = value
  }
}

and for adding or deleting such entries. Simpsim is designed to be extensible, so the user can create arbitrary modes of editting. A greater volume of standard edits would however be a good addition. Furthermore, edit methods should be generalised to take more than a single argument, or apply to more than one file.

As of now, there is one more mode of file editing: nested-c. This appears to work well, but has not been subjected to proper testing.

More Case Studies

Simpsim boasts to be general, but the truth is it has only been tested properly on a single project As more projects make use of Simpsim, missing features and current flaws will become more apparent.

About

A framework for setting up numerical simulation runs in a fool-proof and reproducible fashion.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published