def test_leaks(): function_ids.clear() yield gc.collect() # Clear some internal storage that is allowed to keep references clear_caches() manager = _manager() manager._cp.clear(clear_refs=True) manager._cp_memory.clear() tlm_values = list(manager._tlm.values()) # noqa: F841 manager._tlm.clear() tlm_eqs_values = [ list(eq_tlm_eqs.values()) for eq_tlm_eqs in manager._tlm_eqs.values() ] # noqa: E501,F841 manager._tlm_eqs.clear() manager.drop_references() gc.collect() gc.collect() refs = 0 for F in function_ids.values(): F = F() if F is not None and F.name() != "Coordinates": info(f"{F.name():s} referenced") refs += 1 if refs == 0: info("No references") function_ids.clear() assert refs == 0
def test_EmptySolver(setup_test, test_leaks): class EmptySolver(Equation): def __init__(self): super().__init__([], [], nl_deps=[], ic=False, adj_ic=False) def forward_solve(self, X, deps=None): pass mesh = UnitIntervalMesh(100) X = SpatialCoordinate(mesh) space = FunctionSpace(mesh, "Lagrange", 1) def forward(F): EmptySolver().solve() F_norm_sq = Constant(name="F_norm_sq") NormSqSolver(F, F_norm_sq).solve() J = Functional(name="J") NormSqSolver(F_norm_sq, J.fn()).solve() return J F = Function(space, name="F") interpolate_expression(F, sin(pi * X[0]) * exp(X[0])) start_manager() J = forward(F) stop_manager() manager = _manager() manager.finalize() manager.info() assert len(manager._blocks) == 1 assert len(manager._blocks[0]) == 3 assert len(manager._blocks[0][0].X()) == 0 J_val = J.value() with F.dat.vec_ro as F_v: J_ref = F_v.norm(norm_type=PETSc.NormType.NORM_2)**4 assert abs(J_val - J_ref) < 1.0e-11 dJ = compute_gradient(J, F) min_order = taylor_test(forward, F, J_val=J_val, dJ=dJ) assert min_order > 2.00 ddJ = Hessian(forward) min_order = taylor_test(forward, F, J_val=J_val, ddJ=ddJ) assert min_order > 3.00 min_order = taylor_test_tlm(forward, F, tlm_order=1) assert min_order > 2.00 min_order = taylor_test_tlm_adjoint(forward, F, adjoint_order=1) assert min_order > 2.00 min_order = taylor_test_tlm_adjoint(forward, F, adjoint_order=2) assert min_order > 2.00
def tlm(kappa, zeta): clear_caches() manager = _manager().new() manager.add_tlm(kappa, zeta) manager.start() J = forward(kappa, manager=manager) manager.stop() return J.tlm(kappa, zeta, manager=manager).value()
def forward(kappa, manager=None, output_filename=None): clear_caches() Psi_n = Function(space, name="Psi_n") Psi_np1 = Function(space, name="Psi_np1") eq = EquationSolver(inner(test, trial / dt) * dx + inner(grad(test), kappa * grad(trial)) * dx == inner( test, Psi_n / dt) * dx, Psi_np1, bc, solver_parameters={ "ksp_type": "cg", "pc_type": "sor", "ksp_rtol": 1.0e-14, "ksp_atol": 1.0e-16 }) cycle = AssignmentSolver(Psi_np1, Psi_n) if output_filename is not None: f = File(output_filename, "compressed") AssignmentSolver(Psi_0, Psi_n).solve(manager=manager) if output_filename is not None: f.write(Psi_n, time=0.0) for n in range(N): eq.solve(manager=manager) if n < N - 1: cycle.solve(manager=manager) (_manager() if manager is None else manager).new_block() else: Psi_n = Psi_np1 Psi_n.rename("Psi_n", "a Function") del Psi_np1 if output_filename is not None: f.write(Psi_n, time=(n + 1) * float(dt)) J = Functional(name="J") J.assign(inner(Psi_n, Psi_n) * dx, manager=manager) return J
def forward(m, forward_run=False): class NewtonIterationSolver(Equation): def __init__(self, m, x0, x): super().__init__(x, deps=[x, x0, m], nl_deps=[x0, m], ic=False, adj_ic=False) def forward_solve(self, x, deps=None): _, x0, m = self.dependencies() if deps is None else deps function_set_values( x, 0.5 * (function_get_values(x0)**2 + function_get_values(m)) / function_get_values(x0)) def adjoint_jacobian_solve(self, adj_x, nl_deps, b): return b def adjoint_derivative_action(self, nl_deps, dep_index, adj_x): if dep_index == 1: x0, m = nl_deps F = function_new(x0) function_set_values( F, 0.5 * function_get_values(adj_x) * (function_get_values(m) / (function_get_values(x0)**2) - 1.0)) return F elif dep_index == 2: x0, m = nl_deps F = function_new(x0) function_set_values( F, -0.5 * function_get_values(adj_x) / function_get_values(x0)) return F else: raise EquationException("Unexpected dep_index") x0 = Constant(1.0, name="x0") x1 = Constant(0.0, name="x1") eq0 = NewtonIterationSolver(m, x0, x1) eq1 = AssignmentSolver(x1, x0) fp_eq = FixedPointSolver( [eq0, eq1], solver_parameters={ "absolute_tolerance": 0.0, "relative_tolerance": 1.0e-14, "report": False }) fp_eq.solve() if forward_run: manager = _manager() assert len(manager._to_drop_references) == 0 for eq in [fp_eq, eq0, eq1]: assert not eq._references_dropped for dep in eq.dependencies(): assert not isinstance(dep, Replacement) del eq fp_eq = WeakAlias(fp_eq) assert len(manager._to_drop_references) == 1 for eq in [fp_eq, eq0, eq1]: assert not eq._references_dropped for dep in eq.dependencies(): assert not isinstance(dep, Replacement) del eq manager.drop_references() assert len(manager._to_drop_references) == 0 assert fp_eq._references_dropped for dep in fp_eq.dependencies(): assert isinstance(dep, Replacement) for eq in [eq0, eq1]: assert not eq._references_dropped for dep in eq.dependencies(): assert not isinstance(dep, Replacement) del eq eq0.solve() eq1.solve() if forward_run: assert len(manager._to_drop_references) == 0 for eq in [eq0, eq1]: assert not eq._references_dropped for dep in eq.dependencies(): assert not isinstance(dep, Replacement) del eq eq0 = WeakAlias(eq0) eq1 = WeakAlias(eq1) assert len(manager._to_drop_references) == 2 for eq in [eq0, eq1]: assert not eq._references_dropped for dep in eq.dependencies(): assert not isinstance(dep, Replacement) del eq manager.drop_references() assert len(manager._to_drop_references) == 0 for eq in [eq0, eq1]: assert eq._references_dropped for dep in eq.dependencies(): assert isinstance(dep, Replacement) del eq J = Functional(name="J") J.assign(x1) return J
def forward(m, forward_run=False): class IdentityMatrix(Matrix): def __init__(self): super().__init__(nl_deps=[], ic=False, adj_ic=False) def forward_action(self, nl_deps, x, b, method="assign"): if method == "assign": function_assign(b, x) else: raise EquationException(f"Unexpected method '{method:s}'") def forward_solve(self, x, nl_deps, b): function_assign(x, b) def adjoint_solve(self, adj_x, nl_deps, b): return b def tangent_linear_rhs(self, M, dM, tlm_map, x): return None x = Constant(0.0, name="x") M = IdentityMatrix() b = NormSqRHS(m, M=M) linear_eq = LinearEquation([b, b], x, A=M) linear_eq.solve() if forward_run: manager = _manager() assert len(manager._to_drop_references) == 0 assert not linear_eq._references_dropped assert not b._references_dropped assert not M._references_dropped for dep in linear_eq.dependencies(): assert not isinstance(dep, Replacement) for dep in b.dependencies(): assert not isinstance(dep, Replacement) linear_eq = WeakAlias(linear_eq) assert len(manager._to_drop_references) == 1 assert not linear_eq._references_dropped assert not b._references_dropped assert not M._references_dropped for dep in linear_eq.dependencies(): assert not isinstance(dep, Replacement) for dep in b.dependencies(): assert not isinstance(dep, Replacement) manager.drop_references() assert len(manager._to_drop_references) == 0 assert linear_eq._references_dropped assert not b._references_dropped assert not M._references_dropped for dep in linear_eq.dependencies(): assert isinstance(dep, Replacement) for dep in b.dependencies(): assert not isinstance(dep, Replacement) y = Constant(0.0, name="y") LinearEquation(b, y, A=M).solve() z = Constant(0.0, name="z") AxpySolver(x, 1.0, y, z).solve() if forward_run: manager.drop_references() assert len(manager._to_drop_references) == 0 assert not b._references_dropped assert not M._references_dropped for dep in b.dependencies(): assert not isinstance(dep, Replacement) M = WeakAlias(M) b = WeakAlias(b) assert len(manager._to_drop_references) == 1 assert not b._references_dropped assert not M._references_dropped for dep in b.dependencies(): assert not isinstance(dep, Replacement) manager.drop_references() assert len(manager._to_drop_references) == 0 assert b._references_dropped assert M._references_dropped for dep in b.dependencies(): assert isinstance(dep, Replacement) J = Functional(name="J") NormSqSolver(z, J.fn()).solve() return J