Skip to content

Commit 45b57a3

Browse files
authored
Merge branch 'main' into dolci/return_ZeroBaseForm
2 parents 41ee3a7 + a98394f commit 45b57a3

24 files changed

+973
-151
lines changed

AUTHORS

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ Contributors:
2828
| Corrado Maurini <corrado.maurini@upmc.fr>
2929
| Jack S. Hale <mail@jackhale.co.uk>
3030
| Tuomas Airaksinen <tuomas.airaksinen@gmail.com>
31-
| Nacime Bouziani <nacime.bouziani@gmail.com>
3231
| Reuben W. Hill <reuben.hill10@imperial.ac.uk>
32+
| Cécile Daversin-Catty <cecile@simula.no>
3333
| Nacime Bouziani <n.bouziani18@imperial.ac.uk>
3434
| Matthew Scroggs <matthew.scroggs.14@ucl.ac.uk>
35+
| Jørgen S. Dokken <dokken@simula.no>

test/test_classcoverage.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
Not,
2525
Or,
2626
PermutationSymbol,
27+
RidgeJacobian,
28+
RidgeJacobianDeterminant,
29+
RidgeJacobianInverse,
2730
SpatialCoordinate,
2831
TensorConstant,
2932
VectorConstant,
@@ -292,9 +295,14 @@ def testAll(self):
292295
_test_object(g, (), ())
293296
g = FacetJacobianInverse(domain)
294297
_test_object(g, (dim - 1, dim), ())
295-
296-
g = FacetNormal(domain)
297-
_test_object(g, (dim,), ())
298+
g = RidgeJacobian(domain3D)
299+
_test_object(g, (3, 1), ())
300+
g = RidgeJacobianDeterminant(domain3D)
301+
_test_object(g, (), ())
302+
g = RidgeJacobianInverse(domain3D)
303+
_test_object(g, (1, 3), ())
304+
g = FacetNormal(domain3D)
305+
_test_object(g, (3,), ())
298306
# g = CellNormal(domain)
299307
# _test_object(g, (dim,), ())
300308

test/test_external_operator.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,10 @@ def test_differentiation_procedure_action(V1, V2):
205205
def test_extractions(domain_2d, V1):
206206
from ufl.algorithms.analysis import (
207207
extract_arguments,
208-
extract_arguments_and_coefficients,
209208
extract_base_form_operators,
210209
extract_coefficients,
211210
extract_constants,
211+
extract_terminals_with_domain,
212212
)
213213

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

220220
assert extract_coefficients(e) == [u]
221221
assert extract_arguments(e) == [vstar_e]
222-
assert extract_arguments_and_coefficients(e) == ([vstar_e], [u])
222+
assert extract_terminals_with_domain(e) == ([vstar_e], [u], [])
223223
assert extract_constants(e) == [c]
224224
assert extract_base_form_operators(e) == [e]
225225

226226
F = e * dx
227227

228228
assert extract_coefficients(F) == [u]
229229
assert extract_arguments(e) == [vstar_e]
230-
assert extract_arguments_and_coefficients(e) == ([vstar_e], [u])
230+
assert extract_terminals_with_domain(e) == ([vstar_e], [u], [])
231231
assert extract_constants(F) == [c]
232232
assert F.base_form_operators() == (e,)
233233

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

237237
assert extract_coefficients(e) == [u]
238238
assert extract_arguments(e) == [vstar_e, u_hat]
239-
assert extract_arguments_and_coefficients(e) == ([vstar_e, u_hat], [u])
239+
assert extract_terminals_with_domain(e) == ([vstar_e, u_hat], [u], [])
240240
assert extract_base_form_operators(e) == [e]
241241

242242
F = e * dx
243243

244244
assert extract_coefficients(F) == [u]
245245
assert extract_arguments(e) == [vstar_e, u_hat]
246-
assert extract_arguments_and_coefficients(e) == ([vstar_e, u_hat], [u])
246+
assert extract_terminals_with_domain(e) == ([vstar_e, u_hat], [u], [])
247247
assert F.base_form_operators() == (e,)
248248

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

253253
assert extract_coefficients(e2) == [u, w]
254254
assert extract_arguments(e2) == [vstar_e2, u_hat]
255-
assert extract_arguments_and_coefficients(e2) == ([vstar_e2, u_hat], [u, w])
255+
assert extract_terminals_with_domain(e2) == ([vstar_e2, u_hat], [u, w], [])
256256
assert extract_base_form_operators(e2) == [e, e2]
257257

258258
F = e2 * dx
259259

260260
assert extract_coefficients(e2) == [u, w]
261261
assert extract_arguments(e2) == [vstar_e2, u_hat]
262-
assert extract_arguments_and_coefficients(e2) == ([vstar_e2, u_hat], [u, w])
262+
assert extract_terminals_with_domain(e2) == ([vstar_e2, u_hat], [u, w], [])
263263
assert F.base_form_operators() == (e, e2)
264264

265265

test/test_interpolate.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
from ufl.algorithms.ad import expand_derivatives
2828
from ufl.algorithms.analysis import (
2929
extract_arguments,
30-
extract_arguments_and_coefficients,
3130
extract_base_form_operators,
3231
extract_coefficients,
32+
extract_terminals_with_domain,
3333
)
3434
from ufl.algorithms.expand_indices import expand_indices
3535
from ufl.core.interpolate import Interpolate
@@ -172,12 +172,12 @@ def test_extract_base_form_operators(V1, V2):
172172
# -- Interpolate(u, V2) -- #
173173
Iu = Interpolate(u, V2)
174174
assert extract_arguments(Iu) == [vstar]
175-
assert extract_arguments_and_coefficients(Iu) == ([vstar], [u])
175+
assert extract_terminals_with_domain(Iu) == ([vstar], [u], [])
176176

177177
F = Iu * dx
178178
# Form composition: Iu * dx <=> Action(v * dx, Iu(u; v*))
179179
assert extract_arguments(F) == []
180-
assert extract_arguments_and_coefficients(F) == ([], [u])
180+
assert extract_terminals_with_domain(F) == ([], [u], [])
181181

182182
for e in [Iu, F]:
183183
assert extract_coefficients(e) == [u]
@@ -186,7 +186,7 @@ def test_extract_base_form_operators(V1, V2):
186186
# -- Interpolate(u, V2) -- #
187187
Iv = Interpolate(uhat, V2)
188188
assert extract_arguments(Iv) == [vstar, uhat]
189-
assert extract_arguments_and_coefficients(Iv) == ([vstar, uhat], [])
189+
assert extract_terminals_with_domain(Iv) == ([vstar, uhat], [], [])
190190
assert extract_coefficients(Iv) == []
191191
assert extract_base_form_operators(Iv) == [Iv]
192192

test/test_measures.py

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def test_construct_forms_from_default_measures():
1616
ds = Measure("ds")
1717
dS = Measure("dS")
1818

19+
dl = Measure("dr")
20+
1921
dP = Measure("dP")
2022
# dV = Measure("dV")
2123

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

42+
assert dl.integral_type() == "ridge"
43+
4044
assert dP.integral_type() == "vertex"
4145
# TODO: Change dP to dV:
4246
# assert dP.integral_type() == "point"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from ufl import (
2+
CellVolume,
3+
Coefficient,
4+
FacetArea,
5+
FacetNormal,
6+
FunctionSpace,
7+
Measure,
8+
Mesh,
9+
MeshSequence,
10+
SpatialCoordinate,
11+
TestFunction,
12+
TrialFunction,
13+
grad,
14+
inner,
15+
split,
16+
triangle,
17+
)
18+
from ufl.algorithms import compute_form_data
19+
from ufl.domain import extract_domains
20+
from ufl.finiteelement import FiniteElement, MixedElement
21+
from ufl.pullback import contravariant_piola, identity_pullback
22+
from ufl.sobolevspace import H1, L2, HDiv
23+
24+
25+
def test_mixed_function_space_with_mesh_sequence_basic():
26+
cell = triangle
27+
elem0 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
28+
elem1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2,), contravariant_piola, HDiv)
29+
elem2 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
30+
elem = MixedElement([elem0, elem1, elem2])
31+
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
32+
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
33+
mesh2 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=102)
34+
domain = MeshSequence([mesh0, mesh1, mesh2])
35+
V = FunctionSpace(domain, elem)
36+
u = TrialFunction(V)
37+
v = TestFunction(V)
38+
f = Coefficient(V, count=1000)
39+
g = Coefficient(V, count=2000)
40+
u0, u1, u2 = split(u)
41+
v0, v1, v2 = split(v)
42+
f0, f1, f2 = split(f)
43+
g0, g1, g2 = split(g)
44+
dx1 = Measure("dx", mesh1)
45+
x = SpatialCoordinate(mesh1)
46+
form = x[1] * f0 * inner(grad(u0), v1) * dx1(999)
47+
fd = compute_form_data(
48+
form,
49+
do_apply_function_pullbacks=True,
50+
do_apply_integral_scaling=True,
51+
do_apply_geometry_lowering=True,
52+
preserve_geometry_types=(CellVolume, FacetArea),
53+
do_apply_restrictions=True,
54+
do_estimate_degrees=True,
55+
complex_mode=False,
56+
)
57+
(id0,) = fd.integral_data
58+
assert fd.preprocessed_form.arguments() == (v, u)
59+
assert fd.reduced_coefficients == [f]
60+
assert form.coefficients()[fd.original_coefficient_positions[0]] is f
61+
assert id0.domain is mesh1
62+
assert id0.integral_type == "cell"
63+
assert id0.subdomain_id == (999,)
64+
assert fd.original_form.domain_numbering()[id0.domain] == 0
65+
assert id0.integral_coefficients == set([f])
66+
assert id0.enabled_coefficients == [True]
67+
68+
69+
def test_mixed_function_space_with_mesh_sequence_signature():
70+
cell = triangle
71+
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
72+
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
73+
dx0 = Measure("dx", mesh0)
74+
dx1 = Measure("dx", mesh1)
75+
n0 = FacetNormal(mesh0)
76+
n1 = FacetNormal(mesh1)
77+
form_a = inner(n1, n1) * dx0(999)
78+
form_b = inner(n0, n0) * dx1(999)
79+
assert form_a.signature() == form_b.signature()
80+
assert extract_domains(form_a) == (mesh0, mesh1)
81+
assert extract_domains(form_b) == (mesh1, mesh0)
82+
83+
84+
def test_mixed_function_space_with_mesh_sequence_hash():
85+
cell = triangle
86+
elem0 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
87+
elem1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2,), contravariant_piola, HDiv)
88+
elem2 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
89+
elem = MixedElement([elem0, elem1, elem2])
90+
mesh0 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=100)
91+
mesh1 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=101)
92+
mesh2 = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), ufl_id=102)
93+
domain = MeshSequence([mesh0, mesh1, mesh2])
94+
domain_ = MeshSequence([mesh0, mesh1, mesh2])
95+
V = FunctionSpace(domain, elem)
96+
V_ = FunctionSpace(domain_, elem)
97+
u = TrialFunction(V)
98+
u_ = TrialFunction(V_)
99+
assert hash(domain_) == hash(domain)
100+
assert domain_ == domain
101+
assert hash(V_) == hash(V)
102+
assert V_ == V
103+
assert hash(u_) == hash(u)
104+
assert u_ == u

test/test_piecewise_checks.py

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
FacetJacobian,
3333
FacetJacobianDeterminant,
3434
FacetJacobianInverse,
35+
RidgeJacobian,
36+
RidgeJacobianDeterminant,
37+
RidgeJacobianInverse,
3538
)
3639
from ufl.finiteelement import FiniteElement
3740
from ufl.pullback import identity_pullback
@@ -284,6 +287,13 @@ def mappings_are_cellwise_constant(domain, test):
284287
assert is_cellwise_constant(e) == test
285288
e = FacetJacobianInverse(domain)
286289
assert is_cellwise_constant(e) == test
290+
if domain.topological_dimension() > 2:
291+
e = RidgeJacobian(domain)
292+
assert is_cellwise_constant(e) == test
293+
e = RidgeJacobianDeterminant(domain)
294+
assert is_cellwise_constant(e) == test
295+
e = RidgeJacobianInverse(domain)
296+
assert is_cellwise_constant(e) == test
287297

288298

289299
def test_mappings_are_cellwise_constant_on_linear_affine_cells(affine_domains):

ufl/__init__.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
6363
-AbstractDomain
6464
-Mesh
65+
-MeshSequence
6566
-MeshView
6667
6768
* Sobolev spaces::
@@ -209,7 +210,7 @@
209210
210211
* Integral measures::
211212
212-
-dx, ds, dS, dP
213+
-dx, ds, dS, dP, dl
213214
-dc, dC, dO, dI, dX
214215
-ds_b, ds_t, ds_tb, ds_v, dS_h, dS_v
215216
@@ -265,7 +266,7 @@
265266
from ufl.core.external_operator import ExternalOperator
266267
from ufl.core.interpolate import Interpolate, interpolate
267268
from ufl.core.multiindex import Index, indices
268-
from ufl.domain import AbstractDomain, Mesh, MeshView
269+
from ufl.domain import AbstractDomain, Mesh, MeshSequence, MeshView
269270
from ufl.finiteelement import AbstractFiniteElement
270271
from ufl.form import BaseForm, Form, FormSum, ZeroBaseForm
271272
from ufl.formoperators import (
@@ -296,6 +297,9 @@
296297
MaxFacetEdgeLength,
297298
MinCellEdgeLength,
298299
MinFacetEdgeLength,
300+
RidgeJacobian,
301+
RidgeJacobianDeterminant,
302+
RidgeJacobianInverse,
299303
SpatialCoordinate,
300304
)
301305
from ufl.integral import Integral
@@ -307,6 +311,7 @@
307311
dI,
308312
dO,
309313
dP,
314+
dr,
310315
dS,
311316
ds,
312317
ds_b,
@@ -484,6 +489,7 @@
484489
"MaxFacetEdgeLength",
485490
"Measure",
486491
"Mesh",
492+
"MeshSequence",
487493
"MeshView",
488494
"MinCellEdgeLength",
489495
"MinFacetEdgeLength",
@@ -492,6 +498,9 @@
492498
"Not",
493499
"Or",
494500
"PermutationSymbol",
501+
"RidgeJacobian",
502+
"RidgeJacobianDeterminant",
503+
"RidgeJacobianInverse",
495504
"SpatialCoordinate",
496505
"SymmetricPullback",
497506
"TensorConstant",
@@ -549,6 +558,7 @@
549558
"dot",
550559
"double_contravariant_piola",
551560
"double_covariant_piola",
561+
"dr",
552562
"ds",
553563
"ds_b",
554564
"ds_t",

ufl/action.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ def _get_action_form_arguments(left, right):
215215
elif isinstance(right, CoefficientDerivative):
216216
# Action differentiation pushes differentiation through
217217
# right as a consequence of Leibniz formula.
218-
from ufl.algorithms.analysis import extract_arguments_and_coefficients
218+
from ufl.algorithms.analysis import extract_terminals_with_domain
219219

220-
right_args, right_coeffs = extract_arguments_and_coefficients(right)
220+
right_args, right_coeffs, _ = extract_terminals_with_domain(right)
221221
arguments = left_args + tuple(right_args)
222222
coefficients += tuple(right_coeffs)
223223
elif isinstance(right, (BaseCoefficient, Zero)):

0 commit comments

Comments
 (0)