Skip to content

A cfMesh workflow to speed up and improve your meshing

Here, I’ll cover the basic workflow that I implement when I am using cfMesh.

First, when do I use cfMesh? I love cfMesh. I find it robust, easy to use (with this workflow), and gives high quality hex-dominant meshes for use with OpenFOAM. But there are a few cases where I do not use cfMesh. These are when I am meshing multiple regions (such as rotating zones or conjugate heat transfer) and when I have decided (for some reason) that I am going to do a tet-dominant mesh. With that said, both of those can be accomplished with cfMesh, but I prefer snappyHexMesh for multi-region meshing, and I prefer the built-in Netgen, and gmsh modules of Salome if I am doing a tet-mesh.

What do you need to start?

  • For this workflow using cfMesh, you will obviously need a working installation of cfMesh. Luckily it now comes preloaded as part of OFv18. Even if you prefer a different openfoam flavor, you can use the OFv18 cfMesh to create the mesh, and the mesh will still work in the other flavors.
  • You will also need a working installation of Salome.

Geometry Preparation

Glider model obtained from GrabCad:

Typically, I first start in a CAD program (it doesn’t matter which) and produce a 3D .step, .iges, or .brep representation of the fluid domain. This means that if you are doing an internal flow, you want a geometry file representing everywhere the fluid will go. For an external flow, you want a large open domain with your geometry subtracted from it. This is easily accomplished with a simple Boolean subtraction. You can do this in pretty much any CAD programs. If you are like me and frequently just get the CAD file from a client, I usually load it into the CAD, draw my fluid domain, and perform the subtraction. My CAD software of choice is Onshape (primarily for cost reasons and its similarity Solidworks). Alternatively you can perform boolean subtractions directly in Salome.

For an example, I’ll use the Glider geometry shown in the figure above. I downloaded this model from Grabcad, loaded it into Onshape, cleaned up some of the surfaces and subtracted the glider from a fluid domain:

FMS File Preparation

FMS is the recommended file format for using cfMesh as it contains all of the information that the mesher needs. Even as a relatively heavy user of cfMesh I never knew the answer to the question HOW DO I PRODUCE A FULL FMS FILE?. Yes, you can use the surfaceFeatureEdges script from cfMesh to create an FMS file from your stl or obj file, but these files don’t typically contain all of the patch information you want.

For a very long time, I used cfMesh using a very tedious workflow where I would convert my geometry to fms or ftr, mesh it in using automatic patch naming from cfMesh, load it into paraview, and manually see which patch was which. Needless to say this was time consuming and frustrating. In one project, I was modeling a diffuser with over 100 slots in it. surfaceFeatureEdges extracted all of the sides of the slots as separate patches. I then manually renamed them all.. ugh. Luckily, I have learned my lesson, and I can share with you the trick. Salome.

cfMesh actually comes with two python scripts for Salome. These can be used to output an fms file that contains ALL of the information you need, and also lets you use the Salome GUI to name patches and refinement boundaries.

Selecting Patches

Back on topic: First load your STEP, IGES, or BREP file into geometry module of Salome. Now, we want to create and name our patches. To do this, use the menu New Entity -> Group -> Create Group. Make sure the geometry file is selected in the tree. A window will open where you can select points, edges, surfaces, or solids. We want surfaces.

Type the name of the patch you are going to select. Select the face in the viewer, and click add. Finally hit apply. Repeat this for each patch. In most cases, you will need to hide some surfaces to see the surfaces of the geometry. In those cases, just select the faces you aren’t currently selecting and then hit “Hide Selected”.

Extract Edges

Before we move on to creating our surface mesh, we should extract our edges for cfMesh. This is done by executing the “” python script. Select your the geometry file in the tree, hit CTRL-t, then select the script. If you are running OF1806, it is located in OpenFOAM-v1806/modules/cfmesh/python/Salome.

Generate Surface Mesh

It seems tedious to generate a mesh… before generating a mesh. But rest assured we are only creating a surface mesh. And it should run fast, unless you have a complicated geometry. Regardless, if you choose the default settings of either Netgen 1D-2D, or Mefisto with adaptive wire discretization, it should be fast and produce a good surface triangulation. I have had one slow case, but with tweaking the settings a bit, it wasn’t a problem. For this glider example here, I used a Mefisto meshing and wire discretization on the glider edges to control the grid size.

Dialog to select NETGEN 1D-2D defautls

After building the mesh (hitting the little gear button), we now just need to load our patches from the geometry module, and export to an FMS file.

Surface mesh of outer boundaries created by Salome

Surface mesh of glider created by Salome before exporting to cfMesh

Within the mesh module, select your mesh, and then go to Mesh->Create Groups from Geometry . Select your patches AND your featureEdges (as cfMesh needs these) and hit Apply and Close.

Create Groups from Geometry Dialog

Finally, we are ready to export to an FMS file. To do this, select your mesh on the tree. First you load the Salome module. Hit CTRL-t, and select the python script. This only loads the module. Now, in the python shell at the bottom the screen you write: triSurf().writeFms(‘FileName.fms’) and hit enter. This only takes a few seconds then writes the FMS file in your Salome directory. Copy it into your OpenFOAM directory and you are ready to mesh it with cfMesh.

Mesh Using cfMesh

From here on out, is basic cfMesh meshing. In your system/meshDict file you must select the FileName.fms that you created in the previous steps. I will not cover the meshDict options I used here, as the focus of this article was on the workflow described in the previous sections. But here are some images of the type of results you can expect from cfMesh:

Glider mesh obtained with cfMesh
Surface grid and crinkle-cut showing layers on fuselage
Surface mesh and crinkle-cut showing layers at the wing trailing edge
Crinkle cut showing mesh behind wing

As the general usage of cfMesh is covered in detail in the cfMesh manual, and in another post (the Ahmed Body) I will just give a couple tips and tricks here. A specific Tips and Tricks post may follow.

Use renameBoundary dict to simplify your case

In this workflow, I usually create surfaces for refinement within Salome, and export them. However, having a bunch of different patches can be a bit of a pain. To address this, I export the patches from Salome, select them for refinement within my meshDict, but also rename them in the renameBoundary sub-dict. If you have multiple patches renamed to the same thing, they all get grouped into a single patch. So you can have 10 different refinement patches that you created, but then group them all into a single patch afterwards. Making case setup simpler.

Use the generateBoundaryLayers command

I have found that I get much better results if I first mesh without boundary layers, and then add them after using the generateBoundaryLayers command. This is for a couple reasons. First, this lets you look at the basic mesh and make sure that it is satisfactory. Your mesh without boundary layers should be as high quality as you can make it. Secondly, you can see how the layer addition affects the final mesh. Layer addition can be somewhat an art. And doing it separately makes this much easier. If your base mesh has bad quality, it will be even worse after layering.

Use the crinkle-slice option in Paraview

When viewing your mesh, make sure to select the “crinkle-slice” option when viewing your mesh. If you just take a regular slice (a) you aren’t seeing the actual cells you are seeing a slice of them, and (b) the rendering puts some cross lines which don’t actually exist. You want to see the actual cells, and without extra non-existent lines.

Use the improveMeshQuality command

In some cases where I have had bad mesh quality, I have improved it by running the improveMeshQuality command. It basically runs through some of the improvement algorithms that are executed during the actual meshing, but runs through them again. I have had some success with it, but havent used it extensively. Try your best to have a good mesh quality right from the get-go (duh).

Use checkMesh

This sounds obvious… but checkMesh works. It gives you important statistics on the quality of your mesh. In my experience, take a very close note of nonOrthogonality. If it is high (>70 or so), you need to improve your mesh or introduce some special schemes to account for this. Regardless, you should know how orthogonal your mesh is.

Use .eMesh files for additional control

For some shapes, you may need extra refinement based on edges instead of faces. In this case, you can use the edgeMeshRefinement sub-dict and use an eMesh or vtk file defining the edges.

Good Luck!

If you are struggling with CFD, are interested in getting started, or are looking for consulting services, visit for information on CFD consulting services including training, development, private webinars and other simulation services.

8 thoughts on “A cfMesh workflow to speed up and improve your meshing Leave a comment

  1. Hi,
    many thanks for this article which clarifies a lot the methodology.
    Would you have any advice about how to control a regular distribution on the domain outer faces, ideally with some extrusion scale factor?
    whether it is tetra or poly meshes ?

  2. Hello,
    I followed your workflow using Salome 8.5, but when I try to mesh using the generated .fms file, i get the following error:

    ” Expected a ‘)’ or a ‘}’ while reading FixedList, found on line 9674 the label 2650

    file: C:/kws_work/case/bodyPatches/sprayMesh.fms at line 9674. ”

    Any idea about the origin of this problem???


    • kinda, If you open the fms files you should find a list of nodes/points followed by a list of triangles. If you use vim, you can use % to navigate between the parenthesis. This warning happens when the list of triangles is larger than 3. For some reason when you export the files it includes extra nodes in the triangles list.

      I will troubleshoot this at some point. but my “workaround” was to go back to salome 8.5 (I was using 9.4 when I got this error), re-do my mesh, and use the original python scripts (I think the ones that came with openfoam 1812).

      If I have some time I will go through the newer python 3 scripts

  3. Thanks for sharing this well explained workflow! But I met a problem.. After following the steps I found the mesh after cfMesh didn’t follow the face mesh generated by salome. It seems the face mesh didn’t affect the mesh procedure. Do I need to specify anything besides ‘surfaceFile “filename.fms” ‘ in meshDict?

  4. Hi,
    Thanks for the article! Very helpful. I have questions I am wondering if you can help me:
    I am using Salome 9.3 and OpenFOAM-v1906+ (also tried OpenFOAM-v1812+). When I tried to run the python script to extract the feature edges, I got errors (syntax errors). OS I am using is Linux Mint 19.1. Do I need to update the python script?



Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.