Poisson equation: imposed gradient BC?

Hi all,

I’m slowly transitioning from FEniCS to FEniCSx (although I’m also rusty in FEniCS!) and I’m struggling on a seemingly idiotic thing: how to properly define expression vectors to impose a gradient ?
I’m working on this tutorial, with Neumann BCs where the normal derivative is imposed. I want to tweak it to have a given gradient, and compute myself the dot product of the gradient and the outward normal vector.

So, instead of a weak form with g a known scalar function (normal derivative):

inner(g, v) * ds

I want to have a vector-valued g (the chosen gradient) and a weak form like this:

inner(dot(g, n), v) * ds

I defined my normal vector as n = ufl.CellNormal(x) (with x the SpatialCoordinate of the mesh) and I’m not sure how to define g. My current approach is to have a scalar function space (V) and a vector function space (W) to define the gradient, and then I do

g = fem.Function(W)
g.interpolate(lambda x: (2*x[0], 4*x[1]))  # f(x) = x² + 2y², so grad(f) = (2x, 4y)

Doing this leads to this error when the variational form is evaluated:

ERROR:UFL:What do you want cell normal in gdim=2, tdim=2 to be?
[long backtrace]

Any idea how to interpret this ?

Thanks a lot in advance!

This should be a FacetNormal, as a cell normal is only defined on manifolds.

Note that you can use the following approach:

x = ufl.SpatialCoordinate(mesh)
n = ufl.FacetNormal(mesh)
f = x[0]**2 + 2*x[1]**2
g = ufl.grad(f)
L =+ inner(dot(g, n), v) * ufl.ds

which would avoid interpolation.

2 Likes

Worked like a charm, thanks!
If I somehow doesn’t know the function whose gradient is used but only the gradient form, is my way idiomatic? In FEniCS I’d use a string with a C++ expression and the JIT compiler but from what I understood it’s not used anymore in DolfinX

You can simply use ufl.as_vector((expression_x, expression_y)) if you can express the gradient with spatial coordinates.

1 Like