This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Neumann boundary condition defined by varying function.

+3 votes

In a domain-decomposition context, I wish to define a Neumann boundary condition with a boundary function which itself comes from the solution of another problem. This boundary function is thus unknown at program start.
My problem boils down to the minimal square example below, with Dirichlet BC everywhere except on the right side.
I define a function ("u_b") on this right side (with constant value to make things simple here), using BoundaryMesh :

bmesh = BoundaryMesh(mesh, 'exterior') 
V_b = FunctionSpace(bmesh, 'Lagrange', 1)
u_b = Function(V_b); u_b.assign(Constant(3.0))

The problem is that I can't use this "u_b" in the "L" expression of the variational problem - see the full minimal example below.
Could you please help me with this? Thanks a lot.
Serge

from dolfin import *
mesh = UnitSquareMesh(10, 10)
V = FunctionSpace(mesh, 'Lagrange', 1)

class DirichletBoundary(SubDomain):
    def inside(self, x, on_boundary):
        tol = 1E-14
        return on_boundary and ((abs(x[1] - 1) < tol) or (abs(x[0] - 0) < tol) or (abs(x[1] - 0) < tol))
D_boundary = DirichletBoundary()
bc_D = DirichletBC(V, Constant(0.0), D_boundary)

class RightBoundary(SubDomain):
    def inside(self, x, on_boundary):
        tol = 1E-14
        return on_boundary and (abs(x[0] - 1) < tol)
rightBoundary = RightBoundary()

boundaries = FacetFunction("size_t", mesh)
rightBoundary.mark(boundaries, 1)
dsR = ds(subdomain_id=1, subdomain_data=boundaries)

u = TrialFunction(V)
v = TestFunction(V)
a = inner(grad(u), grad(v))*dx
f = Constant(1.)

u = Function(V)

bmesh = BoundaryMesh(mesh, 'exterior') 
V_b = FunctionSpace(bmesh, 'Lagrange', 1)

#u_b = Constant(3.0) #OK
#u_b = Expression("3.0") #OK
#u_b = Function(V); u_b.assign(Constant(3.0)) # OK
u_b = Function(V_b); u_b.assign(Constant(3.0)) # NOT OK

L = f*v*dx + u_b*v*dsR
solve(a == L, u, bc_D)
asked Jan 6, 2015 by svancri FEniCS Novice (210 points)

1 Answer

+1 vote

We don't yet support function spaces on 'sub-meshes'. In your case, you can just define
the space V_b on the entire mesh.

answered Jan 7, 2015 by Garth N. Wells FEniCS Expert (35,930 points)

Thanks much Garth for this answer.
To go a bit further, note that I in fact wish to use a function defined in an adjacent mesh to define a Neumann BC.
Since it is not yet possible to use functions defined on a sub-mesh (BoundaryMesh here), I try to use directly the function defined in the adjacent mesh:

mesh = RectangleMesh(0., 0, 1., 1, N, N)
mesh_adjacent = RectangleMesh(1., 0, 2., 1, N, N)
V_adjacent = FunctionSpace(mesh_adjacent, 'Lagrange', 1)
u_adjacent = Function(V_adjacent)
u_adjacent.assign(Constant(3.0))

I wish to use this "u_adjacent" in the "L" expression of the variational problem defined on "mesh".
Unsurprisingly, this does not work with the naive minimal implementation below.
Somehow one must tell FEniCS that the right boundary of "mesh" coincides with the left boundary of "mesh_adjacent".
If anybody has a hint - maybe in attacking this problem in a totally different manner - please let me know.
Thank you again Garth anyway.
Serge

from dolfin import *
import numpy as np

N = 10
mesh = RectangleMesh(0., 0, 1., 1, N, N)
mesh_adjacent = RectangleMesh(1., 0, 2., 1, N, N)
V = FunctionSpace(mesh, 'Lagrange', 1)
V_adjacent = FunctionSpace(mesh_adjacent, 'Lagrange', 1)

class DirichletBoundary(SubDomain):
    def inside(self, x, on_boundary):
        tol = 1E-14
        return on_boundary and ((abs(x[1] - 1) < tol) or (abs(x[0] - 0) < tol) or (abs(x[1] - 0) < tol))
D_boundary = DirichletBoundary()
bc_D = DirichletBC(V, Constant(0.0), D_boundary)

class RightBoundary(SubDomain):
    def inside(self, x, on_boundary):
        tol = 1E-14
        return on_boundary and (abs(x[0] - 1) < tol)
rightBoundary = RightBoundary()

boundaries = FacetFunction("size_t", mesh)
rightBoundary.mark(boundaries, 1)
dsR = ds(subdomain_id=1, subdomain_data=boundaries)

u = TrialFunction(V)
v = TestFunction(V)
a = inner(grad(u), grad(v))*dx
f = Constant(1.)

u = Function(V)

u_adjacent = Function(V_adjacent)
u_adjacent.assign(Constant(3.0))

L = f*v*dx + u_adjacent*v*dsR
solve(a == L, u, bc_D)
...