This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Strange error dependence on mesh size

0 votes

I am trying to solve the following equation

$$ \nabla\cdot(\sigma(\nabla\boldsymbol{u} + I)) = 0 $$

on a unit square with $ \boldsymbol{u} $ periodic at the boundary and $I$ denoting the identity matrix. I used the method of manufactured solutions to check my code, so chose $\sigma = 1$ and $\boldsymbol{u} = (-\cos(2\pi y),-\sin(2\pi x))$. When comparing my solver with the exact solution, I find that the error varies strangely with mesh size, for example, if I choose a (32,32) mesh, my error is 0.0000204, but when I choose (64,64), my error is 0.002119. Interestingly, when I consider a mesh size of (256,256), the error is down to 0.000235.

Could anybody suggest why this might be? Thank you!

from dolfin import *

class PeriodicBoundary(SubDomain):

def inside(self, x, on_boundary):
    return bool((near(x[0], 0) or near(x[1], 0)) and 
            (not ((near(x[0], 0) and near(x[1], 1)) or 
                    (near(x[0], 1) and near(x[1], 0)))) and on_boundary)

def map(self, x, y):
    if near(x[0], 1) and near(x[1], 1):
        y[0] = x[0] - 1.
        y[1] = x[1] - 1.
    elif near(x[0], 1):
        y[0] = x[0] - 1.
        y[1] = x[1]
    else:  
        y[0] = x[0]
        y[1] = x[1] - 1.

k = 5
n = 2**k 
mesh = UnitSquareMesh(n,n)
V = VectorFunctionSpace(mesh, "CG", 1, constrained_domain = PeriodicBoundary())

u = TrialFunction(V)
v = TestFunction(V)
s = Expression("1.0")
uex = Expression(("-cos(2*DOLFIN_PI*x[1])","-sin(2*DOLFIN_PI*x[0])"), element=V.ufl_element())
t = Expression(("4*DOLFIN_PI*DOLFIN_PI*cos(2*DOLFIN_PI*x[1])","4*DOLFIN_PI*DOLFIN_PI*sin(2*DOLFIN_PI*x[0])"), element = V.ufl_element())
a = -s*inner(grad(u), grad(v))*dx
L = +s*div(v)*dx + inner(t, v)*dx

u = Function(V)
problem = LinearVariationalProblem(a, L, u, bcs=[])
solver = LinearVariationalSolver(problem) 
solver.parameters["linear_solver"] = "gmres"
solver.parameters["preconditioner"] = "hypre_amg"
solver.parameters["krylov_solver"]["monitor_convergence"] = False
solver.parameters["krylov_solver"]["relative_tolerance"] = 1e-10

solver.solve()
file = File("periodic_trial_%i.pvd" % k)
file << u
file2 = File("periodic_exact.pvd")
u_exact =interpolate(uex, V) 
file2 << u_exact
print "error %f" % assemble(inner(u-u_exact, u-u_exact) * dx)
asked Nov 10, 2016 by caoimherooney FEniCS Novice (120 points)

edit: This "answer" completely missed the point...

The error between your computed solution and the exact one will be bounded above by some constant times the "best approximation error" (see e.g. Cea's lemma). One typically bounds the latter by the error made by an interpolation operator, which in turn is bounded above by the norm of the solution times some power of the grid size. You can check any book on finite element methods for more info (e.g. Grossman, Roos, Stynes, §4.4 and §3.3 for the conforming case).

The finer your grid, the smaller its size, the better the interpolation becomes and consequently your solution.

Hi mdbenito, thank you for getting back to me! I'm not quite sure that you've answered my question. As far as I understand, the theory predicts that the error should quarter as we half the mesh size, so I'm confused that the error increases by a factor of 100 as we go from (32,32) to (64,64).

Ooops! I read your numbers the other way around, sorry for lecturing you... I must say that I don't understand why the error jumps like that. Also, while I was trying to understand it I came up with another question ;) Why do I get terrible error values when I change your s=Expression('1.0') to a s=Constant(1.0) ?

edit: Ah, I see that using Constant(...) is like setting Expression(..., degree=0)

Anyway, sorry for the noise...

...