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