Firstly, again, please enclose your code within triple fences (```
) so that others can run it.
I think you mean range(10, 101, 10)
or something of that sort to check the value of errors with varying mesh size (h
). Alternatively you may also use the inbuilt function errornorm
to calculate the error with respect to a reference solution (your composite expansion).
Since there is a boundary layer for this (singularly) perturbed equation at x=1, I expect that lagrange finite elements will converge poorly, you may see this by simply plotting your solution
from dolfin import *
import matplotlib.pyplot as plt
# Parameters of the problem
nx = 10
epsilon = 0.01
lmbda = 1
f = 1
fig, ax = plt.subplots(1,1,figsize=(8,8))
xvalues = np.linspace(0,1,301)
for nx in range(10, 1001, 201):
# Create mesh and define function space
mesh = UnitIntervalMesh(nx)
Q = FunctionSpace(mesh, 'P', 1)
# Define variational problem
u = TrialFunction(Q)
ue = Function(FunctionSpace(UnitIntervalMesh(nx), "P", 4))
ue.interpolate(Expression("(x[0]-((exp(x[0]/0.1)-1)/exp(1/0.1)-1))", degree=4))
v = TestFunction(Q)
w = Function(Q)
bord1 = CompiledSubDomain("near(x[0], 0)")
bord2 = CompiledSubDomain("near(x[0], 1)")
bcs = [
DirichletBC(Q, Constant(0), bord1),
DirichletBC(Q,Constant(0), bord2)
]
a = epsilon*inner(grad(u), grad(v))*dx + lmbda*inner(u.dx(0), v)*dx
f = Constant(1.)
solve(a==inner(f,v)*dx, w, bcs)
ax.plot(xvalues, np.array([w(x) for x in xvalues], float), label="nx={}".format(nx))
print("error with {} elements = {}".format(nx, errornorm(w, ue, mesh=mesh)/norm(ue, "l2")))
ax.legend(loc=0, ncol=3, fontsize=18)
and also some apriori error estimates and consequent strategies for improved approximation here