How to tag boundaries and surfaces using geometries created in FEniCS

Hello everyone,

I am having trouble assigning tags to surfaces and boundaries to geometries created through FEniCS.

Here is what I tried:

from mshr import *
from ufl import *
from dolfin import * 
import matplotlib.pyplot as plt

from dolfin import *
import meshio
from dolfin import Mesh, XDMFFile, File, MeshValueCollection, cpp

# Optimization options for the form compiler
parameters["form_compiler"]["cpp_optimize"] = True
ffc_options = {"optimize": True, \
               "eliminate_zeros": True, \
               "precompute_basis_const": True, \
               "precompute_ip_const": True}

mesh = generate_mesh(Circle(Point(0,0),3), 50) # Generating mesh for the domain
bmesh = BoundaryMesh(mesh,"exterior") # Generating mesh for the boundary

boundary_markers = MeshFunction("size_t", bmesh, mesh.topology().dim()-1, 0) # Initializing boundary marker to 0
surface_markers = MeshFunction("size_t", mesh, mesh.topology().dim(), 0) # Initializing surface marker to 0
disk=Mesh() # Defining mesh on the disk
disk.mark(surface_markers, 2) # Marking the disk with tag 1
plot(mesh) # Plotting mesh
plot(disk) # Plotting the disk
plt.show() # Showing the plot

This gives the error:

Traceback (most recent call last):
  File "fspex.py", line 23, in <module>
    disk.mark(surface_markers, 2) # Marking the disk with tag 2
AttributeError: 'dolfin.cpp.mesh.Mesh' object has no attribute 'mark'

Any suggestions on how to overcome this would be greatly appreciated. Thank you.

Please consider the following minimal example:

from mshr import Circle, generate_mesh

from dolfin import Mesh, File, MeshFunction, Point, BoundaryMesh, SubDomain, plot, File


class boundary(SubDomain):
    def inside(self, x, on_boundary):
        return on_boundary


class right_side(SubDomain):
    def inside(self, x, on_boundary):
        return x[0] < 0


mesh = generate_mesh(Circle(Point(0, 0), 3), 50)
boundary_markers = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
surface_markers = MeshFunction("size_t", mesh, mesh.topology().dim(), 0)
boundary().mark(boundary_markers, 2)
right_side().mark(surface_markers, 1)

File("mesh.pvd") << mesh
File("surface_marker.pvd") << surface_markers
File("boundary_marker.pvd") << boundary_markers

that producs the following data (left: mesh.pvd, top right: surface_markers.pvd, bottom right: boundary_markers.png)

Hi! I wanted the disk to be tagged 1 and the boundary to be tagged 2. So I made the following changes to the code you suggested:

from mshr import Circle, generate_mesh

from dolfin import Mesh, File, MeshFunction, Point, BoundaryMesh, SubDomain, plot, File


class boundary(SubDomain):
    def inside(self, x, on_boundary):
        return on_boundary


class disk(SubDomain):
    def inside(self, x, on_boundary):
        return x[0] < 0 and x[0] > 0


mesh = generate_mesh(Circle(Point(0, 0), 3), 50)
boundary_markers = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
surface_markers = MeshFunction("size_t", mesh, mesh.topology().dim(), 0)
boundary().mark(boundary_markers, 2)
disk().mark(surface_markers, 1)

File("mesh.pvd") << mesh
File("surface_marker.pvd") << surface_markers
File("boundary_marker.pvd") << boundary_markers

This gives me the tag 0 to the disk and 2 to the boundary. (I dont know how to include figures in posts like you did).

The function inside takes in a coordinate, and returns True if you should mark the entity. The current condition that you have set up can never be satisfied, and thus you only obtain the initial marker value 0. If you change this to:

class disk(SubDomain):
    def inside(self, x, on_boundary):
        return True

it will mark every cell and thus obtain the marking you want

1 Like