def adjoint_derivative_action(self, nl_deps, dep_index, adj_x): eq_deps = self.dependencies() if dep_index < 0 or dep_index >= len(eq_deps): raise EquationException("dep_index out of bounds") elif dep_index == 0: return adj_x dep = eq_deps[dep_index] dF = ufl.conj(derivative(self._rhs, dep, argument=ufl.conj(adj_x))) dF = ufl.algorithms.expand_derivatives(dF) dF = eliminate_zeros(dF) dF = self._nonlinear_replace(dF, nl_deps) dF_val = evaluate_expr(dF) F = function_new(dep) if isinstance(dF_val, (int, np.integer, float, np.floating, complex, np.complexfloating)): dtype = function_dtype(F) function_set_values( F, np.full(function_local_size(F), dtype(dF_val), dtype=dtype)) elif function_is_scalar(F): dtype = function_dtype(F) dF_val_local = np.array([dF_val.sum()], dtype=dtype) dF_val = np.full((1,), np.NAN, dtype=dtype) comm = function_comm(F) comm.Allreduce(dF_val_local, dF_val, op=MPI.SUM) dF_val = dF_val[0] function_assign(F, dF_val) else: assert function_local_size(F) == len(dF_val) function_set_values(F, dF_val) return (-1.0, F)
def test_automatic_simplification(self): cell = triangle element = FiniteElement("Lagrange", cell, 1) v = TestFunction(element) u = TrialFunction(element) assert inner(u, v) == u * conj(v) assert dot(u, v) == u * v assert outer(u, v) == conj(u) * v
def test_basic_interior_facet_assembly(): ghost_mode = dolfin.cpp.mesh.GhostMode.none if (dolfin.MPI.size(dolfin.MPI.comm_world) > 1): ghost_mode = dolfin.cpp.mesh.GhostMode.shared_facet mesh = dolfin.RectangleMesh( dolfin.MPI.comm_world, [numpy.array([0.0, 0.0, 0.0]), numpy.array([1.0, 1.0, 0.0])], [5, 5], cell_type=dolfin.cpp.mesh.CellType.Type.triangle, ghost_mode=ghost_mode) V = dolfin.function.FunctionSpace(mesh, ("DG", 1)) u, v = dolfin.TrialFunction(V), dolfin.TestFunction(V) a = ufl.inner(ufl.avg(u), ufl.avg(v)) * ufl.dS A = dolfin.fem.assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) L = ufl.conj(ufl.avg(v)) * ufl.dS b = dolfin.fem.assemble_vector(L) b.assemble() assert isinstance(b, PETSc.Vec)
def adjoint_derivative_action(self, nl_deps, dep_index, adj_x): # Derived from EquationSolver.derivative_action (see dolfin-adjoint # reference below). Code first added 2017-12-07. # Re-written 2018-01-28 # Updated to adjoint only form 2018-01-29 eq_deps = self.dependencies() if dep_index < 0 or dep_index >= len(eq_deps): raise EquationException("dep_index out of bounds") elif dep_index == 0: return adj_x dep = eq_deps[dep_index] dF = derivative(self._rhs, dep) dF = ufl.algorithms.expand_derivatives(dF) dF = eliminate_zeros(dF) if dF.empty(): return None dF = self._nonlinear_replace(dF, nl_deps) if self._rank == 0: dF = ufl.Form([integral.reconstruct(integrand=ufl.conj(integral.integrand())) # noqa: E501 for integral in dF.integrals()]) # dF = adjoint(dF) dF = assemble( dF, form_compiler_parameters=self._form_compiler_parameters) return (-function_scalar_value(adj_x), dF) else: assert self._rank == 1 dF = assemble( ufl.action(adjoint(dF), coefficient=adj_x), form_compiler_parameters=self._form_compiler_parameters) return (-1.0, dF)
def test_mass_bilinear_form_2d(mode, expected_result): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) a = ufl.inner(u, v) * ufl.dx L = ufl.conj(v) * ufl.dx forms = [a, L] compiled_forms, module = ffc.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}) for f, compiled_f in zip(forms, compiled_forms): assert compiled_f.rank == len(f.arguments()) form0 = compiled_forms[0][0].create_cell_integral(-1) form1 = compiled_forms[1][0].create_cell_integral(-1) c_type, np_type = float_to_type(mode) A = np.zeros((3, 3), dtype=np_type) w = np.array([], dtype=np_type) ffi = cffi.FFI() coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w.ctypes.data), ffi.cast('double *', coords.ctypes.data), 0) b = np.zeros(3, dtype=np_type) form1.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), b.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w.ctypes.data), ffi.cast('double *', coords.ctypes.data), 0) assert np.allclose(A, expected_result) assert np.allclose(b, 1.0 / 6.0)
def test_compute_form_adjoint(self): cell = triangle element = FiniteElement('Lagrange', cell, 1) u = TrialFunction(element) v = TestFunction(element) a = inner(grad(u), grad(v)) * dx assert compute_form_adjoint(a) == conj(inner(grad(v), grad(u))) * dx
def test_remove_complex_nodes(self): cell = triangle element = FiniteElement("Lagrange", cell, 1) u = TrialFunction(element) v = TestFunction(element) f = Coefficient(element) a = conj(v) b = real(u) c = imag(f) d = conj(real(v))*imag(conj(u)) assert remove_complex_nodes(a) == v assert remove_complex_nodes(b) == u with pytest.raises(ufl.log.UFLException): remove_complex_nodes(c) with pytest.raises(ufl.log.UFLException): remove_complex_nodes(d)
def test_conditional(mode, compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) x = ufl.SpatialCoordinate(cell) condition = ufl.Or(ufl.ge(ufl.real(x[0] + x[1]), 0.1), ufl.ge(ufl.real(x[1] + x[1]**2), 0.1)) c1 = ufl.conditional(condition, 2.0, 1.0) a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx x1x2 = ufl.real(x[0] + ufl.as_ufl(2) * x[1]) c2 = ufl.conditional(ufl.ge(x1x2, 0), 6.0, 0.0) b = c2 * ufl.conj(v) * ufl.dx forms = [a, b] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) form0 = compiled_forms[0][0].create_cell_integral(-1) form1 = compiled_forms[1][0].create_cell_integral(-1) ffi = cffi.FFI() c_type, np_type = float_to_type(mode) A1 = np.zeros((3, 3), dtype=np_type) w1 = np.array([1.0, 1.0, 1.0], dtype=np_type) c = np.array([], dtype=np.float64) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.array([[2, -1, -1], [-1, 1, 0], [-1, 0, 1]], dtype=np_type) assert np.allclose(A1, expected_result) A2 = np.zeros(3, dtype=np_type) w2 = np.array([1.0, 1.0, 1.0], dtype=np_type) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form1.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.ones(3, dtype=np_type) assert np.allclose(A2, expected_result)
def test_complex_degree_handling(self): cell = triangle element = FiniteElement("Lagrange", cell, 3) v = TestFunction(element) a = conj(v) b = imag(v) c = real(v) assert estimate_total_polynomial_degree(a) == 3 assert estimate_total_polynomial_degree(b) == 3 assert estimate_total_polynomial_degree(c) == 3
def _real_mangle(form): """If the form contains arguments in the Real function space, replace these with literal 1 before passing to tsfc.""" a = form.arguments() reals = [x.ufl_element().family() == "Real" for x in a] if not any(reals): return form replacements = {} for arg, r in zip(a, reals): if r: replacements[arg] = 1 # If only the test space is Real, we need to turn the trial function into a test function. if reals == [True, False]: replacements[a[1]] = conj(TestFunction(a[1].function_space())) return ufl.replace(form, replacements)
def test_apply_algebra_lowering_complex(self): cell = triangle element = FiniteElement("Lagrange", cell, 1) v = TestFunction(element) u = TrialFunction(element) gv = grad(v) gu = grad(u) a = dot(gu, gv) b = inner(gv, gu) c = outer(gu, gv) lowered_a = apply_algebra_lowering(a) lowered_b = apply_algebra_lowering(b) lowered_c = apply_algebra_lowering(c) lowered_a_index = lowered_a.index() lowered_b_index = lowered_b.index() lowered_c_indices = lowered_c.indices() assert lowered_a == gu[lowered_a_index] * gv[lowered_a_index] assert lowered_b == gv[lowered_b_index] * conj(gu[lowered_b_index]) assert lowered_c == as_tensor(conj(gu[lowered_c_indices[0]]) * gv[lowered_c_indices[1]], (lowered_c_indices[0],) + (lowered_c_indices[1],))
def test_basic_interior_facet_assembly(): mesh = create_rectangle(MPI.COMM_WORLD, [np.array([0.0, 0.0]), np.array([1.0, 1.0])], [5, 5], cell_type=CellType.triangle, ghost_mode=GhostMode.shared_facet) V = FunctionSpace(mesh, ("DG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.avg(u), ufl.avg(v)) * ufl.dS a = form(a) A = assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) L = ufl.conj(ufl.avg(v)) * ufl.dS L = form(L) b = assemble_vector(L) b.assemble() assert isinstance(b, PETSc.Vec)
def test_basic_interior_facet_assembly(): mesh = dolfinx.RectangleMesh( MPI.COMM_WORLD, [numpy.array([0.0, 0.0, 0.0]), numpy.array([1.0, 1.0, 0.0])], [5, 5], cell_type=dolfinx.cpp.mesh.CellType.triangle, ghost_mode=dolfinx.cpp.mesh.GhostMode.shared_facet) V = fem.FunctionSpace(mesh, ("DG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.avg(u), ufl.avg(v)) * ufl.dS A = dolfinx.fem.assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) L = ufl.conj(ufl.avg(v)) * ufl.dS b = dolfinx.fem.assemble_vector(L) b.assemble() assert isinstance(b, PETSc.Vec)
def B_inv_action(x): y = function_new(x) assemble(eps * inner(ufl.conj(x), test) * dx, tensor=function_vector(y)) return y
def R_inv_action(x): y = function_new(x) assemble(inner(grad(ufl.conj(x)), grad(test)) * dx, tensor=function_vector(y)) return y
def forward(y, x_0=None): if x_0 is None: x_0 = project(y, space_1, name="x_0", solver_parameters=ls_parameters_cg) x = Function(space_1, name="x") class TestSolver(ProjectionSolver): def __init__(self, y, x, form_compiler_parameters=None, solver_parameters=None): if form_compiler_parameters is None: form_compiler_parameters = {} if solver_parameters is None: solver_parameters = {} assert is_function(y) super().__init__( inner(y, TestFunction(x.function_space())) * dx, x, form_compiler_parameters=form_compiler_parameters, solver_parameters=solver_parameters, cache_jacobian=False, cache_rhs_assembly=False) def forward_solve(self, x, deps=None): rhs = self._rhs if deps is not None: rhs = self._replace(rhs, deps) J = assemble( self._J, form_compiler_parameters=self._form_compiler_parameters) b = assemble( rhs, form_compiler_parameters=self._form_compiler_parameters) solver = linear_solver(J, self._linear_solver_parameters) solver.solve(x, b) assert solver.ksp.getIterationNumber() == 0 def adjoint_jacobian_solve(self, adj_x, nl_deps, b): assert adj_x is not None J = assemble( self._J, form_compiler_parameters=self._form_compiler_parameters) solver = linear_solver(J, self._linear_solver_parameters) solver.solve(adj_x, b) # test_adj_ic defined in test scope below assert not test_adj_ic or solver.ksp.getIterationNumber() == 0 return adj_x def tangent_linear(self, M, dM, tlm_map): x, y = self.dependencies() tau_y = get_tangent_linear(y, M, dM, tlm_map) if tau_y is None: return NullSolver(tlm_map[x]) else: return TestSolver( tau_y, tlm_map[x], form_compiler_parameters=self. _form_compiler_parameters, # noqa: E501 solver_parameters=self._solver_parameters) AssignmentSolver(x_0, x).solve() TestSolver(y, x, solver_parameters={ "ksp_type": "cg", "pc_type": "sor", "ksp_rtol": 1.0e-10, "ksp_atol": 1.0e-16, "ksp_initial_guess_nonzero": True }).solve() J = Functional(name="J") J.assign((dot(x, x)**2) * dx) J_val = J.value() # test_adj_ic defined in test scope below if test_adj_ic: adj_x_0 = Function(space_1, name="adj_x_0", static=True) solve(inner(trial_1, test_1) * dx == 4 * dot(ufl.conj(dot(x, x) * x), ufl.conj(test_1)) * dx, adj_x_0, solver_parameters=ls_parameters_cg, annotate=False, tlm=False) NullSolver(x).solve() J_term = space_new(J.space()) InnerProductSolver(x, adj_x_0, J_term).solve() J.addto(J_term) else: adj_x_0 = None # Active equation which requires no adjoint initial condition, but # for which one will be supplied z = Function(space_1, name="z") ProjectionSolver(zero * x, z, solver_parameters=ls_parameters_cg).solve() J.addto(dot(z, z) * dx) assert abs(J.value() - J_val) == 0.0 return x, adj_x_0, z, J