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
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 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 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 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 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 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 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 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 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 _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_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 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 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 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 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_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 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 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 __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 _make_indicator_function(self, marker): dofs = self._meshfunction.where_equal(marker) f = Function(self._proj_space) f.vector()[dofs] = 1.0 return f
"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), ]
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]
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(