Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 33 additions & 20 deletions .github/workflows/run-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,43 @@ jobs:
cd $GITHUB_WORKSPACE/benchmarks/linear-elastic-plate-with-hole/
python generate_config.py

- name: generate-snakemake-fenics-workflow
shell: bash -l {0}
run: |
cd $GITHUB_WORKSPACE/benchmarks/common/
python simulation_tool_snakefile_generator.py --benchmark_name linear-elastic-plate-with-hole --tool fenics --simulation_script run_fenics_simulation.py --environment_file environment_simulation.yml

- name: run_linear-elastic-plate-with-hole-benchmarks_snakemake
shell: bash -l {0}
run: |
cd $GITHUB_WORKSPACE/benchmarks/linear-elastic-plate-with-hole/
snakemake --use-conda --force --cores 'all'
snakemake --use-conda --force --cores all \
snakemake --use-conda --force --cores 'all' --config tool="fenics"
snakemake --use-conda --force --cores all --config tool="fenics" \
--reporter metadata4ing \
--report-metadata4ing-paramscript ../common/parameter_extractor.py \
--report-metadata4ing-filename snakemake_provenance
unzip snakemake_provenance -d snakemake_provenance

- name: run_linear-elastic-plate-with-hole-benchmarks_nextflow
shell: bash -l {0}
run: |
cd $GITHUB_WORKSPACE/benchmarks/linear-elastic-plate-with-hole/
nextflow run main.nf -params-file workflow_config.json -c ../common/nextflow.config -plugins nf-prov@1.4.0
--report-metadata4ing-filename snakemake_provenance_fenics
unzip snakemake_provenance_fenics -d snakemake_provenance_fenics

- name: Archive Linear Elastic plate with a hole benchmark data for snakemake
snakemake --use-conda --force --cores 'all' --config tool="kratos"
snakemake --use-conda --force --cores all --config tool="kratos" \
--reporter metadata4ing \
--report-metadata4ing-paramscript ../common/parameter_extractor.py \
--report-metadata4ing-filename snakemake_provenance_kratos
unzip snakemake_provenance_kratos -d snakemake_provenance_kratos

- name: Archive Linear Elastic plate with a hole benchmark data for snakemake fenics
uses: actions/upload-artifact@v4
with:
name: snakemake_results_linear-elastic-plate-with-hole
name: snakemake_fenics_result_linear-elastic-plate-with-hole
path: |
benchmarks/linear-elastic-plate-with-hole/snakemake_provenance/
benchmarks/linear-elastic-plate-with-hole/snakemake_provenance_fenics/

- name: Archive Linear Elastic plate with a hole benchmark data for nextflow
- name: Archive Linear Elastic plate with a hole benchmark data for snakemake kratos
uses: actions/upload-artifact@v4
with:
name: nextflow_results_linear-elastic-plate-with-hole
name: snakemake_kratos_result_linear-elastic-plate-with-hole
path: |
benchmarks/linear-elastic-plate-with-hole/nextflow_results/
benchmarks/linear-elastic-plate-with-hole/snakemake_provenance_kratos/

process-artifacts:
runs-on: ubuntu-latest
Expand All @@ -82,11 +89,17 @@ jobs:
- name: Checkout repo content
uses: actions/checkout@v2

- name: Download artifact
- name: Download snakemake fenics artifact
uses: actions/download-artifact@v4
with:
name: snakemake_fenics_result_linear-elastic-plate-with-hole
path: ./snakemake_fenics_provenance

- name: Download snakemake kratos artifact
uses: actions/download-artifact@v4
with:
name: snakemake_results_linear-elastic-plate-with-hole
path: ./snakemake_provenance
name: snakemake_kratos_result_linear-elastic-plate-with-hole
path: ./snakemake_kratos_provenance

- name: Setup Mambaforge with postprocessing env
uses: conda-incubator/setup-miniconda@v3
Expand All @@ -99,7 +112,7 @@ jobs:
- name: Run plotting script
shell: bash -l {0}
run: |
python benchmarks/linear-elastic-plate-with-hole/plot_metrics.py ./snakemake_provenance
python benchmarks/linear-elastic-plate-with-hole/plot_metrics.py ./snakemake_fenics_provenance ./snakemake_kratos_provenance

- name: Upload PDF plot as artifact
uses: actions/upload-artifact@v4
Expand Down
2 changes: 0 additions & 2 deletions .gitignore

This file was deleted.

27 changes: 0 additions & 27 deletions benchmarks/common/nextflow.config

This file was deleted.

104 changes: 104 additions & 0 deletions benchmarks/common/simulation_tool_snakefile_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
Script to generate a Snakefile for simulation tools in the benchmark workflow.

This script creates a standardized Snakefile that follows the expected output format
for integration with the main benchmark workflow.
"""

import argparse
import os
from pathlib import Path


def generate_snakefile(benchmark_name: str, tool_name: str, environment_file: str, simulation_script: str, output_path: str = None):
"""
Generate a Snakefile for a simulation tool.

Args:
tool_name: Name of the simulation tool (e.g., 'fenics', 'kratos')
environment_file: Path to the conda environment YAML file (relative to tool directory)
simulation_script: Path to the simulation Python script (relative to tool directory)
output_path: Optional path where to save the Snakefile. If None, saves to {tool_name}/Snakefile
"""

# Load template from external file
template_path = Path(__file__).parent / "snakefile_template.txt"
with open(template_path, 'r') as f:
snakefile_template = f.read()

# Replace placeholders with actual values
snakefile_content = snakefile_template.replace("{TOOL_NAME}", tool_name) \
.replace("{SIMULATION_SCRIPT}", simulation_script) \
.replace("{ENVIRONMENT_FILE}", environment_file)

# Determine output path
if output_path is None:
output_path = f"../{benchmark_name}/{tool_name}/Snakefile"

# Write the Snakefile
with open(output_path, 'w') as f:
f.write(snakefile_content)

print(f"Snakefile generated successfully: {output_path}")

def main():
parser = argparse.ArgumentParser(
description="Generate a simulation-tool-specific Snakefile for running the simulation.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=
"""
!IMPORTANT!:The scripts to be stored inside the tool's sub-directory in the benchmark folder. E.g., benchmarks/linear-elastic-plate-with-hole/tool_name/

Execution example for fenics:
python generate_tool_snakefile.py --tool fenics --env environment_simulation.yml --script run_fenics_simulation.py

The simulation script must accept these command-line arguments:
--input_parameter_file: JSON file with simulation parameters
--input_mesh_file: Input mesh file (.msh format)
--output_solution_file_zip: Output ZIP file containing solution visualization files (VTK)
--output_metrics_file: Output JSON file with computed metrics

"""
)
parser.add_argument(
'--benchmark_name',
type=str,
required=True,
help='Name of the benchmark (same as the benchmark directory name)'
)

parser.add_argument(
'--tool',
type=str,
required=True,
help='Name of the simulation tool (e.g., fenics, kratos, abaqus)'
)

parser.add_argument(
'--environment_file',
type=str,
required=True,
help='Conda environment YAML file name'
)

parser.add_argument(
'--simulation_script',
type=str,
required=True,
help='Simulation script name'
)

args = parser.parse_args()

generate_snakefile(
benchmark_name=args.benchmark_name,
tool_name=args.tool,
environment_file=args.environment_file,
simulation_script=args.simulation_script
)

if __name__ == "__main__":
main()


Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import json
import os

tool = "fenics"
tool = "{TOOL_NAME}"
result_dir = "snakemake_results/" + config["benchmark"]
configuration_to_parameter_file = config["configuration_to_parameter_file"]
configurations = config["configurations"]


rule run_fenics_simulation:
rule run_{TOOL_NAME}_simulation:
input:
script = "{tool}/run_fenics_simulation.py",
script = f"{tool}/{SIMULATION_SCRIPT}",
parameters = lambda wildcards: configuration_to_parameter_file[wildcards.configuration],
mesh = f"{result_dir}/mesh/mesh_{{configuration}}.msh",
mesh = f"{result_dir}/{tool}/mesh/mesh_{{configuration}}.msh",
output:
zip = f"{result_dir}/{{tool}}/solution_field_data_{{configuration}}.zip",
metrics = f"{result_dir}/{{tool}}/solution_metrics_{{configuration}}.json",
zip = f"{result_dir}/{tool}/solution_field_data_{{configuration}}.zip",
metrics = f"{result_dir}/{tool}/solution_metrics_{{configuration}}.json",
conda:
"environment_simulation.yml",
"{ENVIRONMENT_FILE}",
shell:
"""
python3 {input.script} --input_parameter_file {input.parameters} --input_mesh_file {input.mesh} --output_solution_file_zip {output.zip} --output_metrics_file {output.metrics}
"""
"""
59 changes: 0 additions & 59 deletions benchmarks/linear-elastic-plate-with-hole/README.md

This file was deleted.

22 changes: 7 additions & 15 deletions benchmarks/linear-elastic-plate-with-hole/Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ configfile: "workflow_config.json"
result_dir = "snakemake_results/" + config["benchmark"]
configuration_to_parameter_file = config["configuration_to_parameter_file"]
configurations = config["configurations"]
tools = config["tools"]
tool = config["tool"]
benchmark = config["benchmark"]
benchmark_uri = config["benchmark_uri"]


rule all:
input:
expand(f"{result_dir}/{{tool}}/summary.json", tool=tools),
f"{result_dir}/{tool}/summary.json"

rule create_mesh:
input:
Expand All @@ -21,21 +21,19 @@ rule create_mesh:
# otherwise, you could just write configuration_to_parameter_file(configuration)
parameters = lambda wildcards: configuration_to_parameter_file[wildcards.configuration],
output:
mesh = f"{result_dir}/mesh/mesh_{{configuration}}.msh",
mesh = f"{result_dir}/{tool}/mesh/mesh_{{configuration}}.msh",
conda: "environment_mesh.yml"
shell:
"""
python3 {input.script} --input_parameter_file {input.parameters} --output_mesh_file {output.mesh}
"""

# Include tool-specific rules
# The should have at least the mesh file and the parameters as input
# They should have at least the mesh file and the parameters as input
# and output for each configuration a
# solution_metrics_{configuration}.json and
# and solution_field_data_{configuration}.zip whee all the visualization files are stored
# (e.g. vtk)
for tool in tools:
include: f"{tool}/Snakefile"
# and solution_field_data_{configuration}.zip where all the visualization files are stored (e.g. vtk)
include: f"{tool}/Snakefile"


rule summary:
Expand All @@ -44,7 +42,7 @@ rule summary:
# (snakemake_results/linear-elastic-plate-with-hole/fenics/summary.json)
script = "../common/summarize_results.py",
parameters = expand("{param}", param=[configuration_to_parameter_file[c] for c in configurations]),
mesh = expand(f"{result_dir}/mesh/mesh_{{configuration}}.msh", configuration=configurations),
mesh = expand(f"{result_dir}/{tool}/mesh/mesh_{{configuration}}.msh", configuration=configurations),
metrics = lambda wildcards: expand(
f"{result_dir}/{{tool}}/solution_metrics_{{configuration}}.json",
tool=[wildcards.tool], configuration=configurations
Expand All @@ -70,12 +68,6 @@ rule summary:
"""

"""
Steps to add a new simulation tool to the workflow:

1. Write the tool-specific workflow, scripts, environment file and store them in the benchmarks/linear-elastic-plate-with-hole/tool_name/.
2. Add the tool name to "tools" workflow_config.json (generated here using generate_config.py)

------------------------------------------------------------------------------------------------------------------------
"rule all" defines the final target of the workflow. Knowing the final target, the snakemake determines
the dependency chain automatically.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies:
- python=3.12
- fenics-dolfinx=0.9.*
- libadios2=2.10.1
- mpich
- petsc4py
- pint
- python-gmsh
Expand Down
Loading
Loading