I am now trying to use FEniCSx/Dolfinx to solve a simple equation but I want to import a gmsh mesh which has boundaries etc. However, whenever I try this I get errors such as:
Traceback (most recent call last):
File “/home/fenics/HeatConduction/src/heat_conduction/test4.py”, line 60, in
msh = xdmf.read_mesh(name=“Grid”)
File “/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/io/utils.py”, line 258, in read_mesh
cell_shape, cell_degree = super().read_cell_type(name, xpath)
RuntimeError: Cannot recognise cell type. Unknown value: mixed
I am confused to what I am doing wrong!
Note I have tried using Docker Dolfinx and conda but neither works (the later doesn’t even install fenics/dolfinx!). I am on an M3 MBP.
The code I am using is:
import gmsh
import meshio
from mpi4py import MPI
from dolfinx.io import XDMFFile
import dolfinx.fem as fem
def create_doughnut_mesh(filename, refinement_level):
gmsh.initialize()
gmsh.model.add("Doughnut")
# Define the outer and inner circles
outer_circle = gmsh.model.occ.addCircle(0, 0, 0, 1)
inner_circle = gmsh.model.occ.addCircle(0, 0, 0, 0.5)
# Create the plane surface between the circles
outer_loop = gmsh.model.occ.addCurveLoop([outer_circle])
inner_loop = gmsh.model.occ.addCurveLoop([inner_circle])
surface = gmsh.model.occ.addPlaneSurface([outer_loop, inner_loop])
# Synchronize the CAD kernel with the Gmsh model
gmsh.model.occ.synchronize()
# Ensure no quadrilaterals are created
gmsh.option.setNumber("Mesh.CharacteristicLengthFactor", 1.0 / refinement_level)
# Generate the mesh
gmsh.model.mesh.generate(2)
# Ensure the mesh contains only triangles
element_types, element_tags, node_tags = gmsh.model.mesh.getElements()
if len(element_tags) == 0 or len(element_tags[0]) == 0:
raise RuntimeError("Mesh generation failed: no elements found.")
if any(element_type != 2 for element_type in element_types): # 2 corresponds to triangles in Gmsh
print(element_types)
# Get the boundary entities
outer_boundary = gmsh.model.getBoundary([(2, surface)], oriented=False, recursive=False)
inner_boundary = gmsh.model.getBoundary([(2, surface)], oriented=False, recursive=False)
# Create physical groups for the boundary edges
outer_boundary_group = gmsh.model.addPhysicalGroup(1, [edge[1] for edge in outer_boundary], tag=1)
inner_boundary_group = gmsh.model.addPhysicalGroup(1, [edge[1] for edge in inner_boundary], tag=2)
gmsh.model.setPhysicalName(1, outer_boundary_group, "OuterBoundary")
gmsh.model.setPhysicalName(1, inner_boundary_group, "InnerBoundary")
# Optionally, save the mesh to a file
gmsh.write(filename)
gmsh.finalize()
# Example usage
create_doughnut_mesh("doughnut.msh", refinement_level=10)
# Convert the Gmsh mesh to XDMF format
mesh = meshio.read("doughnut.msh")
meshio.write("doughnut_filtered.xdmf", mesh)
# Load the mesh into FEniCSx
with XDMFFile(MPI.COMM_WORLD, "doughnut_filtered.xdmf", "r") as xdmf:
msh = xdmf.read_mesh(name="Grid")
# Read the filtered mesh from the XDMF file
filtered_mesh = meshio.read("doughnut_filtered.xdmf")
# Extract boundary edges
boundary_edges = []
for cell_block in filtered_mesh.cells:
if cell_block.type == "triangle":
for triangle in cell_block.data:
for i in range(3):
edge = tuple(sorted([triangle[i], triangle[(i + 1) % 3]]))
if edge not in boundary_edges:
boundary_edges.append(edge)
# Print the boundary edges
print("Boundary edges:")
for edge in boundary_edges:
print(edge)
V = fem.FunctionSpace(msh, ("CG", 1))