Skip to content
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
43 changes: 43 additions & 0 deletions test/test_reference_grad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Tests for the user-facing ``ufl.reference_grad`` wrapper."""

from utils import LagrangeElement

import ufl
from ufl import Coefficient, FunctionSpace, Mesh, interval, reference_grad, triangle
from ufl.classes import ReferenceGrad, ReferenceValue


def test_reference_grad_is_exported():
assert ufl.reference_grad is reference_grad
assert "reference_grad" in ufl.__all__


def test_reference_grad_returns_reference_grad():
domain = Mesh(LagrangeElement(triangle, 1, (2,)))
V = FunctionSpace(domain, LagrangeElement(triangle, 1))
f = Coefficient(V)

expr = reference_grad(ReferenceValue(f))

assert isinstance(expr, ReferenceGrad)
assert expr == ReferenceGrad(ReferenceValue(f))


def test_reference_grad_shape_appends_topological_dimension():
domain = Mesh(LagrangeElement(triangle, 1, (2,)))
V = FunctionSpace(domain, LagrangeElement(triangle, 1))
f = Coefficient(V)

expr = reference_grad(ReferenceValue(f))

assert expr.ufl_shape == (2,)


def test_reference_grad_on_interval():
domain = Mesh(LagrangeElement(interval, 1, (1,)))
V = FunctionSpace(domain, LagrangeElement(interval, 1))
f = Coefficient(V)

expr = reference_grad(ReferenceValue(f))

assert expr.ufl_shape == (1,)
2 changes: 2 additions & 0 deletions ufl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@
perp,
rank,
real,
reference_grad,
rot,
shape,
sign,
Expand Down Expand Up @@ -645,6 +646,7 @@
"r",
"rank",
"real",
"reference_grad",
"register_integral_type",
"replace",
"rhs",
Expand Down
28 changes: 27 additions & 1 deletion ufl/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@
OrCondition,
)
from ufl.constantvalue import ComplexValue, RealValue, Zero, as_ufl
from ufl.differentiation import Curl, Div, Grad, NablaDiv, NablaGrad, VariableDerivative
from ufl.differentiation import (
Curl,
Div,
Grad,
NablaDiv,
NablaGrad,
ReferenceGrad,
VariableDerivative,
)
from ufl.domain import extract_domains
from ufl.form import Form
from ufl.geometry import FacetNormal, SpatialCoordinate
Expand Down Expand Up @@ -403,6 +411,24 @@ def grad(f):
return Grad(f)


def reference_grad(f):
"""Take the gradient of f with respect to reference cell coordinates.

Unlike :py:func:`grad`, which differentiates with respect to physical
coordinates, ``reference_grad`` differentiates with respect to the
coordinates of the reference cell.

The operand must already be in the reference frame; for example,
a :py:class:`Coefficient` should be wrapped in
:py:class:`ReferenceValue` before applying ``reference_grad``.

See also: :py:func:`grad`

"""
f = as_ufl(f)
return ReferenceGrad(f)


def div(f):
"""Take the divergence of f.

Expand Down