def assign(self, expr, subset=None): """Set the :class:`Function` value to the pointwise value of expr. expr may only contain :class:`Function`\s on the same :class:`.FunctionSpace` as the :class:`Function` being assigned to. Similar functionality is available for the augmented assignment operators `+=`, `-=`, `*=` and `/=`. For example, if `f` and `g` are both Functions on the same :class:`.FunctionSpace` then:: f += 2 * g will add twice `g` to `f`. If present, subset must be an :class:`pyop2.Subset` of this :class:`Function`'s ``node_set``. The expression will then only be assigned to the nodes on that subset. """ if isinstance(expr, Function) and \ expr.function_space() == self.function_space(): expr.dat.copy(self.dat, subset=subset) return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression( assemble_expressions.Assign(self, expr), subset) return self
def __idiv__(self, expr): if np.isscalar(expr): self.dat /= expr return self if isinstance(expr, Function) and expr._function_space == self._function_space: self.dat /= expr.dat return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression(assemble_expressions.IDiv(self, expr)) return self
def __idiv__(self, expr): if np.isscalar(expr): self.dat /= expr return self if isinstance(expr, Function) and \ expr.function_space() == self.function_space(): self.dat /= expr.dat return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression( assemble_expressions.IDiv(self, expr)) return self
def __imul__(self, expr): if np.isscalar(expr): self.dat *= expr return self if isinstance(expr, Function) and \ expr.function_space() == self.function_space(): self.dat *= expr.dat return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression( assemble_expressions.IMul(self, expr)) return self
def __imul__(self, expr): if np.isscalar(expr): self.dat *= expr return self if isinstance(expr, Function) and \ expr._function_space == self._function_space: self.dat *= expr.dat return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression( assemble_expressions.IMul(self, expr)) return self
def __isub__(self, expr): if np.isscalar(expr): self.dat -= expr return self if isinstance(expr, vector.Vector): expr = expr.function if isinstance(expr, Function) and \ expr.function_space() == self.function_space(): self.dat -= expr.dat return self from firedrake import assemble_expressions assemble_expressions.evaluate_expression( assemble_expressions.ISub(self, expr)) return self
def test_expression_cache(): mesh = UnitSquareMesh(1, 1) V = VectorFunctionSpace(mesh, "CG", 1) W = TensorFunctionSpace(mesh, "CG", 1) u = Function(V) v = Function(V) w = Function(W) i, j = indices(2) exprA = Assign(u, as_vector(2 * u[i], i)) exprB = Assign(u, as_vector(2 * u[j], j)) assert len(u._expression_cache) == 0 evaluate_expression(exprA) assert exprA.fast_key in u._expression_cache assert exprA.slow_key in u._expression_cache assert exprB.fast_key not in u._expression_cache assert exprB.slow_key in u._expression_cache evaluate_expression(exprB) assert exprB.fast_key in u._expression_cache assert exprA.fast_key in u._expression_cache assert exprB.slow_key == exprA.slow_key assert len(u._expression_cache) == 3 u.assign(as_vector([1, 2])) u.assign(as_vector(2 * u[i], i)) v.assign(as_vector(2 * u[j], j)) w.assign(as_tensor([[1, 2], [0, 3]])) w.assign(as_tensor(w[i, j] + w[j, i], (i, j))) u -= as_vector([2, 4]) assert u.dat.norm < 1e-15 v -= as_vector([4, 8]) assert v.dat.norm < 1e-15 w -= as_tensor([[2, 2], [2, 6]]) assert w.dat.norm < 1e-15 assert len(u._expression_cache) == 5