From b8c9d9d640fce9080c4848020e90d2a5201af481 Mon Sep 17 00:00:00 2001 From: Henrik Finsberg Date: Mon, 10 Mar 2025 19:30:46 +0100 Subject: [PATCH] Add script for running stiffness sensitivty --- demos/stiffness_sensitivity.py | 76 +++++++++++++++++++++++++++++++ src/simcardems/config.py | 1 + src/simcardems/mechanics_model.py | 3 +- src/simcardems/models/em_model.py | 1 + 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 demos/stiffness_sensitivity.py diff --git a/demos/stiffness_sensitivity.py b/demos/stiffness_sensitivity.py new file mode 100644 index 00000000..914083a2 --- /dev/null +++ b/demos/stiffness_sensitivity.py @@ -0,0 +1,76 @@ +# # Simple demo +# +# In this demo we show the most simple usage of the `simcardems` library using the python API. +# +# Import the necessary libraries +# + +from pathlib import Path +import simcardems +import matplotlib.pyplot as plt +import numpy as np + +here = Path(__file__).absolute().parent +geometry_path = here / "geometries/slab.h5" +geometry_schema_path = here / "geometries/slab.json" + + +def run(outdir: Path, a: float = 2.28): + outdir.mkdir(exist_ok=True, parents=True) + results_file = outdir.joinpath("results.h5") + if results_file.exists(): + values = np.load(outdir.joinpath("values.npy"), allow_pickle=True).item() + + t = values["time"] + lmbda = values["mechanics"]["lambda"] + return t, lmbda + config = simcardems.Config( + outdir=outdir, + geometry_path=geometry_path, + geometry_schema_path=geometry_schema_path, + coupling_type="fully_coupled_ORdmm_Land", + T=1000, + material_parameter_a=a, + ) + runner = simcardems.Runner(config) + runner.solve(T=config.T, save_freq=config.save_freq, show_progress_bar=True) + + loader = simcardems.datacollector.DataLoader(results_file) + values = simcardems.postprocess.extract_traces(loader, reduction="center") + np.save(outdir.joinpath("values.npy"), values) + + t = values["time"] + lmbda = values["mechanics"]["lambda"] + fig, ax = plt.subplots() + ax.plot(t, lmbda) + ax.set_xlabel("Time [ms]") + ax.set_ylabel("Lambda") + ax.set_title(f"Material parameter a = {a}") + fig.savefig(outdir.joinpath(f"lambda_{a}.png")) + + return t, lmbda + # simcardems.postprocess.plot_state_traces(outdir.joinpath("results.h5"), "center") + + +def main(): + outdir = here / "results_stiffness_sensitivity-new" + fig, ax = plt.subplots() + a_default = 2.28 + for a in [ + a_default / 4.0, + a_default / 2.0, + a_default, + a_default * 2.0, + a_default * 4.0, + ]: + t, lmbda = run(outdir=outdir / f"a_{a}", a=a) + ax.plot(t, lmbda, label=f"a = {a}") + ax.legend() + ax.set_xlabel("Time [ms]") + ax.set_ylabel("Lambda") + ax.set_title("Stiffness sensitivity") + fig.savefig(outdir / "stiffness_sensitivity.png") + + +if __name__ == "__main__": + main() diff --git a/src/simcardems/config.py b/src/simcardems/config.py index 10e4edce..ae5ce306 100644 --- a/src/simcardems/config.py +++ b/src/simcardems/config.py @@ -54,6 +54,7 @@ class Config: "explicit_ORdmm_Land", "pureEP_ORdmm_Land", ] = "fully_coupled_ORdmm_Land" + material_parameter_a: float = 2.28 def as_dict(self): return {k: v for k, v in self.__dict__.items()} diff --git a/src/simcardems/mechanics_model.py b/src/simcardems/mechanics_model.py index 482097ab..af7f5ffc 100644 --- a/src/simcardems/mechanics_model.py +++ b/src/simcardems/mechanics_model.py @@ -34,6 +34,7 @@ def setup_solver( linear_solver="mumps", use_custom_newton_solver: bool = config.Config.mechanics_use_custom_newton_solver, state_prev=None, + material_parameter_a: float = 2.28, ): """Setup mechanics model with dirichlet boundary conditions or rigid motion.""" @@ -43,7 +44,7 @@ def setup_solver( # Use parameters from Biaxial test in Holzapfel 2019 (Table 1). material_parameters = dict( - a=2.28, + a=material_parameter_a, a_f=1.686, b=9.726, b_f=15.779, diff --git a/src/simcardems/models/em_model.py b/src/simcardems/models/em_model.py index f65fa3ea..164760b3 100644 --- a/src/simcardems/models/em_model.py +++ b/src/simcardems/models/em_model.py @@ -70,6 +70,7 @@ def setup_EM_model( use_custom_newton_solver=config.mechanics_use_custom_newton_solver, debug_mode=config.debug_mode, ActiveModel=cls_ActiveModel, + material_parameter_a=config.material_parameter_a, ) if mech_state_init is not None: mech_heart.state.assign(mech_state_init)