The minimum working code example is based on the ft03_heat.py tutorial, which describes a time dependent poisson equation and is governed by the following equations:
u′=Δu+f in the unit square
u=u_D on the boundary (Dirichlet boundary conditions)
u=u_0 at t = 0
I implemented u for t=0 by the following UserExpression instead of using an Expression like
u_D = Expression(‘1 + x[0]x[0] + alphax[1]x[1] + betat’, degree=2, alpha=alpha, beta=beta, t=0),
like it’s used in the tutorial:
# define u for t=0
class MyExpression_t0(UserExpression):
def eval(self, value, x):
x = SpatialCoordinate(mesh)
tol = 1E-14
# u on left boundary
if x[0] < tol:
u = Constant(2.5)
# u on left domain
elif x[0] > 0 and x[0] <= 0.1:
u = Constant(0.5)
# u for the rest of the domain and boundaries
else:
u = 0
return u
u_n = MyExpression_t0()
Unfortunately, I get the following error message:
WARNING: user expression has not supplied value_shape method or an element. Assuming scalar element.
UFL conditions cannot be evaluated as bool in a Python context.
Traceback (most recent call last):
File "ft03_heat_u0.py", line 38, in <module>
u_n = interpolate(u_D, V)
File "/usr/local/lib/python3.6/dist-packages/dolfin/fem/interpolation.py", line 71, in interpolate
Pv.interpolate(v._cpp_object)
File "/usr/local/lib/python3.6/dist-packages/dolfin/function/function.py", line 365, in interpolate
self._cpp_object.interpolate(u)
File "/usr/local/lib/python3.6/dist-packages/dolfin/function/expression.py", line 53, in wrapped_eval
self.user_expression.eval(values, x)
File "ft03_heat_u0.py", line 20, in eval
if x[0] < tol:
File "/usr/local/lib/python3.6/dist-packages/ufl/conditional.py", line 46, in __bool__
error("UFL conditions cannot be evaluated as bool in a Python context.")
File "/usr/local/lib/python3.6/dist-packages/ufl/log.py", line 172, in error
raise self._exception_type(self._format_raw(*message))
ufl.log.UFLException: UFL conditions cannot be evaluated as bool in a Python context.
How am I able to fix this? Of course, the use of an UserExpression isn´t mandatory. It was just what I came up with.
Here is the full MWCE:
from fenics import *
T = 2.0 # final time
num_steps = 10 # number of time steps
dt = T / num_steps # time step size
alpha = 3 # parameter alpha
beta = 1.2 # parameter beta
# Create mesh and define function space
nx = ny = 8
mesh = UnitSquareMesh(nx, ny)
V = FunctionSpace(mesh, 'P', 1)
# define u for t=0
class MyExpression_t0(UserExpression):
def eval(self, value, x):
x = SpatialCoordinate(mesh)
tol = 1E-14
# u on left boundary
if x[0] < tol:
u = Constant(2.5)
# u on left domain
elif x[0] > 0 and x[0] <= 0.1:
u = Constant(0.5)
# u for the rest of the domain and boundaries
else:
u = 0
return u
u_D = MyExpression_t0()
def boundary(x, on_boundary):
return on_boundary
bc = DirichletBC(V, u_D, boundary)
# Define initial value
u_n = interpolate(u_D, V)
# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(beta - 2 - 2*alpha)
F = u*v*dx + dt*dot(grad(u), grad(v))*dx - (u_n + dt*f)*v*dx
a, L = lhs(F), rhs(F)
# Time-stepping
u = Function(V)
t = 0
for n in range(num_steps):
# Update current time
t += dt
# Compute solution
solve(a == L, u, bc)
# Update previous solution
u_n.assign(u)
# Hold plot
interactive()