Tetrahedral and Triangular Meshes Imported from Gmsh in FEniCSx

Hello everyone,

I’m currently facing an issue with importing a .msh file, generated with Gmsh, into FEniCSx. The challenge lies in accurately defining the physical domains and surfaces created in Gmsh, which are crucial for specifying the integrands of dx and ds.

While resolving this problem is relatively straightforward in FEniCS, I’ve encountered difficulties in FEniCSx, particularly in defining tetrahedral and triangular meshes. Below is the approach I’ve taken so far:

1. Mesh Creation and Conversion:

  • Using meshio, I read the .msh file and extracted tetrahedral and triangular cells along with their corresponding physical domain information.

2. Mesh Manipulation:

  • I converted the mesh data into formats compatible with FEniCSx and saved them as XDMF files.
import numpy as np
from mpi4py import MPI
from petsc4py import PETSc
from dolfinx import *
from dolfinx.mesh import *
from dolfinx.cpp.mesh import *
from dolfinx.io import *
from dolfinx.la import *
from ufl import *

import meshio

path = "/home/"
filename = "3Dmesh"
 
mesh = meshio.read(path + filename + ".msh")
 
def create_mesh(mesh, cell_type, prune_z=False):
    cells = mesh.get_cells_type(cell_type)
    cell_data = mesh.get_cell_data("gmsh:physical", cell_type)
    out_mesh = meshio.Mesh(points=mesh.points, cells={
                           cell_type: cells}, cell_data={"name_to_read": [cell_data]})
    if prune_z:
        out_mesh.prune_z_0()
    return out_mesh
 
tetra_mesh = create_mesh(mesh, "tetra")
triangle_mesh = create_mesh(mesh, "triangle")
meshio.write(path + filename + "_tetra.xdmf", tetra_mesh)
meshio.write(path + filename + "_triangle.xdmf", triangle_mesh)

3. Defining Mesh Functions:

  • In FEniCS, I could readily define mesh functions using the imported mesh data. However, in FEniCSx, this process seems to present challenges.
mesh = Mesh()
mvc_3d = MeshValueCollection("size_t", mesh, 3)
with XDMFFile(path + filename + "_tetra.xdmf") as infile:
    infile.read(mvc_3d, "name_to_read")
mf_3d = cpp.mesh.MeshFunctionSizet(mesh, mvc_3d)

mvc_2d = MeshValueCollection("size_t", mesh, 2)
with XDMFFile(path + filename + "_triangle.xdmf") as infile:
    infile.read(mvc_2d, "name_to_read")
    
mf_2d = cpp.mesh.MeshFunctionSizet(mesh, mvc_2d)

4. Integration Measures:

  • The ultimate goal is to define integration measures such as dx and ds, which require accurate subdomain data.
ds = Measure("ds",domain=mesh, subdomain_data=mf_2d)
dS_c = Measure("dS",domain=mesh, subdomain_data=mf_2d)
dx = Measure("dx",domain=mesh, subdomain_data=mf_3d)

Currently, I’m stuck at the step of defining mesh functions and integrating over the domains and boundaries using FEniCSx.

Would anyone have insights or suggestions on how to address this issue in FEniCSx? Any help or guidance would be greatly appreciated.

Thank you!

All of those tasks can be done in dolfinx with a new datastructure, called MeshTags. Conversion from gmsh does not require anymore meshio, but can be done with dolfinx.io.gmsh.model_to_mesh. Please use the search button with that words as keyword, and you’ll find plenty of posts and links to existing tutorials.

2 Likes