Skip to content

Commit fcd3863

Browse files
author
dtyagi
committed
Add FEniCS Nextflow benchmark and update environment configurations
1 parent 1dded98 commit fcd3863

18 files changed

+808
-0
lines changed

.github/workflows/run-benchmark.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ jobs:
4242
run: |
4343
cd $GITHUB_WORKSPACE/benchmarks/linear-elastic-plate-with-hole/FEniCS/
4444
snakemake --use-conda --force --cores 'all'
45+
46+
- name: run-fenics-nextflow-benchmark
47+
shell: bash -l {0}
48+
run: |
49+
cd $GITHUB_WORKSPACE/benchmarks/linear-elastic-plate-with-hole/FEniCS_nextflow/
50+
nextflow run main.nf
4551
4652
- name: run-Kratos-benchmarks
4753
shell: bash -l {0}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import json
2+
import sys
3+
4+
import gmsh
5+
from pint import UnitRegistry
6+
7+
ureg = UnitRegistry()
8+
9+
10+
# Parameters
11+
name = sys.argv[1]
12+
#experiment_file = sys.argv[2]
13+
parameter_file = sys.argv[2]
14+
15+
# Load parameters
16+
with open(parameter_file) as f:
17+
parameters = json.load(f)
18+
print(parameters)
19+
20+
length = (
21+
ureg.Quantity(parameters["length"]["value"], parameters["length"]["unit"])
22+
.to_base_units()
23+
.magnitude
24+
)
25+
radius = (
26+
ureg.Quantity(parameters["radius"]["value"], parameters["radius"]["unit"])
27+
.to_base_units()
28+
.magnitude
29+
)
30+
# create mesh
31+
"""
32+
4---------3
33+
| |
34+
5_ |
35+
\ |
36+
1______2
37+
38+
"""
39+
40+
41+
gmsh.initialize()
42+
gmsh.model.add(name)
43+
44+
element_size = (
45+
ureg.Quantity(
46+
parameters["element-size"]["value"], parameters["element-size"]["unit"]
47+
)
48+
.to_base_units()
49+
.magnitude
50+
)
51+
gmsh.option.setNumber("Mesh.CharacteristicLengthMin", element_size)
52+
gmsh.option.setNumber("Mesh.CharacteristicLengthMax", element_size)
53+
gmsh.option.setNumber("Mesh.CharacteristicLengthFactor", 1.0)
54+
gmsh.option.setNumber("Mesh.ElementOrder", parameters["element-order"])
55+
56+
z = 0.0
57+
lc = 1.0
58+
59+
x0 = 0.0
60+
x1 = x0 + radius
61+
x2 = x0 + length
62+
y0 = 0.0
63+
y1 = y0 + radius
64+
y2 = y0 + length
65+
66+
center = gmsh.model.geo.addPoint(x0, y0, z, lc)
67+
p1 = gmsh.model.geo.addPoint(x1, y0, z, lc)
68+
p2 = gmsh.model.geo.addPoint(x2, y0, z, lc)
69+
p3 = gmsh.model.geo.addPoint(x2, y2, z, lc)
70+
p4 = gmsh.model.geo.addPoint(x0, y2, z, lc)
71+
p5 = gmsh.model.geo.addPoint(x0, y1, z, lc)
72+
73+
l1 = gmsh.model.geo.addLine(p1, p2)
74+
l2 = gmsh.model.geo.addLine(p2, p3)
75+
l3 = gmsh.model.geo.addLine(p3, p4)
76+
l4 = gmsh.model.geo.addLine(p4, p5)
77+
l5 = gmsh.model.geo.addCircleArc(p5, center, p1)
78+
79+
curve = gmsh.model.geo.addCurveLoop([l1, l2, l3, l4, l5])
80+
plane = gmsh.model.geo.addPlaneSurface([curve])
81+
gmsh.model.geo.synchronize()
82+
gmsh.model.geo.removeAllDuplicates()
83+
gmsh.model.addPhysicalGroup(2, [plane], 1, name="surface")
84+
gmsh.model.addPhysicalGroup(1, [l4], 1, name="boundary_left")
85+
gmsh.model.addPhysicalGroup(1, [l1], 2, name="boundary_bottom")
86+
gmsh.model.addPhysicalGroup(1, [l2], 3, name="boundary_right")
87+
gmsh.model.addPhysicalGroup(1, [l3], 4, name="boundary_top")
88+
89+
gmsh.model.mesh.generate(2)
90+
#gmsh.write("data/mesh_" + name + ".msh")
91+
gmsh.write("mesh_" + name + ".msh")
92+
gmsh.finalize()
93+
94+
#parameters["mesh-file"] = "data/mesh_" + name + ".msh"
95+
parameters["mesh-file"] = "mesh_" + name + ".msh"
96+
#with open("data/input_" + name + ".json", "w") as f:
97+
with open("input_" + name + ".json", "w") as f:
98+
json.dump(parameters, f, indent=4)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: plate-with-hole
2+
channels:
3+
- conda-forge
4+
- defaults
5+
dependencies:
6+
- python>=3.10
7+
- fenics-dolfinx
8+
- libadios2=2.10.1
9+
- petsc4py
10+
- python-gmsh
11+
- pint
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "linear elastic plate with hole",
3+
"description": "Benchmark for linear elasticity with a plate with a hole"
4+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Default parameter input
2+
params.ip_files_script = Channel.value(file('create_input_files.py'))
3+
params.run_sim_script = Channel.value(file('run_simulation.py'))
4+
//params.summary_script = Channel.value(file('summary.py'))
5+
6+
// split process
7+
process generate_input_files {
8+
publishDir "data/"
9+
conda 'environment.yml'
10+
11+
input:
12+
path python_script
13+
val name
14+
path parameters_json
15+
16+
output:
17+
tuple val(name), path("input_${name}.json"), path("mesh_${name}.msh"), path(parameters_json)
18+
19+
script:
20+
"""
21+
python3 $python_script $name $parameters_json
22+
"""
23+
}
24+
25+
process run_simulation {
26+
27+
publishDir "data/"
28+
conda 'environment.yml'
29+
30+
input:
31+
path python_script
32+
tuple val(name), path(input_json), path(mesh_msh), path(parameters_json)
33+
34+
output:
35+
tuple val(name), path("output_${name}.vtk"), path(input_json), path(mesh_msh), path(parameters_json)
36+
37+
script:
38+
"""
39+
python3 $python_script $name $input_json
40+
"""
41+
}
42+
43+
process summary {
44+
45+
publishDir "data/"
46+
//conda 'environment.yml'
47+
48+
input:
49+
//path python_script
50+
tuple val(name), path(output_vtk), path(input_json), path(mesh_msh), path(parameters_json)
51+
52+
output:
53+
path("summary_${name}.json")
54+
55+
script:
56+
"""
57+
#!/usr/bin/env python
58+
import json
59+
import pyvista
60+
from xml.etree import ElementTree as ET
61+
from pathlib import Path
62+
import sys
63+
import os
64+
65+
summary = {}
66+
summary["name"] = "$name"
67+
summary["parameters"] = "$parameters_json"
68+
summary["input"] = "$input_json"
69+
summary["mesh"] = "$mesh_msh"
70+
summary["output"] = "$output_vtk"
71+
72+
# Load the mesh and output data
73+
max_mises_stress = 42.0
74+
75+
tree = ET.parse(summary["output"])
76+
root = tree.getroot()
77+
pvtu_filenames = []
78+
path = Path(os.path.realpath(summary["output"])).parent
79+
for dataset in root.findall(".//DataSet"):
80+
pvtu_filenames.append(path / dataset.get("file"))
81+
meshes = [pyvista.read(pvtu_filename) for pvtu_filename in pvtu_filenames]
82+
for mesh in meshes:
83+
print("Mesh:", mesh)
84+
# Assuming the mesh has a 'von_mises_stress' array
85+
try:
86+
max_mises_stress = float(mesh["von_mises_stress"].max())
87+
except KeyError:
88+
print("von_mises_stress not found in mesh.")
89+
summary["max_mises_stress"] = max_mises_stress # Replace with actual computation
90+
with open(f"summary_{summary["name"]}.json", "w") as f:
91+
json.dump(summary, f, indent=4)
92+
93+
"""
94+
}
95+
96+
// Workflow block
97+
workflow {
98+
99+
def ch_parameter_files = Channel.fromPath('parameters_*.json', checkIfExists: true)
100+
//ch_parameter_files.view()
101+
102+
def parameters_files = files('parameters_*.json')
103+
def names = parameters_files.baseName.collect{it.split('_')[1]}
104+
//println names
105+
def ch_file_names = Channel.fromList(names)
106+
107+
output_gen_input_files = generate_input_files(params.ip_files_script, ch_file_names, ch_parameter_files)
108+
//output_gen_input_files.view()
109+
output_run_sim = run_simulation(params.run_sim_script, output_gen_input_files)
110+
//output_run_sim.view()
111+
summary(output_run_sim)
112+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
profiles {
2+
conda {
3+
process.conda = 'environment.yml'
4+
}
5+
}
6+
//No need to specify profile each time
7+
conda.enabled = true // this or use -with-conda in command line
8+
9+
//plugins {
10+
// id 'nf-prov'
11+
//}
12+
//
13+
//prov {
14+
// enabled = true
15+
// formats {
16+
// legacy {
17+
// file = 'provenance.json'
18+
// overwrite = true
19+
// }
20+
// }
21+
//}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"radius": {
3+
"value": 0.33,
4+
"unit": "m"
5+
},
6+
"length": {
7+
"value": 1.0,
8+
"unit": "m"
9+
},
10+
"load": {
11+
"value": 100.0,
12+
"unit": "MPa"
13+
},
14+
"element-size": {
15+
"value": 0.003125,
16+
"unit": "m"
17+
},
18+
"element-order": 1,
19+
"element-degree": 1,
20+
"quadrature-rule": "gauss",
21+
"quadrature-degree": 1,
22+
"young-modulus": {
23+
"value": 210e9,
24+
"unit": "Pa"
25+
},
26+
"poisson-ratio": {
27+
"value": 0.3,
28+
"unit": ""
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"radius": {
3+
"value": 0.33,
4+
"unit": "m"
5+
},
6+
"length": {
7+
"value": 1.0,
8+
"unit": "m"
9+
},
10+
"load": {
11+
"value": 100.0,
12+
"unit": "MPa"
13+
},
14+
"element-size": {
15+
"value": 0.00625,
16+
"unit": "m"
17+
},
18+
"element-order": 1,
19+
"element-degree": 1,
20+
"quadrature-rule": "gauss",
21+
"quadrature-degree": 1,
22+
"young-modulus": {
23+
"value": 210e9,
24+
"unit": "Pa"
25+
},
26+
"poisson-ratio": {
27+
"value": 0.3,
28+
"unit": ""
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"radius": {
3+
"value": 0.33,
4+
"unit": "m"
5+
},
6+
"length": {
7+
"value": 1.0,
8+
"unit": "m"
9+
},
10+
"load": {
11+
"value": 100.0,
12+
"unit": "MPa"
13+
},
14+
"element-size": {
15+
"value": 0.0125,
16+
"unit": "m"
17+
},
18+
"element-order": 1,
19+
"element-degree": 1,
20+
"quadrature-rule": "gauss",
21+
"quadrature-degree": 1,
22+
"young-modulus": {
23+
"value": 210e9,
24+
"unit": "Pa"
25+
},
26+
"poisson-ratio": {
27+
"value": 0.3,
28+
"unit": ""
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"radius": {
3+
"value": 0.33,
4+
"unit": "m"
5+
},
6+
"length": {
7+
"value": 1.0,
8+
"unit": "m"
9+
},
10+
"load": {
11+
"value": 100.0,
12+
"unit": "MPa"
13+
},
14+
"element-size": {
15+
"value": 0.025,
16+
"unit": "m"
17+
},
18+
"element-order": 1,
19+
"element-degree": 1,
20+
"quadrature-rule": "gauss",
21+
"quadrature-degree": 1,
22+
"young-modulus": {
23+
"value": 210e9,
24+
"unit": "Pa"
25+
},
26+
"poisson-ratio": {
27+
"value": 0.3,
28+
"unit": ""
29+
}
30+
}

0 commit comments

Comments
 (0)