Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion firedrake/solving.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,17 @@ def _assemble(f, tensor=None, bcs=None):

"""

kernels = compile_form(f, "form")
# We stash the form and kernels on the tensor if we reassemble for an
# existing tensor, to save having to compile the form again if identical
# Note that forms override == to construct an equation, so we have to
# explicitly test for object identity
if getattr(tensor, "_form", None) is f and hasattr(tensor, "_kernels"):
kernels = tensor._kernels
else:
kernels = compile_form(f, "form")
if tensor:
tensor._form = f
tensor._kernels = kernels

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this safe? I would have thought that we can use the same tensor to assemble a different form as long as the function spaces match. I think this means the following would fail:

v = TestFunction(V)

f = assemble(v*dx)

# do stuff with f

f = assemble(Constant(2)*v*dx, tensor=f)

Now the second time f is v_dx, not 2_v*dx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could check by:

if blah and form is tensor._form:
   ...

I think

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that exactly what I'm doing? Note that the check in line 389 is identical to this:

if hasattr(tensor, "_form") and hasattr(tensor, "_kernels") and tensor._form is f


fd = f.form_data()

Expand Down
23 changes: 23 additions & 0 deletions tests/regression/test_assemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ def test_zero_form(M, f, one):
assert isinstance(zero_form, float)
assert abs(zero_form - 0.5 * np.prod(f.shape())) < 1.0e-12


def test_assemble_with_tensor(cg1):
v = TestFunction(cg1)
L = v*dx
f = Function(cg1)
# Assemble a form into f
f = assemble(L, f)
# Assemble a different form into f
f = assemble(Constant(2)*L, f)
# Make sure we get the result of the last assembly
assert np.allclose(f.dat.data, 2*assemble(L).dat.data, rtol=1e-14)


def test_assemble_mat_with_tensor(dg0):
u = TestFunction(dg0)
v = TrialFunction(dg0)
a = u*v*dx
M = assemble(a)
# Assemble a different form into M
M = assemble(Constant(2)*a, M)
# Make sure we get the result of the last assembly
assert np.allclose(M.M.values, 2*assemble(a).M.values, rtol=1e-14)

if __name__ == '__main__':
import os
pytest.main(os.path.abspath(__file__))