Tutorial
Your parameterized model templates are usually stored in the project directory.
The default location is a subdirectory modelTemplates in the root of the project directory,
but this can be customized by changing the project configuration settings.
In some cases it is practical to store all model templates in a centralized location, separate from
the project directory.
In this tutorial we will set up a very simple simulation project example, with one model template located inside the project directory.
For this tutorial, we assume that you work in Linux or Cygwin.
Parsim is a command-line tool. The main program is called psm. Use it with option -h to get information about available subcommands. You get detailed information about each subcommand using the command psm help <command>.
Creating a project
Let’s call our project “myProject” and assume we want it in project directory my_proj in our
home directory. We create the project directory and initialize it using the psm init command:
$ mkdir ~/my_proj
$ cd ~/my_proj
$ psm init myProject
INFO: Parsim project "myProject" successfully created
Creating a simple model template
Assume we have the following Python script, named boxcalc.py, which represents a very simple “simulation model”:
#! /usr/bin/env python
from __future__ import print_function
import json
# Model parameters
#- Geometry
length = 12
width = 4
height = 1.5
#- Material properties
density = 1000 # kg/m3
color = 'black'
# Calculations...
base_area = length * width
volume = base_area * height
mass = volume * density
# Print output (in json format)
output = {
'base_area': base_area,
'volume': volume,
'mass': mass
}
print('base_area =', base_area)
print('volume =', volume)
print('mass =', mass)
with open('output.json', 'w') as f:
f.write(json.dumps(output))
print('Successfully written results to output file "output.json"')
You can run this script through the Python interpreter:
$ python boxcalc.py
base_area = 48
volume = 72.0
mass = 72000.0
Successfully written results to output file "output.json"
If you run Linux, you can give the script executable permissions and run it directly:
$ ./boxcalc.py
base_area = 48
volume = 72.0
mass = 72000.0
Successfully written results to output file "output.json"
The script uses the json library to format the output dictionary in json format.
The resulting output file output.json has the following content:
{"base_area": 48, "volume": 72.0, "mass": 72000.0}
This script has hard-coded parameter values. We can say that these values define
a working reference case, where the results are known and “validated”, in some sense.
This is a good starting point for creating a parameterized model template, which we will call box.
By default, Parsim assumes that model templates are stored in a subdirectory modelTemplates in the
project directory.
Let us start by creating the model template directory, and copy our existing model files there.
For your convenience, the boxcalc.py script can be found in the demo subdirectory of
your Parsim installation; in our case, Parsim is installed in $HOME/psm.
As we copy, we change the name of the script to calc.py.
Inside the project directory,
$ mkdir modelTemplate
$ mkdir modelTemplate/box
$ copy $HOME/psm/demo/boxcalc.py modelTemplate/box/calc.py
Now we go to the template directory, and continue there:
cd modelTemplate/box
In a real application, the executable for running the simulation would usually read input data from another file,
but in our example the input data is hard-coded in the script itself. This means that the script itself will be
parameterized. Let us start by adding the extension .macro to the file name, so that Parsim will parse it for
parameter substitution when you create cases from the template. We also set execute permissions on the script file
(permission of the parameterized file will be inherited by the resulting script file, when
cases are created):
$ mv calc.py calc.py.macro
$ chmod u+x calc.py.macro
The file contains the following numerical model parameters: length, width, height and density.
It also contains the string parameter color. We note that the name of the output file is also hard-coded
in the script file; while we’re at it, we let this file name be a parameter, too.
We now create a default parameter file with the standard name default.parameters. We use the hard-coded
values as the default values, as this represents our known and presumably validated reference case…
The contents of default.parameters could then be:
#==========================================================
# Model template "Box"
#
# Computes base area, volume and mass of a rectangular box
#==========================================================
#-----------------------
# Geometry
#-----------------------
length: 12 # [m]
width: 4 # [m]
height: 1.5 # [m]
#-----------------------
# Material properties
#-----------------------
density: 1000 # [kg/m3] Density of the solid material
color: 'black' # Color of the box
#-----------------------
# Configuration
#-----------------------
output_file: 'results.json' # Holds scalar results, written as a json-format dictionary
Note that we this file is in parameter file format, and that we have used comments to document the model template.
The next step is to substitute the hard-coded values in the script file with the parameters we defined:
#! /usr/bin/env python
from __future__ import print_function
import json
# Model parameters
#- Geometry
length = $(length)
width = $(width)
height = $(height)
#- Material properties
density = $(density) # kg/m3
color = '$(color)'
# Calculations...
base_area = length * width
volume = base_area * height
mass = volume * density
# Print output (in json format)
output = {
'base_area': base_area,
'volume': volume,
'mass': mass
}
print('base_area =', base_area)
print('volume =', volume)
print('mass =', mass)
with open('$(output_file)', 'w') as f:
f.write(json.dumps(output))
print('Successfully written results to output file "%s"' % '$(output_file)')
Note that we put quotes around $(output_file), as the parameter substitution returns the string without quotes.
That’s it, our first model template is ready!
Creating a case and running the simulation
To create cases, we use the psm case command. See psm case for details.
The following creates a case in a case directory case_ref, with the default parameters defined above:
$ psm case --template box ref
INFO: Found template in project template directory: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "ref" successfully created
In this simple example, we can easily make a custom case with parameters modified on the command-line. For example, let’s make a case “bigBox”, with higher box and larger density:
$ psm case --template box --define height=20,density=1200 bigBox
INFO: Found template in project template directory: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "bigBox" successfully created
Let’s run the “simulation” of this larger box, using the psm run command:
$ psm run bigBox calc.py
INFO: Executing command/script/executable: calc.py
bigBox: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.068663)
Executable : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.err
As indicated by the console output, the standard output of the script is found
in the file calc.out in the case directory:
base_area = 48
volume = 960
mass = 1152000
Successfully written results to output file "results.json"
Creating and running a study
It is equally simple to setup and operate on a whole parameter study, containing several cases, using the psm study command.
You would usually use a parameter file to define parameter values that are common to all cases and a caselist file to define the case names and the parameters that differ between cases. In our simple tutorial example, however, it is sufficient to use only a caselist file.
Let us assume that we want to create a study named variants, with case names and parameters defined
in a caselist file named variants_caselist, as follows:
CASENAME length height density
A1 10 12 1200
A2 10 16 1000
A3 10 20 900
B1 15 12 1200
B2 15 16 1000
B3 15 20 900
We now use the psm study command to create the study and all its cases:
$ psm study --template box --description "Variants in series A and B" --name "variants" variants_caselist
INFO: Found template in project template directory: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim study "variants" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A1" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A2" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A3" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "B1" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "B2" successfully created
INFO: Found template as absolute or relative path: C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
INFO: Parsim case "B3" successfully created
This creates a study directory study_variants in the current directory; the study directory
contains all the case directories.
Note that we used option --name for naming the study and the option --description
to provide useful information about its content.
We can run the simulation of all cases of the study with one single command:
$ psm run variants calc.py
INFO: Starts RUN operation on cases (executable: calc.py)...
INFO: Executing command/script/executable: calc.py
A1: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.069174)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A1\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A1\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A1\calc.err
INFO: Executing command/script/executable: calc.py
A2: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.077443)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A2\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A2\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A2\calc.err
INFO: Executing command/script/executable: calc.py
A3: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.064913)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A3\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A3\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_A3\calc.err
INFO: Executing command/script/executable: calc.py
B1: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.067247)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B1\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B1\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B1\calc.err
INFO: Executing command/script/executable: calc.py
B2: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.065968)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B2\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B2\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B2\calc.err
INFO: Executing command/script/executable: calc.py
B3: Running executable...
INFO: Executable finished successfully (runtime: 0:00:00.066673)
Executable : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B3\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B3\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\study_variants\case_B3\calc.err
INFO: Successfully finished RUN operation!
Collecting results from a Study
We can use the psm collect command to collect the output data from all cases and present it in one single table.
$ psm collect variants
INFO: Start collecting case results...
Case results files (input) : ['results.json']
Study results file (output) : results.txt
C:\Users\olawi\repos\psm\src\parsim\core.py:1716: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\s+'`` instead
self._results = pd.read_csv(os.path.join(self.path, 'study.results'),
INFO: Successfully finished collecting case results!
By default, results are read from a JSON formatted file results.json in the case directories. For the example
here, a results file in a case would look something like this:
{"base_area": 40, "volume": 800, "mass": 720000}
The --input option can be used to specify a custom file path inside the case directory (a comma-separated list
of multiple files is allowed).
Unless a delimited format is requested (by defining a delimiter with the --delim option),
the output is in tabular format, white fixed column spacing.
The name of the output file is derived from the name of the (first) input file, unless specified explicitly with
the --output option. )
In this example, the output is written to the file results.txt, located in the study directory:
CASENAME base_area mass volume density height length
A1 40 576000 480 1200 12 10
A2 40 640000 640 1000 16 10
A3 40 720000 800 900 20 10
B1 60 864000 720 1200 12 15
B2 60 960000 960 1000 16 15
B3 60 1080000 1200 900 20 15
If the input file is missing or incomplete for one or more cases, this will be reported. Only the succesfully processed cases will be included in the output file.
Every time the collect command is run (e.g. collecting additional results from another simulation in the same Study),
a tabular text file “study.results” inside the Study directory will be updated with the new data. This file will
then contain all aggregated results for the study. All cases are reported in this file, even if
data is missing. Missing data is reported as “NaN” in the table. Input parameters are not included in “study.results”.
These can instead be found separately in the file “study.caselist”. The files “study.results” and “study.caselist”
could be conveniently imported into pandas DataFrame objects for further processing. As an example, consider a study
with 16 cases created from the “box” template. One simulation executable outputs results variables “basearea”, “mass”
and “volume” for all 16 cases. Another simulation outputs the result variable “d_eff” in another results file, but this
simulation fails for several of the cases. The psm collect command is run separately after each of the simulations,
to collect results. The file “study.results” would now look something like this:
CASENAME base_area d_eff mass volume
1 69.976002 8.365166 124886.521349 118.945208
2 69.976002 8.365166 113003.895050 118.945208
3 69.976002 8.365166 95527.388551 90.982798
4 69.976002 8.365166 86438.207050 90.982798
5 42.007998 NaN 74971.884491 71.405195
6 42.007998 NaN 67838.505510 71.405195
7 42.007998 NaN 57347.008010 54.618799
8 42.007998 NaN 51890.589990 54.618799
9 49.999998 7.071068 89235.246931 84.989997
10 49.999998 7.071068 80744.746270 84.989997
11 49.999998 7.071068 68257.246770 65.009997
12 49.999998 7.071068 61762.748029 65.009997
13 30.016002 NaN 53569.709150 51.021200
14 30.016002 NaN 48472.691250 51.021200
15 30.016002 NaN 40976.194750 39.026806
16 30.016002 NaN 37077.416851 39.026806
Note that all output variables of both simulations are included in the file, but there is missing data, “NaN”, in the “d_eff” column for some of the cases.
Object information and event logs
We can use the psm info to get information about the properties of a case, study or about the project as
a whole. For example, let’s look at the properties of
the bigBox case:
$ psm info bigBox
Case ID : bigBox
Creation date : 2025-11-09 21:24:16
Description :
Project name : myProject
Study name :
Template path : C:\Users\olawi\repos\psm\doc\demo\modelTemplates\box
Creation log file : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\.psm\create.log
Parsim version : 2.2.0
Project path : C:\Users\olawi\repos\psm\doc\demo
Study path :
--------------------------------------------------------
User parameters (command-line or parameter file)
--------------------------------------------------------
density : 1200
height : 20
--------------------------------------------------------
Default parameters (defined in template)
--------------------------------------------------------
color : black
length : 12
output_file : results.json
width : 4
All Parsim objects (cases, studies and project) have an event log, where all events and operations are logged.
The psm log command prints the event log to the console.
For example, we look at the event log of the bigBox case:
$ psm log bigBox
2025-11-09 21:24:16 - INFO: Parsim case "bigBox" successfully created
2025-11-09 21:24:17 - INFO: Executing command/script/executable: calc.py
2025-11-09 21:24:17 - INFO: Executable finished successfully (runtime: 0:00:00.068663)
Executable : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.py
stdout : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.out
stderr : C:\Users\olawi\repos\psm\doc\demo\case_bigBox\calc.err