In your code, you are comparing your solution with the interpolated analytic solution in the same FE space as your approximation. What happens if you interpolate your exact solution into a higher order finite element space, like CG3 or CG4? I suspect you may get the rate you're expecting after that (if not, then some magic is happening...)
Best regards,
- Thomas
mesh = UnitSquareMesh(20,20,quadrilateral=False)
Q = FunctionSpace(mesh,CG,2)
...
x = SpatialCoordinate(Q.mesh())
u_exact = interpolate(sin(2*x[0]**2*math.pi)*sin(2*x[1]**2*math.pi),Q)
f = interpolate( 16*math.pi**2*sin(2*math.pi*x[0]**2)*sin(2*math.pi*x[1]**2)*(x[0]**2+x[1]**2)
- 4*math.pi*(cos(2*math.pi*x[0]**2)*sin(2*math.pi*x[1]**2) + sin(2*math.pi*x[0]**2)*cos(2*math.pi*x[1]**2)),Q)
...
L2_error = errornorm(u_exact,u_h)