Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix coarsening for R space #3814

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions firedrake/mg/ufl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,20 +268,21 @@ def coarsen_snescontext(context, self, coefficient_mapping=None):
coarse._fine = context
context._coarse = coarse

solutiondm = context._problem.u.function_space().dm
parentdm = get_parent(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
parentdm = get_parent(context._problem.u.function_space().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)
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 Expand Up @@ -384,7 +385,8 @@ def create_interpolation(dmc, dmf):
mat.setType(mat.Type.PYTHON)
mat.setPythonContext(ctx)
mat.setUp()
return mat, None
rscale = mat.createVecLeft() if row_size == col_size else None
Copy link
Contributor Author

@pbrubeck pbrubeck Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure whether Right or Left is the correct thing here. But it does not really matter if the sizes are the same.

return mat, rscale


def create_injection(dmc, dmf):
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, degree", [("CG", 1), ("R", 0)])
def test_cached_transfer(family, degree):
# 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, degree)
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very fragile. If we decided not to emit this warning any more, or even changed the content of the warning message, then this would always pass regardless of whether or not we were actually reusing transfer managers.

Is a better way to do this not to somehow retrieve the transfer managers from whatever mesh/DM they are attached to and check that they are the same?

solve(F == 0, u, solver_parameters=sp)
Loading