Skip to content

Commit 8905425

Browse files
committed
Merged in remove-tpve-tpte (pull request #33)
* remove-tpve-tpte: Purge now unnecessary OPVE and OPTE Support building Vector/TensorElement from elements
2 parents 6eb8619 + 3dd3e86 commit 8905425

File tree

7 files changed

+88
-280
lines changed

7 files changed

+88
-280
lines changed

test/test_change_to_reference_frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
4141
from ufl.algorithms.transformer import ReuseTransformer, apply_transformer
4242
from ufl.compound_expressions import determinant_expr, cross_expr, inverse_expr
43-
from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, TensorProductElement, TensorProductVectorElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
43+
from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, TensorProductElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
4444
'''
4545

4646

ufl/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
FiniteElement,
5858
MixedElement, VectorElement, TensorElement
5959
EnrichedElement, RestrictedElement,
60-
TensorProductElement, TensorProductVectorElement, TensorProductTensorElement,
61-
HDiv, HCurl
60+
TensorProductElement,
61+
HDivElement, HCurlElement
6262
BrokenElement, TraceElement
6363
FacetElement, InteriorElement
6464
@@ -215,7 +215,6 @@
215215
from ufl.finiteelement import FiniteElementBase, FiniteElement, \
216216
MixedElement, VectorElement, TensorElement, EnrichedElement, \
217217
RestrictedElement, TensorProductElement, \
218-
TensorProductVectorElement, TensorProductTensorElement, \
219218
HDivElement, HCurlElement, BrokenElement, TraceElement, \
220219
FacetElement, InteriorElement
221220

@@ -313,7 +312,7 @@
313312
'FiniteElementBase', 'FiniteElement',
314313
'MixedElement', 'VectorElement', 'TensorElement', 'EnrichedElement',
315314
'RestrictedElement', 'TensorProductElement',
316-
'TensorProductVectorElement', 'TensorProductTensorElement', 'HDivElement', 'HCurlElement',
315+
'HDivElement', 'HCurlElement',
317316
'BrokenElement', 'TraceElement', 'FacetElement', 'InteriorElement',
318317
'register_element', 'show_elements',
319318
'FunctionSpace',

ufl/algorithms/apply_function_pullbacks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
from ufl.tensors import as_tensor, as_vector
3636

3737
from ufl.finiteelement import (FiniteElement, EnrichedElement, VectorElement, MixedElement,
38-
TensorProductElement, TensorProductVectorElement, TensorElement,
39-
FacetElement, InteriorElement, BrokenElement, TraceElement)
38+
TensorProductElement, FacetElement, InteriorElement,
39+
BrokenElement, TraceElement)
4040
from ufl.utils.sequences import product
4141

4242
def sub_elements_with_mappings(element):

ufl/algorithms/change_to_reference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
from ufl.permutation import compute_indices
4646

4747
from ufl.compound_expressions import determinant_expr, cross_expr, inverse_expr
48-
from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, TensorProductElement, TensorProductVectorElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
48+
from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, TensorProductElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
4949

5050
from ufl.algorithms.apply_function_pullbacks import apply_function_pullbacks
5151
from ufl.algorithms.apply_geometry_lowering import apply_geometry_lowering

ufl/finiteelement/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
from ufl.finiteelement.enrichedelement import EnrichedElement
3232
from ufl.finiteelement.restrictedelement import RestrictedElement
3333
from ufl.finiteelement.tensorproductelement import TensorProductElement
34-
from ufl.finiteelement.tensorproductelement import TensorProductVectorElement
35-
from ufl.finiteelement.tensorproductelement import TensorProductTensorElement
3634
from ufl.finiteelement.hdivcurl import HDivElement, HCurlElement
3735
from ufl.finiteelement.brokenelement import BrokenElement
3836
from ufl.finiteelement.traceelement import TraceElement
@@ -49,8 +47,6 @@
4947
"EnrichedElement",
5048
"RestrictedElement",
5149
"TensorProductElement",
52-
"TensorProductVectorElement",
53-
"TensorProductTensorElement",
5450
"HDivElement",
5551
"HCurlElement",
5652
"BrokenElement",

ufl/finiteelement/mixedelement.py

Lines changed: 81 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -248,36 +248,18 @@ def shortstr(self):
248248
class VectorElement(MixedElement):
249249
"A special case of a mixed finite element where all elements are equal"
250250

251-
def __new__(cls, family, cell, degree, dim=None,
252-
form_degree=None, quad_scheme=None):
253-
"""Intercepts construction, such that it returns an
254-
TensorProductVectorElement when FiniteElement returns an
255-
TensorProductElement.
256-
"""
257-
# Create mixed element from list of finite elements
258-
sub_element = FiniteElement(family, cell, degree,
259-
form_degree=form_degree,
260-
quad_scheme=quad_scheme)
261-
262-
from ufl.finiteelement.tensorproductelement import TensorProductElement
263-
from ufl.finiteelement.tensorproductelement import TensorProductVectorElement
264-
if isinstance(sub_element, TensorProductElement):
265-
return TensorProductVectorElement(sub_element, dim=dim)
266-
267-
return super(VectorElement, cls).__new__(cls)
268-
269-
def __init__(self, family, cell, degree, dim=None,
251+
def __init__(self, family, cell=None, degree=None, dim=None,
270252
form_degree=None, quad_scheme=None):
271253
"""
272254
Create vector element (repeated mixed element)
273255
274256
*Arguments*
275257
family (string)
276-
The finite element family
258+
The finite element family (or a FiniteElement)
277259
cell
278-
The geometric cell
260+
The geometric cell (ignored if family is FiniteElement)
279261
degree (int)
280-
The polynomial degree
262+
The polynomial degree (ignored if family is a FiniteElement)
281263
dim (int)
282264
The value dimension of the element (optional)
283265
form_degree (int)
@@ -286,20 +268,23 @@ def __init__(self, family, cell, degree, dim=None,
286268
quad_scheme
287269
The quadrature scheme (optional)
288270
"""
289-
if cell is not None:
290-
cell = as_cell(cell)
271+
if isinstance(family, FiniteElementBase):
272+
sub_element = family
273+
cell = sub_element.cell()
274+
else:
275+
if cell is not None:
276+
cell = as_cell(cell)
277+
# Create sub element
278+
sub_element = FiniteElement(family, cell, degree,
279+
form_degree=form_degree,
280+
quad_scheme=quad_scheme)
291281

292282
# Set default size if not specified
293283
if dim is None:
294284
ufl_assert(cell is not None,
295285
"Cannot infer vector dimension without a cell.")
296286
dim = cell.geometric_dimension()
297287

298-
# Create sub element
299-
sub_element = FiniteElement(family, cell, degree,
300-
form_degree=form_degree,
301-
quad_scheme=quad_scheme)
302-
303288
# Create list of sub elements for mixed element constructor
304289
sub_elements = [sub_element]*dim
305290

@@ -311,16 +296,15 @@ def __init__(self, family, cell, degree, dim=None,
311296
MixedElement.__init__(self, sub_elements, value_shape=value_shape, reference_value_shape=reference_value_shape)
312297
# FIXME: Storing this here is strange, isn't that handled by subclass?
313298
self._family = sub_element.family()
314-
self._degree = degree
299+
self._degree = sub_element.degree()
315300
self._sub_element = sub_element
316301
self._form_degree = form_degree # Storing for signature_data, not sure if it's needed
317302

318303
# Cache repr string
319304
qs = self.quadrature_scheme()
320305
quad_str = "" if qs is None else ", quad_scheme=%r" % (qs,)
321-
self._repr = ("VectorElement(%r, %r, %r, dim=%d%s)" %
322-
(self._family, self.cell(), self._degree,
323-
len(self._sub_elements), quad_str))
306+
self._repr = ("VectorElement(%r, dim=%d%s)" %
307+
(sub_element, len(self._sub_elements), quad_str))
324308

325309
def __str__(self):
326310
"Format as string for pretty printing."
@@ -340,38 +324,77 @@ class TensorElement(MixedElement):
340324
"_sub_element_mapping", "_flattened_sub_element_mapping",
341325
"_mapping")
342326

343-
def __new__(cls, family, cell, degree, shape=None,
344-
symmetry=None, quad_scheme=None):
345-
"""Intercepts construction, such that it returns an
346-
TensorProductTensorElement when FiniteElement returns an
347-
TensorProductElement.
348-
"""
349-
# Compute sub element
350-
sub_element = FiniteElement(family, cell, degree, quad_scheme)
351-
352-
from ufl.finiteelement.tensorproductelement import TensorProductElement
353-
from ufl.finiteelement.tensorproductelement import TensorProductTensorElement
354-
if isinstance(sub_element, TensorProductElement):
355-
return TensorProductTensorElement(sub_element, shape=shape, symmetry=symmetry)
356-
357-
return super(TensorElement, cls).__new__(cls)
358-
359-
def __init__(self, family, cell, degree, shape=None,
360-
symmetry=None, quad_scheme=None):
327+
def __init__(self, family, cell=None, degree=None, shape=None, symmetry=None, quad_scheme=None):
361328
"Create tensor element (repeated mixed element with optional symmetries)"
362-
# Create scalar sub element
363-
sub_element = FiniteElement(family, cell, degree, quad_scheme)
329+
if isinstance(family, FiniteElementBase):
330+
sub_element = family
331+
else:
332+
if cell is not None:
333+
cell = as_cell(cell)
334+
sub_element = FiniteElement(family, cell, degree, quad_scheme)
364335
ufl_assert(sub_element.value_shape() == (),
365336
"Expecting only scalar valued subelement for TensorElement.")
366337

367-
shape, symmetry, sub_elements, sub_element_mapping, flattened_sub_element_mapping, \
368-
reference_value_shape, mapping = _tensor_sub_elements(sub_element, shape, symmetry)
338+
# Set default shape if not specified
339+
if shape is None:
340+
ufl_assert(sub_element.cell() is not None,
341+
"Cannot infer tensor shape without a cell.")
342+
dim = sub_element.cell().geometric_dimension()
343+
shape = (dim, dim)
344+
345+
if symmetry is None:
346+
symmetry = EmptyDict
347+
elif symmetry is True:
348+
# Construct default symmetry dict for matrix elements
349+
ufl_assert(len(shape) == 2 and shape[0] == shape[1],
350+
"Cannot set automatic symmetry for non-square tensor.")
351+
symmetry = dict( ((i, j), (j, i)) for i in range(shape[0])
352+
for j in range(shape[1]) if i > j )
353+
else:
354+
ufl_assert(isinstance(symmetry, dict), "Expecting symmetry to be None (unset), True, or dict.")
355+
356+
# Validate indices in symmetry dict
357+
for i, j in iteritems(symmetry):
358+
ufl_assert(len(i) == len(j),
359+
"Non-matching length of symmetry index tuples.")
360+
for k in range(len(i)):
361+
ufl_assert(i[k] >= 0 and j[k] >= 0 and
362+
i[k] < shape[k] and j[k] < shape[k],
363+
"Symmetry dimensions out of bounds.")
364+
365+
# Compute all index combinations for given shape
366+
indices = compute_indices(shape)
367+
368+
# Compute mapping from indices to sub element number, accounting for symmetry
369+
sub_elements = []
370+
sub_element_mapping = {}
371+
for index in indices:
372+
if index in symmetry:
373+
continue
374+
sub_element_mapping[index] = len(sub_elements)
375+
sub_elements += [sub_element]
376+
377+
# Update mapping for symmetry
378+
for index in indices:
379+
if index in symmetry:
380+
sub_element_mapping[index] = sub_element_mapping[symmetry[index]]
381+
flattened_sub_element_mapping = [sub_element_mapping[index] for i, index in enumerate(indices)]
382+
383+
# Compute reference value shape based on symmetries
384+
if symmetry:
385+
# Flatten and subtract symmetries
386+
reference_value_shape = (product(shape)-len(symmetry),)
387+
mapping = "symmetries"
388+
else:
389+
# Do not flatten if there are no symmetries
390+
reference_value_shape = shape
391+
mapping = "identity"
369392

370393
# Initialize element data
371394
MixedElement.__init__(self, sub_elements, value_shape=shape,
372395
reference_value_shape=reference_value_shape)
373396
self._family = sub_element.family()
374-
self._degree = degree
397+
self._degree = sub_element.degree()
375398
self._sub_element = sub_element
376399
self._shape = shape
377400
self._symmetry = symmetry
@@ -382,9 +405,8 @@ def __init__(self, family, cell, degree, shape=None,
382405
# Cache repr string
383406
qs = self.quadrature_scheme()
384407
quad_str = "" if qs is None else ", quad_scheme=%r" % (qs,)
385-
self._repr = ("TensorElement(%r, %r, %r, shape=%r, symmetry=%r%s)" %
386-
(self._family, self.cell(), self._degree, self._shape,
387-
self._symmetry, quad_str))
408+
self._repr = ("TensorElement(%r, shape=%r, symmetry=%r%s)" %
409+
(sub_element, self._shape, self._symmetry, quad_str))
388410

389411
def mapping(self):
390412
if self._symmetry:
@@ -435,64 +457,3 @@ def shortstr(self):
435457
sym = ""
436458
return "Tensor<%s x %s%s>" % (self.value_shape(),
437459
self._sub_element.shortstr(), sym)
438-
439-
440-
def _tensor_sub_elements(sub_element, shape, symmetry):
441-
# Set default shape if not specified
442-
if shape is None:
443-
ufl_assert(sub_element.cell() is not None,
444-
"Cannot infer tensor shape without a cell.")
445-
dim = sub_element.cell().geometric_dimension()
446-
shape = (dim, dim)
447-
448-
if symmetry is None:
449-
symmetry = EmptyDict
450-
elif symmetry is True:
451-
# Construct default symmetry dict for matrix elements
452-
ufl_assert(len(shape) == 2 and shape[0] == shape[1],
453-
"Cannot set automatic symmetry for non-square tensor.")
454-
symmetry = dict( ((i, j), (j, i)) for i in range(shape[0])
455-
for j in range(shape[1]) if i > j )
456-
else:
457-
ufl_assert(isinstance(symmetry, dict), "Expecting symmetry to be None (unset), True, or dict.")
458-
459-
# Validate indices in symmetry dict
460-
for i, j in iteritems(symmetry):
461-
ufl_assert(len(i) == len(j),
462-
"Non-matching length of symmetry index tuples.")
463-
for k in range(len(i)):
464-
ufl_assert(i[k] >= 0 and j[k] >= 0 and
465-
i[k] < shape[k] and j[k] < shape[k],
466-
"Symmetry dimensions out of bounds.")
467-
468-
# Compute all index combinations for given shape
469-
indices = compute_indices(shape)
470-
471-
# Compute mapping from indices to sub element number, accounting for symmetry
472-
sub_elements = []
473-
sub_element_mapping = {}
474-
for index in indices:
475-
if index in symmetry:
476-
continue
477-
sub_element_mapping[index] = len(sub_elements)
478-
sub_elements += [sub_element]
479-
480-
# Update mapping for symmetry
481-
for index in indices:
482-
if index in symmetry:
483-
sub_element_mapping[index] = sub_element_mapping[symmetry[index]]
484-
flattened_sub_element_mapping = [sub_element_mapping[index] for i, index in enumerate(indices)]
485-
486-
# Compute reference value shape based on symmetries
487-
if symmetry:
488-
# Flatten and subtract symmetries
489-
reference_value_shape = (product(shape)-len(symmetry),)
490-
mapping = "symmetries"
491-
else:
492-
# Do not flatten if there are no symmetries
493-
reference_value_shape = shape
494-
mapping = "identity"
495-
496-
497-
return shape, symmetry, sub_elements, sub_element_mapping, \
498-
flattened_sub_element_mapping, reference_value_shape, mapping

0 commit comments

Comments
 (0)