Neumann Boundary Condition on Subdomains

Hello, everyone

I am trying to get \chi_1 in the problem below with Neumann Boundary Condition. And I wish the Neumann Boundary Condition is defined on the edges, where \chi_1[0] = -1, \chi_1[0] = 1, \chi_1[1] = -1, \chi_1[1] = 1.


So I wrote the following code:

from dolfin import *
from mshr import *

mesh = RectangleMesh.create([Point(-1,-1), Point(1, 1)],[10, 10],CellType.Type.quadrilateral)

tol = -1E-1
subdomains = MeshFunction("size_t", mesh, 2)
class Omega_0(SubDomain):
    def inside(self, x, on_boundary):
        return True if x[1] <= tol else False
class Omega_1(SubDomain):
    def inside(self, x, on_boundary):
        return True if x[1] >= tol else False
subdomain_0 = Omega_0()
subdomain_1 = Omega_1()
subdomain_0.mark(subdomains, 0)
subdomain_1.mark(subdomains, 1)

V0 = FunctionSpace(mesh,"DG",0)
k = Function(V0)
kvalues = [2, 8] # values of k in the two subdomains
for cell in range(len(subdomains.array())):
    subdomain_cell = subdomains.array()[cell]
    k.vector()[cell] = kvalues[subdomain_cell]

class LeftBoundary(SubDomain):
    def inside(self,x,on_boundary):
        return on_boundary and near(x[0], -1)
class RightBoundary(SubDomain):
    def inside(self,x,on_boundary):
        return on_boundary and near(x[0], 1)    
class TopBoundary(SubDomain):
    def inside(self,x,on_boundary):
        return on_boundary and near(x[1], 1)
class BottomBoundary(SubDomain):
    def inside(self,x,on_boundary):
        return on_boundary and near(x[1], -1)
left_bc = LeftBoundary()
right_bc = RightBoundary()
top_bc = TopBoundary()
bottom_bc = BottomBoundary()

Ve = FiniteElement('Lagrange', mesh.ufl_cell(), 1)  
Re = FiniteElement('Real', mesh.ufl_cell(), 0)
X = FunctionSpace(mesh, MixedElement([Ve, Re]))
dx = Measure('dx', subdomain_data=subdomains)
n = FacetNormal(mesh)
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
dS = Measure('dS', domain=mesh, subdomain_data=boundaries)
bottom_bc.mark(boundaries,1)
right_bc.mark(boundaries,2)
top_bc.mark(boundaries,3)
left_bc.mark(boundaries,4)

u, m = TrialFunctions(X)
v, r = TestFunctions(X)
F1 = inner(nabla_grad(u) + Constant((1,0)), k*nabla_grad(v))*dx + u*r*dx + m*v*dx
- inner(Constant((1,0)),n('-'))*v*dS(1) - inner(Constant((1,0)),n('-'))*v*dS(2)
- inner(Constant((1,0)),n('-'))*v*dS(3) - inner(Constant((1,0)),n('-'))*v*dS(4)
a1, l1 = lhs(F1), rhs(F1)

x = Function(X)
solve(a1 == l1, x)
uh_x, mh_x = x.split()
File("uh_x.pvd") << uh_x

But the result seems like unreasonable. I am wondering what is the problem in this code. And I also tried to print the code below but got 0.

print(assemble(inner(Constant((1,0)),n('-'))*dS(1) + inner(Constant((1,0)),n('-'))*dS(2) 
               + inner(Constant((1,0)),n('-'))*dS(3) + inner(Constant((1,0)),n('-'))*dS(4)
               + Constant(0)*dx(domain=mesh, subdomain_data=subdomains)))

Is there someone who might be able to help me with this? I would appreciate it.

dS are interior facets. If you want the integral of all exterior facets, you should use Measure("ds",…)

I replaced all ‘dS’ by ‘ds’. But the results have no changes.

And it is also strange for me that the number of mesh vertices is not equal to the length of u_array (larger than mesh.num_vertices() by 1).

To check the result I printed assemble(dot(k*(grad(uh_x)+Constant((1,0))), n)*ds(2)). I expected to get the result 1 but got -3.305997451106021e-15.

Thank you for any feed back.

Ve = FiniteElement('Lagrange', mesh.ufl_cell(), 1)  
Re = FiniteElement('Real', mesh.ufl_cell(), 0)
X = FunctionSpace(mesh, MixedElement([Ve, Re]))
dx = Measure('dx', subdomain_data=subdomains)
n = FacetNormal(mesh)
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
bottom_bc.mark(boundaries,1)
right_bc.mark(boundaries,2)
top_bc.mark(boundaries,3)
left_bc.mark(boundaries,4)

u, m = TrialFunctions(X)
v, r = TestFunctions(X)
F1 = inner(nabla_grad(u) + Constant((1,0)), k*nabla_grad(v))*dx + u*r*dx + m*v*dx
- inner(Constant((1,0)),n)*v*ds(1) - inner(Constant((1,0)),n)*v*ds(2)
- inner(Constant((1,0)),n)*v*ds(3) - inner(Constant((1,0)),n)*v*ds(4)
a1, l1 = lhs(F1), rhs(F1)

x = Function(X)
solve(a1 == l1, x)
uh_x, mh_x = x.split()
u_array = uh_x.vector().get_local()
print(mesh.num_vertices()) 
print(len(u_array))

test = assemble(dot(k*(grad(uh_x)+Constant((1,0))), n)*ds(2))
print(test)

Calling split without deepcopy=True does not break the vector into two pieces (i.e. it has all dofs): Bitbucket

Could you start by calling

print(assemble(1*ds(2))

and check that it gives you the surface area of your boundary?

Thanks for your quick reply.

yes, I got
1.9999999999999996
when I run

print(assemble(1*ds(2))

I think maybe the way I calculate uh_x is wrong, but I couldn’t find the bugs.

Start by making sure that assemble(k*ds(2)) makes sense, and work your way through the terms (i.e. check that uh_x looks like expected). As your code is fragmented over many posts, its hard to give further guidance. Please consider making a new post with the complete code as it is on your computer now.