def unload(self, save=False): """ Unload the geometry """ if save: self.save(self.problem.geometry.mesh, "original_geometry/mesh", "0") logger.info("".center(72, "-")) logger.info("Start unloading".center(72, "-")) logger.info("".center(72, "-")) logger.info( ( "\nLV Volume of original geometry = " "{:.3f} ml".format(self.problem.geometry.cavity_volume(chamber="lv")) ), ) if self.problem.geometry.is_biv: logger.info( ( "RV Volume of original geometry = " "{:.3f} ml".format( self.problem.geometry.cavity_volume(chamber="rv"), ) ), ) residual = utils.ResidualCalculator(self.problem.geometry.mesh) u = self.initial_solve(True) self.U = Function(u.function_space()) self.unload_step(u, residual, save=save) logger.info("".center(72, "#") + "\nUnloading suceeding")
def backward_displacement(self): """ Return the current backward displacement as a function on the original geometry. """ W = dolfin.VectorFunctionSpace(self.U.function_space().mesh(), "CG", 1) u_int = interpolate(self.U, W) u = Function(W) u.vector()[:] = -1 * u_int.vector() return u
def update_function(mesh, f): """Given a function :math:`f` defined on some domain, update the function so that it now is defined on the domain given in the mesh """ f_new = Function(dolfin.FunctionSpace(mesh, f.ufl_element())) numpy_mpi.assign_to_vector(f_new.vector(), numpy_mpi.gather_vector(f.vector())) return f_new
def assign_sub(self, f, i): """ Assign subfunction :param f: The function you want to assign :param int i: The subspace number """ f_ = Function(self.basespace) f_.assign(f) self.function_assigner[i].assign(self.split()[i], f_)
def increment_control(self): for c, s in zip(self.control, self.step): if isinstance(c, (dolfin.Function, Function)): c_arr = numpy_mpi.gather_vector(c.vector()) c_tmp = Function(c.function_space()) c_tmp.vector()[:] = c_arr + s c.assign(c_tmp) else: c_arr = c c.assign(Constant(constant2float(c) + s))
def calc_cross_products(e1, e2, VV): e_crossed = Function(VV) e1_arr = e1.vector().get_local().reshape((-1, 3)) e2_arr = e2.vector().get_local().reshape((-1, 3)) crosses = [] for c1, c2 in zip(e1_arr, e2_arr): crosses.extend(np.cross(c1, c2.tolist())) e_crossed.vector()[:] = np.array(crosses)[:] return e_crossed
def _init_spaces(self): logger.debug("Initialize spaces for mechanics problem") mesh = self.geometry.mesh P2 = dolfin.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = dolfin.FiniteElement("Lagrange", mesh.ufl_cell(), 1) # P2_space = FunctionSpace(mesh, P2) # P1_space = FunctionSpace(mesh, P1) self.state_space = dolfin.FunctionSpace(mesh, P2 * P1) self.state = Function(self.state_space, name="state") self.state_test = dolfin.TestFunction(self.state_space)
def __init__(self, fun, n, name="material_parameters"): """ Initialize Mixed parameter. This will instanciate a function in a dolfin.MixedFunctionSpace consiting of `n` subspaces of the same type as `fun`. This is of course easy for the case when `fun` is a normal dolfin function, but in the case of a `RegionalParameter` it is not that straight forward. This class handles this case as well. :param fun: The type of you want to make a du :type fun: (:py:class:`dolfin.Function`) :param int n: number of subspaces :param str name: Name of the function .. todo:: Implement support for MixedParameter with different types of subspaces, e.g [RegionalParamter, R_0, CG_1] """ msg = "Please provide a dolin function as argument to MixedParameter" assert isinstance(fun, (dolfin.Function, Function, RegionalParameter)), msg if isinstance(fun, RegionalParameter): raise NotImplementedError # We can just make a usual mixed function space # with n copies of the original one V = fun.function_space() W = dolfin.MixedFunctionSpace([V] * n) Function.__init__(self, W, name=name) # Create a function assigner self.function_assigner = [ FunctionAssigner(W.sub(i), V) for i in range(n) ] # Store the original function space self.basespace = V if isinstance(fun, RegionalParameter): self._meshfunction = fun._meshfunction
def make_mechanics_problem(geometry, space="R_0"): # Material = NeoHookean Material = HolzapfelOgden if space == 'regional': activation = RegionalParameter(geometry.cfun) else: family, degree = space.split('_') activation = Function( dolfin.FunctionSpace(geometry.mesh, family, int(degree))) matparams = Material.default_parameters() # mu = RegionalParameter(geometry.cfun) # mu_val = get_constant(mu.value_size(), value_rank=0, val=matparams["mu"]) # mu.assign(mu_val) # matparams["mu"] = mu material = Material(activation=activation, parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0) #bcs = cardiac_boundary_conditions(geometry, base_spring=1.0) bcs_parameters = MechanicsProblem.default_bcs_parameters() bcs_parameters['base_spring'] = 1.0 bcs_parameters['base_bc'] = 'fix_x' problem = MechanicsProblem(geometry, material, bcs_parameters=bcs_parameters) return problem
def load_local_basis(h5file, lgroup, mesh, geo): if h5file.has_dataset(lgroup): # Get local bais functions local_basis_attrs = h5file.attributes(lgroup) lspace = local_basis_attrs["space"] family, order = lspace.split("_") namesstr = local_basis_attrs["names"] names = namesstr.split(":") if DOLFIN_VERSION_MAJOR > 1.6: elm = dolfin.VectorElement( family=family, cell=mesh.ufl_cell(), degree=int(order), quad_scheme="default", ) V = dolfin.FunctionSpace(mesh, elm) else: V = dolfin.VectorFunctionSpace(mesh, family, int(order)) for name in names: lb = Function(V, name=name) io_utils.read_h5file(h5file, lb, lgroup + "/{}".format(name)) setattr(geo, name, lb) else: setattr(geo, "circumferential", None) setattr(geo, "radial", None) setattr(geo, "longitudinal", None)
def _set_parameter_attrs(self, geometry=None): for k, v in self.parameters.items(): if isinstance(v, (float, int)): setattr(self, k, Constant(v, name=k)) elif isinstance(v, RegionalParameter): if geometry is not None: v_new = RegionalParameter(geometry.sfun) numpy_mpi.assign_to_vector( v_new.vector(), numpy_mpi.gather_vector(v.vector()), ) v = v_new ind_space = v.proj_space setattr(self, k, Function(ind_space, name=k)) mat = getattr(self, k) matfun = v.function mat.assign(project(matfun, ind_space)) else: if geometry is not None and v.ufl_element().cell() is not None: v_new = update_function(geometry.mesh, v) v = v_new setattr(self, k, v)
def map_vector_field(f0, new_mesh, u=None, name="fiber", normalize=True): """ Map a vector field (f0) onto a new mesh (new_mesh) where the new mesh can be a moved version of the original one according to some displacement (u). In that case we will just a Piola transform to map the vector field. """ representation = dolfin.parameters["form_compiler"]["representation"] if DOLFIN_VERSION_MAJOR > 2016: dolfin.parameters["form_compiler"]["representation"] = "quadrature" dolfin.parameters["form_compiler"]["quadrature_degree"] = 4 ufl_elem = f0.function_space().ufl_element() f0_new = Function(dolfin.FunctionSpace(new_mesh, ufl_elem)) if u is not None: f0_mesh = f0.function_space().mesh() u_elm = u.function_space().ufl_element() V = dolfin.FunctionSpace(f0_mesh, u_elm) u0 = Function(V) # arr = numpy_mpi.gather_vector(u.vector()) # numpy_mpi.assign_to_vector(u0.vector(), arr) u0.vector()[:] = u.vector() from .kinematics import DeformationGradient F = DeformationGradient(u0) f0_updated = project(F * f0, f0.function_space()) if normalize: f0_updated = normalize_vector_field(f0_updated) f0_new.vector()[:] = f0_updated.vector() # f0_arr = numpy_mpi.gather_vector(f0_updated.vector()) # numpy_mpi.assign_to_vector(f0_new.vector(), f0_arr) else: # f0_arr = numpy_mpi.gather_vector(f0.vector()) # numpy_mpi.assign_to_vector(f0_new.vector(), f0_arr) f0_new.vector()[:] = f0.vector() if DOLFIN_VERSION_MAJOR > 2016: dolfin.parameters["form_compiler"]["representation"] = representation return f0_new
def get_initial_step(current, target, nsteps=5): """ Estimate the step size needed to step from current to target in `nsteps`. """ diff = get_diff(current, target) if isinstance(diff, dolfin.GenericVector): step = Function(current.function_space()) step.vector().axpy(1.0 / float(nsteps), diff) else: step = diff / float(nsteps) logger.debug(("Intial number of steps: {} with step size {}" "").format(nsteps, step), ) return step
def vectorfield_to_components(u, S, dim): components = [Function(S) for i in range(dim)] assigners = [ FunctionAssigner(S, u.function_space().sub(i)) for i in range(dim) ] for i, comp, assigner in zip(range(dim), components, assigners): assigner.assign(comp, u.split()[i]) return components
def _init_spaces(self): mesh = self.geometry.mesh element = dolfin.VectorElement("P", mesh.ufl_cell(), 1) self.state_space = dolfin.FunctionSpace(mesh, element) self.state = Function(self.state_space) self.state_test = dolfin.TestFunction(self.state_space) # Add penalty factor self.kappa = Constant(1e3)
def __init__( self, problem, pressure, h5name="test.h5", options=None, h5group="", overwrite=False, merge_control="", ): self.problem = problem self.pressure = pressure self.U = Function(problem.get_displacement(annotate=True).function_space()) self.merge_control = merge_control self.h5name = h5name self.h5group = h5group if os.path.isfile(h5name) and overwrite: if mpi_comm_world().rank == 0: os.remove(h5name) self.n = int(np.rint(np.max(np.divide(pressure, 0.4)))) self.parameters = self.default_parameters() if options is not None: self.parameters.update(**options) msg = ( "\n\n" + " Unloading options ".center(72, "-") + "\n\n" + f"\tTarget pressure: {pressure}\n" + f"\tmaxiter = {self.parameters['maxiter']}\n" + f"\ttolerance = {self.parameters['tol']}\n" + "\tregenerate_fibers (serial only)= " "{}\n\n".format(self.parameters["regen_fibers"]) + "".center(72, "-") + "\n" ) logger.info(msg)
def _init_spaces(self): mesh = self.geometry.mesh P1 = dolfin.FiniteElement("Lagrange", mesh.ufl_cell(), 1) P2 = dolfin.VectorElement("Lagrange", mesh.ufl_cell(), 2) P3 = dolfin.VectorElement("Real", mesh.ufl_cell(), 0, 6) self.state_space = dolfin.FunctionSpace(mesh, dolfin.MixedElement([P1, P2, P3])) self.state = Function(self.state_space, name="state") self.state_test = dolfin.TestFunction(self.state_space)
def change_step_for_final_iteration(self, prev_control): """Change step size so that target is reached in the next iteration """ logger.debug("Change step size for final iteration") target = delist(self.target) prev_control = delist(prev_control) if isinstance(target, (dolfin.Function, Function)): step = Function(target.function_space()) step.vector().axpy(1.0, target.vector()) step.vector().axpy(-1.0, prev_control.vector()) elif isinstance(target, (list, np.ndarray, tuple)): if isinstance(prev_control, (dolfin.Function, Function)): prev = numpy_mpi.gather_vector( prev_control.vector(), prev_control.function_space().dim(), ) else: prev = prev_control step = np.array([ constant2float(t) - constant2float(c) for (t, c) in zip(target, prev) ], ) elif isinstance(target, (dolfin.Constant, Constant)): step = constant2float(target) - constant2float(prev_control) else: step = target - prev_control self.step = step
def get_displacement(self, annotate=False): D = self.state_space.sub(0) V = D.collapse() fa = FunctionAssigner(V, D) u = Function(V, name="displacement") if has_dolfin_adjoint: fa.assign(u, self.state.split()[0], annotate=annotate) else: fa.assign(u, self.state.split()[0]) return u
def __init__(self, meshfunction): # assert isinstance( # meshfunction, dolfin.MeshFunctionSizet # ), "Invalid meshfunction for regional gamma" mesh = meshfunction.mesh() # FIXME self._values = set(numpy_mpi.gather_broadcast(meshfunction.array())) self._nvalues = len(self._values) V = dolfin.VectorFunctionSpace(mesh, "R", 0, dim=self._nvalues) Function.__init__(self, V) self._meshfunction = meshfunction # Functionspace for the indicator functions self._proj_space = dolfin.FunctionSpace(mesh, "DG", 0) # Make indicator functions self._ind_functions = [] for v in self._values: self._ind_functions.append(self._make_indicator_function(v))
def move(mesh, u, factor=1.0): """ Move mesh according to some displacement times some factor """ W = dolfin.VectorFunctionSpace(u.function_space().mesh(), "CG", 1) # Use interpolation for now. It is the only thing that makes sense u_int = interpolate(u, W) u0 = Function(W) # arr = factor * numpy_mpi.gather_vector(u_int.vector()) # numpy_mpi.assign_to_vector(u0.vector(), arr) u0.vector()[:] = factor * u_int.vector() V = dolfin.VectorFunctionSpace(mesh, "CG", 1) U = Function(V) U.vector()[:] = u0.vector() # numpy_mpi.assign_to_vector(U.vector(), arr) dolfin.ALE.move(mesh, U) return u0
def load_microstructure(h5file, fgroup, mesh, geo, include_sheets=True): if h5file.has_dataset(fgroup): # Get fibers fiber_attrs = h5file.attributes(fgroup) fspace = fiber_attrs["space"] if fspace is None: # Assume quadrature 4 # family = "Quadrature" # order = 4 family = "CG" order = 1 else: family, order = fspace.split("_") namesstr = fiber_attrs["names"] if namesstr is None: names = ["fiber"] else: names = namesstr.split(":") # Check that these fibers exists for name in names: fsubgroup = fgroup + f"/{name}" if not h5file.has_dataset(fsubgroup): msg = ("H5File does not have dataset {}").format(fsubgroup) logger.warning(msg) if DOLFIN_VERSION_MAJOR > 1.6: elm = dolfin.VectorElement( family=family, cell=mesh.ufl_cell(), degree=int(order), quad_scheme="default", ) V = dolfin.FunctionSpace(mesh, elm) else: V = dolfin.VectorFunctionSpace(mesh, family, int(order)) attrs = ["f0", "s0", "n0"] for i, name in enumerate(names): func = Function(V, name=name) fsubgroup = fgroup + f"/{name}" io_utils.read_h5file(h5file, func, fsubgroup) setattr(geo, attrs[i], func)
def increment_control(self): for c, s in zip(self.control, self.step): # if isinstance(s, (dolfin.Function, Function)) if isinstance(c, (dolfin.Function, Function)): c_arr = numpy_mpi.gather_vector(c.vector(), c.function_space().dim()) c_tmp = Function(c.function_space()) c_tmp.vector().set_local(np.array(c_arr + s)) c_tmp.vector().apply("") c.assign(c_tmp) else: c_arr = c c.assign(Constant(constant2float(c) + s))
def make_unit_vector(V, VV, dofs_x, fill_coordinates, foc=None): e_c_x = Function(V) e_c_y = Function(V) e_c_z = Function(V) for i, coord in enumerate(dofs_x): fill_coordinates(i, e_c_x, e_c_y, e_c_z, coord, foc) e = Function(VV) fa = [FunctionAssigner(VV.sub(i), V) for i in range(3)] for i, e_c_comp in enumerate([e_c_x, e_c_y, e_c_z]): fa[i].assign(e.split()[i], e_c_comp) return e
f0 = interpolate(Expression(("1.0", "0.0", "0.0"), degree=1), V_f) # Sheets s0 = interpolate(Expression(("0.0", "1.0", "0.0"), degree=1), V_f) # Fiber-sheet normal n0 = interpolate(Expression(("0.0", "0.0", "1.0"), degree=1), V_f) microstructure = pulse.Microstructure(f0=f0, s0=s0, n0=n0) # Create the geometry geometry = pulse.Geometry( mesh=mesh, microstructure=microstructure, ) # - activation = Function(dolfin.FunctionSpace(geometry.mesh, "R", 0)) activation.assign(Constant(0.2)) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden( activation=activation, parameters=matparams, f0=geometry.f0, s0=geometry.s0, n0=geometry.n0, ) problem = RigidMotionProblem(geometry, material) problem.solve() u = problem.state.split(deepcopy=True)[1]
def _make_indicator_function(self, marker): dofs = self._meshfunction.where_equal(marker) f = Function(self._proj_space) f.vector()[dofs] = 1.0 return f
class MechanicsProblem(object): """ Base class for mechanics problem """ def __init__( self, geometry: Geometry, material: Material, bcs=None, bcs_parameters=None, solver_parameters=None, ): logger.debug("Initialize mechanics problem") self.geometry = geometry self.material = material self._handle_bcs(bcs=bcs, bcs_parameters=bcs_parameters) # Make sure that the material has microstructure information for attr in ("f0", "s0", "n0"): setattr(self.material, attr, getattr(self.geometry, attr)) self.solver_parameters = NonlinearSolver.default_solver_parameters() if solver_parameters is not None: self.solver_parameters.update(**solver_parameters) self._init_spaces() self._init_forms() def _handle_bcs(self, bcs, bcs_parameters): if bcs is None: if isinstance(self.geometry, HeartGeometry): self.bcs_parameters = MechanicsProblem.default_bcs_parameters() if bcs_parameters is not None: self.bcs_parameters.update(**bcs_parameters) else: raise ValueError(("Please provive boundary conditions " "to MechanicsProblem"), ) self.bcs = cardiac_boundary_conditions(self.geometry, **self.bcs_parameters) else: self.bcs = bcs # TODO: FIX THIS or require this # Just store this as well in case both is provided self.bcs_parameters = MechanicsProblem.default_bcs_parameters() if bcs_parameters is not None: self.bcs_parameters.update(**bcs_parameters) @staticmethod def default_bcs_parameters(): return dict(pericardium_spring=0.0, base_spring=0.0, base_bc="fixed") def _init_spaces(self): logger.debug("Initialize spaces for mechanics problem") mesh = self.geometry.mesh P2 = dolfin.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = dolfin.FiniteElement("Lagrange", mesh.ufl_cell(), 1) # P2_space = FunctionSpace(mesh, P2) # P1_space = FunctionSpace(mesh, P1) self.state_space = dolfin.FunctionSpace(mesh, P2 * P1) self.state = Function(self.state_space, name="state") self.state_test = dolfin.TestFunction(self.state_space) def _init_forms(self): logger.debug("Initialize forms mechanics problem") # Displacement and hydrostatic_pressure u, p = dolfin.split(self.state) v, q = dolfin.split(self.state_test) # Some mechanical quantities F = dolfin.variable(kinematics.DeformationGradient(u)) J = kinematics.Jacobian(F) dx = self.geometry.dx internal_energy = (self.material.strain_energy(F, ) + self.material.compressibility(p, J)) self._virtual_work = dolfin.derivative( internal_energy * dx, self.state, self.state_test, ) external_work = self._external_work(u, v) if external_work is not None: self._virtual_work += external_work self._set_dirichlet_bc() self._jacobian = dolfin.derivative( self._virtual_work, self.state, dolfin.TrialFunction(self.state_space), ) self._init_solver() def _init_solver(self): if has_dolfin_adjoint: self._problem = NonlinearVariationalProblem( J=self._jacobian, F=self._virtual_work, u=self.state, bcs=self._dirichlet_bc, ) self.solver = NonlinearVariationalSolver(self._problem) else: self._problem = NonlinearProblem( J=self._jacobian, F=self._virtual_work, bcs=self._dirichlet_bc, ) self.solver = NonlinearSolver( self._problem, self.state, parameters=self.solver_parameters, ) def _set_dirichlet_bc(self): # DirichletBC for dirichlet_bc in self.bcs.dirichlet: msg = ("DirichletBC only implemented for as " "callable. Please provide DirichletBC " "as a callable with argument being the " "state space only") if hasattr(dirichlet_bc, "__call__"): try: self._dirichlet_bc = dirichlet_bc(self.state_space) except Exception as ex: logger.error(msg) raise ex else: raise NotImplementedError(msg) def _external_work(self, u, v): F = dolfin.variable(kinematics.DeformationGradient(u)) N = self.geometry.facet_normal ds = self.geometry.ds dx = self.geometry.dx external_work = [] for neumann in self.bcs.neumann: n = neumann.traction * ufl.cofac(F) * N external_work.append(dolfin.inner(v, n) * ds(neumann.marker)) for robin in self.bcs.robin: external_work.append( dolfin.inner(robin.value * u, v) * ds(robin.marker)) for body_force in self.bcs.body_force: external_work.append( -dolfin.derivative(dolfin.inner(body_force, u) * dx, u, v), ) if len(external_work) > 0: return list_sum(external_work) return None def reinit(self, state, annotate=False): """Reinitialze state""" if has_dolfin_adjoint: try: self.state.assign(state, annotate=annotate) except Exception as ex: print(ex) self.state.assign(state) else: self.state.assign(state) self._init_forms() @staticmethod def default_solver_parameters(): return NonlinearSolver.default_solver_parameters() def solve(self): r""" Solve the variational problem .. math:: \delta W = 0 """ logger.debug("Solving variational problem") # Get old state in case of non-convergence if has_dolfin_adjoint: try: old_state = self.state.copy(deepcopy=True, name="Old state (pulse)") except TypeError: # In case this is a dolfin fuction and not a # dolfin-adjoint function old_state = self.state.copy(deepcopy=True) else: old_state = self.state.copy(deepcopy=True) try: logger.debug("Try to solve") nliter, nlconv = self.solver.solve() if not nlconv: logger.debug("Failed") raise SolverDidNotConverge("Solver did not converge...") except RuntimeError as ex: logger.debug("Failed") logger.debug("Reintialize old state and raise exception") self.reinit(old_state) raise SolverDidNotConverge(ex) from ex else: logger.debug("Sucess") return nliter, nlconv def get_displacement(self, annotate=False): D = self.state_space.sub(0) V = D.collapse() fa = FunctionAssigner(V, D) u = Function(V, name="displacement") if has_dolfin_adjoint: fa.assign(u, self.state.split()[0], annotate=annotate) else: fa.assign(u, self.state.split()[0]) return u def SecondPiolaStress(self): u, p = self.state.split(deepcopy=True) F = kinematics.DeformationGradient(u) return self.material.SecondPiolaStress(F, p) def FirstPiolaStress(self): u, p = self.state.split(deepcopy=True) F = kinematics.DeformationGradient(u) return self.material.FirstPiolaStress(F, p) def ChachyStress(self): u, p = self.state.split(deepcopy=True) F = kinematics.DeformationGradient(u) return self.material.CauchyStress(F, p) def GreenLagrangeStrain(self): u, p = self.state.split(deepcopy=True) F = kinematics.DeformationGradient(u) return kinematics.GreenLagrangeStrain(F)
facet_function = dolfin.MeshFunction("size_t", mesh, "data/facet_function.xml") marker_functions = pulse.MarkerFunctions(ffun=facet_function) # Markers with open("data/markers.json", "r") as f: markers = json.load(f) # Fiber fiber_element = dolfin.VectorElement( family="Quadrature", cell=mesh.ufl_cell(), degree=4, quad_scheme="default", ) fiber_space = dolfin.FunctionSpace(mesh, fiber_element) fiber = Function(fiber_space, "data/fiber.xml") 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(
"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): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) return [ DirichletBC(V, zero, xlow), DirichletBC(V, x, xhigh), ]
try: from dolfin_adjoint import Constant, DirichletBC, Function, Mesh, interpolate except ImportError: from dolfin import Function, Constant, DirichletBC, Mesh, interpolate gamma_space = "R_0" geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths["simple_ellipsoid"]) # geometry = pulse.geometries.prolate_ellipsoid_geometry(mesh_size_factor=3.0) if gamma_space == "regional": activation = pulse.RegionalParameter(geometry.cfun) target_activation = pulse.dolfin_utils.get_constant(0.2, len(activation)) else: activation = Function(dolfin.FunctionSpace(geometry.mesh, "R", 0)) target_activation = Constant(0.2) matparams = pulse.HolzapfelOgden.default_parameters() material = pulse.HolzapfelOgden( 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")