When solving a PDE on a submesh \Omega_0\subset\Omega of a given mesh \Omega, how do I apply boundary conditions to the PDE?
I'm able to correctly extract the submesh and set up the FunctionSpaces
. I suppose it's something about the Measure
s that I'm missing here.
The following code tries to setup the solution of Poisson's equation on \Omega_1 = {(x,y)\in(0,1)^2: x<0.5}\subset \Omega = (0,1)^2. On the left boundary of \Omega_1, I'd like to enforce n\cdot\nabla u = \alpha (u_0 - u) with some given \alpha, u_0\in\mathbb{R}.
Dolfin solves something, but the suggested solution just looks funky.
from dolfin import *
mesh = UnitSquareMesh(20, 20, 'left/right')
class OmegaLeft(SubDomain):
def inside(self, x, on_boundary):
return x[0] <= 0.5
omegaL = OmegaLeft()
subdomains = CellFunction('size_t', mesh)
subdomains.set_all(0)
omegaL.mark(subdomains, 1)
dx = Measure('dx')[subdomains]
submesh_omegaL = SubMesh(mesh, subdomains, 1)
class LeftBoundary(SubDomain):
def inside(self, x, on_boundary):
return on_boundary and abs(x[0]) < DOLFIN_EPS
left_boundary = LeftBoundary()
omegaL_boundaries = FacetFunction('size_t', submesh_omegaL)
omegaL_boundaries.set_all(0)
left_boundary.mark(omegaL_boundaries, 1)
ds_omegaL = Measure('ds')[omegaL_boundaries]
f = Constant(0.0)
V = FunctionSpace(submesh_omegaL, 'CG', 1)
u = TrialFunction(V)
v = TestFunction(V)
alpha = 1.0
u0 = 0.421
F = dot(grad(u), grad(v)) * dx(1) \
- alpha * (u0-u) * v * ds_omegaL(1) \
- f * v * dx(1)
a = lhs(F)
L = rhs(F)
sol = Function(V)
solve(a == L, sol)
plot(sol)
interactive()
Even simpler, when only applying Dirichlet boundary conditions, e.g.,
from dolfin import *
mesh = UnitSquareMesh(4, 4, 'left/right')
class OmegaLeft(SubDomain):
def inside(self, x, on_boundary):
return x[0] <= 0.5
omegaL = OmegaLeft()
subdomains = CellFunction('size_t', mesh)
subdomains.set_all(0)
omegaL.mark(subdomains, 1)
dx = Measure('dx')[subdomains]
submesh_omegaL = SubMesh(mesh, subdomains, 1)
class LeftBoundary(SubDomain):
def inside(self, x, on_boundary):
return on_boundary and abs(x[0]) < DOLFIN_EPS
left_boundary = LeftBoundary()
f = Constant(0.0)
V = FunctionSpace(submesh_omegaL, 'CG', 1)
u = TrialFunction(V)
v = TestFunction(V)
F = dot(grad(u), grad(v)) * dx(1) \
- f * v * dx(1)
bcs = DirichletBC(V, 0.421, 'on_boundary')
a = lhs(F)
L = rhs(F)
sol = Function(V)
solve(a == L, sol, bcs=bcs)
plot(sol)
interactive()
one gets
*** Error: Unable to set given rows to identity matrix.
*** Reason: some diagonal elements not preallocated (try assembler option keep_diagonal).
*** Where: This error was encountered inside PETScMatrix.cpp.