Tensor contraction function is broken
Issue #111
new
The contraction
function doesn't work because it tries to modify a tuple.
MWE:
from ufl import FiniteElement, Coefficient, grad, triangle
from ufl.operators import contraction
element = FiniteElement("CG", triangle, 1)
w = Coefficient(element)
con = contraction(grad(w), [0], grad(w), [0])
Output:
Traceback (most recent call last):
File "ctest.py", line 7, in <module>
mag = contraction(grad(w), [0], grad(w), [0])
File "/home/gbruer/anaconda3/envs/latest/lib/python3.7/site-packages/ufl/operators.py", line 202, in contraction
aii[j] = cii[i]
TypeError: 'tuple' object does not support item assignment
I think this can be fixed in the contraction function in ufl/operators.py just by casting the return value of indices()
to a list, and then converting it back to a tuple when necessary.
def contraction(a, a_axes, b, b_axes):
"UFL operator: Take the contraction of a and b over given axes."
ai, bi = a_axes, b_axes
if len(ai) != len(bi):
error("Contraction must be over the same number of axes.")
ash = a.ufl_shape
bsh = b.ufl_shape
aii = list(indices(len(a.ufl_shape))) ######### Convert tuple to list
bii = list(indices(len(b.ufl_shape))) ######### Convert tuple to list
cii = indices(len(ai))
shape = [None] * len(ai)
for i, j in enumerate(ai):
aii[j] = cii[i]
shape[i] = ash[j]
for i, j in enumerate(bi):
bii[j] = cii[i]
if shape[i] != bsh[j]:
error("Shape mismatch in contraction.")
aii = tuple(aii) ######### Convert list back to tuple
bii = tuple(bii) ######### Convert list back to tuple
s = a[aii] * b[bii]
cii = set(cii)
ii = tuple(i for i in (aii + bii) if i not in cii)
return as_tensor(s, ii)