Open hiroe- opened 5 months ago
So this is an interesting bit of Python and numpy magic that is going on. If you multiply a numpy float by a container (think list, tuple, array etc) then numpy actually goes and does the vectorised thing and multiplies by each element to produce a new array. E.g. np.float64(0.1) * [1, 2, 3] == [0.1, 0.2, 0.3]
.
I was able to produce a minimal example showing that custom data types need to define __len__
and __getitem__
for this to happen:
import numpy as np
class MyContainer:
def __init__(self, data):
self._data = data
def __len__(self):
return len(self._data)
def __getitem__(self, index):
return self._data[index]
# Uncommenting this line prevents the behaviour
# __iter__ = None
myobj = MyContainer([1, 2, 3])
print(np.float64(0.1) * myobj) # prints [0.1, 0.2, 0.3]
print(0.1 * myobj) # errors
What is happening specifically here is that Functions
are iterable (i.e. you can write for indexed in my_function: ...
) and so multiplying by a numpy data type unpacks this and an array is passed through to assign
, which confuses it.
I think there are 3 solutions here:
assign
.assign
work with arrays.Functions
not be iterable (set __iter__
to None
).I prefer option 3 but that would require changes in UFL that might be breaking. I don't think that it makes sense for Functions
to be iterable.
@dham what is your opinion?
I get
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
when doingwhere
W
is a mixed function space:and
weights
is a list of float numbers. The full error message is below.The error disappears when using Constant() around weights[0]:
The relevant code is here at line 754:
https://github.com/colinjcotter/sketchpad/blob/a85a61b6b06c105d4f5aa3d45527893f94d910ce/averaging/disc_aver_sw_paradiag.py
To reproduce the error, get rid of Constant() from line 754 and run the code with
$ mpiexec -n 2 python disc_aver_sw_paradiag.py
Environment:
firedrake-status