Hello all,
I hope someone can help me out with the following problem I am having. I am recently quite new to finite elements and Fenics is my first open-source solver. I have been looking through tutorials and done a lot of research online.
My aim is: Solve the diffusion equation D div(grad(u)) = du/dt on a domain that has two different D values (D1,D2). There is a large 2D squared domain (we will call it DOMAIN 1) and then a lot of polygons inside this 2D squared domain which we will refer to DOMAIN 2. DOMAIN 1 has diffusivitiy value D1 and DOMAIN 2 has diffusviity value D2.
My code works fine solving the temporal diffusion equation without any interface boundary condition between the two domains. Here is a brief of the code.
I want to add now a interface boundary condition that should set D dU/dX(‘+) = kappa*(u(’+‘) - u(’-')) . The interface boundary should set the flux based on the jump variation in the normal direction.
I am imposing the interface condition in the variational form but seems to not be working. Apart from that, it seems that the Dirichlet condition is also not applied. I have checked my boundary markers plotting and they seem fine. Does anyone have any idea?
V = FunctionSpace(mesh, 'CG', 1)
u = TrialFunction(V)
v = TestFunction(V)
D_intra = Constant(1.)
D_extra = Constant(2.5)
diffusivity = Function(V)
diffusivity_expression = DiffusivityExpression(triangle_domains, 1., 2.5, degree=1)
diffusivity.interpolate(diffusivity_expression)
bc = DirichletBC(V, Constant(0), boundary_markers, 4)
u0 = Expression('x[0] >= -2. && x[0] <= 2. && x[1] >= -2. && x[1] <=2. ? 1.0 : 0.0', degree=1)
u_n = Function(V)
u_n.interpolate(u0)
# Normalize so that the integral over the domain is 1
u_n.vector()[:] /= assemble(u_n*dx)
# Define time-stepping parameters
T = 500
dt = Constant(.25)
f = Constant(0.)
kappa = Constant(0.01)
n = FacetNormal(mesh)
n_2d = as_vector([n[0], n[1]]) # Project normal onto z=0 plane
# Define variational form
dS_internal = Measure('dS', domain=mesh, subdomain_data=facet_domains, subdomain_id=6)
D = Constant(2.)
un_plus_normal = dot(grad(u('+')), n_2d('+'))
un_minus_normal = dot(grad(u('-')), n_2d('-'))
# Incorporate spatially varying diffusivity and boundary conditions
F = dt * (diffusivity * dot(grad(u), grad(v)) * dx - kappa * (un_plus_normal - un_minus_normal) * jump(v) * dS_internal) + u * v * dx - u_n * v * dx
a,L = lhs(F), rhs(F)
output_file = XDMFFile(comm, "output.xdmf")
output_file.parameters["flush_output"] = True
output_file.parameters["functions_share_mesh"] = True
output_file.write(u_n, 0.0)
# Define linear solver
solver = PETScKrylovSolver()
#solver.parameters.update(solver_parameters)
# Time loop
t = 0
step = 0
u = Function(V)
dtss=0.25
while t <= T:
t += dtss
step += 1
A, b = assemble_system(a, L, bc)
# Solve linear system
solver.solve(A, u.vector(), b)
# Update solution at previous time step
u_n.assign(u)
# Write solution to file
output_file.write(u_n, t)
With class
class BoundaryConditionExpressionBetweenDomains(UserExpression):
def __init__(self, cell_domains, kappa, **kwargs):
super().__init__(**kwargs)
self.cell_domains = cell_domains
self.kappa = kappa
def eval_cell(self, values, x, cell):
if self.cell_domains[cell.index] == 1:
values[0] = self.kappa * (1/2.5) # your boundary condition for subdomain 1
elif self.cell_domains[cell.index] == 2:
values[0] = self.kappa * (1) # your boundary condition for subdomain 2
else:
raise RuntimeError("This cell does not have a subdomain attributed to it")