Skip to content

Commit 0b50282

Browse files
div-tygCopilot
andauthored
Neumann BC for linear elastic plate example in fenics and kratos (#72)
* Switch to Neumann BC for fenics and kratos example * updated parameter files in the linear elastic benchmark folder * reverted to the previous kratos workflow * modification in parameter_extractor to accommodate new parameters.json file * kratos example with new BCs Co-authored-by: Copilot <copilot@github.com> * update workflow file Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com>
1 parent 1456912 commit 0b50282

14 files changed

Lines changed: 942 additions & 38 deletions

.github/workflows/run-benchmark-examples.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ on:
1414

1515
env:
1616
CACHE_NUMBER: 1 # increase to reset cache manually
17-
SNAKEMAKE_RESULT_FILE: metadata4ing_provenance
18-
PROVENANACE_FILE_NAME: element_size_vs_max_mises_stress.pdf
1917

2018
jobs:
2119
run-examples:
@@ -43,12 +41,25 @@ jobs:
4341
cd $GITHUB_WORKSPACE/examples/linear-elastic-plate-with-hole/fenics/
4442
python run_benchmark.py
4543
44+
- name: Run linear-elastic-plate-with-hole using kratos
45+
shell: bash -l {0}
46+
run: |
47+
cd $GITHUB_WORKSPACE/examples/linear-elastic-plate-with-hole/kratos/
48+
python run_benchmark.py
49+
4650
- name: Archive results of the fenics run of linear-elastic-plate-with-hole
4751
uses: actions/upload-artifact@v4
4852
with:
49-
name: snakemake_results_linear-elastic-plate-with-hole
53+
name: fenics_results_linear-elastic-plate-with-hole
5054
path: |
5155
examples/linear-elastic-plate-with-hole/fenics/results/
5256
57+
- name: Archive results of the kratos run of linear-elastic-plate-with-hole
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: kratos_results_linear-elastic-plate-with-hole
61+
path: |
62+
examples/linear-elastic-plate-with-hole/kratos/results/
63+
5364
5465

benchmarks/linear-elastic-plate-with-hole/kratos/MainKratos.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

examples/linear-elastic-plate-with-hole/fenics/run_benchmark.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
with open(file, "r") as f:
4545
data = json.load(f)
4646
if data.get("element-size").get("value") >= 0.025:
47-
47+
4848
# Create output directory for the configuration
4949
output_dir = root_unzipped_benchmark_dir / "results" / data.get("configuration")
5050
output_dir.mkdir(parents=True, exist_ok=True)

examples/linear-elastic-plate-with-hole/fenics/run_fenics_simulation.py renamed to examples/linear-elastic-plate-with-hole/fenics/run_simulation.py

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import numpy as np
99
import ufl
1010
from dolfinx.fem.petsc import LinearProblem
11-
from petsc4py.PETSc import ScalarType
1211
from mpi4py import MPI
1312
from pint import UnitRegistry
1413

@@ -40,8 +39,6 @@ def run_fenics_simulation(
4039
# Boundary conditions
4140
dofs_left = df.fem.locate_dofs_topological(V.sub(0), 1, tags_left)
4241
dofs_bottom = df.fem.locate_dofs_topological(V.sub(1), 1, tags_bottom)
43-
dofs_right = df.fem.locate_dofs_topological(V, 1, tags_right)
44-
dofs_top = df.fem.locate_dofs_topological(V, 1, tags_top)
4542

4643
bc_left = df.fem.dirichletbc(0.0, dofs_left, V.sub(0))
4744
bc_bottom = df.fem.dirichletbc(0.0, dofs_bottom, V.sub(1))
@@ -128,29 +125,38 @@ def as_tensor(v):
128125
domain=mesh,
129126
subdomain_data=facet_tags,
130127
)
131-
stress_space = df.fem.functionspace(
132-
mesh, ("CG", parameters["element-degree"], (2, 2))
133-
)
134-
stress_function = df.fem.Function(stress_space)
135128

136129
u = df.fem.Function(V, name="u")
137-
u_prescribed = df.fem.Function(V, name="u_prescribed")
138-
u_prescribed.interpolate(lambda x: analytical_solution.displacement(x))
139-
u_prescribed.x.scatter_forward()
140130

141131
u_ = ufl.TestFunction(V)
142132
v_ = ufl.TrialFunction(V)
143133
a = df.fem.form(ufl.inner(sigma(u_), eps(v_)) * dx)
144134

145-
# set rhs to zero
146-
f = df.fem.form(ufl.inner(df.fem.Constant(mesh, np.array([0.0, 0.0])), u_) * ufl.ds)
135+
# Apply Neumann tractions on right and top boundaries from analytical stress.
136+
traction_right = df.fem.Function(V, name="traction_right")
137+
traction_top = df.fem.Function(V, name="traction_top")
138+
139+
def traction_right_expr(x: np.ndarray) -> np.ndarray:
140+
sxx, sxy, _ = analytical_solution.stress(x)
141+
return np.vstack((np.asarray(sxx), np.asarray(sxy)))
142+
143+
def traction_top_expr(x: np.ndarray) -> np.ndarray:
144+
_, sxy, syy = analytical_solution.stress(x)
145+
return np.vstack((np.asarray(sxy), np.asarray(syy)))
146+
147+
traction_right.interpolate(traction_right_expr)
148+
traction_top.interpolate(traction_top_expr)
149+
traction_right.x.scatter_forward()
150+
traction_top.x.scatter_forward()
151+
152+
f = df.fem.form(
153+
ufl.inner(traction_right, u_) * ds(3) + ufl.inner(traction_top, u_) * ds(4)
154+
)
147155

148-
bc_right = df.fem.dirichletbc(u_prescribed, dofs_right)
149-
bc_top = df.fem.dirichletbc(u_prescribed, dofs_top)
150156
solver = LinearProblem(
151157
a,
152158
f,
153-
bcs=[bc_left, bc_bottom, bc_right, bc_top],
159+
bcs=[bc_left, bc_bottom],
154160
u=u,
155161
petsc_options={
156162
"ksp_type": "gmres",
@@ -160,6 +166,30 @@ def as_tensor(v):
160166
)
161167
solver.solve()
162168

169+
# Support reaction on the left boundary
170+
n = ufl.FacetNormal(mesh)
171+
traction = ufl.dot(sigma(u), n)
172+
reaction_left_x_local = df.fem.assemble_scalar(df.fem.form(traction[0] * ds(1)))
173+
reaction_left_y_local = df.fem.assemble_scalar(df.fem.form(traction[1] * ds(1)))
174+
reaction_left_x = MPI.COMM_WORLD.allreduce(reaction_left_x_local, op=MPI.SUM)
175+
reaction_left_y = MPI.COMM_WORLD.allreduce(reaction_left_y_local, op=MPI.SUM)
176+
177+
178+
# Compute L2 error norm between FE displacement and analytical displacement.
179+
u_analytical = df.fem.Function(V, name="u_analytical")
180+
181+
def analytical_displacement_expr(x: np.ndarray) -> np.ndarray:
182+
ux, uy = analytical_solution.displacement(x)
183+
return np.vstack((np.asarray(ux), np.asarray(uy)))
184+
185+
u_analytical.interpolate(analytical_displacement_expr)
186+
u_analytical.x.scatter_forward()
187+
188+
l2_error_form = df.fem.form(ufl.inner(u - u_analytical, u - u_analytical) * dx)
189+
l2_error_sq_local = df.fem.assemble_scalar(l2_error_form)
190+
l2_error_sq_global = MPI.COMM_WORLD.allreduce(l2_error_sq_local, op=MPI.SUM)
191+
l2_error_displacement = np.sqrt(l2_error_sq_global)
192+
163193
# Evaluate displacement at the specified evaluation point
164194
displacement_eval_point = np.array(
165195
[[displacement_evaluation_x, displacement_evaluation_y, 0.0]],
@@ -293,6 +323,9 @@ def mises_stress(u):
293323
metrics = {
294324
"max_von_mises_stress_nodes": max_mises_stress_nodes,
295325
"max_von_mises_stress_gauss_points": max_mises_stress_gauss_points,
326+
"l2_error_displacement": l2_error_displacement,
327+
"reaction_force_left_boundary_x": reaction_left_x,
328+
"reaction_force_left_boundary_y": reaction_left_y,
296329
f"displacement_x_at_evaluation_point (x={displacement_evaluation_x}, y={displacement_evaluation_y})": displacement_x_at_evaluation_point,
297330
}
298331

@@ -355,3 +388,5 @@ def mises_stress(u):
355388
args.output_solution_file_zip,
356389
args.output_metrics_file,
357390
)
391+
#python3 run_fenics_simulation.py --input_parameter_file parameters_1.json --input_mesh_file mesh_1.msh --output_solution_file_zip results/solution_field_data.zip --output_metrics_file results/solution_metrics.json
392+
#conda activate /home/dtyagi/NFDI4IngModelValidationPlatform/examples/linear-elastic-plate-with-hole/fenics/conda_envs/68782c9259a7e25569f1ab0241a766c5_
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import json
2+
import os
3+
4+
kratos_input_template = "input_template.json"
5+
kratos_material_template = "StructuralMaterials_template.json"
6+
7+
rule all:
8+
input:
9+
"solution_metrics.json",
10+
"solution_field_data.zip"
11+
12+
rule mesh_to_mdpa:
13+
input:
14+
parameters = "parameters.json",
15+
mesh = "mesh.msh",
16+
script = "msh_to_mdpa.py",
17+
output:
18+
mdpa = "mesh.mdpa",
19+
conda:
20+
"environment_simulation.yml",
21+
shell:
22+
"""
23+
python3 {input.script} \
24+
--input_parameter_file {input.parameters} \
25+
--input_mesh_file {input.mesh} \
26+
--output_mdpa_file {output.mdpa}
27+
"""
28+
29+
rule create_kratos_input_and_run_simulation:
30+
input:
31+
parameters = "parameters.json",
32+
mdpa = "mesh.mdpa",
33+
kratos_input_template = kratos_input_template,
34+
kratos_material_template = kratos_material_template,
35+
script_create_kratos_input = "create_kratos_input.py",
36+
script_run_kratos_simulation = "run_simulation.py",
37+
output:
38+
kratos_inputfile = "ProjectParameters.json",
39+
kratos_materialfile = "MaterialParameters.json",
40+
result_vtk = "vtk/Structure_0_1.vtk",
41+
conda:
42+
"environment_simulation.yml",
43+
shell:
44+
"""
45+
python3 {input.script_create_kratos_input} \
46+
--input_parameter_file {input.parameters} \
47+
--input_mdpa_file {input.mdpa} \
48+
--input_kratos_input_template {input.kratos_input_template} \
49+
--input_material_template {input.kratos_material_template} \
50+
--output_kratos_inputfile {output.kratos_inputfile} \
51+
--output_kratos_materialfile {output.kratos_materialfile}
52+
53+
python3 {input.script_run_kratos_simulation} \
54+
--input_parameter_file {input.parameters} \
55+
--input_kratos_inputfile {output.kratos_inputfile} \
56+
--input_kratos_materialfile {output.kratos_materialfile} \
57+
"""
58+
59+
rule postprocess_kratos_results:
60+
input:
61+
parameters = "parameters.json",
62+
result_vtk = "vtk/Structure_0_1.vtk",
63+
script = "postprocess_results.py",
64+
output:
65+
zip = "solution_field_data.zip",
66+
metrics = "solution_metrics.json",
67+
conda:
68+
"environment_simulation.yml",
69+
shell:
70+
"""
71+
python3 {input.script} \
72+
--input_parameter_file {input.parameters} \
73+
--input_result_vtk {input.result_vtk} \
74+
--output_solution_file_zip {output.zip} \
75+
--output_metrics_file {output.metrics}
76+
"""
77+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"properties": [
3+
{
4+
"model_part_name": "Structure",
5+
"properties_id": 1,
6+
"Material": {
7+
"constitutive_law": {
8+
"name": "LinearElasticPlaneStress2DLaw"
9+
},
10+
"Variables": {
11+
"YOUNG_MODULUS": "{{YOUNG_MODULUS}}",
12+
"POISSON_RATIO": "{{POISSON_RATIO}}"
13+
},
14+
"Tables": {}
15+
}
16+
}
17+
]
18+
}

0 commit comments

Comments
 (0)