Tensor contraction function is broken

Issue #111 new
Grant Bruer created an issue

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)

Comments (0)

  1. Log in to comment