1
# This demo program calculates the electrostatic potential
2
# in the unit square by solving Laplace's equation
4
# div \epsilon_r grad u(x, y) = 0
6
# The lower half is filled with a dielectric material
7
# with dielectric constant \epsilon_r.
9
# The boundary conditions are:
11
# u(x, y) = 0 for y > 0
12
# u(x,y) = V for y = 0
14
__author__ = "Kristen Kaasbjerg (cosby@fys.ku.dk)"
15
__date__ = "2008-02-14 -- 2008-12-13"
17
__license__ = "GNU LGPL Version 2.1"
19
# Modified by Kristian Oelgaard 2008
23
l = 1.0; h = 1.0 # unit square
24
h_ = 0.5 # position of the dielectric interface
25
e_r = 10 # dielectric constant for y<h_ (e_r=1 for y>h_
26
V = 1.0 # applied voltage at the y=0 boundary
28
# Create mesh and finite element
31
editor.open(mesh, "triangle", 2, 2)
32
editor.initVertices(4)
34
editor.addVertex(0, 0.0, 0.0)
35
editor.addVertex(1, 0.0, h)
36
editor.addVertex(2, l, h)
37
editor.addVertex(3, l,0)
38
editor.addCell(0, 0, 1, 2)
39
editor.addCell(1, 0, 2, 3)
43
for refine in range(4):
47
V2 = FunctionSpace(mesh, "CG", 2) # last argument: order of the polynomial
49
# Discontinuous element needed for the dielectric function
50
V0 = FunctionSpace(mesh, "DG", 0) # 0'th order are possible for DG elements
53
class Exact(Function):
54
def eval(self, values, x):
56
N = 20 # N needs to be rather large (~200) in other to have u=V for y=0 !
61
X = (1.-exp(2*n_*pi*(1-h_)))/(1+exp(2*n_*pi*(1-h_)))
62
u -= sin(n_*pi*x[0])*4*V/(pi*n_) * ( (1+e_r*X)*exp(n_*pi*(x[1]-h_))+
63
(-1.+e_r*X)*exp(-n_*pi*(x[1]-h_)) ) /\
64
( (1.-e_r*X)*exp(n_*pi*h_) -
65
(1.+e_r*X)*exp(-n_*pi*h_))
69
X = (1.-exp(2*n_*pi*(1-h_)))/(1+exp(2*n_*pi*(1-h_)))
70
X1 = 1./(1+exp(2*n_*pi*(1-h_)))
71
X2 = exp(2*n_*pi*(1-h_))/(1+exp(2*n_*pi*(1-h_)))
72
u += sin(n_*pi*x[0])*4*V/(pi*n_) * ( 2*e_r*X1*exp(n_*pi*(x[1]-h_)) -
73
2*e_r*X2*exp(-n_*pi*(x[1]-h_))) /\
74
( (1.+e_r*X)*exp(-n_*pi*h_) -
75
(1.-e_r*X)*exp(n_*pi*h_) )
79
class Coefficient(Function):
80
def eval(self, values, x):
86
# Dirichlet boundary condition
87
class DirichletFunction(Function):
88
def eval(self, values, x):
94
# Sub domain for Dirichlet boundary condition
95
class DirichletBoundary(SubDomain):
96
def inside(self, x, on_boundary):
97
return on_boundary and True
99
# Define variational problem
101
u = TrialFunction(V2)
102
f = Constant(mesh, 0)
104
a = b*dot(grad(v), grad(u))*dx
107
# Define boundary condition
108
u0 = DirichletFunction(V2)
109
bc = DirichletBC(V2, u0, DirichletBoundary())
111
# Solve PDE and plot solution
112
problem = VariationalProblem(a, L, bc)
117
# Calculate difference between exact and FEM solution
118
# Use higher order element for exact solution,
119
# because it is an interpolation of the exact solution
120
# in the finite element space!
121
Pk = FunctionSpace(mesh, "CG", 5)
126
norm = sqrt(assemble(L2_norm))
128
print "L2-norm of error is: ", norm