Skip to content

Commit 0c592ec

Browse files
authored
Merge pull request #30 from firedrakeproject/merge_fenics
Merge fenics
2 parents 9135be1 + 3f5ad50 commit 0c592ec

19 files changed

+195
-82
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ test/.pytest_cache
88
*.egg-info
99
dist/
1010
release/
11+
12+
.*.swp

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# future
33
[metadata]
44
name = fenics-ufl
5-
version = 2022.2.0.dev0
5+
version = 2022.3.0.dev0
66
author = FEniCS Project Contributors
77
88
maintainer = FEniCS Project Steering Council

test/test_sobolevspace.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
FiniteElement, triangle, interval,
1010
quadrilateral, HDiv, HCurl)
1111
from ufl.sobolevspace import SobolevSpace, DirectionalSobolevSpace
12-
from ufl import H2, H1, HDiv, HCurl, L2
12+
from ufl import H2, H1, HDiv, HCurl, L2, HInf
13+
from math import inf
1314

1415

1516
# Construct directional Sobolev spaces, with varying smoothness in
1617
# spatial coordinates
1718
H0dx0dy = DirectionalSobolevSpace((0, 0))
1819
H1dx1dy = DirectionalSobolevSpace((1, 1))
1920
H2dx2dy = DirectionalSobolevSpace((2, 2))
21+
Hinfdxinfdy = DirectionalSobolevSpace((inf, inf))
2022
H1dx = DirectionalSobolevSpace((1, 0))
2123
H1dy = DirectionalSobolevSpace((0, 1))
2224
H000 = DirectionalSobolevSpace((0, 0, 0))
@@ -44,6 +46,8 @@ def test_directional_space_relations():
4446
assert H1dx1dy <= HCurl
4547
assert H2dx2dy <= H1dx1dy
4648
assert H2dhH1dz < H1
49+
assert Hinfdxinfdy <= HInf
50+
assert Hinfdxinfdy < H2dx2dy
4751
assert H1dz > H2dhH1dz
4852
assert H1dh < L2
4953
assert H1dz < L2
@@ -63,7 +67,6 @@ def xtest_contains_mixed():
6367

6468
def test_contains_l2():
6569
l2_elements = [
66-
FiniteElement("Real", triangle, 0),
6770
FiniteElement("DG", triangle, 0),
6871
FiniteElement("DG", triangle, 1),
6972
FiniteElement("DG", triangle, 2),
@@ -132,6 +135,22 @@ def test_contains_h2():
132135
assert h2_element in H0dx0dy
133136

134137

138+
def test_contains_hinf():
139+
hinf_elements = [
140+
FiniteElement("R", triangle, 0)
141+
]
142+
for hinf_element in hinf_elements:
143+
assert hinf_element in HInf
144+
assert hinf_element in H2
145+
assert hinf_element in H2dx2dy
146+
assert hinf_element in H1
147+
assert hinf_element in H1dx1dy
148+
assert hinf_element in HDiv
149+
assert hinf_element in HCurl
150+
assert hinf_element in L2
151+
assert hinf_element in H0dx0dy
152+
153+
135154
def test_contains_hdiv():
136155
hdiv_elements = [
137156
FiniteElement("RT", triangle, 1),

ufl/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@
6868
- L2
6969
- H1
7070
- H2
71+
- HInf
7172
- HDiv
7273
- HCurl
74+
- HEin
75+
- HDivDiv
7376
7477
* Elements::
7578
@@ -272,7 +275,7 @@
272275
)
273276

274277
# Sobolev spaces
275-
from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl
278+
from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl, HEin, HDivDiv, HInf
276279

277280
# Finite elements classes
278281
from ufl.finiteelement import FiniteElementBase, FiniteElement, \
@@ -369,7 +372,7 @@
369372
'UFLException', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
370373
'as_cell', 'AbstractCell', 'Cell', 'TensorProductCell',
371374
'as_domain', 'AbstractDomain', 'Mesh', 'MeshView', 'TensorProductMesh',
372-
'L2', 'H1', 'H2', 'HCurl', 'HDiv',
375+
'L2', 'H1', 'H2', 'HCurl', 'HDiv', 'HInf', 'HEin', 'HDivDiv',
373376
'SpatialCoordinate',
374377
'CellVolume', 'CellDiameter', 'Circumradius',
375378
'MinCellEdgeLength', 'MaxCellEdgeLength',

ufl/algorithms/apply_restrictions.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from ufl.corealg.map_dag import map_expr_dag
1515
from ufl.algorithms.map_integrands import map_integrand_dags
1616
from ufl.measure import integral_type_to_measure_name
17+
from ufl.sobolevspace import H1
1718

1819

1920
class RestrictionPropagator(MultiFunction):
@@ -128,12 +129,7 @@ def reference_value(self, o):
128129

129130
def coefficient(self, o):
130131
"Allow coefficients to be unrestricted (apply default if so) if the values are fully continuous across the facet."
131-
e = o.ufl_element()
132-
d = e.degree()
133-
f = e.family()
134-
# TODO: Move this choice to the element class?
135-
continuous_families = ["Lagrange", "Q", "S"]
136-
if (f in continuous_families and d > 0) or f == "Real":
132+
if o.ufl_element() in H1:
137133
# If the coefficient _value_ is _fully_ continuous
138134
return self._default_restricted(o) # Must still be computed from one of the sides, we just don't care which
139135
else:

ufl/constant.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ def __eq__(self, other):
6666
self._ufl_domain == other._ufl_domain and
6767
self._ufl_shape == self._ufl_shape)
6868

69+
def _ufl_signature_data_(self, renumbering):
70+
"Signature data for constant depends on renumbering"
71+
return "Constant({}, {}, {})".format(
72+
self._ufl_domain._ufl_signature_data_(renumbering), repr(self._ufl_shape),
73+
repr(renumbering[self]))
74+
6975

7076
def VectorConstant(domain, count=None):
7177
domain = as_domain(domain)

ufl/finiteelement/brokenelement.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
# Modified by Massimiliano Leoni, 2016
99

1010
from ufl.finiteelement.finiteelementbase import FiniteElementBase
11+
from ufl.sobolevspace import L2
1112

1213

1314
class BrokenElement(FiniteElementBase):
1415
"""The discontinuous version of an existing Finite Element space."""
1516
def __init__(self, element):
1617
self._element = element
17-
self._repr = "BrokenElement(%s)" % repr(element)
1818

1919
family = "BrokenElement"
2020
cell = element.cell()
@@ -25,15 +25,22 @@ def __init__(self, element):
2525
FiniteElementBase.__init__(self, family, cell, degree,
2626
quad_scheme, value_shape, reference_value_shape)
2727

28+
def __repr__(self):
29+
return f"BrokenElement({repr(self._element)})"
30+
2831
def mapping(self):
2932
return self._element.mapping()
3033

34+
def sobolev_space(self):
35+
"""Return the underlying Sobolev space."""
36+
return L2
37+
3138
def reconstruct(self, **kwargs):
3239
return BrokenElement(self._element.reconstruct(**kwargs))
3340

3441
def __str__(self):
35-
return "BrokenElement(%s)" % str(self._element)
42+
return f"BrokenElement({repr(self._element)})"
3643

3744
def shortstr(self):
38-
"Format as string for pretty printing."
39-
return "BrokenElement(%s)" % str(self._element.shortstr())
45+
"""Format as string for pretty printing."""
46+
return f"BrokenElement({repr(self._element)})"

ufl/finiteelement/elementlist.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from numpy import asarray
1717

1818
from ufl.log import warning, error
19-
from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl, HEin, HDivDiv
19+
from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl, HEin, HDivDiv, HInf
2020
from ufl.utils.formatting import istr
2121
from ufl.cell import Cell, TensorProductCell
2222

@@ -137,7 +137,7 @@ def show_elements():
137137
register_element("FacetBubble", "FB", 0, H1, "identity", (2, None), simplices)
138138
register_element("Quadrature", "Quadrature", 0, L2, "identity", (0, None),
139139
any_cell)
140-
register_element("Real", "R", 0, L2, "identity", (0, 0),
140+
register_element("Real", "R", 0, HInf, "identity", (0, 0),
141141
any_cell + ("TensorProductCell",))
142142
register_element("Undefined", "U", 0, L2, "identity", (0, None), any_cell)
143143
register_element("Radau", "Rad", 0, L2, "identity", (0, None), ("interval",))
@@ -464,9 +464,6 @@ def canonical_element_description(family, cell, order, form_degree):
464464
error('Order "%s" invalid for "%s" finite element.' %
465465
(istr(order), family))
466466

467-
# Override sobolev_space for piecewise constants (TODO: necessary?)
468-
if order == 0:
469-
sobolev_space = L2
470467
if value_rank == 2:
471468
# Tensor valued fundamental elements in HEin have this shape
472469
if gdim is None or tdim is None:

ufl/finiteelement/enrichedelement.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,11 @@ def __init__(self, *elements):
6161
quad_scheme, value_shape,
6262
reference_value_shape)
6363

64-
# Cache repr string
65-
self._repr = "%s(%s)" % (class_name, ", ".join(repr(e) for e in self._elements))
66-
6764
def mapping(self):
6865
return self._elements[0].mapping()
6966

7067
def sobolev_space(self):
71-
"Return the underlying Sobolev space."
68+
"""Return the underlying Sobolev space."""
7269
elements = [e for e in self._elements]
7370
if all(e.sobolev_space() == elements[0].sobolev_space()
7471
for e in elements):
@@ -85,6 +82,13 @@ def sobolev_space(self):
8582
sobolev_space, = intersect
8683
return sobolev_space
8784

85+
def variant(self):
86+
try:
87+
variant, = {e.variant() for e in self._elements}
88+
return variant
89+
except ValueError:
90+
return None
91+
8892
def reconstruct(self, **kwargs):
8993
return type(self)(*[e.reconstruct(**kwargs) for e in self._elements])
9094

@@ -104,6 +108,9 @@ def is_cellwise_constant(self):
104108
element is spatially constant over each cell."""
105109
return all(e.is_cellwise_constant() for e in self._elements)
106110

111+
def __repr__(self):
112+
return "EnrichedElement(" + ", ".join(repr(e) for e in self._elements) + ")"
113+
107114
def __str__(self):
108115
"Format as string for pretty printing."
109116
return "<%s>" % " + ".join(str(e) for e in self._elements)
@@ -127,6 +134,9 @@ def is_cellwise_constant(self):
127134
element is spatially constant over each cell."""
128135
return False
129136

137+
def __repr__(self):
138+
return "NodalEnrichedElement(" + ", ".join(repr(e) for e in self._elements) + ")"
139+
130140
def __str__(self):
131141
"Format as string for pretty printing."
132142
return "<Nodal enriched element(%s)>" % ", ".join(str(e) for e in self._elements)

ufl/finiteelement/finiteelement.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@
2424
class FiniteElement(FiniteElementBase):
2525
"The basic finite element class for all simple finite elements."
2626
# TODO: Move these to base?
27-
__slots__ = ("_short_name",
28-
"_sobolev_space",
29-
"_mapping",
30-
"_variant")
27+
__slots__ = ("_short_name", "_sobolev_space",
28+
"_mapping", "_variant", "_repr")
3129

3230
def __new__(cls,
3331
family,
@@ -188,11 +186,16 @@ def __init__(self,
188186
repr(self.family()), repr(self.cell()), repr(self.degree()), quad_str, var_str)
189187
assert '"' not in self._repr
190188

189+
def __repr__(self):
190+
"""Format as string for evaluation as Python object."""
191+
return self._repr
192+
191193
def mapping(self):
194+
"""Return the mapping type for this element ."""
192195
return self._mapping
193196

194197
def sobolev_space(self):
195-
"Return the underlying Sobolev space."
198+
"""Return the underlying Sobolev space."""
196199
return self._sobolev_space
197200

198201
def variant(self):

0 commit comments

Comments
 (0)