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\Ola\PycharmProjects\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\Ola\PycharmProjects\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.059957)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\calc.out
stderr : C:\Users\Ola\PycharmProjects\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:
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:
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\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim study "variants" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A1" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A2" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim case "A3" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim case "B1" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
INFO: Parsim case "B2" successfully created
INFO: Found template as absolute or relative path: C:\Users\Ola\PycharmProjects\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.070959)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A1\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A1\calc.out
stderr : C:\Users\Ola\PycharmProjects\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.058967)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A2\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A2\calc.out
stderr : C:\Users\Ola\PycharmProjects\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.056948)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A3\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_A3\calc.out
stderr : C:\Users\Ola\PycharmProjects\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.058966)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B1\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B1\calc.out
stderr : C:\Users\Ola\PycharmProjects\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.057967)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B2\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B2\calc.out
stderr : C:\Users\Ola\PycharmProjects\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.061950)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B3\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\study_variants\case_B3\calc.out
stderr : C:\Users\Ola\PycharmProjects\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
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 volume mass
1 69.976002 118.945208 124886.521349
2 49.999998 84.989997 89235.246931
3 42.007998 71.405195 74971.884491
4 30.016002 51.021200 53569.709150
5 69.976002 90.982798 95527.388551
6 49.999998 65.009997 68257.246770
7 42.007998 54.618799 57347.008010
8 30.016002 39.026806 40976.194750
9 69.976002 118.945208 113003.895050
10 49.999998 84.989997 80744.746270
11 42.007998 71.405195 67838.505510
12 30.016002 51.021200 48472.691250
13 69.976002 90.982798 86438.207050
14 49.999998 65.009997 61762.748029
15 42.007998 54.618799 51890.589990
16 30.016002 39.026806 37077.416851
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 : 2020-07-30 12:03:22
Description :
Project name : myProject
Study name :
Template path : C:\Users\Ola\PycharmProjects\psm\doc\demo\modelTemplates\box
Creation log file : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\.psm\create.log
Parsim version : 2.0.0
Project path : C:\Users\Ola\PycharmProjects\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
2020-07-30 12:03:22 - INFO: Parsim case "bigBox" successfully created
2020-07-30 12:03:23 - INFO: Executing command/script/executable: calc.py
2020-07-30 12:03:23 - INFO: Executable finished successfully (runtime: 0:00:00.059957)
Executable : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\calc.py
stdout : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\calc.out
stderr : C:\Users\Ola\PycharmProjects\psm\doc\demo\case_bigBox\calc.err