-
Notifications
You must be signed in to change notification settings - Fork 160
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
Error when assembling ufl.derivative with mixed function space #1723
Comments
Using |
Can you try this patch? The problem is some missing zero simplification in the form splitter leaving us with a nonsense J[1] form. By calling expand derivatives beforehand everything works its way out. Alternately, here I just handle that case. diff --git a/firedrake/formmanipulation.py b/firedrake/formmanipulation.py
index 472c4e0e..b56e13d5 100644
--- a/firedrake/formmanipulation.py
+++ b/firedrake/formmanipulation.py
@@ -69,6 +69,16 @@ class ExtractSubBlock(MultiFunction):
# [v_0, v_2, v_3][1, 2]
return self.expr(o, *map_expr_dags(self.index_inliner, operands))
+ def coefficient_derivative(self, o, expr, coefficients, arguments, cds):
+ # If we're only taking a derivative wrt part of an argument in
+ # a mixed space other bits might come back as zero. We want to
+ # propagate a zero in that case.
+ argument, = arguments
+ if all(isinstance(a, Zero) for a in argument.ufl_operands):
+ return Zero(o.ufl_shape, o.ufl_free_indices, o.ufl_index_dimensions)
+ else:
+ return self.reuse_if_untouched(o, expr, coefficients, arguments, cds)
+
def argument(self, o):
from ufl import split
from firedrake import MixedFunctionSpace, FunctionSpace
diff --git a/firedrake/ufl_expr.py b/firedrake/ufl_expr.py
index a6ad68f4..690ddf96 100644
--- a/firedrake/ufl_expr.py
+++ b/firedrake/ufl_expr.py
@@ -139,7 +139,8 @@ def derivative(form, u, du=None, coefficient_derivatives=None):
"""
# TODO: What about Constant?
u_is_x = isinstance(u, ufl.SpatialCoordinate)
- if not u_is_x and len(u.split()) > 1 and set(extract_coefficients(form)) & set(u.split()):
+ uc, = extract_coefficients(u)
+ if not u_is_x and len(uc.split()) > 1 and set(extract_coefficients(form)) & set(uc.split()):
raise ValueError("Taking derivative of form wrt u, but form contains coefficients from u.split()."
"\nYou probably meant to write split(u) when defining your form.")
@@ -163,17 +164,21 @@ def derivative(form, u, du=None, coefficient_derivatives=None):
if coefficient_derivatives is not None:
cds.update(coefficient_derivatives)
coefficient_derivatives = cds
- elif isinstance(u, firedrake.Function):
- V = u.function_space()
+ elif isinstance(uc, firedrake.Function):
+ V = uc.function_space()
du = argument(V)
- elif isinstance(u, firedrake.Constant):
- if u.ufl_shape != ():
+ elif isinstance(uc, firedrake.Constant):
+ if uc.ufl_shape != ():
raise ValueError("Real function space of vector elements not supported")
V = firedrake.FunctionSpace(mesh, "Real", 0)
du = argument(V)
else:
raise RuntimeError("Can't compute derivative for form")
+ if u.ufl_shape != du.ufl_shape:
+ raise ValueError("Shapes of u and du do not match.\n"
+ "If you passed an indexed part of split(u) into "
+ "derivative, you need to provide an appropriate du as well.")
return ufl.derivative(form, u, du, coefficient_derivatives) |
This patch works! |
Do you mind preparing a test and PR? |
Will do that |
And fixed. |
Here's the code that fails at assembly
The following error is raised
The above code works in FEniCS.
Using
J = inner(grad(w0), grad(dw0))*dx
works as expected, so there is some bug specifically related to usingufl.derivative
on splitted arguments.Also
firedrake.derivative
is broken in this caseThe text was updated successfully, but these errors were encountered: