def create_forward_problem( mesh, activation, active_value=0.0, active_model="active_stain", T_ref=1.0, ): ffun = df.MeshFunction("size_t", mesh, 2) ffun.set_all(0) left = df.CompiledSubDomain("on_boundary && near(x[0], 0)") left_marker = 1 left.mark(ffun, left_marker) # Collect the functions containing the markers marker_functions = pulse.MarkerFunctions(ffun=ffun) def dirichlet_bc(W): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) return da.DirichletBC(V, da.Constant((0.0, 0.0, 0.0)), left) bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc, ), ) f0 = df.as_vector([1, 0, 0]) microstructure = pulse.Microstructure(f0=f0) geometry = pulse.Geometry( mesh=mesh, marker_functions=marker_functions, microstructure=microstructure, ) material_parameters = dict( a=2.28, a_f=1.686, b=9.726, b_f=15.779, a_s=0.0, b_s=0.0, a_fs=0.0, b_fs=0.0, ) material = pulse.HolzapfelOgden( active_model=active_model, parameters=material_parameters, activation=activation, T_ref=T_ref, ) problem = pulse.MechanicsProblem(geometry, material, bcs) problem.solve() if active_value > 0.0: pulse.iterate.iterate(problem, activation, active_value) return problem
def setup_material(material_model): """ Choose parameters based on Hadjicharalambous, Myrianthi, et al. "Analysis of passive cardiac constitutive laws for parameter estimation using 3D tagged MRI." Biomechanics and modeling in mechanobiology 14.4 (2015): 807-828. These parameters did not really match the Klotz curve here. Perhaps they did some more tuning? """ if material_model == "guccione": matparams = pulse.Guccione.default_parameters() matparams["C"] = 0.18 # kPa matparams["bf"] = 27.75 matparams["bt"] = 5.37 matparams["bfs"] = 2.445 material = pulse.Guccione( parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0, ) elif material_model == "neo_hookean": matparams = pulse.NeoHookean.default_parameters() matparams["mu"] = 10.0 # kPa material = pulse.NeoHookean(parameters=matparams) elif material_model == "holzapfel_ogden": matparams = pulse.HolzapfelOgden.default_parameters() matparams["a"] = 4.0 # kPa matparams["a_f"] = 10.0 # kPa matparams["b"] = 5.0 matparams["b_f"] = 5.0 material = pulse.HolzapfelOgden( parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0, ) return material
def build_problem(geometry, matparams): activation = dolfin.Function(dolfin.FunctionSpace(geometry.mesh, "R", 0)) material = pulse.HolzapfelOgden( activation=activation, parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0, ) # LV Pressure lvp = dolfin.Constant(0.0) lv_marker = geometry.markers["ENDO"][0] lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name="lv") neumann_bc = [lv_pressure] # Add spring term at the base with stiffness 1.0 kPa/cm^2 base_spring = 1.0 robin_bc = [ pulse.RobinBC( value=dolfin.Constant(base_spring), marker=geometry.markers["BASE"][0] ) ] # 0 in V.sub(0) refers to x-direction, which is the longitudinal direction def fix_basal_plane(W): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) bc = dolfin.DirichletBC( V.sub(0), dolfin.Constant(0.0), geometry.ffun, geometry.markers["BASE"][0] ) return bc dirichlet_bc = [fix_basal_plane] # Collect boundary conditions bcs = pulse.BoundaryConditions( dirichlet=dirichlet_bc, neumann=neumann_bc, robin=robin_bc ) # Create the problem problem = pulse.MechanicsProblem(geometry, material, bcs) return problem, activation, lvp
) # Use the default material parameters material_parameters = pulse.HolzapfelOgden.default_parameters() # Select model for active contraction active_model = pulse.ActiveModels.active_strain # active_model = "active_stress" # Set the activation activation = Constant(0.0) # Create material material = pulse.HolzapfelOgden( active_model=active_model, parameters=material_parameters, activation=activation, ) # Make Dirichlet boundary conditions def dirichlet_bc(W): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) return DirichletBC(V, Constant((0.0, 0.0, 0.0)), fixed) # Make Neumann boundary conditions neumann_bc = pulse.NeumannBC(traction=Constant(0.0), marker=free_marker) # Collect Boundary Conditions bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=(neumann_bc,))
""" This demo demonstrates how to unload a geometry using the backward displament method which is an iterative fixed point method. """ import matplotlib.pyplot as plt import dolfin import pulse geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths['simple_ellipsoid']) material = pulse.HolzapfelOgden() # material = pulse.Guccione() # Parameter for the cardiac boundary conditions bcs_parameters = pulse.MechanicsProblem.default_bcs_parameters() bcs_parameters['base_spring'] = 1.0 bcs_parameters['base_bc'] = 'fix_x' # Create the problem # When performing unloading you should pass the # bcs parameters instead of the bcs directly problem = pulse.MechanicsProblem(geometry, material, bcs_parameters=bcs_parameters) # Suppose geometry is loaded with a pressure of 1 kPa # and create the unloader unloader = pulse.FixedPointUnloader(problem=problem, pressure=1.0) # Unload the geometry
microstructure = pulse.Microstructure(f0=fiber) # Create the geometry geometry = pulse.HeartGeometry( mesh=mesh, markers=markers, marker_functions=marker_functions, microstructure=microstructure, ) activation = Function(dolfin.FunctionSpace(geometry.mesh, "R", 0)) activation.assign(Constant(0.0)) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden( activation=activation, parameters=matparams, f0=geometry.f0, ) # LV Pressure lvp = Constant(0.0) lv_marker = markers["ENDO"][0] lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name="lv") neumann_bc = [lv_pressure] # Add spring term at the base with stiffness 1.0 kPa/cm^2 base_spring = 1.0 robin_bc = [ pulse.RobinBC(value=Constant(base_spring), marker=markers["BASE"][0]) ]
def create_problem(): geometry = pulse.HeartGeometry.from_file( pulse.mesh_paths["simple_ellipsoid"]) activation = dolfin_adjoint.Function(dolfin.FunctionSpace( geometry.mesh, "R", 0), name="activation") activation.assign(dolfin_adjoint.Constant(0.0)) matparams = pulse.HolzapfelOgden.default_parameters() V = dolfin.FunctionSpace(geometry.mesh, "R", 0) control = dolfin_adjoint.Function(V) control.assign(dolfin_adjoint.Constant(1.0)) # control = dolfin_adjoint.Constant(1.0, name="matparam control (a)") matparams["a"] = control f0 = dolfin_adjoint.Function(geometry.f0.function_space()) f0.assign(geometry.f0) s0 = dolfin_adjoint.Function(geometry.s0.function_space()) s0.assign(geometry.s0) n0 = dolfin_adjoint.Function(geometry.n0.function_space()) n0.assign(geometry.n0) material = pulse.HolzapfelOgden(activation=activation, parameters=matparams, f0=f0, s0=s0, n0=n0) # LV Pressure lvp = dolfin_adjoint.Constant(0.0, name="lvp") lv_marker = geometry.markers["ENDO"][0] lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name="lv") neumann_bc = [lv_pressure] # Add spring term at the base with stiffness 1.0 kPa/cm^2 base_spring = 1.0 robin_bc = [ pulse.RobinBC( value=dolfin_adjoint.Constant(base_spring, name="base_spring"), marker=geometry.markers["BASE"][0], ) ] # Fix the basal plane in the longitudinal direction # 0 in V.sub(0) refers to x-direction, which is the longitudinal direction def fix_basal_plane(W): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) bc = dolfin_adjoint.DirichletBC( V.sub(0), dolfin.Constant(0.0, name="fix_base"), geometry.ffun, geometry.markers["BASE"][0], ) return bc dirichlet_bc = [fix_basal_plane] # Collect boundary conditions bcs = pulse.BoundaryConditions(dirichlet=dirichlet_bc, neumann=neumann_bc, robin=robin_bc) # Create the problem problem = pulse.MechanicsProblem(geometry, material, bcs) return problem, control
# Use the default material parameters from the paper material_parameters = { "a": 0.059, "b": 8.023, "a_f": 18.472, "b_f": 16.026, "a_s": 2.481, "b_s": 11.120, "a_fs": 0.216, "b_fs": 11.436, } # Create material material = pulse.HolzapfelOgden(parameters=material_parameters) # Make a space for controling the amount of shear displacement X_space = dolfin.VectorFunctionSpace(mesh, "R", 0) x = Function(X_space) zero = Constant((0.0, 0.0, 0.0)) # Make a method that will return def create_experiment(case): # noqa: C901 if case == "fs": def dirichlet_bc(W):
import pulse from fenics_plotly import plot gamma_space = "R_0" geometry = pulse.Geometry.from_file(pulse.mesh_paths["prolate_ellipsoid"]) # geometry = pulse.geometries.prolate_ellipsoid_geometry(mesh_size_factor=3.0) geometry.mesh.coordinates()[:] *= 0.1 # breakpoint() activation = Function(dolfin.FunctionSpace(geometry.mesh, "R", 0)) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden( active_model=pulse.ActiveModels.active_stress, T_ref=1.0, # Total active stress should be activation * T_ref eta=0.2, # Fraction of transverse stress activation=activation, parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0, ) # LV Pressure lvp = Constant(0.0) lv_marker = geometry.markers["ENDO"][0] lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name="lv") neumann_bc = [lv_pressure] # Add spring term at the base with stiffness 1.0 kPa/cm^2 base_spring = 1.0 robin_bc = [ pulse.RobinBC(value=Constant(base_spring),
import matplotlib.pyplot as plt import dolfin import pulse from geometry import Geometry, example_meshes geo = Geometry.from_file(example_meshes['simple_ellipsoid']) activation = dolfin.Function(dolfin.FunctionSpace(geo.mesh, "R", 0)) activation.assign(dolfin.Constant(0.2)) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden(activation=activation, parameters=matparams, f0=geo.f0, s0=geo.s0, n0=geo.n0) # LV Pressure lvp = dolfin.Constant(1.0) lv_marker = geo.markers['ENDO'][0] lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name='lv') neumann_bc = [lv_pressure] # Add spring term at the base with stiffness 1.0 kPa/cm^2 base_spring = 1.0 robin_bc = [pulse.RobinBC(value=dolfin.Constant(base_spring), marker=geo.markers["BASE"][0])] # Fix the basal plane in the longitudinal direction