def boundary_conditions(geometry, **bcs_parameters): try: pericardium_spring = bcs_parameters['pericardium_spring'] base_spring = bcs_parameters['base_spring'] base_bc = bcs_parameters['base_bc'] except KeyError: msg = "Not all boundary conditions have been set. You have provided "\ "{}".format(bcs_parameters.keys()) raise KeyError(msg) # Neumann BCs lv_pressure = pulse.NeumannBC(traction=Constant(0.0, name="lv_pressure"), marker=geometry.get_lv_marker(), name="lv") neumann_bc = [lv_pressure] if geometry.has_rv(): rv_pressure = pulse.NeumannBC(traction=Constant(0.0, name="rv_pressure"), marker=geometry.get_rv_marker(), name="rv") neumann_bc += [rv_pressure] # Robin BC robin_bc = [] if pericardium_spring > 0.0: robin_bc += [ pulse.RobinBC(value=Constant(pericardium_spring), marker=geometry.get_epi_marker()) ] if base_spring > 0.0: robin_bc += [ pulse.RobinBC(value=Constant(base_spring), marker=geometry.get_base_marker()) ] # Dirichlet BC if base_bc == "fixed": dirichlet_bc = [ partial( dirichlet_fix_base, ffun=geometry.ffun, marker=geometry.get_base_marker(), ) ] elif base_bc == "fix_x": dirichlet_bc = [ partial(dirichlet_fix_base_directional, ffun=geometry.ffun, marker=geometry.get_base_marker()) ] return pulse.BoundaryConditions(dirichlet=dirichlet_bc, neumann=neumann_bc, robin=robin_bc)
def mechanics_bcs(geometry): # LV Pressure lvp = df.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=df.Constant(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 = df.DirichletBC(V.sub(0), df.Constant(0.0), geometry.ffun, geometry.markers["BASE"][0]) return bc dirichlet_bc = [fix_basal_plane] bcs = pulse.BoundaryConditions(dirichlet=dirichlet_bc, neumann=neumann_bc, robin=robin_bc) return bcs
def create_mechanics_problem(solver_parameters): import pulse # from pulse import (MechanicsProblem, HeartGeometry, BoundaryConditions, # NeumannBC, RobinBC, MarkerFunctions, Marker, CRLBasis) from pulse.material import HolzapfelOgden mfun = pulse.MarkerFunctions(ffun=solver_parameters['facet_function'], cfun=solver_parameters['mesh_function']) material = solver_parameters['material'] microstructure = pulse.Microstructure(f0=material.f0, s0=material.s0, n0=material.f0) crl_basis = pulse.CRLBasis( c0=solver_parameters['crl_basis']['circumferential'], r0=solver_parameters['crl_basis']['radial'], l0=solver_parameters['crl_basis']['longitudinal']) geometry = pulse.HeartGeometry(mesh=solver_parameters['mesh'], markers=solver_parameters['markers'], marker_functions=mfun, microstructure=microstructure, crl_basis=crl_basis) neumann = [] names = ['lv', 'rv'] for i, n in enumerate(solver_parameters['bc']['neumann']): neumann.append( pulse.NeumannBC(traction=n[0], marker=n[1], name=names[i])) robin = [] for i, n in enumerate(solver_parameters['bc']['robin']): robin.append(pulse.RobinBC(value=n[0], marker=n[1])) if hasattr(solver_parameters['bc']['dirichlet'], '__len__'): dirichlet = solver_parameters['bc']['dirichlet'] else: dirichlet = (solver_parameters['bc']['dirichlet'], ) bcs = pulse.BoundaryConditions(dirichlet=dirichlet, neumann=neumann, robin=robin) problem = pulse.MechanicsProblem(geometry, material, bcs) return problem
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
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]) ] # 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 = DirichletBC(V.sub(0), Constant(0.0), geometry.ffun, markers["BASE"][0]) return bc dirichlet_bc = [fix_basal_plane] # You can also use a built in function for this # from functools import partial
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
material = pulse.HolzapfelOgden(activation=activation, parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0) # LV Pressure lvp = dolfin.Constant(1.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])] # 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.DirichletBC(V.sub(0), dolfin.Constant(0.0), geometry.ffun, geometry.markers["BASE"][0]) return bc dirichlet_bc = [fix_basal_plane] # You can also use a built in function for this # from functools import partial
activation.assign(dolfin.Constant(0.2)) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden(activation=activation, parameters=matparams, f0=geometry.f0) # LV Pressure lvp = dolfin.Constant(1.0) lv_marker = markers_dict["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=markers_dict["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.DirichletBC(V.sub(0), dolfin.Constant(0.0), geometry.ffun, markers_dict["BASE"][0]) return bc dirichlet_bc = [fix_basal_plane] # You can also use a built in function for this # from functools import partial
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 epicardium of stiffness 1.0 kPa/cm^2 to represent pericardium base_spring = 1.0 robin_bc = [ pulse.RobinBC(value=Constant(base_spring), marker=geometry.markers["EPI"][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 = DirichletBC( V.sub(0), Constant(0.0), geometry.ffun, geometry.markers["BASE"][0], ) return bc
def solve( geometry, EDP=1.0, ESP=15.0, Ta=60, material_parameters=None, ): """ Arguments --------- EDP : float End diastolic pressure ESP : float End systolic pressure Ta : float Peak active tension (at ES) material_parameters : dict A dictionart with parameter in the Guccione model. Default: {'C': 2.0, 'bf': 8.0, 'bt': 2.0, 'bfs': 4.0} filename : str Filname where to store the results """ # Create model activation = df.Function(df.FunctionSpace(geometry.mesh, "R", 0)) matparams = pulse.Guccione.default_parameters() if material_parameters is not None: matparams.update(material_parameters) material = pulse.Guccione(activation=activation, parameters=matparams, active_model="active_stress", f0=geometry.f0, s0=geometry.s0, n0=geometry.n0) lvp = df.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=df.Constant(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 = df.DirichletBC(V.sub(0), df.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) xdmf = df.XDMFFile(df.mpi_comm_world(), 'output.xdmf') # Solve the problem print(("Do an initial solve with pressure = 0 kPa " "and active tension = 0 kPa")) problem.solve() u, p = problem.state.split() xdmf.write(u, 0.0) print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u))) # Solve for ED print(("Solver for ED with pressure = {} kPa and active tension = 0 kPa" "".format(EDP))) pulse.iterate.iterate(problem, lvp, EDP, initial_number_of_steps=20) u, p = problem.state.split(deepcopy=True) xdmf.write(u, 1.0) df.File("ED_displacement.xml") << u print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u))) # Solve for ES print(("Solver for ES with pressure = {} kPa and active tension = {} kPa" "".format(ESP, Ta))) pulse.iterate.iterate(problem, lvp, ESP, initial_number_of_steps=50) pulse.iterate.iterate(problem, activation, Ta, adapt_step=False, max_iters=100, initial_number_of_steps=40) u, p = problem.state.split(deepcopy=True) xdmf.write(u, 2.0) df.File("ES_displacement.xml") << u print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u)))