MonoVentricular#

Passive + active hyperelastic simulation of an ellipsoidal left-ventricle model.

Combines a Holzapfel-Ogden orthotropic law (fiber + sheet directions), an active stress along the fiber direction, and a follower pressure on the endocardial surface. Time integration uses the midpoint hyperbolic scheme.

Reproduces Benchmark 1: monoventricular mechanics (§3) of the cardiac elastodynamics benchmark published in Comput. Methods Appl. Mech. Engrg.: https://www.sciencedirect.com/science/article/pii/S0045782524007394

The mesh.msh / fiber.vtu / sheet.vtu files read for fiberSource="vtu" are generated beforehand with the cardiac_benchmark_toolkit — see the module docstring of utils.py for the exact procedure. (fiberSource="analytic" builds the fibers/sheets directly in EasyFEA and needs no external data.)

With useCoarseConfig=False this becomes a large 3D, non-linear, transient problem for which the default direct solver is slow. In that case it is recommended to run it either in parallel with MPI and PETSc (e.g. mpiexec -n <N> python MonoVentricular.py with a PETSc-backed solver), or, on a single process, with the pypardiso solver — both markedly cut the solve time. The default useCoarseConfig=True is light enough to run as-is.

MonoVentricularParticle p0, Particle p1
===== hyperelastic problem at iteration 0 =====
At Newton iteration 1 norm is 8.686270292626e-02
At Newton iteration 2 norm is 2.026777061849e-04
At Newton iteration 3 norm is 2.476805657965e-09


===== hyperelastic problem at iteration 1 =====
At Newton iteration 1 norm is 8.627104418308e-02
At Newton iteration 2 norm is 7.783879848245e-04
At Newton iteration 3 norm is 3.817813043733e-08


===== hyperelastic problem at iteration 2 =====
At Newton iteration 1 norm is 6.626617918429e-02
At Newton iteration 2 norm is 6.155599929113e-04
At Newton iteration 3 norm is 2.220433209860e-08


===== hyperelastic problem at iteration 3 =====
At Newton iteration 1 norm is 5.365199085190e-02
At Newton iteration 2 norm is 3.217898859458e-04
At Newton iteration 3 norm is 5.280662666287e-09


===== hyperelastic problem at iteration 4 =====
At Newton iteration 1 norm is 3.448445477588e-02
At Newton iteration 2 norm is 1.651105212249e-04
At Newton iteration 3 norm is 7.904903585581e-10


===== hyperelastic problem at iteration 5 =====
At Newton iteration 1 norm is 3.232023636819e-02
At Newton iteration 2 norm is 9.636747040827e-05
At Newton iteration 3 norm is 1.695388706846e-10


===== hyperelastic problem at iteration 6 =====
At Newton iteration 1 norm is 2.005162696371e-02
At Newton iteration 2 norm is 4.861897171624e-05
At Newton iteration 3 norm is 4.367432338704e-11


===== hyperelastic problem at iteration 7 =====
At Newton iteration 1 norm is 1.879130633303e-02
At Newton iteration 2 norm is 2.350685330318e-05
At Newton iteration 3 norm is 8.781039636974e-12


===== hyperelastic problem at iteration 8 =====
At Newton iteration 1 norm is 1.079876021448e-02
At Newton iteration 2 norm is 1.367831305412e-05
At Newton iteration 3 norm is 2.527809298010e-12


===== hyperelastic problem at iteration 9 =====
At Newton iteration 1 norm is 1.186998995129e-02
At Newton iteration 2 norm is 7.941399724594e-06


==== hyperelastic problem at iteration 10 ====
At Newton iteration 1 norm is 6.296101809138e-03
At Newton iteration 2 norm is 3.410862824393e-06


==== hyperelastic problem at iteration 11 ====
At Newton iteration 1 norm is 7.292086420178e-03
At Newton iteration 2 norm is 2.415955353113e-06


==== hyperelastic problem at iteration 12 ====
At Newton iteration 1 norm is 4.146024277092e-03
At Newton iteration 2 norm is 1.043102533053e-06


==== hyperelastic problem at iteration 13 ====
At Newton iteration 1 norm is 1.012064090368e-02
At Newton iteration 2 norm is 2.954788400160e-06


==== hyperelastic problem at iteration 14 ====
At Newton iteration 1 norm is 1.668500585128e+00
At Newton iteration 2 norm is 8.144096288499e-02
At Newton iteration 3 norm is 4.910819037402e-04
At Newton iteration 4 norm is 1.606760612740e-08


==== hyperelastic problem at iteration 15 ====
At Newton iteration 1 norm is 1.864700262373e+00
At Newton iteration 2 norm is 4.799670120590e-01
At Newton iteration 3 norm is 3.843351422930e-04
At Newton iteration 4 norm is 6.334592679363e-09


==== hyperelastic problem at iteration 16 ====
At Newton iteration 1 norm is 1.561591222740e+00
At Newton iteration 2 norm is 4.993259773779e-01
At Newton iteration 3 norm is 1.623810601839e-04
At Newton iteration 4 norm is 2.416276960278e-09


==== hyperelastic problem at iteration 17 ====
At Newton iteration 1 norm is 1.486987763500e+00
At Newton iteration 2 norm is 3.506808946576e-01
At Newton iteration 3 norm is 1.277215927848e-04
At Newton iteration 4 norm is 1.762255552074e-09


==== hyperelastic problem at iteration 18 ====
At Newton iteration 1 norm is 1.402419150178e+00
At Newton iteration 2 norm is 2.899970761077e-01
At Newton iteration 3 norm is 5.801775436488e-05
At Newton iteration 4 norm is 1.865332615734e-10


==== hyperelastic problem at iteration 19 ====
At Newton iteration 1 norm is 1.370015019157e+00
At Newton iteration 2 norm is 2.645047452374e-01
At Newton iteration 3 norm is 6.059281399009e-05
At Newton iteration 4 norm is 2.377590994952e-10


==== hyperelastic problem at iteration 20 ====
At Newton iteration 1 norm is 1.266025514063e+00
At Newton iteration 2 norm is 2.057743195323e-01
At Newton iteration 3 norm is 3.505876167608e-05
At Newton iteration 4 norm is 6.949942387966e-11


==== hyperelastic problem at iteration 21 ====
At Newton iteration 1 norm is 1.232544598814e+00
At Newton iteration 2 norm is 1.619180149489e-01
At Newton iteration 3 norm is 3.632762760828e-05
At Newton iteration 4 norm is 9.585773023623e-11


==== hyperelastic problem at iteration 22 ====
At Newton iteration 1 norm is 1.129384135821e+00
At Newton iteration 2 norm is 1.351449983385e-01
At Newton iteration 3 norm is 2.312182284610e-05
At Newton iteration 4 norm is 4.275772660276e-11


==== hyperelastic problem at iteration 23 ====
At Newton iteration 1 norm is 1.137071588823e+00
At Newton iteration 2 norm is 1.068045114488e-01
At Newton iteration 3 norm is 2.712726181860e-05
At Newton iteration 4 norm is 6.155209824573e-11


==== hyperelastic problem at iteration 24 ====
At Newton iteration 1 norm is 1.002514755093e+00
At Newton iteration 2 norm is 8.252330081836e-02
At Newton iteration 3 norm is 1.515170364713e-05
At Newton iteration 4 norm is 2.177543656872e-11


==== hyperelastic problem at iteration 25 ====
At Newton iteration 1 norm is 1.020288334802e+00
At Newton iteration 2 norm is 6.770902107195e-02
At Newton iteration 3 norm is 1.556709343493e-05
At Newton iteration 4 norm is 2.182322492913e-11


==== hyperelastic problem at iteration 26 ====
At Newton iteration 1 norm is 8.994396136678e-01
At Newton iteration 2 norm is 5.177220568847e-02
At Newton iteration 3 norm is 8.393353337694e-06


==== hyperelastic problem at iteration 27 ====
At Newton iteration 1 norm is 9.030962138815e-01
At Newton iteration 2 norm is 4.106379099813e-02
At Newton iteration 3 norm is 8.120305110433e-06


==== hyperelastic problem at iteration 28 ====
At Newton iteration 1 norm is 7.944549454180e-01
At Newton iteration 2 norm is 3.153698026084e-02
At Newton iteration 3 norm is 4.402181396957e-06


==== hyperelastic problem at iteration 29 ====
At Newton iteration 1 norm is 7.945841772426e-01
At Newton iteration 2 norm is 2.484569345572e-02
At Newton iteration 3 norm is 4.232181201768e-06


==== hyperelastic problem at iteration 30 ====
At Newton iteration 1 norm is 6.978326590220e-01
At Newton iteration 2 norm is 1.916305658325e-02
At Newton iteration 3 norm is 2.340905302667e-06


==== hyperelastic problem at iteration 31 ====
At Newton iteration 1 norm is 6.959190103828e-01
At Newton iteration 2 norm is 1.535135817434e-02
At Newton iteration 3 norm is 2.229548738171e-06


==== hyperelastic problem at iteration 32 ====
At Newton iteration 1 norm is 6.148350779583e-01
At Newton iteration 2 norm is 1.218723825883e-02
At Newton iteration 3 norm is 1.295377321038e-06


==== hyperelastic problem at iteration 33 ====
At Newton iteration 1 norm is 6.087707482561e-01
At Newton iteration 2 norm is 9.981387860338e-03
At Newton iteration 3 norm is 1.198289818118e-06


==== hyperelastic problem at iteration 34 ====
At Newton iteration 1 norm is 5.440994521029e-01
At Newton iteration 2 norm is 8.226683861519e-03
At Newton iteration 3 norm is 7.387502323566e-07


==== hyperelastic problem at iteration 35 ====
At Newton iteration 1 norm is 5.318692836384e-01
At Newton iteration 2 norm is 6.882257891791e-03
At Newton iteration 3 norm is 6.580372741413e-07


==== hyperelastic problem at iteration 36 ====
At Newton iteration 1 norm is 4.838829358096e-01
At Newton iteration 2 norm is 5.853381989491e-03
At Newton iteration 3 norm is 4.294597536441e-07


==== hyperelastic problem at iteration 37 ====
At Newton iteration 1 norm is 4.631346903222e-01
At Newton iteration 2 norm is 4.948881865972e-03
At Newton iteration 3 norm is 3.653153313352e-07


==== hyperelastic problem at iteration 38 ====
At Newton iteration 1 norm is 3.736270457552e-01
At Newton iteration 2 norm is 3.373137985145e-03
At Newton iteration 3 norm is 1.494676499701e-07


==== hyperelastic problem at iteration 39 ====
At Newton iteration 1 norm is 6.704807451418e+00
At Newton iteration 2 norm is 3.058130447115e-01
At Newton iteration 3 norm is 1.163816551455e-03
At Newton iteration 4 norm is 7.605399175078e-08


==== hyperelastic problem at iteration 40 ====
At Newton iteration 1 norm is 6.165291742807e+00
At Newton iteration 2 norm is 1.234224662142e+00
At Newton iteration 3 norm is 1.072820113297e-02
At Newton iteration 4 norm is 7.189251973393e-06


==== hyperelastic problem at iteration 41 ====
At Newton iteration 1 norm is 4.057648321975e+00
At Newton iteration 2 norm is 1.204701586988e+00
At Newton iteration 3 norm is 4.177049374979e-03
At Newton iteration 4 norm is 1.421998616507e-06


==== hyperelastic problem at iteration 42 ====
At Newton iteration 1 norm is 3.079002105428e+00
At Newton iteration 2 norm is 7.034866918116e-01
At Newton iteration 3 norm is 1.233401229724e-03
At Newton iteration 4 norm is 1.254613192790e-07


==== hyperelastic problem at iteration 43 ====
At Newton iteration 1 norm is 1.884407486835e+00
At Newton iteration 2 norm is 5.230490771215e-01
At Newton iteration 3 norm is 3.210529552672e-04
At Newton iteration 4 norm is 8.691995924511e-09


==== hyperelastic problem at iteration 44 ====
At Newton iteration 1 norm is 1.805652277006e+00
At Newton iteration 2 norm is 3.317918404334e-01
At Newton iteration 3 norm is 2.374305946549e-04
At Newton iteration 4 norm is 5.106988780644e-09


==== hyperelastic problem at iteration 45 ====
At Newton iteration 1 norm is 1.333568056084e+00
At Newton iteration 2 norm is 2.217189655145e-01
At Newton iteration 3 norm is 8.713697103929e-05
At Newton iteration 4 norm is 6.365856600309e-10


==== hyperelastic problem at iteration 46 ====
At Newton iteration 1 norm is 1.262242782626e+00
At Newton iteration 2 norm is 1.260243805086e-01
At Newton iteration 3 norm is 6.096424367479e-05
At Newton iteration 4 norm is 3.609231695559e-10


==== hyperelastic problem at iteration 47 ====
At Newton iteration 1 norm is 1.136765084211e+00
At Newton iteration 2 norm is 8.978774810143e-02
At Newton iteration 3 norm is 2.005211249672e-05
At Newton iteration 4 norm is 2.050186738598e-11


==== hyperelastic problem at iteration 48 ====
At Newton iteration 1 norm is 1.023859872386e+00
At Newton iteration 2 norm is 4.541939147262e-02
At Newton iteration 3 norm is 1.357368093771e-05
At Newton iteration 4 norm is 1.388272020651e-11


==== hyperelastic problem at iteration 49 ====
At Newton iteration 1 norm is 1.012948847924e+00
At Newton iteration 2 norm is 3.209181262697e-02
At Newton iteration 3 norm is 4.608167756439e-06


==== hyperelastic problem at iteration 50 ====
At Newton iteration 1 norm is 9.011848606483e-01
At Newton iteration 2 norm is 1.514114435145e-02
At Newton iteration 3 norm is 2.649317509595e-06


==== hyperelastic problem at iteration 51 ====
At Newton iteration 1 norm is 9.147499543620e-01
At Newton iteration 2 norm is 1.182898822835e-02
At Newton iteration 3 norm is 9.585085960859e-07


==== hyperelastic problem at iteration 52 ====
At Newton iteration 1 norm is 8.262571045568e-01
At Newton iteration 2 norm is 5.116555475740e-03
At Newton iteration 3 norm is 5.523169250187e-07


==== hyperelastic problem at iteration 53 ====
At Newton iteration 1 norm is 8.340493842286e-01
At Newton iteration 2 norm is 4.510645600581e-03
At Newton iteration 3 norm is 3.220947802889e-07


==== hyperelastic problem at iteration 54 ====
At Newton iteration 1 norm is 7.673833114224e-01
At Newton iteration 2 norm is 1.893075604962e-03
At Newton iteration 3 norm is 1.017537400198e-07


==== hyperelastic problem at iteration 55 ====
At Newton iteration 1 norm is 7.658377469920e-01
At Newton iteration 2 norm is 1.806908734077e-03
At Newton iteration 3 norm is 1.232743151761e-07


==== hyperelastic problem at iteration 56 ====
At Newton iteration 1 norm is 7.143977434337e-01
At Newton iteration 2 norm is 8.793858776794e-04
At Newton iteration 3 norm is 5.046029910889e-08


==== hyperelastic problem at iteration 57 ====
At Newton iteration 1 norm is 7.035265861309e-01
At Newton iteration 2 norm is 7.682477952640e-04
At Newton iteration 3 norm is 3.358157699911e-08


==== hyperelastic problem at iteration 58 ====
At Newton iteration 1 norm is 6.629224135079e-01
At Newton iteration 2 norm is 4.467451354865e-04
At Newton iteration 3 norm is 3.860050859672e-08


==== hyperelastic problem at iteration 59 ====
At Newton iteration 1 norm is 6.449768305255e-01
At Newton iteration 2 norm is 3.411592777240e-04
At Newton iteration 3 norm is 6.323641182039e-09


==== hyperelastic problem at iteration 60 ====
At Newton iteration 1 norm is 6.115152876412e-01
At Newton iteration 2 norm is 2.043579222177e-04
At Newton iteration 3 norm is 3.770304606054e-09


==== hyperelastic problem at iteration 61 ====
At Newton iteration 1 norm is 5.895107293471e-01
At Newton iteration 2 norm is 1.758866635145e-04
At Newton iteration 3 norm is 9.623302568997e-10


==== hyperelastic problem at iteration 62 ====
At Newton iteration 1 norm is 5.598658875646e-01
At Newton iteration 2 norm is 1.091781553641e-04
At Newton iteration 3 norm is 4.444991781652e-10


==== hyperelastic problem at iteration 63 ====
At Newton iteration 1 norm is 5.359774646064e-01
At Newton iteration 2 norm is 1.067069369856e-04
At Newton iteration 3 norm is 3.663179626993e-10


==== hyperelastic problem at iteration 64 ====
At Newton iteration 1 norm is 5.083926956332e-01
At Newton iteration 2 norm is 7.128406133681e-05
At Newton iteration 3 norm is 1.401431295383e-10


==== hyperelastic problem at iteration 65 ====
At Newton iteration 1 norm is 4.838931730274e-01
At Newton iteration 2 norm is 7.282729287596e-05
At Newton iteration 3 norm is 2.249769469348e-10


==== hyperelastic problem at iteration 66 ====
At Newton iteration 1 norm is 4.577219107045e-01
At Newton iteration 2 norm is 5.496200771711e-05
At Newton iteration 3 norm is 1.184096267569e-10


==== hyperelastic problem at iteration 67 ====
At Newton iteration 1 norm is 4.333488299598e-01
At Newton iteration 2 norm is 5.584181487155e-05
At Newton iteration 3 norm is 1.599480318462e-10


==== hyperelastic problem at iteration 68 ====
At Newton iteration 1 norm is 4.084094019859e-01
At Newton iteration 2 norm is 4.546875915601e-05
At Newton iteration 3 norm is 1.064058454259e-10


==== hyperelastic problem at iteration 69 ====
At Newton iteration 1 norm is 3.846636417678e-01
At Newton iteration 2 norm is 4.610317427581e-05
At Newton iteration 3 norm is 1.126593035097e-10


==== hyperelastic problem at iteration 70 ====
At Newton iteration 1 norm is 3.610055281702e-01
At Newton iteration 2 norm is 3.976958232826e-05
At Newton iteration 3 norm is 8.161407068905e-11


==== hyperelastic problem at iteration 71 ====
At Newton iteration 1 norm is 3.382929501894e-01
At Newton iteration 2 norm is 3.967652130545e-05
At Newton iteration 3 norm is 7.476727071146e-11


==== hyperelastic problem at iteration 72 ====
At Newton iteration 1 norm is 3.160822917140e-01
At Newton iteration 2 norm is 3.551852763531e-05
At Newton iteration 3 norm is 5.526866323652e-11


==== hyperelastic problem at iteration 73 ====
At Newton iteration 1 norm is 2.947598112758e-01
At Newton iteration 2 norm is 3.462575531913e-05
At Newton iteration 3 norm is 4.659129433842e-11


==== hyperelastic problem at iteration 74 ====
At Newton iteration 1 norm is 2.742313667930e-01
At Newton iteration 2 norm is 3.155568012090e-05
At Newton iteration 3 norm is 3.430819861929e-11


==== hyperelastic problem at iteration 75 ====
At Newton iteration 1 norm is 2.546482912632e-01
At Newton iteration 2 norm is 3.023962475218e-05
At Newton iteration 3 norm is 2.732291361128e-11


==== hyperelastic problem at iteration 76 ====
At Newton iteration 1 norm is 2.360972905034e-01
At Newton iteration 2 norm is 2.777899516777e-05
At Newton iteration 3 norm is 1.987429435907e-11


==== hyperelastic problem at iteration 77 ====
At Newton iteration 1 norm is 2.186241117195e-01
At Newton iteration 2 norm is 2.628079129927e-05
At Newton iteration 3 norm is 1.525485890433e-11


==== hyperelastic problem at iteration 78 ====
At Newton iteration 1 norm is 2.024069659626e-01
At Newton iteration 2 norm is 2.424610478122e-05
At Newton iteration 3 norm is 1.116391676533e-11


==== hyperelastic problem at iteration 79 ====
At Newton iteration 1 norm is 1.874644769478e-01
At Newton iteration 2 norm is 2.277558533684e-05
At Newton iteration 3 norm is 8.841991736615e-12


==== hyperelastic problem at iteration 80 ====
At Newton iteration 1 norm is 1.740276406620e-01
At Newton iteration 2 norm is 2.106130764842e-05
At Newton iteration 3 norm is 7.088083490341e-12
Saved mesh data in:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.11.0/examples/CardiacElastoDynamics/results/ellipsoid_0.03_D_dt0.0125_analytic_mass/Meshes
Saved simulation and summary in:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.11.0/examples/CardiacElastoDynamics/results/ellipsoid_0.03_D_dt0.0125_analytic_mass

Generate movie 01/20 (5.00 %) 2.93 s
Generate movie 02/20 (10.00 %) 2.40 s
Generate movie 03/20 (15.00 %) 2.26 s
Generate movie 04/20 (20.00 %) 2.12 s
Generate movie 05/20 (25.00 %) 1.94 s
Generate movie 06/20 (30.00 %) 1.88 s
Generate movie 07/20 (35.00 %) 1.64 s
Generate movie 08/20 (40.00 %) 1.50 s
Generate movie 09/20 (45.00 %) 1.37 s
Generate movie 10/20 (50.00 %) 1.24 s
Generate movie 11/20 (55.00 %) 1.15 s
Generate movie 12/20 (60.00 %) 1.05 s
Generate movie 13/20 (65.00 %) 925.11 ms
Generate movie 14/20 (70.00 %) 788.25 ms
Generate movie 15/20 (75.00 %) 656.24 ms
Generate movie 16/20 (80.00 %) 530.01 ms
Generate movie 17/20 (85.00 %) 397.80 ms
Generate movie 18/20 (90.00 %) 265.50 ms
Generate movie 19/20 (95.00 %) 132.69 ms
Generate movie 20/20 (100.00 %) 0.00 µs

 21 from enum import Enum
 22
 23 import numpy as np
 24
 25 from EasyFEA import Display, Folder, PyVista, MatrixType, Models, Simulations, AlgoType
 26 from EasyFEA.FEM import Operators
 27 from EasyFEA.Utilities import _params
 28
 29 from utils import RESULTS_DIR, DATA_DIR, Get_config, Get_values
 30
 31
 32 class CardiacElastoDynamics(Simulations.HyperElastic):
 33
 34     pressure = _params.PositiveScalarParameter()
 35
 36     def __init__(
 37         self, mesh, model, folder="", tolConv=0.00001, maxIter=20, verbosity=False
 38     ):
 39         super().__init__(mesh, model, folder, tolConv, maxIter, verbosity)
 40         self.pressure = 0.0
 41
 42     def Construct_local_matrix_system(self, problemType):
 43
 44         assert isinstance(self.material, Models.HyperElastic.HolzapfelOgden)
 45         nPg = self.material.T1.shape[1]
 46
 47         results = super().Construct_local_matrix_system(problemType, nPg)
 48
 49         # current Newton-Raphson iterate (updated via u += delta_u)
 50         displacement = self._Solver_Get_Newton_Raphson_current_solution()
 51         if self.algo in AlgoType.Get_Hyperbolic_Types():
 52             displacement, _, _ = self._Solver_Evaluate_u_v_a_for_time_scheme(
 53                 problemType, displacement
 54             )
 55
 56         for groupElem in self.mesh.Get_list_groupElem(self.dim - 1):
 57
 58             # Following pressure (operator returns slot-ready values)
 59             tangent_e, residual_e = Operators.NonLinear.FollowingPressure(
 60                 displacement,
 61                 groupElem,
 62                 self.pressure,
 63                 groupElem.Get_Elements_Tag("endo"),
 64                 MatrixType.mass,
 65             )
 66
 67             # top — isotropic surface mass penalty (Robin α·u + β·u̇ = 0)
 68             M_e = Operators.Bilinear.UV(groupElem, dof_n=3)
 69
 70             Ktop_e = np.zeros_like(M_e)
 71             Ctop_e = np.zeros_like(M_e)
 72             if "top" in groupElem.elementTags:
 73                 top_e = groupElem.Get_Elements_Tag("top")
 74                 alpha_top = 1e5
 75                 Ktop_e[top_e] = alpha_top * M_e[top_e]
 76
 77                 beta_top = 5e3
 78                 Ctop_e[top_e] = beta_top * M_e[top_e]
 79
 80             # epi — normal-direction mass penalty (Robin α·(u·n̂) + β·(u̇·n̂) = 0)
 81             Ms_e = Operators.Bilinear.MassAlongNormal(groupElem)
 82
 83             Kepi_e = np.zeros_like(Ms_e)
 84             Cepi_e = np.zeros_like(Ms_e)
 85             if "epi" in groupElem.elementTags:
 86                 epi_e = groupElem.Get_Elements_Tag("epi")
 87                 alpha_epi = 1e8
 88                 Kepi_e[epi_e] = alpha_epi * Ms_e[epi_e]
 89
 90                 beta_epi = 5e3
 91                 Cepi_e[epi_e] = beta_epi * Ms_e[epi_e]
 92
 93             # Penalty residual contribution: −K_penalty · u_t at current iterate
 94             K_penalty_e = Ktop_e + Kepi_e
 95             assembly_e = groupElem.Get_assembly_e(self.dim)
 96             u_e = displacement[assembly_e]  # (Ne_surf, nPe·3)
 97             f_penalty_e = np.einsum("eij,ej->ei", K_penalty_e, u_e)
 98
 99             results[groupElem] = (
100                 tangent_e + K_penalty_e,
101                 Ctop_e + Cepi_e,
102                 None,
103                 residual_e - f_penalty_e,
104             )
105
106         return results
107
108
109 class Config(str, Enum):
110     D = "D"  # active_stress + pressure
111     A = "A"  # active_stress
112     B = "B"  # pressure
113
114
115 if __name__ == "__main__":
116
117     Display.Clear()
118
119     # ----------------------------------------------
120     # Config
121     # ----------------------------------------------
122
123     useCoarseConfig = True
124
125     ellipsoid = "ellipsoid_0.03" if useCoarseConfig else "ellipsoid_0.005"
126
127     config = Config.D
128
129     fiberSource = "analytic"
130     # fiberSource = "vtu"
131
132     matrixType = MatrixType.mass
133     # matrixType = 15
134
135     results_dir = Folder.Join(RESULTS_DIR, ellipsoid + f"_{config.name}")
136
137     doSimu = True
138     plotGraph = False
139     plotParticles = True
140     saveParticles = True
141     makeMovie = True
142
143     # ----------------------------------------------
144     # time-history needed for plotting in both doSimu / Load_Simu flows
145
146     Nt = 80 if useCoarseConfig else 1000
147
148     t_values, activeStress_values, pressure_values = Get_values(Tmax=1.0, Nt=Nt)
149     dt = t_values[1] - t_values[0]
150     results_dir += f"_dt{dt}_{fiberSource}_{matrixType}"
151
152     if plotGraph:
153         ax = Display.Init_Axes()
154         ax.grid()
155         ax.set_xlabel(r"$t$ [s]")
156         ax.set_ylabel(r"$\tau(t)$ [Pa]")
157         ax.plot(t_values, activeStress_values)
158         name = "active_pressure"
159         Display.Save_fig(results_dir, name)
160
161         ax = Display.Init_Axes()
162         ax.grid()
163         ax.set_xlabel(r"$t$ [s]")
164         ax.set_ylabel(r"$p(t)$ [Pa]")
165         ax.plot(t_values, pressure_values)
166         name = "pressure"
167         Display.Save_fig(results_dir, name)
168
169     if config is Config.B:
170         activeStress_values *= 0
171     if config is Config.A:
172         pressure_values *= 0
173
174     if doSimu:
175
176         # ----------------------------------------------
177         # Mesh, fibers and sheets
178         # ----------------------------------------------
179
180         mesh, fibers_e_pg, sheets_e_pg = Get_config(
181             Folder.Join(DATA_DIR, ellipsoid),
182             matrixType=matrixType,
183             fiberSource=fiberSource,
184             plotMesh=False,
185             plotTags=False,
186             plotFibers=False,
187         )
188
189         # ----------------------------------------------
190         # Material
191         # ----------------------------------------------
192
193         # solid
194         a = 59.0
195         a_f = 18472.0
196         a_fs = 216.0
197         a_s = 2481.0
198         b = 8.023
199         b_f = 16.026
200         b_fs = 11.436
201         b_s = 11.12
202
203         material = Models.HyperElastic.HolzapfelOgden(
204             dim=3,
205             C0=a / 2 / b,
206             C1=b,
207             C2=a_f / 2 / b_f,
208             C3=b_f,
209             C4=a_s / 2 / b_s,
210             C5=b_s,
211             C6=a_fs / 2 / b_fs,
212             C7=b_fs,
213             K=1e6,
214             Mu1=0.0,
215             Mu2=0.0,
216             T1=fibers_e_pg,
217             T2=sheets_e_pg,
218             ks=100,
219         )
220         material.eta = 100.0
221         material.Set_active_stress_vec(material.T1)
222
223         # ----------------------------------------------
224         # Simulation
225         # ----------------------------------------------
226
227         simu = CardiacElastoDynamics(mesh, material, folder=results_dir)
228
229         simu.Solver_Set_Hyperbolic_Algorithm(dt, algo=AlgoType.midpoint)
230         simu.rho = 1000
231
232         for t in t_values:
233             simu.Bc_Init()
234             simu.pressure = np.interp(t + dt / 2, t_values, pressure_values)
235             material.active_stress = np.interp(
236                 t + dt / 2, t_values, activeStress_values
237             )
238             simu.Solve()
239             simu.Save_Iter()
240
241         simu.Save(results_dir)
242
243     else:
244         simu = Simulations.Load_Simu(results_dir)
245
246     simu._Gather()
247
248     if plotParticles and simu.isGathered:
249
250         coords = [(0.025, 0.03, 0), (0, 0.03, 0)]
251         evalCoords = np.array(coords)
252         evalElements = simu.mesh.groupElem._Get_nearby_elements(evalCoords)
253
254         Niter = simu.Niter
255         values = np.empty((Niter, len(coords), 3))
256         for i in range(Niter):
257             simu.Set_Iter(i)
258             values[i] = simu.mesh.Evaluate_dofsValues_at_coordinates(
259                 evalCoords, simu.displacement, evalElements
260             )
261
262         times = t_values[:Niter]
263         axs = Display.plt.subplots(3, 2, sharex=True)[1]
264
265         for p, (particle, coord) in enumerate(zip(["p0", "p1"], coords)):
266
267             for c, component in enumerate(["x", "y", "z"]):
268
269                 ax: Display.plt.Axes = axs[c, p]
270
271                 ax.grid()
272
273                 if c == 2:
274                     ax.set_xlabel("Time [s]")
275                 if p == 0:
276                     ax.set_ylabel(f"Displacement {component}-component [m]")
277                 if c == 0:
278                     ax.set_title(f"Particle {particle}")
279
280                 ax.plot(times, values[:, p, c])
281
282         width, height = ax.figure.get_size_inches()
283         ax.figure.set_size_inches(width * 1.5, height * 2.5)
284         Display.Save_fig(results_dir, "particles")
285
286     if saveParticles and simu.isGathered:
287
288         # per-iteration deformed volume
289         volumes = np.empty(Niter)
290         for i in range(Niter):
291             simu.Set_Iter(i)
292             deformed = simu.mesh.copy()
293             deformed.coord += simu.displacement.reshape(-1, 3)
294             volumes[i] = deformed.volume
295
296         dict_particles = {
297             "time": times,
298             "displacement": {
299                 f"p{p}": {
300                     "ux": values[:, p, 0],
301                     "uy": values[:, p, 1],
302                     "uz": values[:, p, 2],
303                     "magnitude": np.linalg.norm(values[:, p, :], axis=1),
304                 }
305                 for p in range(2)
306             },
307             "stress": {
308                 "time": None,
309                 "p0": {"magnitude": None},
310                 "p1": {"magnitude": None},
311             },
312             "volume": volumes,
313         }
314         Simulations.Save_pickle(dict_particles, results_dir, "particles")
315
316     if makeMovie:
317         values = [simu.Result("ux", iter=i) for i in range(simu.Niter)]
318         clim = (np.min(values), np.max(values))
319         PyVista.Movie_simu(
320             simu,
321             "ux",
322             results_dir,
323             "ux.gif",
324             N=20,
325             deformFactor=1.0,
326             clim=clim,
327             plotMesh=True,
328         )
329
330     Display.plt.show()

Total running time of the script: (0 minutes 19.953 seconds)

Gallery generated by Sphinx-Gallery