def adjoint(form, reordered_arguments=None, adjoint_arguments=None): """ Wrapper for the DOLFIN adjoint function. Accepts the additional optional adjoint_arguments, which if supplied should be a tuple of Argument s corresponding to the adjoint test and trial functions. """ if adjoint_arguments is None: a_form = dolfin.adjoint(form, reordered_arguments=reordered_arguments) elif not reordered_arguments is None: raise InvalidArgumentException( "Cannot supply both reordered_arguments and adjoint_arguments keyword arguments" ) else: if not len(adjoint_arguments) == 2 \ or not isinstance(adjoint_arguments[0], ufl.argument.Argument) \ or not isinstance(adjoint_arguments[1], ufl.argument.Argument): raise InvalidArgumentException( "adjoint_arguments must be a pair of Argument s") a_test, a_trial = adjoint_arguments a_form = dolfin.adjoint(form) test, trial = extract_test_and_trial(a_form) if not test.element() == a_test.element() or not trial.element( ) == a_trial.element(): raise InvalidArgumentException("Invalid adjoint_arguments") a_form = dolfin.replace(a_form, {test: a_test, trial: a_trial}) return a_form
def differentiate_expr(expr, u, expand = True): """ Wrapper for the UFL derivative function. This chooses an argument equal to Constant(1.0). Form s should be differentiated using the derivative function. """ if not isinstance(expr, ufl.expr.Expr): raise InvalidArgumentException("expr must be an Expr") if isinstance(u, ufl.indexed.Indexed): op = u.operands() assert(len(op) == 2) if not isinstance(op[0], (dolfin.Constant, dolfin.Function)): raise InvalidArgumentException("Invalid Indexed") elif not isinstance(u, (dolfin.Constant, dolfin.Function)): raise InvalidArgumentException("u must be an Indexed, Constant, or Function") if expr is u: der = ufl.constantvalue.IntValue(1) else: unity = dolfin.Constant(1.0) der = dolfin.replace(ufl.derivative(expr, u, argument = unity), {unity:ufl.constantvalue.IntValue(1)}) if expand: # Based on code from expand_derivatives1 in UFL file ad.py, (see e.g. bzr # 1.1.x branch revision 1484) cell = der.cell() if cell is None: dim = 0 else: dim = der.cell().geometric_dimension() der = ufl.algorithms.expand_derivatives(der, dim = dim) return der
def differentiate_expr(expr, u, expand = True): """ Wrapper for the UFL derivative function. This chooses an argument equal to Constant(1.0). Form s should be differentiated using the derivative function. """ if not isinstance(expr, ufl.core.expr.Expr): raise InvalidArgumentException("expr must be an Expr") if isinstance(u, ufl.indexed.Indexed): op = u.operands() assert(len(op) == 2) if not isinstance(op[0], (dolfin.Constant, dolfin.Function)): raise InvalidArgumentException("Invalid Indexed") elif not isinstance(u, (dolfin.Constant, dolfin.Function)): raise InvalidArgumentException("u must be an Indexed, Constant, or Function") if expr is u: der = ufl.constantvalue.IntValue(1) else: unity = dolfin.Constant(1.0) der = dolfin.replace(ufl.derivative(expr, u, argument = unity), {unity:ufl.constantvalue.IntValue(1)}) if expand: # Based on code from expand_derivatives1 in UFL file ad.py, (see e.g. bzr # 1.1.x branch revision 1484) cell = der.cell() if cell is None: dim = 0 else: dim = der.cell().geometric_dimension() der = ufl.algorithms.expand_derivatives(der, dim = dim) return der
def __init__(selfmat, *args, **kwargs): if 'initial_guess' in kwargs: selfmat.initial_guess = kwargs['initial_guess'] del kwargs['initial_guess'] else: selfmat.initial_guess = None replace_map = kwargs['replace_map'] del kwargs['replace_map'] adjlinalg.Matrix.__init__(selfmat, *args, **kwargs) selfmat.adjoint = kwargs['adjoint'] if P is None: selfmat.operators = (dolfin.replace(A, replace_map), None) else: selfmat.operators = (dolfin.replace(A, replace_map), dolfin.replace(P, replace_map))
def __init__(self, *args, **kwargs): if 'initial_guess' in kwargs: self.initial_guess = kwargs['initial_guess'] del kwargs['initial_guess'] else: self.initial_guess = None replace_map = kwargs['replace_map'] del kwargs['replace_map'] adjlinalg.Matrix.__init__(self, *args, **kwargs) self.adjoint = kwargs['adjoint'] if P is None: self.operators = (dolfin.replace(A, replace_map), None) else: self.operators = (dolfin.replace(A, replace_map), dolfin.replace(P, replace_map))
def unwrap_fns(form): """ Return a form with all WrappedFunction s unwrapped. """ repl = {} for dep in ufl.algorithms.extract_coefficients(form): if isinstance(dep, WrappedFunction): repl[dep] = dep.fn() return dolfin.replace(form, repl)
def matrix_optimisation(form): """ Attempt to convert a linear form into the action of a bi-linear form. Return a (bi-linear Form, Function) pair on success, and None on failure. """ if not isinstance(form, ufl.form.Form): raise InvalidArgumentException("form must be a Form") # Find the test function args = ufl.algorithms.extract_arguments(form) if not len(args) == 1: # This is not a linear form return None # Look for a single non-static Function dependency tcs = extract_non_static_coefficients(form) if not len(tcs) == 1: # Found too many non-static coefficients return None elif not isinstance(tcs[0], dolfin.Function): # The only non-static coefficient is not a Function return None # Found a single non-static Function dependency fn = tcs[0] # Look for a static bi-linear form whose action can be used to construct # the linear form mat_form = derivative( form, fn, # Hack to work around an obscure FEniCS bug expand=dolfin.MPI.size(dolfin.mpi_comm_world()) == 1 or (not is_r0_function_space(args[0].function_space()) and not is_r0_function(fn))) if n_non_static_coefficients(mat_form) > 0: # The form is non-linear return None try: rhs_form = dolfin.rhs( dolfin.replace(form, {fn: dolfin.TrialFunction(fn.function_space())})) except ufl.log.UFLException: # The form might be inhomogeneous return None if not is_empty_form(rhs_form): # The form might be inhomogeneous return None # Success return mat_form, fn
def replace(e, mapping): """ Wrapper for the DOLFIN replace function. Correctly handles QForm s. """ if not isinstance(mapping, dict): raise InvalidArgumentException("mapping must be a dictionary") if len(mapping) == 0: return e ne = dolfin.replace(e, mapping) if isinstance(e, QForm): return QForm(ne, quadrature_degree = form_quadrature_degree(e)) else: return ne
def is_self_adjoint_form(form): """ Return True if the supplied Form is self-adjoint. May return false negatives. """ if not isinstance(form, ufl.form.Form): raise InvalidArgumentException("form must be a Form") a_form = dolfin.adjoint(form) test, trial = extract_test_and_trial(form) a_test, a_trial = extract_test_and_trial(a_form) if not test.element() == a_trial.element(): return False elif not trial.element() == a_test.element(): return False a_form = dolfin.replace(a_form, {a_test:trial, a_trial:test}) return expand(form) == expand(a_form)
def match_tensor(self, tensor=None): """ Addition of GenericMatrix s can be more efficient if the sparsity patterns match. Extend the sparsity pattern of the input GenericMatrix and any relevant internally stored GenericMatrix so that their sparsity patterns match. Return the expanded GenericMatrix if tensor is not None. Otherwise return a copy of an internal GenericMatrix if one exists, or None otherwise. Must be called after the pre_assemble method. Arguments: tensor: The GenericMatrix whose sparsity pattern is to match any relevant internally stored GenericMatrix s. """ if self._n == 0: return tensor elif not self._rank == 2: raise StateException("Unexpected form rank: %i" % self._rank) if not tensor is None and not isinstance(tensor, dolfin.GenericMatrix): raise InvalidArgumentException("tensor must be a GenericMatrix") one = dolfin.Constant(1.0) form = dolfin.replace( self._form, {c: one for c in ufl.algorithms.extract_coefficients(self._form)}) if self._rank == 1: tensor = self._assemble(form) elif self._rank == 2: if self.__tensor is None: self.__tensor = self._assemble(form) if tensor is None: tensor = self.__tensor.copy() else: self.__tensor.axpy(0.0, tensor, False) tensor.axpy(0.0, self.__tensor, False) else: raise StateException("Unexpected form rank: %i" % self._rank) return tensor