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

Computing error between Function and Expression

+2 votes

I would like to calculate the error in some approximated Function compared to an exact solution. When defining an Expression to represent an exact solution, the keyword degree can be set. However, once the Expression has been constructed, I can't find a way to set it...

Take for example:

from dolfin import *
parameters["krylov_solver"]["relative_tolerance"] = 1e-15

mesh = UnitSquareMesh(1,1)
V = FunctionSpace(mesh, "CG", 1) # Linear space

# Do not set degree
exact = Expression(("x[0]*x[0]")) # Quadratic function
approx = interpolate(exact, V)
print assemble(inner(approx-exact,approx-exact)*dx) # Understandable that this is zero

# Set degree in construction
exact = Expression(("x[0]*x[0]"), degree=2) 
print assemble(inner(approx-exact,approx-exact)*dx) # Expect this to to be 1/60

# Set degree after construction...
exact = Expression(("x[0]*x[0]"))
exact.degree = 2 # Would be nice if this works
print assemble(inner(approx-exact,approx-exact)*dx) # Is zero, should be 1/60?

Basically, I want to know the "best practice" on computing the error between an arbitrary Expression and a Function. Does it require an expensive projection of the Expression to a higher-order FunctionSpace.

Anybody got any ideas?

asked Feb 6, 2014 by Øyvind Evju FEniCS Expert (17,700 points)

3 Answers

0 votes

I'll answer myself with a dirty solution:

exact = Expression(("x[0]*x[0]"))
el = FiniteElement('Lagrange', None, 2, None)
exact._element = el
print assemble(inner(approx-exact,approx-exact)*dx)

Doesn't feel right at all, but it does the trick...

answered Feb 6, 2014 by Øyvind Evju FEniCS Expert (17,700 points)
+1 vote

IMO it would be preferable to first either interpolate or project (depending on expression and required accuracy) the expression onto (refined) V, then construct the error function by difference of coefficient vectors and then to integrate this error. Also see errornorm.

answered Feb 6, 2014 by meigel FEniCS User (1,520 points)

The problem with this is that it might be expensive, and potentially requires a large function space (memory).

This is exactly what I was hoping to avoid ;)

+1 vote

There is a function called errornorm that can be used for this purpose. Try this:

help(errornorm)

Notice in particular that the evaluation assemble(inner(approx-exact,approx-exact)*dx) may lead to a very visible effect from round-off errors. The errornorm function therefore uses a slightly different method.

answered Feb 6, 2014 by logg FEniCS Expert (11,790 points)

Sorry, I didn't look carefully enough at the errornorm. I was surprised to see that

errornorm(expr, func)

gave me a result, whereas

errornorm(func, expr)

did not (*** Reason: Expecting a Function or Expression for u.)

However, I realized the point where I end up in trouble, is that instead of vector Expressions, I have a list of scalar Expressions. I can use as_vector to use that list in a form. However, errornorm does not work with the following:

errornorm(as_vector([exp0, exp1]), vector_func)

I've had the same problem with vector-valued functions. What you can always do of course is compute errornorm() component-wise (and square them, add them up, take the root).

...