I am trying to find a way to integrate a second order expression with "sufficient" accuracy using assemble(). The simplified working examples below demonstrate the issue I am having. I would have expected an answer much closer to zero (I was hopping for something less than 1e-6). As shown below, the situation improves when refining the mesh, but I am perplexed by the odd way it improves. I am new to FENICS, and would very much appreciate any insight on how to address this (I have been unsuccessful finding it elsewhere).
from __future__ import print_function
from __future__ import division
from dolfin import *
import mshr as ms
import numpy as np
seg = 100
circle = ms.Circle(Point(0,0), 1, seg)
mesh = ms.generate_mesh(circle, seg/3.14)
dx = Measure('dx', domain=mesh)
expr = Expression('2*(x[0]*x[0] + x[1]*x[1]) - 1', degree=2)
int1 = assemble(expr*dx)
V = FunctionSpace(mesh, "CG", 2)
expr_i = interpolate(expr, V)
int2 = assemble(expr_i*dx)
V = FunctionSpace(mesh, "CG", 1)
expr_i = interpolate(expr, V)
int3 = assemble(expr_i*dx)
print('int1={} int2={} int3={}'.format(int1, int2, int3))
Result:
int1=-0.00206504578602 int2=-0.00206504578602 int3=0.00127584823819
Below I just refine the mesh by changing by increasing seg from 100 to 400
seg = 400
circle = ms.Circle(Point(0,0), 1, seg)
mesh = ms.generate_mesh(circle,seg/3.14)
dx = Measure('dx', domain=mesh)
expr = Expression('2*(x[0]*x[0] + x[1]*x[1]) - 1', degree=2)
int1 = assemble(expr*dx)
V = FunctionSpace(mesh, "CG", 2)
expr_i = interpolate(expr, V)
int2 = assemble(expr_i*dx)
V = FunctionSpace(mesh, "CG", 1)
expr_i = interpolate(expr, V)
int3 = assemble(expr_i*dx)
print('int1={} int2={} int3={}'.format(int1, int2, int3))
Result:
int1=-0.000129184850435 int2=-0.000129184850435 int3=7.73547968041e-05
With seg = 500 I get:
int1=-0.000129184850435 int2=-8.26801403224e-05 int3=5.02225121338e-05