I am trying to integrate over internal surfaces, evaluating the total content of a function across vertical slices within the domain. I’m using dS (cf previous topics). I find in my real code, a zero value is (incorrectly) returned. But my solution function is Mixed and if I project the target component into a fresh Function, then it assembles into a nonzero value as expected. But it shouldn’t be necessary to have to project to get the job done.
My domain is a triangle. A minimum working example suggests this geometry is part of the problem. I’ve set up a constant Function with value π everywhere. Operating over a square unit mesh, integration over vertical slices returns 3.14159 as expected. But after changing to a triangular mesh, assembly over the VerticalSampleLines returns 0.
My MWE is
from dolfin import *
import mshr
import numpy
# define internal surface subdomains as vertical lines at position X
class VerticalSampleLine(SubDomain):
def __init__(self, X, **kwargs):
self.X = X
super().__init__(**kwargs)
def inside(self, x, on_boundary):
return near(x[0],self.X)
# simple 2D mesh
useSquareMesh = False
if useSquareMesh:
mesh = UnitSquareMesh(10,10)
else:
unitRightTriangle = mshr.Polygon([Point([0,0]),Point([1,0]),Point([1,1])])
mesh = mshr.generate_mesh(unitRightTriangle, 10)
V = FunctionSpace(mesh, "CG", 1)
# use a constant function with value π
f = project(Constant(numpy.pi),V)
verticalBoundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
# set up a set of 5 internal surfaces to test
xset = numpy.linspace(0.1,0.9, 5)
verticalBoundarySet=[]
for i, x in enumerate(xset):
lineIndex=i+1
verticalBoundarySet.append( VerticalSampleLine(x) )
verticalBoundarySet[lineIndex-1].mark(verticalBoundaries, lineIndex)
dS = Measure('dS', domain=mesh, subdomain_data=verticalBoundaries)
for i, verticalBoundary in enumerate(verticalBoundarySet):
lineIndex=i+1
lineValue = assemble(f*dS(lineIndex))
# vertical line integrals should = π
print("lineValue {} at x={:.1} is {}".format(lineIndex,verticalBoundary.X,lineValue))
With the triangular mesh (useSquareMesh = False
) it prints
lineValue 1 at x=0.1 is 0.0
lineValue 2 at x=0.3 is 0.0
lineValue 3 at x=0.5 is 0.0
lineValue 4 at x=0.7 is 0.0
lineValue 5 at x=0.9 is 0.0
Set useSquareMesh = True
to see the behaviour on the square mesh:
lineValue 1 at x=0.1 is 3.1415926535897936
lineValue 2 at x=0.3 is 3.141592653589793
lineValue 3 at x=0.5 is 3.141592653589794
lineValue 4 at x=0.7 is 3.141592653589794
lineValue 5 at x=0.9 is 3.1415926535897944
Why does lineValue get set to 0 when the triangular mesh is used (useSquareMesh = False
) ?