UserExpression instantiated inside Python function does not work if the Python function returns only DirichletBC
Issue #1070
new
When instantiating a UserExpression inside a Python function in order to create a DirichletBC, if the Python function returns only the prepared DirichletBC, the code gives the error:
*** Error: Unable to evaluate expression.
*** Reason: Missing eval() function (must be overloaded).
*** Where: This error was encountered inside Expression.cpp.
If the Python function also returns the UserExpression, the code simply works. Below, follows a minimal example based on the FEniCS example for solving the Poisson equation. The code does not work if test_mode is set as 1, but works if test_mode is set as 2. Apparently, in the case it does not work, the code loses the reference count of the UserExpression.
from dolfin import *
test_mode = 1
# 1 = Does not work
# 2 = Works
print("Create mesh and define function space")
mesh = UnitSquareMesh(32, 32)
V = FunctionSpace(mesh, "Lagrange", 1)
print("Define boundary condition")
class BoundaryValues(UserExpression):
def eval(self, values, x):
values[0] = 0.0
l = 1.0/6.0
gbar = 100.0
if near(x[0], 0.0) or near(x[0], 1.0):
if 0.0 < x[1] < 0.20:
values[0] = 1.0
elif 0.30 < x[1] < 1.0:
values[0] = -1.0
else:
values[0] = 0.0
def value_shape(self):
return ()
def get_bcs():
print("get_bcs")
bv_expression = BoundaryValues(degree = 2)
bc = DirichletBC(V, bv_expression, "on_boundary")
bcs = [bc]
if test_mode == 1:
return bcs
else:
return bcs, bv_expression
if test_mode == 1:
bcs = get_bcs()
else:
bcs, bv_expression = get_bcs()
print("Define variational problem")
u = TrialFunction(V)
v = TestFunction(V)
f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)", degree = 2)
a = inner(grad(u), grad(v))*dx
L = f*v*dx
print("Compute solution")
u = Function(V)
solve(a == L, u, bcs)
A. Thank you, I was running into this problem.
B. Even this only somewhat solves the issue. If you have more complicated code, save the “bv_expression” variable as a class variable to some class you are actively using otherwise the python GC will eat up you “bv_expression”. (This happened to me)