Mesh generation#

This example demonstrates how to generate a mesh for a NACA airfoil using Fluent Meshing.

Starting from the geometry created in the previous example, the script generates a mesh using Fluent Meshing. The parameters are set to generate a mesh with a surface mesh size of 2 and 1000, and a volume mesh size of 512. It leverages the Fluent Meshing Workflow API to create the mesh.

import os

import ansys.fluent.core as pyfluent

Parameters for the script#

The following parameters are used to control the script execution. You can modify these parameters to suit your needs.

# NACA 4-digits airfoil geometry
NACA_AIRFOIL = "6412"

# Data directory
DATA_DIR = os.path.join(os.path.dirname(__file__), "outputs")

Generate the mesh#

The function generate_mesh generates a mesh for a NACA airfoil using Fluent Meshing. The function takes the following parameters:

  • naca_airfoil: NACA 4-digits airfoil number.

  • data_dir: Directory to save the mesh file.

  • ui_mode: User interface mode. The default is None.

  • container_dict: Configuration for the Fluent container. The default is None.

The function launches Fluent Meshing and initializes the workflow for watertight geometry. It imports the geometry, generates the surface mesh, describes the geometry, updates boundaries and regions, adds boundary layers, generates the volume mesh, checks the mesh, writes the mesh, and closes Fluent Meshing.

def generate_mesh(
    naca_airfoil: str,
    data_dir: str,
    ui_mode: str | None = None,
    container_dict: dict | None = None,
):
    """
    Generate a mesh for a NACA airfoil using Fluent Meshing.

    Parameters
    ----------
    naca_airfoil : str
        NACA 4-digits airfoil number.
    data_dir : str
        Directory to save the mesh file.
    ui_mode : str, optional
        User interface mode. The default is None.
    container_dict : dict, optional
        Configuration for the Fluent container. The default is None.
    """

    # Launch Fluent Meshing
    if container_dict is not None:
        meshing = pyfluent.launch_fluent(
            container_dict=container_dict,
            start_container=True,
            precision="double",
            processor_count=4,
            mode="meshing",
            ui_mode="no_gui_or_graphics",
            cwd=data_dir,
            cleanup_on_exit=False,
        )
    else:
        meshing = pyfluent.launch_fluent(
            precision="double",
            processor_count=4,
            mode="meshing",
            ui_mode=ui_mode,
            cwd=data_dir,
        )

    # Initialize workflow - Watertight Geometry
    meshing.workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")

    # Import the geometry
    geo_import = meshing.workflow.TaskObject["Import Geometry"]
    geo_import.Arguments.set_state(
        {
            "FileName": os.path.join(data_dir, f"NACA_Airfoil_{naca_airfoil}.pmdb"),
        }
    )
    geo_import.Execute()

    # Generate surface mesh
    surface_mesh_gen = meshing.workflow.TaskObject["Generate the Surface Mesh"]
    surface_mesh_gen.Arguments.set_state(
        {"CFDSurfaceMeshControls": {"MaxSize": 1000, "MinSize": 2}}
    )
    surface_mesh_gen.Execute()

    # Describe the geometry
    describe_geo = meshing.workflow.TaskObject["Describe Geometry"]
    describe_geo.UpdateChildTasks(SetupTypeChanged=False)
    describe_geo.Arguments.set_state(
        {"SetupType": "The geometry consists of only fluid regions with no voids"}
    )
    describe_geo.UpdateChildTasks(SetupTypeChanged=True)
    describe_geo.Execute()

    # Update boundaries
    meshing.workflow.TaskObject["Update Boundaries"].Execute()

    # Update regions
    meshing.workflow.TaskObject["Update Regions"].Execute()

    # Add boundary layers
    add_boundary_layer = meshing.workflow.TaskObject["Add Boundary Layers"]
    add_boundary_layer.Arguments.set_state({"NumberOfLayers": 12})
    add_boundary_layer.AddChildAndUpdate()

    # Generate volume mesh
    volume_mesh_gen = meshing.workflow.TaskObject["Generate the Volume Mesh"]
    volume_mesh_gen.Arguments.set_state(
        {
            "VolumeFill": "poly-hexcore",
            "VolumeFillControls": {"HexMaxCellLength": 512},
            "VolumeMeshPreferences": {
                "CheckSelfProximity": "yes",
                "ShowVolumeMeshPreferences": True,
            },
        }
    )
    volume_mesh_gen.Execute()

    # Check mesh
    meshing.tui.mesh.check_mesh()

    # Write mesh
    meshing.tui.file.write_mesh(os.path.join(data_dir, f"NACA_Airfoil_{naca_airfoil}.msh.h5"))

    # Close Fluent Meshing
    meshing.exit()

Executing the mesh generation#

The previous function is called to generate the mesh for the NACA airfoil. The mesh is saved in the outputs directory. Depending on the environment, the script will run in a container or locally.

Depending on the environment, the script will run in a container or locally.

if os.getenv("PYANSYS_WORKFLOWS_CI") == "true":
    container_dict = {
        "host_mount_path": DATA_DIR,
        "timeout": 300,
    }
    # https://fluent.docs.pyansys.com/version/stable/api/general/launcher/fluent_container.html
    generate_mesh(NACA_AIRFOIL, "/mnt/pyfluent", container_dict=container_dict)
else:
    generate_mesh(NACA_AIRFOIL, DATA_DIR)
pyfluent.general WARNING: Using 'mount_source = /home/runner/work/pyansys-workflows/pyansys-workflows/geometry-mesh-fluent/outputs' for 'configure_container_dict()' instead of 'host_mount_path = /home/runner/work/pyansys-workflows/pyansys-workflows/geometry-mesh-fluent/outputs'.
pyfluent.launcher WARNING: Starting Fluent container mounted to /home/runner/work/pyansys-workflows/pyansys-workflows/geometry-mesh-fluent/outputs, with this path available as /mnt/pyfluent for the Fluent session running inside the container.

Warning: PMDB file will not be saved as the same is being imported.

Importing one geom object per program-controlled and one zone per body ...
writing cad import logs to "/mnt/pyfluent/cadImport1745724472.106028.log"

Reading "/mnt/pyfluent/FM_47a74122f62a_149/out1745724472.103745149.tgf"...

nodes: 1612
edges: 812
faces: 1604
cells: 0
generating pointers...done.
extracting boundary entities...
 1612 boundary nodes.
 1604 boundary faces.
 4 boundary face zones.
done.
analyzing boundary connectivity...done.


---------------- Import of NACA_Airfoil_6412, consisting of 2 parts/objects, complete.


---------------- Import complete in  0.04 minutes.
Writing "/mnt/pyfluent/FM_47a74122f62a_149/TaskObject3.msh.h5" ...
writing 1 node zones
writing 6 edge zones
writing 4 face zones
writing node curvature data
done.
---------------- The Global Max size was adjusted to 1000

Importing one mesh object per program-controlled and one zone per body ...
writing cad import logs to "/mnt/pyfluent/cadImport1745724474.933534.log"

Reading "/mnt/pyfluent/FM_47a74122f62a_149/out1745724474.931875149.tgf"...

nodes: 127452
edges: 15813
faces: 223338
cells: 0
appending mesh...
done.
generating pointers...done.
extracting boundary entities...
 129064 boundary nodes.
 224942 boundary faces.
 8 boundary face zones.
done.

Reading "/mnt/pyfluent/FM_47a74122f62a_149/NACA_Airfoil_6412.sf"...

ANSYS(R) TGLib(TM) 3D, revision 24.1.0
 Read 277427 vertices
0 faces marked.

    computing regions...
Warning: Region is named after face zone label "a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil" based on alphabetical order of face zone labels (a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil airfoil-faces).
done


-------------------------------------------- --------------------- -------------------- ---------------- ----------
                                        name skewed-cells (> 0.80)    averaged-skewness maximum-skewness face count
-------------------------------------------- --------------------- -------------------- ---------------- ----------

  a419ce14-7279-4cad-8130-c4fcea5b4e0b-fluid                     0           0.14042012       0.79997719     221266
a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil                     0           0.14118697       0.79997719     219720
-------------------------------------------- --------------------- -------------------- ---------------- ----------
                                        name skewed-cells (> 0.80)    averaged-skewness maximum-skewness face count
-------------------------------------------- --------------------- -------------------- ---------------- ----------

a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil                     0            0.1408022       0.79997719     221266

---------------- After Surface mesh, the model consists of 2 fluid/solid regions and 0 voids.

---------------- Surface Meshing of NACA_Airfoil_6412 complete in  0.14 minutes, with a maximum skewness of  0.80.


---------------- Velocity-inlet zone type was automatically assigned to zones containing the string '*inlet*'.

---------------- Pressure-outlet zone type was automatically assigned to zones containing the string '*outlet*'.

---------------- Describe Geometry task complete in  0.00 minutes.

---------------- Boundary Conditions Updated

---------------- Regions Updated

Created Scoped Prism: smooth-transition_1

---------------- Inflation control added to a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil
Writing "/mnt/pyfluent/FM_47a74122f62a_149/TaskObject11.msh.h5" ...
writing 2 node zones
writing 13 edge zones
writing 8 face zones
writing node curvature data
done.
    updating regions...
    done.
checking object "a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil"...
    skipping validating regions of mesh object "a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil"...done.
auto meshing object a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil...

processing scoped prisms...
    starting orientation...
done.
    setting prism growth...done.
done.
Identifying Topology...

The octree hexcore cells will be refined using local surface mesh sizes and body of influence (boi) size controls, if there are any defined.
Generating Prisms...

Generating initial mesh...

Refining mesh...

Create polyhedra ...

delete virtual and dead zones.

Merging zones...

Cleaning up dead entities...


Merging Domains...
done.

                     name       id cells (quality < 0.05)  minimum quality cell count
------------------------- -------- ---------------------- ---------------- ----------
a419ce14-7279-4cad-8130-c4fcea5b4e0b-fluid      122                     16     0.0090161806    2196821
a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil      117                      0       0.10017045    1875396

                     name       id cells (quality < 0.05)  minimum quality cell count
------------------------- -------- ---------------------- ---------------- ----------
          Overall Summary     none                     16     0.0090161806    4072217

Total Number of Cell Zones : 2

[Quality Measure : Orthogonal Quality]

---------------- Volume mesh creation completed in :  5.23 minutes

---------------- 4072217 cells were created in :  5.32 minutes

---------------- The volume meshing of a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil is complete.


Domain extents.
  x-coordinate: min = -4.500000e+03, max = 5.500000e+03.
  y-coordinate: min = -1.000000e+03, max = 1.000000e+03.
  z-coordinate: min = -2.000000e+03, max = 3.000000e+03.
Volume statistics.
  minimum volume: 1.449715e-03.
  maximum volume: 1.479827e+08.
    total volume: 1.000000e+11.
Face area statistics.
   minimum face area: 1.698896e-03.
   maximum face area: 6.993715e+05.
   average face area: 1.369629e+02.
Checking number of nodes per edge.
Checking number of nodes per face.
Checking number of nodes per cell.
Checking number of faces/neighbors per cell.
Checking cell faces/neighbors.
Checking isolated cells.
Checking face handedness.
Checking periodic face pairs.
Checking face children.
Checking face zone boundary conditions.
Checking for invalid node coordinates.
Checking poly cells.
Checking zones.
Checking neighborhood.
Checking modified centroid.
Checking non-positive or too small area.
Checking face zones thread type.

Total running time of the script: (5 minutes 56.560 seconds)