Hello
I am trying to solve two coupled equations (Nernst-Planck and Poisson) for a simple domain. First of all I would like to explain my equations and boundary conditions. The equations are:
For the above equations c and phi are the unknowns corresponding to the concentration and electrical potential respectively. In addition, epsilon is constant = 0.0082
The domain is a square as shown below:
The Dirichlet boundary condition should be applied on the top and the bottom boundaries:
For both unknowns, zero Neumann boundary condition should be applied on all of the boundaries.
In order to derive the weak form of the Eq.1 we can multiply the Eq.1 by a test function (v_1) :
After integration by parts and applying zero Neumann boundary conditions:
After discretizing the first term in the Eq.4:
The c_0 in the above equation corresponds to the solution in the previous time step.Finally the weak form of the Eq.1 can be derived as:
We can derive the weak form of the Eq.2 easily by multiplying it by another test function (v_2):
After integration by parts (and considering zero Neumann B.C) the weak form of the Eq.2 can be derived as:
The weak form of the whole system is obtained by summing up the Eq.6 and Eq.8:
As far as I know, I should use a mixed function space for the two unknowns in this problem (c & phi). I have implemented it in a code but I am getting an error. This is my complete code:
from dolfin import *
import mshr
# Define boundaries
class Left(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 0.0)
class Right(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 1.0)
class Bottom(SubDomain):
def inside(self, x, on_boundary):
return near(x[1], 0.0)
class Top(SubDomain):
def inside(self, x, on_boundary):
return near(x[1], 1.0)
# Initialize sub-domain instances
left = Left()
top = Top()
right = Right()
bottom = Bottom()
# Domain
domain = mshr.Rectangle(Point(0,0), Point(1,1))
# Mesh
mesh = mshr.generate_mesh(domain, 20)
# Marking boundary domains
boundaries = FacetFunction("size_t", mesh)
boundaries.set_all(0)
left.mark(boundaries, 2)
top.mark(boundaries, 1)
right.mark(boundaries, 4)
bottom.mark(boundaries, 3)
#Defining the function spaces for the concentration
V_c = FunctionSpace(mesh, 'CG', 1)
#Defining the function spaces for the voltage
V_phi = FunctionSpace(mesh, 'CG', 1)
#Defining the mixed function space
W = MixedFunctionSpace((V_c, V_phi))
#Defining the Trial functions
(c, phi) = TrialFunctions(W)
#Defining the test functions
(v_1, v_2) = TestFunctions(W)
# Time variables
dt = 0.05; t = 0; T = 1.1
# Previous solution
W_const = Constant((1200))
C_previous= interpolate(W_const, V_c)
# Define Dirichlet boundary conditions at top boundary (V=4.0 volt)
Voltage = Constant((4.0))
bc_top = DirichletBC(W.sub(1), Voltage, 1)
# Define Dirichlet boundary conditions at bottom boundary (V=0.0 volt)
bc_bottom = DirichletBC(W.sub(1), 0.0, 3)
#Collecting the boundary conditions
bcs = [bc_top, bc_bottom]
#Define eps in the weak form
eps=0.0082
# Define variational form
a = dot(grad(phi),grad(v_2))*dx - (1./(2*(pow(eps,2))))*c*v_2*dx\
+ (1./(2*(pow(eps,2))))*v_2*dx+c*v_1*dx\
+dt *eps*dot(grad(c),grad(v_1))*dx\
+dt*eps*c*dot(grad(phi),grad(v_1))*dx
L = C_previous*v_1*dx
u = Function(W)
while t <= T:
A, b = assemble_system(a, L, bcs)
solve(A, u.vector(), b)
(c, phi) = u.split()
C_previous.assign(c)
t += dt
plot(c, interactive=False)
This is the error I get:
#line 87, in <module>
A, b = assemble_system(a, L, bcs)
I think there is something wrong in the defining the variational form that should be exactly the Eq.9. In addition to that I am not sure about this line:
solve(A, u.vector(), b)
As you can see in the code, finally I want to split the mixed space and for example plot the concentration (c) over the time.
Could you please help get this code to work? Thanks in advance for your time.