Skip to content

CAD to 3D mesh

Matthew Hockley edited this page Nov 12, 2020 · 6 revisions

Once a design has been created in a CAD package, it should be exported as "STEP" file. From experimenting, "STEP" files appear to have a higher success rate compared to "STL" files. This is likely due to how "STL" files differ from "STEP" files. GMSH or Netgen can be used to create 3D meshes with surface labels. For GMSH, a guide is available in CAD to 2D mesh and return to Meshio "MSH" to 3D "XDMF" conversion. Netgen is an mesh generation and will pre-label all boundaries in a "MSH" mesh file unlike GMSH which requires user-defined physical labels. NETGEN is more user-friendly in this regard but may fail to import CAD correctly and require STEP healing.

Netgen STEP to MSH mesh generation

Once exported as an "STEP", the file can be imported in Netgen. Once in Netgen, it is worth doing a low density mesh to check whether the "STEP" model needs to be repaired. If the mesh model has errors completing, it is worth attempting to heal the mesh using "IGES/STEP Topology Explorer/Doctor". The interface will "Analyze geometry", print to command prompt and allow the user to heal the model by adjusting the "Healing tolerance, removing excess faces and edges as required. If healing the surface fails or leads to unrealistic models, the CAD model could be re-created or attempted in GMSH (see 2D guide). Images top left to bottom right, "IGES/STEP Topology Explorer/Doctor", "General Meshing Options", "Advanced Meshing Options".

IGES/STEP Topology Explorer/Doctor General Meshing OptionsAdvanced Meshing Options

Assuming a successful mesh import, the mesh setting should be defined in Mesh > Meshing Options. A "Mesh options" panel appears where pre-defined mesh density can be selected from a drop-down menu in the "General" tab, "General Meshing Options", "Mesh Granularity" from very coarse to very fine. Additionally, user defined mesh density can be set in the "Mesh Size" tab, defining the "min mesh-size" and "min mesh-size". The mesh-size is relative to the mesh size. For example, if the mesh is in millimetres, 0.01 will be 0.01 millimetres.

Once adjusted mesh density, set "Meshing Threads" in "General Meshing Options" to an appropriate amount for your workstation, close the "Mesh options" panel and click "Generate Mesh" on the Netgen interface.

After mesh generation, subdomain surface labels can be viewed using Mesh > Edit Boundary Conditions which all boundaries can be numerically stepped through. For larger meshes and to save time, the subdomains file generated by Meshio can be opened in Paraview and each boundary label viewed in 3D by hoovering a mouse over. To export the mesh, first define mesh file type using File > Export Filetype and selecting "Gmsh2 format". Note the Gmsh format does not work. Next select "Export mesh" and make sure the filetype is "Gmsh2 Format (*gmsh2)" from the file type drop down menu and save with an appropriate name.

Meshio "MSH" to 3D "XDMF" conversion

Once GMSH or Netgen has generated a "MSH", the file needs to be converted to "XDMF" for FEniCS import using Meshio. "XDMF" is used due to the performance comparison compared to other mesh file formats (see Meshio performance comparison table below).

Comparison of mesh file types from Meshio

For 3D conversion, there is a importScript.py available. The file will automated the conversion from "MSH" to "XDMF" using Meshio.

The first line of the code imports the "MSH" file we created in either GMSH or Netgen. In this example, the filename was Spiral3D02.msh.

msh = meshio.read("Spiral3D02.msh")

The next line exports the mesh in "XDMF" format. In this example, the exported file is labelled mesh_Spiral3D.xdmf which can be changed. This extract the 3D volume in tetra, short for tetrahedral cells.

meshio.write("mesh_Spiral3D.xdmf", meshio.Mesh(points=msh.points, cells={"tetra": msh.cells["tetra"]}))

The next part of the code extracts the physical triangle labels important for defining the subdomains boundaries. The triangle cells signifies 3D surface boundaries. The file is labelled mf_Spiral3D.xdmf.

meshio.write("mf_Spiral3D.xdmf", meshio.Mesh(points=msh.points, cells={"triangle": msh.cells["triangle"]}, cell_data={"triangle": {"name_to_read": msh.cell_data["triangle"]["gmsh:physical"]}}))

The final, optional part tests the physical labelling. The code uses the dolfin package, from dolfin import *, to import the "XDMF" file mesh and subdomains. Through importing both meshes, It_facet = SubsetIterator(mf,14) can be used to find all physical labels which are labelled "14".

from dolfin import *
mesh = Mesh()
with XDMFFile("mesh_Spiral3D.xdmf") as infile:
    infile.read(mesh)
mvc = MeshValueCollection("size_t", mesh, 2)
with XDMFFile("mf_Spiral3D.xdmf") as infile:
    infile.read(mvc, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)
It_facet = SubsetIterator(mf,14)

For 3D models, the labelling can be viewed in Paraview by importing the subdomains file, for example "mf_Spiral3D.xdmf", and using "Hover Cells" to get the physical label.