Mesh elements are not fully marked on boundary subdomain

Hello,

I’m trying to mark the boundaries of my mesh, but not all of the elements are marked.

tol = 1E-8
xmin_sd = dolfin.CompiledSubDomain("near(x[0], x0, tol) && on_boundary", x0=xmin, tol=tol)
xmax_sd = dolfin.CompiledSubDomain("near(x[0], x0, tol) && on_boundary", x0=xmax, tol=tol)
ymin_sd = dolfin.CompiledSubDomain("near(x[1], x0, tol) && on_boundary", x0=ymin, tol=tol)
ymax_sd = dolfin.CompiledSubDomain("near(x[1], x0, tol) && on_boundary", x0=ymax, tol=tol)
zmin_sd = dolfin.CompiledSubDomain("near(x[2], x0, tol) && on_boundary", x0=zmin, tol=tol)
zmax_sd = dolfin.CompiledSubDomain("near(x[2], x0, tol) && on_boundary", x0=zmax, tol=tol)

xmin_id = 1
xmax_id = 2
ymin_id = 3
ymax_id = 4
zmin_id = 5
zmax_id = 6

boundaries_mf = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()-1) 
boundaries_mf.set_all(0)
xmin_sd.mark(boundaries_mf, xmin_id)
xmax_sd.mark(boundaries_mf, xmax_id)
ymin_sd.mark(boundaries_mf, ymin_id)
ymax_sd.mark(boundaries_mf, ymax_id)
zmin_sd.mark(boundaries_mf, zmin_id)
zmax_sd.mark(boundaries_mf, zmax_id)

Here is my subdomain, but some elements are not marked.

Thanks in advance for your suggestions to mark all the elements on the boundary.

Please provide a minimal working example so that I can reproduce the issue and analyze it further.

1 Like

Here is the minimal working example:

import gmsh
import os
import math
import meshio
import dolfin

###################################################################################################################################################################
fname = 'cube'
width = 1
r = width/2.5
shift_x = width/2
shift_y = width/2
shift_z = width/2

center = width/2
xmin = 0.
ymin = 0.
zmin = 0.
xmax = width
ymax = width
zmax = width
x0 = center
y0 = center
z0 = center
r0 = r
l = width/10
e = 1e-6


def setPeriodic(coord):
    # From https://gitlab.onelab.info/gmsh/gmsh/-/issues/744
    smin = gmsh.model.getEntitiesInBoundingBox(xmin - e, ymin - e, zmin - e,
                                                (xmin + e) if (coord == 0) else (xmax + e),
                                                (ymin + e) if (coord == 1) else (ymax + e),
                                                (zmin + e) if (coord == 2) else (zmax + e),
                                                2)
    dx = (xmax - xmin) if (coord == 0) else 0
    dy = (ymax - ymin) if (coord == 1) else 0
    dz = (zmax - zmin) if (coord == 2) else 0

    for i in smin:
        bb = gmsh.model.getBoundingBox(i[0], i[1])
        bbe = [bb[0] - e + dx, bb[1] - e + dy, bb[2] - e + dz,
                bb[3] + e + dx, bb[4] + e + dy, bb[5] + e + dz]
        smax = gmsh.model.getEntitiesInBoundingBox(bbe[0], bbe[1], bbe[2],
                                                    bbe[3], bbe[4], bbe[5])
        for j in smax:
            bb2 = list(gmsh.model.getBoundingBox(j[0], j[1]))
            bb2[0] -= dx; bb2[1] -= dy; bb2[2] -= dz;
            bb2[3] -= dx; bb2[4] -= dy; bb2[5] -= dz;
            if ((abs(bb2[0] - bb[0]) < e) and (abs(bb2[1] - bb[1]) < e) and
                (abs(bb2[2] - bb[2]) < e) and (abs(bb2[3] - bb[3]) < e) and
                (abs(bb2[4] - bb[4]) < e) and (abs(bb2[5] - bb[5]) < e)):
                gmsh.model.mesh.setPeriodic(2, [j[1]], [i[1]], [1, 0, 0, dx,\
                                                                0, 1, 0, dy,\
                                                                0, 0, 1, dz,\
                                                                0, 0, 0, 1 ])

gmsh.initialize()

box_tag = 1
hole_tag1 = 2
rve_tag = 3

gmsh.model.occ.addBox(x=xmin, y=ymin, z=zmin, dx=xmax-xmin, dy=ymax-ymin, dz=zmax-zmin, tag=box_tag)
gmsh.model.occ.addSphere(xc=xmin+shift_x, yc=ymin+shift_y, zc=zmin+shift_z, radius=r0, tag=hole_tag1)
gmsh.model.occ.cut(objectDimTags=[(3, box_tag)], toolDimTags=[(3, hole_tag1)], tag=rve_tag)
gmsh.model.occ.synchronize()
gmsh.model.addPhysicalGroup(dim=3, tags=[rve_tag])
setPeriodic(0)
setPeriodic(1)
setPeriodic(2)

gmsh.model.mesh.setSize(dimTags=gmsh.model.getEntities(0), size=l)
gmsh.model.mesh.generate(dim=3)


gmsh.write(fname+"-mesh.vtk")
gmsh.finalize()

mesh = meshio.read(fname+"-mesh.vtk")
mesh.points = mesh.points[:, :3]
meshio.write(fname+"-mesh.xdmf", mesh)

mesh = dolfin.Mesh()
dolfin.XDMFFile(fname+"-mesh.xdmf").read(mesh)

vol = width**3
phi = (4/3*math.pi*r**3)/vol
print("porosity:" +str(phi))



#####################################

tol = 1E-8
xmin_sd = dolfin.CompiledSubDomain("near(x[0], x0, tol) && on_boundary", x0=xmin, tol=tol)
xmax_sd = dolfin.CompiledSubDomain("near(x[0], x0, tol) && on_boundary", x0=xmax, tol=tol)
ymin_sd = dolfin.CompiledSubDomain("near(x[1], x0, tol) && on_boundary", x0=ymin, tol=tol)
ymax_sd = dolfin.CompiledSubDomain("near(x[1], x0, tol) && on_boundary", x0=ymax, tol=tol)
zmin_sd = dolfin.CompiledSubDomain("near(x[2], x0, tol) && on_boundary", x0=zmin, tol=tol)
zmax_sd = dolfin.CompiledSubDomain("near(x[2], x0, tol) && on_boundary", x0=zmax, tol=tol)

xmin_id = 1
xmax_id = 2
ymin_id = 3
ymax_id = 4
zmin_id = 5
zmax_id = 6

boundaries_mf = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim()-1) 
boundaries_mf.set_all(0)
xmin_sd.mark(boundaries_mf, xmin_id)
xmax_sd.mark(boundaries_mf, xmax_id)
ymin_sd.mark(boundaries_mf, ymin_id)
ymax_sd.mark(boundaries_mf, ymax_id)
zmin_sd.mark(boundaries_mf, zmin_id)
zmax_sd.mark(boundaries_mf, zmax_id)

xdmf_file_boundaries = dolfin.XDMFFile(fname+"-boundaries.xdmf")
xdmf_file_boundaries.write(boundaries_mf)
xdmf_file_boundaries.close()

It works with finer mesh, but I don’t know why this problem exists with coarser mesh.
Thanks!

I cannot spot which elements you mean are not marked.


Could you please point out what elements you are talking about?

Thanks for your response!
Here are some elements on the boundaries which have not been marked.

What is the visualization mode you use in Paraview for this?

I cannot reproduce it with “Surface with Edges”.
As you have a 3D mesh, and what you are looking at is edges, it is not clear how you expect an edge to have a marking (when you are marking facets in your code).

My visualization mode is “Wireframe” with another mesh with “Surface” on the background. I’m marking surfaces, so I would expect all of the mesh elements on the surface to be marked, right?

Imagine you have a single Edge of a tetrahedron connected by several triangles with different values (in your case 0 on all interior facets, and a non-zero value on all exterior facets). What color should that edge have? It is not obvious for me or Paraview that this should be a non-zero value.