Skip to content

Commit

Permalink
add a test
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrubeck committed Oct 21, 2024
1 parent f4fdbb8 commit 292191a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 16 deletions.
30 changes: 14 additions & 16 deletions firedrake/mg/ufl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,23 +268,21 @@ def coarsen_snescontext(context, self, coefficient_mapping=None):
coarse._fine = context
context._coarse = coarse

solution = context._problem.u
solutiondm = solution.function_space().dm
solutiondm = context._problem.u.function_space().dm
parentdm = get_parent(solutiondm)
if parentdm != solutiondm:
# Now that we have the coarse snescontext, push it to the coarsened DMs
# Otherwise they won't have the right transfer manager when they are
# coarsened in turn
for val in chain(coefficient_mapping.values(), (bc.function_arg for bc in problem.bcs)):
if isinstance(val, (firedrake.Function, firedrake.Cofunction)):
V = val.function_space()
coarseneddm = V.dm

# Now attach the hook to the parent DM
if get_appctx(coarseneddm) is None:
push_appctx(coarseneddm, coarse)
teardown = partial(pop_appctx, coarseneddm, coarse)
add_hook(parentdm, teardown=teardown)
# Now that we have the coarse snescontext, push it to the coarsened DMs
# Otherwise they won't have the right transfer manager when they are
# coarsened in turn
for val in chain(coefficient_mapping.values(), (bc.function_arg for bc in problem.bcs)):
if isinstance(val, (firedrake.Function, firedrake.Cofunction)):
V = val.function_space()
coarseneddm = V.dm

# Now attach the hook to the parent DM
if get_appctx(coarseneddm) is None:
push_appctx(coarseneddm, coarse)
if parentdm.getAttr("__setup_hooks__"):
add_hook(parentdm, teardown=partial(pop_appctx, coarseneddm, coarse))

ises = problem.J.arguments()[0].function_space()._ises
coarse._nullspace = self(context._nullspace, self, coefficient_mapping=coefficient_mapping)
Expand Down
23 changes: 23 additions & 0 deletions tests/multigrid/test_transfer_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
import numpy
import warnings
from firedrake import *
from firedrake.mg.ufl_utils import coarsen
from firedrake.utils import complex_mode
Expand Down Expand Up @@ -131,3 +132,25 @@ def test_transfer_manager_dat_version_cache(action, transfer_op, spaces):

else:
raise ValueError(f"Unrecognized action {action}")


@pytest.mark.parametrize("family", ("DG", "R"))
def test_cached_transfer(family):
# Test that we can properly reuse transfers within solve
sp = {"mat_type": "matfree",
"pc_type": "mg",
"mg_coarse_pc_type": "none",
"mg_levels_pc_type": "none"}

base = UnitSquareMesh(1, 1)
hierarchy = MeshHierarchy(base, 3)
mesh = hierarchy[-1]

V = FunctionSpace(mesh, family, 0)
u = Function(V)
F = inner(u - 1, TestFunction(V)) * dx

# This test will fail if we raise this warning
with warnings.catch_warnings():
warnings.filterwarnings("error", "Creating new TransferManager", RuntimeWarning)
solve(F == 0, u, solver_parameters=sp)

Check failure on line 156 in tests/multigrid/test_transfer_manager.py

View workflow job for this annotation

GitHub Actions / Firedrake complex

test_transfer_manager.test_cached_transfer[DG]

NotImplementedError: In complex mode we are waiting for Slate
Raw output
Vf = WithGeometry(FunctionSpace(<firedrake.mesh.MeshTopology object at 0x7f63da373d40>, FiniteElement('Discontinuous Lagrange', triangle, 0), name=None), Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 13267))
Vc = WithGeometry(FunctionSpace(<firedrake.mesh.MeshTopology object at 0x7f63da344e00>, FiniteElement('Discontinuous Lagrange', triangle, 0), name=None), Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 13266))

    def inject_kernel(Vf, Vc):
        hierarchy, level = utils.get_level(Vc.mesh())
        cache = hierarchy._shared_data_cache["transfer_kernels"]
        coordinates = Vf.mesh().coordinates
        if Vf.extruded:
            assert Vc.extruded
            level_ratio = (Vf.mesh().layers - 1) // (Vc.mesh().layers - 1)
        else:
            level_ratio = 1
        key = (("inject", level_ratio)
               + Vf.ufl_element().value_shape
               + entity_dofs_key(Vc.finat_element.complex.get_topology())
               + entity_dofs_key(Vf.finat_element.complex.get_topology())
               + entity_dofs_key(Vc.finat_element.entity_dofs())
               + entity_dofs_key(Vf.finat_element.entity_dofs())
               + entity_dofs_key(Vc.mesh().coordinates.function_space().finat_element.entity_dofs())
               + entity_dofs_key(coordinates.function_space().finat_element.entity_dofs()))
        try:
>           return cache[key]
E           KeyError: ('inject', 1, (0, (0,), (1,), (2,)), (1, (1, 2), (0, 2), (0, 1)), (2, (0, 1, 2)), (0, (0,), (1,), (2,)), (1, (1, 2), (0, 2), (0, 1)), (2, (0, 1, 2)), (0, (), (), ()), (1, (), (), ()), (2, (0,)), (0, (), (), ()), (1, (), (), ()), (2, (0,)), (0, (0,), (1,), (2,)), (1, (), (), ()), (2, ()), (0, (0,), (1,), (2,)), (1, (), (), ()), (2, ()))

firedrake/mg/kernels.py:400: KeyError

During handling of the above exception, another exception occurred:

family = 'DG'

    @pytest.mark.parametrize("family", ("DG", "R"))
    def test_cached_transfer(family):
        # Test that we can properly reuse transfers within solve
        sp = {"mat_type": "matfree",
              "pc_type": "mg",
              "mg_coarse_pc_type": "none",
              "mg_levels_pc_type": "none"}
    
        base = UnitSquareMesh(1, 1)
        hierarchy = MeshHierarchy(base, 3)
        mesh = hierarchy[-1]
    
        V = FunctionSpace(mesh, family, 0)
        u = Function(V)
        F = inner(u - 1, TestFunction(V)) * dx
    
        # This test will fail if we raise this warning
        with warnings.catch_warnings():
            warnings.filterwarnings("error", "Creating new TransferManager", RuntimeWarning)
>           solve(F == 0, u, solver_parameters=sp)

tests/multigrid/test_transfer_manager.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
petsc4py/PETSc/Log.pyx:188: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
petsc4py/PETSc/Log.pyx:189: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
firedrake/adjoint_utils/solving.py:57: in wrapper
    output = solve(*args, **kwargs)
firedrake/solving.py:141: in solve
    _solve_varproblem(*args, **kwargs)
firedrake/solving.py:195: in _solve_varproblem
    solver.solve()
petsc4py/PETSc/Log.pyx:188: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
petsc4py/PETSc/Log.pyx:189: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
firedrake/adjoint_utils/variational_solver.py:89: in wrapper
    out = solve(self, **kwargs)
firedrake/variational_solver.py:324: in solve
    self.snes.solve(None, work)
petsc4py/PETSc/SNES.pyx:1724: in petsc4py.PETSc.SNES.solve
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/PETSc.pyx:323: in petsc4py.PETSc.PetscPythonErrorHandler
    ???
petsc4py/PETSc/petscdmshell.pxi:239: in petsc4py.PETSc.DMSHELL_Coarsen
    ???
petsc4py/PETSc/Log.pyx:188: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
petsc4py/PETSc/Log.pyx:189: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
firedrake/dmhooks.py:433: in coarsen
    cctx = coarsen(ctx, coarsen)
/usr/lib/python3.12/functools.py:909: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
firedrake/mg/ufl_utils.py:251: in coarsen_snescontext
    problem = self(context._problem, self, coefficient_mapping=coefficient_mapping)
/usr/lib/python3.12/functools.py:909: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
firedrake/mg/ufl_utils.py:201: in coarsen_nlvp
    coefficient_mapping[c] = self(c, self, coefficient_mapping=coefficient_mapping)
/usr/lib/python3.12/functools.py:909: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
firedrake/mg/ufl_utils.py:158: in coarsen_function
    manager.inject(expr, new)
firedrake/mg/embedded.py:299: in inject
    self.op(uf, uc, transfer_op=Op.INJECT)
petsc4py/PETSc/Log.pyx:188: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
petsc4py/PETSc/Log.pyx:189: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
firedrake/mg/embedded.py:250: in op
    self._native_transfer(source_element, transfer_op)(source, target)
petsc4py/PETSc/Log.pyx:188: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
petsc4py/PETSc/Log.pyx:189: in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
    ???
firedrake/mg/interface.py:189: in inject
    kernel, dg = kernels.inject_kernel(Vf, Vc)
firedrake/mg/kernels.py:404: in inject_kernel
    return cache.setdefault(key, (dg_injection_kernel(Vf, Vc, ncandidate), True))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

Vf = WithGeometry(FunctionSpace(<firedrake.mesh.MeshTopology object at 0x7f63da373d40>, FiniteElement('Discontinuous Lagrange', triangle, 0), name=None), Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 13267))
Vc = WithGeometry(FunctionSpace(<firedrake.mesh.MeshTopology object at 0x7f63da344e00>, FiniteElement('Discontinuous Lagrange', triangle, 0), name=None), Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 13266))
ncell = 4

    def dg_injection_kernel(Vf, Vc, ncell):
        from firedrake import Tensor, AssembledVector, TestFunction, TrialFunction
        from firedrake.slate.slac import compile_expression
        if complex_mode:
>           raise NotImplementedError("In complex mode we are waiting for Slate")
E           NotImplementedError: In complex mode we are waiting for Slate

firedrake/mg/kernels.py:521: NotImplementedError

0 comments on commit 292191a

Please sign in to comment.