Confirming functional superconvergence

Asked by Jason Hicken

Hi,

First: remarkable piece of software engineering.

Now my problem. I am trying to confirm functional superconvergence where the solution comes from a Galerkin approximation to a simple 1-D Poisson problem. For a given polynomial order p, it is my understanding that an integral functional should be 2p order accurate for this problem. I obtain this rate for p = 1 and p = 2, but not for higher-order polynomials.

The function below can be used to reproduce the effect: e.g., run with (num=20, p = 3) and (num=40, p=3) and then estimate the convergence rate using log(Error_Functional(num=40)/Error_Functional(num=20))/log(0.5).

Any insights would be appreciated.

Jason
_____________________________________________________________

from dolfin import *
import numpy

def solve(num, p):
    """Solves a 1-D BVP and returns the L2 error, the functional and its error

    *Inputs*
    num: number of finite-elements
    p: polynomial order

    *Output*
    functional error
    functional error estimate
    correct functional error

    """

    # Create mesh and define function space
    mesh = UnitInterval(num)
    V = FunctionSpace(mesh, "CG", p)

    # Define Dirichlet boundary (x = 0 or x = 1)
    def boundary(x):
        return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS
    def u0_boundary(x, on_boundary):
        return on_boundary

    # Define exact solution, source, and boundary conditions
    u0 = Expression("1.0 + x[0]*sin(pi*x[0])")
    f = Expression("2.0*pi*cos(pi*x[0]) - pi*pi*x[0]*sin(pi*x[0])")
    bc = DirichletBC(V, u0, u0_boundary)

    # define the bilinear form a and linear form L
    v = TestFunction(V)
    u = TrialFunction(V)
    a = -inner(grad(u), grad(v))*dx
    L = f*v*dx

    # Solve variational problem and print L2 solution error
    u = Function(V)
    problem = LinearVariationalProblem(a, L, u, bcs=bc)
    solver = LinearVariationalSolver(problem)
    solver.solve()
    print "L2 solution error:", errornorm(u0, u)

    # Compute functional and its error
    energy = u*dx
    E = assemble(energy)
    E_e = 1.0/pi + 1.0
    print "Functional value:", E
    print "Functional error:", E_e - E

    return [E, E_e - E]

Question information

Language:
English Edit question
Status:
Solved
For:
DOLFIN Edit question
Assignee:
No assignee Edit question
Solved by:
Garth Wells
Solved:
Last query:
Last reply:
Revision history for this message
Best Garth Wells (garth-wells) said :
#1

On 10 August 2012 20:06, Jason Hicken
<email address hidden> wrote:
> New question #205519 on DOLFIN:
> https://answers.launchpad.net/dolfin/+question/205519
>
> Hi,
>
> First: remarkable piece of software engineering.
>

Thanks.

> Now my problem. I am trying to confirm functional superconvergence where the solution comes from a Galerkin approximation to a simple 1-D Poisson problem. For a given polynomial order p, it is my understanding that an integral functional should be 2p order accurate for this problem. I obtain this rate for p = 1 and p = 2, but not for higher-order polynomials.
>
> The function below can be used to reproduce the effect: e.g., run with (num=20, p = 3) and (num=40, p=3) and then estimate the convergence rate using log(Error_Functional(num=40)/Error_Functional(num=20))/log(0.5).
>
> Any insights would be appreciated.
>

The errornorm function interpolates finite element functions in an FE
space and defaults to degree 3. You can force a higher degree, e.g.

     print "L2 solution error:", errornorm(u0, u, degree = p+6)

I think this explains why you run into an issue for p >2.

Also, DOLFIN/FFC interpolates all functions in a finite element space,
so when computing errors some care is necessary to be sure that
analytical expressions are evaluated with sufficient accuracy. Doing

    u0 = Expression("1.0 + x[0]*sin(pi*x[0])")
    f = Expression("2.0*pi*cos(pi*x[0]) - pi*pi*x[0]*sin(pi*x[0])")

the form compiler FFC will try to determine a suitable order Lagrange
basis. This should be high enough, but to be sure you can force the
degree, say

    u0 = Expression("1.0 + x[0]*sin(pi*x[0])", degree=p+6)
    f = Expression("2.0*pi*cos(pi*x[0]) - pi*pi*x[0]*sin(pi*x[0])",
degree=p+6)

Garth

> Jason
> _____________________________________________________________
>
> from dolfin import *
> import numpy
>
> def solve(num, p):
> """Solves a 1-D BVP and returns the L2 error, the functional and its error
>
> *Inputs*
> num: number of finite-elements
> p: polynomial order
>
> *Output*
> functional error
> functional error estimate
> correct functional error
>
> """
>
> # Create mesh and define function space
> mesh = UnitInterval(num)
> V = FunctionSpace(mesh, "CG", p)
>
> # Define Dirichlet boundary (x = 0 or x = 1)
> def boundary(x):
> return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS
> def u0_boundary(x, on_boundary):
> return on_boundary
>
> # Define exact solution, source, and boundary conditions
> u0 = Expression("1.0 + x[0]*sin(pi*x[0])")
> f = Expression("2.0*pi*cos(pi*x[0]) - pi*pi*x[0]*sin(pi*x[0])")
> bc = DirichletBC(V, u0, u0_boundary)
>
> # define the bilinear form a and linear form L
> v = TestFunction(V)
> u = TrialFunction(V)
> a = -inner(grad(u), grad(v))*dx
> L = f*v*dx
>
> # Solve variational problem and print L2 solution error
> u = Function(V)
> problem = LinearVariationalProblem(a, L, u, bcs=bc)
> solver = LinearVariationalSolver(problem)
> solver.solve()
> print "L2 solution error:", errornorm(u0, u)
>
> # Compute functional and its error
> energy = u*dx
> E = assemble(energy)
> E_e = 1.0/pi + 1.0
> print "Functional value:", E
> print "Functional error:", E_e - E
>
> return [E, E_e - E]
>
> --
> You received this question notification because you are a member of
> DOLFIN Team, which is an answer contact for DOLFIN.

Revision history for this message
Garth Wells (garth-wells) said :
#2

I've just created a bug reported related to this:

    https://bugs.launchpad.net/bugs/1036135

Revision history for this message
Jason Hicken (jason-hicken+launchpad) said :
#3

Hi Garth,

Thank you for a quick response.

I actually get the expected results from the errornorm function, even for p > 2. That is, the error has a convergence rate of p+1.

My problem arises when I compute an integral functional of the solution (see the code below the last comment in the example). I did try specifying the degree for the source term f, but I find I get unpredictable results.

For example, if I use degree=p+6 for the source expression, the functional error is machine zero for p >= 2. If I use degree=p+1 for the source, then I get the expected convergence rate of 2p for p <= 3; however, problems show up again for p = 4, where the rate is h^6 rather than h^8. It seems like I can obtain arbitrary convergence rates by changing the degree of the source term.

Thanks again,
Jason

Revision history for this message
Anders Logg (logg) said :
#4

On Mon, Aug 13, 2012 at 01:41:12PM -0000, Jason Hicken wrote:
> Question #205519 on DOLFIN changed:
> https://answers.launchpad.net/dolfin/+question/205519
>
> Status: Answered => Open
>
> Jason Hicken is still having a problem:
> Hi Garth,
>
> Thank you for a quick response.
>
> I actually get the expected results from the errornorm function, even
> for p > 2. That is, the error has a convergence rate of p+1.
>
> My problem arises when I compute an integral functional of the solution
> (see the code below the last comment in the example). I did try
> specifying the degree for the source term f, but I find I get
> unpredictable results.
>
> For example, if I use degree=p+6 for the source expression, the
> functional error is machine zero for p >= 2. If I use degree=p+1 for
> the source, then I get the expected convergence rate of 2p for p <= 3;
> however, problems show up again for p = 4, where the rate is h^6 rather
> than h^8. It seems like I can obtain arbitrary convergence rates by
> changing the degree of the source term.

It looks to me like the convergence rate for the functional is
something like p + 1 for p odd and p + 2 for p even.

  1 2
  2 4
  3 4
  4 6

This is the case even if you just check the convergence rate for

  1/pi + 1 - assemble(u0*dx, mesh=mesh)

for various choices for the degree of the Expression for u0.

I couldn't go higher than degree 4 since then the error becomes small
enough that I run into problems with machine precision.

I have no idea if this is the expected convergence rate but it would
indicate order p + 1 in general and superconvergence p + 2 for p even.

--
Anders

Revision history for this message
Jason Hicken (jason-hicken+launchpad) said :
#5

Anders and Garth:

On closer inspection, it appears that setting the degree of the source expression does solve the problem. The strange convergence rates reported in my previous post were caused by using a too fine a mesh: the high order (p > 2) elements were already running into machine precision problems at 10 elements.

Thank you for your help.

Revision history for this message
Jason Hicken (jason-hicken+launchpad) said :
#6

Thanks Garth Wells, that solved my question.