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

Update ufl #61

Merged
merged 5 commits into from
Mar 7, 2025
Merged
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
56 changes: 28 additions & 28 deletions .github/workflows/tsfc-tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# This workflow will install tsfc and run its unit tests

name: tsfc integration
# This workflow will test the UFL branch against the latest Firedrake container
name: TSFC integration

on:
pull_request:
Expand All @@ -11,37 +10,38 @@ jobs:
tsfc-tests:
name: Run TSFC tests
runs-on: ubuntu-latest

container:
image: firedrakeproject/firedrake-vanilla-default:latest
# Github hosted runners require running as root user:
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem
options: --user root
env:
CC: gcc-10
CXX: g++-10

# Since we are running as root we need to set PYTHONPATH to be able to find the installed
# packages
PYTHONPATH: /home/firedrake/firedrake:/home/firedrake/.local/lib/python3.12/site-packages
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
# Download UFL into a subdirectory not called 'ufl' to make sure
# that the package installs correctly. Otherwise 'import ufl' may
# work even if the installation failed because it is a subdirectory.
path: ufl-repo

- name: Uninstall existing UFL
run: |
python3 -m pip uninstall --break-system-packages -y ufl

- name: Create virtual environment
run: |
python3 -m venv venv-ufl

- name: Install UFL
run: |
pip3 install .
. venv-ufl/bin/activate
pip install ./ufl-repo
pip list

- name: Clone tsfc
uses: actions/checkout@v4
with:
path: ./tsfc
repository: firedrakeproject/tsfc
ref: master
- name: Install tsfc
- name: Run TSFC tests
run: |
cd tsfc
pip install -r requirements-ext.txt
pip install git+https://github.com/coneoproject/COFFEE.git#egg=coffee
pip install git+https://github.com/firedrakeproject/fiat.git#egg=fenics-fiat
pip install git+https://github.com/FInAT/FInAT.git#egg=finat
pip install git+https://github.com/firedrakeproject/loopy.git#egg=loopy
pip install .[ci]
pip install pytest
- name: Run tsfc unit tests
run: python3 -m pytest tsfc/tests
. venv-ufl/bin/activate
python -m pytest /home/firedrake/firedrake/tests/tsfc
3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Contributors:
| Corrado Maurini <[email protected]>
| Jack S. Hale <[email protected]>
| Tuomas Airaksinen <[email protected]>
| Nacime Bouziani <[email protected]>
| Reuben W. Hill <[email protected]>
| Cécile Daversin-Catty <[email protected]>
| Nacime Bouziani <[email protected]>
| Matthew Scroggs <[email protected]>
| Jørgen S. Dokken <[email protected]>
14 changes: 11 additions & 3 deletions test/test_classcoverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
Not,
Or,
PermutationSymbol,
RidgeJacobian,
RidgeJacobianDeterminant,
RidgeJacobianInverse,
SpatialCoordinate,
TensorConstant,
VectorConstant,
Expand Down Expand Up @@ -292,9 +295,14 @@ def testAll(self):
_test_object(g, (), ())
g = FacetJacobianInverse(domain)
_test_object(g, (dim - 1, dim), ())

g = FacetNormal(domain)
_test_object(g, (dim,), ())
g = RidgeJacobian(domain3D)
_test_object(g, (3, 1), ())
g = RidgeJacobianDeterminant(domain3D)
_test_object(g, (), ())
g = RidgeJacobianInverse(domain3D)
_test_object(g, (1, 3), ())
g = FacetNormal(domain3D)
_test_object(g, (3,), ())
# g = CellNormal(domain)
# _test_object(g, (dim,), ())

Expand Down
23 changes: 15 additions & 8 deletions test/test_external_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from ufl.algorithms.apply_derivatives import apply_derivatives
from ufl.core.external_operator import ExternalOperator
from ufl.finiteelement import FiniteElement
from ufl.form import BaseForm
from ufl.form import BaseForm, ZeroBaseForm
from ufl.pullback import identity_pullback
from ufl.sobolevspace import H1

Expand Down Expand Up @@ -205,10 +205,10 @@ def test_differentiation_procedure_action(V1, V2):
def test_extractions(domain_2d, V1):
from ufl.algorithms.analysis import (
extract_arguments,
extract_arguments_and_coefficients,
extract_base_form_operators,
extract_coefficients,
extract_constants,
extract_terminals_with_domain,
)

u = Coefficient(V1)
Expand All @@ -219,15 +219,15 @@ def test_extractions(domain_2d, V1):

assert extract_coefficients(e) == [u]
assert extract_arguments(e) == [vstar_e]
assert extract_arguments_and_coefficients(e) == ([vstar_e], [u])
assert extract_terminals_with_domain(e) == ([vstar_e], [u], [])
assert extract_constants(e) == [c]
assert extract_base_form_operators(e) == [e]

F = e * dx

assert extract_coefficients(F) == [u]
assert extract_arguments(e) == [vstar_e]
assert extract_arguments_and_coefficients(e) == ([vstar_e], [u])
assert extract_terminals_with_domain(e) == ([vstar_e], [u], [])
assert extract_constants(F) == [c]
assert F.base_form_operators() == (e,)

Expand All @@ -236,14 +236,14 @@ def test_extractions(domain_2d, V1):

assert extract_coefficients(e) == [u]
assert extract_arguments(e) == [vstar_e, u_hat]
assert extract_arguments_and_coefficients(e) == ([vstar_e, u_hat], [u])
assert extract_terminals_with_domain(e) == ([vstar_e, u_hat], [u], [])
assert extract_base_form_operators(e) == [e]

F = e * dx

assert extract_coefficients(F) == [u]
assert extract_arguments(e) == [vstar_e, u_hat]
assert extract_arguments_and_coefficients(e) == ([vstar_e, u_hat], [u])
assert extract_terminals_with_domain(e) == ([vstar_e, u_hat], [u], [])
assert F.base_form_operators() == (e,)

w = Coefficient(V1)
Expand All @@ -252,14 +252,14 @@ def test_extractions(domain_2d, V1):

assert extract_coefficients(e2) == [u, w]
assert extract_arguments(e2) == [vstar_e2, u_hat]
assert extract_arguments_and_coefficients(e2) == ([vstar_e2, u_hat], [u, w])
assert extract_terminals_with_domain(e2) == ([vstar_e2, u_hat], [u, w], [])
assert extract_base_form_operators(e2) == [e, e2]

F = e2 * dx

assert extract_coefficients(e2) == [u, w]
assert extract_arguments(e2) == [vstar_e2, u_hat]
assert extract_arguments_and_coefficients(e2) == ([vstar_e2, u_hat], [u, w])
assert extract_terminals_with_domain(e2) == ([vstar_e2, u_hat], [u, w], [])
assert F.base_form_operators() == (e, e2)


Expand Down Expand Up @@ -516,3 +516,10 @@ def test_replace(V1):

dN_replaced = dN._ufl_expr_reconstruct_(u, argument_slots=(A, uhat))
assert G == dN_replaced


def test_ZeroDerivative(V1):
u = Coefficient(V1, count=1)
N = ExternalOperator(Coefficient(V1, count=0), function_space=V1)
dN1 = expand_derivatives(derivative(N, u))
assert isinstance(dN1, ZeroBaseForm)
8 changes: 4 additions & 4 deletions test/test_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
from ufl.algorithms.ad import expand_derivatives
from ufl.algorithms.analysis import (
extract_arguments,
extract_arguments_and_coefficients,
extract_base_form_operators,
extract_coefficients,
extract_terminals_with_domain,
)
from ufl.algorithms.expand_indices import expand_indices
from ufl.core.interpolate import Interpolate
Expand Down Expand Up @@ -172,12 +172,12 @@ def test_extract_base_form_operators(V1, V2):
# -- Interpolate(u, V2) -- #
Iu = Interpolate(u, V2)
assert extract_arguments(Iu) == [vstar]
assert extract_arguments_and_coefficients(Iu) == ([vstar], [u])
assert extract_terminals_with_domain(Iu) == ([vstar], [u], [])

F = Iu * dx
# Form composition: Iu * dx <=> Action(v * dx, Iu(u; v*))
assert extract_arguments(F) == []
assert extract_arguments_and_coefficients(F) == ([], [u])
assert extract_terminals_with_domain(F) == ([], [u], [])

for e in [Iu, F]:
assert extract_coefficients(e) == [u]
Expand All @@ -186,7 +186,7 @@ def test_extract_base_form_operators(V1, V2):
# -- Interpolate(u, V2) -- #
Iv = Interpolate(uhat, V2)
assert extract_arguments(Iv) == [vstar, uhat]
assert extract_arguments_and_coefficients(Iv) == ([vstar, uhat], [])
assert extract_terminals_with_domain(Iv) == ([vstar, uhat], [], [])
assert extract_coefficients(Iv) == []
assert extract_base_form_operators(Iv) == [Iv]

Expand Down
4 changes: 4 additions & 0 deletions test/test_measures.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def test_construct_forms_from_default_measures():
ds = Measure("ds")
dS = Measure("dS")

dl = Measure("dr")

dP = Measure("dP")
# dV = Measure("dV")

Expand All @@ -37,6 +39,8 @@ def test_construct_forms_from_default_measures():
assert ds.integral_type() == "exterior_facet"
assert dS.integral_type() == "interior_facet"

assert dl.integral_type() == "ridge"

assert dP.integral_type() == "vertex"
# TODO: Change dP to dV:
# assert dP.integral_type() == "point"
Expand Down
104 changes: 104 additions & 0 deletions test/test_mixed_function_space_with_mesh_sequence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
from ufl import (
CellVolume,
Coefficient,
FacetArea,
FacetNormal,
FunctionSpace,
Measure,
Mesh,
MeshSequence,
SpatialCoordinate,
TestFunction,
TrialFunction,
grad,
inner,
split,
triangle,
)
from ufl.algorithms import compute_form_data
from ufl.domain import extract_domains
from ufl.finiteelement import FiniteElement, MixedElement
from ufl.pullback import contravariant_piola, identity_pullback
from ufl.sobolevspace import H1, L2, HDiv


def test_mixed_function_space_with_mesh_sequence_basic():
cell = triangle
elem0 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
elem1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2,), contravariant_piola, HDiv)
elem2 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
elem = MixedElement([elem0, elem1, elem2])
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
mesh2 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=102)
domain = MeshSequence([mesh0, mesh1, mesh2])
V = FunctionSpace(domain, elem)
u = TrialFunction(V)
v = TestFunction(V)
f = Coefficient(V, count=1000)
g = Coefficient(V, count=2000)
u0, u1, u2 = split(u)
v0, v1, v2 = split(v)
f0, f1, f2 = split(f)
g0, g1, g2 = split(g)
dx1 = Measure("dx", mesh1)
x = SpatialCoordinate(mesh1)
form = x[1] * f0 * inner(grad(u0), v1) * dx1(999)
fd = compute_form_data(
form,
do_apply_function_pullbacks=True,
do_apply_integral_scaling=True,
do_apply_geometry_lowering=True,
preserve_geometry_types=(CellVolume, FacetArea),
do_apply_restrictions=True,
do_estimate_degrees=True,
complex_mode=False,
)
(id0,) = fd.integral_data
assert fd.preprocessed_form.arguments() == (v, u)
assert fd.reduced_coefficients == [f]
assert form.coefficients()[fd.original_coefficient_positions[0]] is f
assert id0.domain is mesh1
assert id0.integral_type == "cell"
assert id0.subdomain_id == (999,)
assert fd.original_form.domain_numbering()[id0.domain] == 0
assert id0.integral_coefficients == set([f])
assert id0.enabled_coefficients == [True]


def test_mixed_function_space_with_mesh_sequence_signature():
cell = triangle
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
dx0 = Measure("dx", mesh0)
dx1 = Measure("dx", mesh1)
n0 = FacetNormal(mesh0)
n1 = FacetNormal(mesh1)
form_a = inner(n1, n1) * dx0(999)
form_b = inner(n0, n0) * dx1(999)
assert form_a.signature() == form_b.signature()
assert extract_domains(form_a) == (mesh0, mesh1)
assert extract_domains(form_b) == (mesh1, mesh0)


def test_mixed_function_space_with_mesh_sequence_hash():
cell = triangle
elem0 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
elem1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2,), contravariant_piola, HDiv)
elem2 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
elem = MixedElement([elem0, elem1, elem2])
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
mesh2 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=102)
domain = MeshSequence([mesh0, mesh1, mesh2])
domain_ = MeshSequence([mesh0, mesh1, mesh2])
V = FunctionSpace(domain, elem)
V_ = FunctionSpace(domain_, elem)
u = TrialFunction(V)
u_ = TrialFunction(V_)
assert hash(domain_) == hash(domain)
assert domain_ == domain
assert hash(V_) == hash(V)
assert V_ == V
assert hash(u_) == hash(u)
assert u_ == u
10 changes: 10 additions & 0 deletions test/test_piecewise_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
FacetJacobian,
FacetJacobianDeterminant,
FacetJacobianInverse,
RidgeJacobian,
RidgeJacobianDeterminant,
RidgeJacobianInverse,
)
from ufl.finiteelement import FiniteElement
from ufl.pullback import identity_pullback
Expand Down Expand Up @@ -284,6 +287,13 @@ def mappings_are_cellwise_constant(domain, test):
assert is_cellwise_constant(e) == test
e = FacetJacobianInverse(domain)
assert is_cellwise_constant(e) == test
if domain.topological_dimension() > 2:
e = RidgeJacobian(domain)
assert is_cellwise_constant(e) == test
e = RidgeJacobianDeterminant(domain)
assert is_cellwise_constant(e) == test
e = RidgeJacobianInverse(domain)
assert is_cellwise_constant(e) == test


def test_mappings_are_cellwise_constant_on_linear_affine_cells(affine_domains):
Expand Down
Loading