Case Metadata Format
The case.yml file contains metadata for simulation cases. This file is used
by multiphasepy to manage case information, validation data, and workflow
parameters.
name: "Name of the Case"
workflow:
Allrun:
container: "oras://<registry>/<image>:<tag>.sif"
resources:
cores: 4 # Ignored for OpenFOAM Foundation Software setups which obtain
# number of cores from number of subdomains in
# `system/decomposeParDict`
runtime: 1h
partition: "cpu-skylake"
validation:
"alpha.air":
experiment: "validation/experiment/alpha.dat"
reference: "validation/reference/line.csv"
simulation: "postProcessing/../line.csv"
keywords:
BUBBLE SIZE: "monodisperse"
BUBBLE SIZE CHANGES: "coalescence-breakup"
File Location
The metadata file should be placed in the root directory of a simulation case:
simulation-case/
├── Allrun
├── case.yml # Metadata file
├── system/
├── constant/
└── validation/
File Format
The case.yml uses YAML format and supports the following top-level keys:
Schema
name
Human-readable name for the simulation case.
Type: string
workflow
Workflow-related configuration for job scheduling and execution.
workflow.<rule_name>
Configuration for the given rule.
Available rule names are:
Allpre
Allrun
Allvalidate
Allupdate
Allclean
custom_command
Example:
workflow:
Allrun:
...
workflow.<rule_name>.input
Declaration of case-to-case dependencies.
Type: list[string]
To understand the syntax it is necessary to understand that the successful
execution of a rule for a case produces a marker file of the form
(<target_dir>)/path/to/case/.<rule_name>. A dependency is considered as
resolved if this marker file is present in the case that is the dependency.
It is possible to have a list of dependencies.
The path to the marker file has to be specified relative to the dependent case,
with the consequence that it must be updated when the case is moved within the
case database. The path definition also depends on whether the source and the
target case are regular or template cases or a mixture thereof. Examples are
given for the scenario of using the OpenFOAM Foundation Software utility
foamMergeCase to manage case variations. The concept also applies for mapping
of results from one case to another.
Example for two regular case setups:
# case.yml
workflow:
Allpre:
input:
- "../<regular-source-case>/.init"
This will pause execution of the Allpre script until the source case has been
initialized. The corresponding Allpre script should look like this
#!/bin/bash
cd "${0%/*}" || exit 1 # Run from this directory
# Source run functions
. "$WM_PROJECT_DIR/bin/tools/RunFunctions"
runApplication foamMergeCase ../<regular-source-case>
Note that for applying foamMergeCase it is mandatory that it is placed in
Allpre to keep the single_timestep workflow option functioning, which
adjusts the (OpenFOAM Foundation Software) case when the Allrun rule is
executed. This however happens before the corresponding case-level Allrun is
executed, so the case has to be complete and executable before the Allrun
rule. For the use case of mapping of simulation results, the dependency can be
encoded into the Allrun script.
Also note that because of the additional requirement that cases should also be
executable standalone merely be running the Allrun script, a safeguard is
required in Allrun to keep the Allpre script from being executed in a
workflow
#!/bin/bash
cd "${0%/*}" || exit 1 # Run from this directory
# Source run functions
. "$WM_PROJECT_DIR/bin/tools/RunFunctions"
if [ -z "${SNAKEMAKE_WORKFLOW:-}" ]; then
./Allpre
fi
which implies that the Allpre script will execute if the SNAKEMAKE_WORKFLOW
variable has a zero length.
Example for two templated case setups
# case.yml.jinja
workflow:
Allpre:
input:
- "../../<templated-source-case>/{{case}}/.init"
Here the execution of the Allpre script depends on initialization of the
matching <templated-source-case>/{{case}} variant, with {{case}} being the
place holder (template parameter) of the case variant in
caseParameterTable.ecsv. Because the cases derived from a template live inside
subdirectories, the path needs two ../ segments. The corresponding
Allpre.jinja script should look like this
#!/bin/bash
cd "${0%/*}" || exit 1 # Run from this directory
# Source run functions
. "$WM_PROJECT_DIR/bin/tools/RunFunctions"
runApplication foamMergeCase ../../<templated-source-case>/{{case}}
Example for a regular case depending on a template case
# case.yml
workflow:
Allpre:
input:
- "../<regular-source-case>/<case-variant>/.init"
Here the execution of the Allpre script depends on the matching
<templated-source-case>/<case-variant> variant, with <case-variant> being
the actual name of the case variant in the caseParameterTable.ecsv of the
<templated-source-case> forming the dependency. The corresponding
Allpre script should look like this
#!/bin/bash
cd "${0%/*}" || exit 1 # Run from this directory
# Source run functions
. "$WM_PROJECT_DIR/bin/tools/RunFunctions"
runApplication foamMergeCase ../<templated-source-case>/<case-variant>
workflow.<rule_name>.container
Container image URL for running the simulation in a containerized environment.
Set the container to false to force the rule to run without container, even if
a default container is set. To explicitly use the default container, set the
container to true.
Type: string | bool
Example with Apptainer|Singularity:
workflow:
Allrun:
container: "oras://<registry>/<image>:<tag>.sif"
Example with Docker:
workflow:
Allrun:
container: "docker://<registry>/<image>:<tag>"
Note that the selected container can be a template parameter as well to test different versions of a simulation software.
# case.yml.jinja
workflow:
container: {{image}}
workflow.<rule_name>.resources
Rule resources configuration, resources include: cores, runtime, partition, mem, gpu
workflow.<rule_name>.resources.cores
Number of CPU cores to use for the simulation.
Type: integer
Example:
workflow:
Allrun:
resources:
cores: 4
workflow.<rule_name>.resources.runtime
Amount of wall clock time a job needs to run. It can be given as an integer
defining minutes or as a string defining a time span. A time span is a number
followed by a unit (s, m, h, d for seconds, minutes, hours, days).
Type: integer | string
Example:
workflow:
Allrun:
resources:
runtime: 1h
workflow.<rule_name>.resources.partition
Cluster partition name for job scheduling.
Type: string
Example:
workflow:
Allrun:
resources:
partition: "cpu"
workflow.<rule_name>.resources.mem
Amount of memory needed for the job. They are given as strings with a number
followed by a unit (B, KB, MB, GB, TB).
Type: string
Example:
workflow:
Allrun:
resources:
mem: 100GB
workflow.<rule_name>.resources.gpu
Number of GPU cards to use for the simulation.
Type: integer
Example:
workflow:
Allrun:
resources:
gpu: 2
validation
Validation data configuration for comparing simulation results with experimental or reference data.
Type: object
Each field in the validation section represents a physical quantity to be
validated. The key format is typically <field> (e.g., alpha.air,
U.water).
Properties for each field:
experiment(string): Path to experimental data filereference(string): Path to reference/baseline data filesimulation(string): Path to simulation output data file
Example:
validation:
"alpha.air":
experiment: "validation/alpha.dat"
reference: "validation/reference/line.csv"
simulation: "postProcessing/sampleFields/4/line.csv"
"U.water":
experiment: "validation/velocity.dat"
reference: "validation/reference/velocity.csv"
simulation: "postProcessing/sampleFields/4/velocity.csv"
keywords
Keywords for categorizing and searching simulation cases. Keywords follow a controlled vocabulary defined in the reference keywords file.
Type: object
Each keyword category contains an applicable value.
Example:
keywords:
BUBBLE SIZE: "monodisperse"
BUBBLE SIZE CHANGES: "coalescence-breakup"