Fluids simulation#

This example demonstrates how to solve the flow around a NACA airfoil using Fluent.

Starting from the mesh created in the previous example, the script solves the flow around a NACA airfoil using Fluent. The parameters are set to solve the flow with a Mach number of 0.3, a temperature of 255.56 K, an angle of attack of 3.06 degrees, and a pressure of 80600 Pa. Overall, these are the conditions for a compressible flow.

import os

import ansys.fluent.core as pyfluent
import numpy as np

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")

# Simulation parameters
SIM_MACH = 0.3  # 0.8395 # Mach number
SIM_TEMPERATURE = 255.56  # In Kelvin
SIM_AOA = 3.06  # in degrees
SIM_PRESSURE = 80600  # in Pa

Solve the flow around the airfoil#

The function solve_airfoil_flow solves the flow around a NACA airfoil using Fluent. The function takes the following parameters:

  • naca_airfoil: NACA 4-digits airfoil number.

  • sim_mach: Mach number.

  • sim_temperature: Temperature in Kelvin.

  • sim_aoa: Angle of attack in degrees.

  • sim_pressure: Pressure in Pascal.

  • data_dir: Directory to save the mesh file.

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

  • iter_count: Number of iterations to solve. The default is 25.

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

The function switches to the Fluent solver and loads the mesh. It defines the model, material, boundary conditions, operating conditions, initializes the flow field, saves the case file, solves for the requested iterations, and exits Fluent.

def solve_airfoil_flow(
    naca_airfoil: str,
    sim_mach: float,
    sim_temperature: float,
    sim_aoa: float,
    sim_pressure: float,
    data_dir: str,
    container_dict: dict | None = None,
    iter_count: int = 25,
    ui_mode: str | None = None,
):
    """
    Solve the flow around a NACA airfoil using Fluent.

    Parameters
    ----------
    naca_airfoil : str
        NACA 4-digits airfoil number.
    sim_mach : float
        Mach number.
    sim_temperature : float
        Temperature in Kelvin.
    sim_aoa : float
        Angle of attack in degrees.
    sim_pressure : float
        Pressure in Pascal.
    data_dir : str
        Directory to save the mesh file.
    container_dict : dict, optional
        Configuration for the Fluent container. The default is None.
    iter_count : int, optional
        Number of iterations to solve. The default is ``25``.
    ui_mode : str, optional
        User interface mode. The default is None.
    """

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

    # Load mesh
    solver.file.read_mesh(file_name=f"{data_dir}/NACA_Airfoil_{naca_airfoil}.msh.h5")

    # Verify the mesh
    solver.mesh.check()

    # Define the model
    # model : k-omega
    # k-omega model : sst
    viscous = solver.setup.models.viscous
    viscous.model = "k-omega"
    viscous.k_omega_model = "sst"

    # Define material
    #
    # density : ideal-gas
    # viscosity : sutherland
    # viscosity method : three-coefficient-method
    # reference viscosity : 1.716e-05 [kg/(m s)]
    # reference temperature : 273.11 [K]
    # effective temperature : 110.56 [K]
    air = solver.setup.materials.fluid["air"]
    air.density.option = "ideal-gas"
    air.viscosity.option = "sutherland"
    air.viscosity.sutherland.option = "three-coefficient-method"
    air.viscosity.sutherland.reference_viscosity = 1.716e-05
    air.viscosity.sutherland.reference_temperature = 273.11
    air.viscosity.sutherland.effective_temperature = 110.56

    # Define Boundary conditions
    #
    # gauge pressure : 0 [Pa]
    # turbulent intensity : 5 [%]solve
    # turbulent viscosity ratio : 10
    #
    solver.setup.boundary_conditions.set_zone_type(
        zone_list=["inlet-fluid"], new_type="pressure-far-field"
    )

    inlet_fluid = solver.setup.boundary_conditions.pressure_far_field["inlet-fluid"]
    aoa = np.deg2rad(sim_aoa)
    if solver.get_fluent_version() < pyfluent.FluentVersion.v242:
        inlet_fluid.gauge_pressure = 0
        inlet_fluid.m = sim_mach
        inlet_fluid.t = sim_temperature
        inlet_fluid.flow_direction[0] = np.cos(aoa)
        inlet_fluid.flow_direction[1] = np.sin(aoa)
        inlet_fluid.turbulent_intensity = 0.05
        inlet_fluid.turbulent_viscosity_ratio_real = 10

    else:
        inlet_fluid.momentum.gauge_pressure = 0
        inlet_fluid.momentum.mach_number = sim_mach
        inlet_fluid.thermal.temperature = sim_temperature
        inlet_fluid.momentum.flow_direction[0] = np.cos(aoa)
        inlet_fluid.momentum.flow_direction[1] = np.sin(aoa)
        inlet_fluid.turbulence.turbulent_intensity = 0.05
        inlet_fluid.turbulence.turbulent_viscosity_ratio = 10

    # Define operating conditions
    #
    solver.setup.general.operating_conditions.operating_pressure = sim_pressure

    # Initialize flow field
    solver.solution.initialization.hybrid_initialize()

    # Save case file
    solver.file.write(
        file_name=f"{data_dir}/NACA_Airfoil_{naca_airfoil}_initialization.cas.h5",
        file_type="case",
    )

    # Solve for requested iterations
    solver.solution.run_calculation.iterate(iter_count=iter_count)
    solver.file.write(
        file_name=f"{data_dir}/NACA_Airfoil_{naca_airfoil}_resolved.cas.h5",
        file_type="case",
    )
    # Write data file as well
    solver.file.write(
        file_name=f"{data_dir}/NACA_Airfoil_{naca_airfoil}_resolved.dat.h5",
        file_type="data",
    )

    # Exit Fluent
    solver.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
    # Solve the flow around the airfoil
    solve_airfoil_flow(
        NACA_AIRFOIL,
        SIM_MACH,
        SIM_TEMPERATURE,
        SIM_AOA,
        SIM_PRESSURE,
        "/mnt/pyfluent",
        container_dict=container_dict,
    )
else:
    # Solve the flow around the airfoil
    solve_airfoil_flow(NACA_AIRFOIL, SIM_MACH, SIM_TEMPERATURE, SIM_AOA, SIM_PRESSURE, 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.
Fast-loading "/ansys_inc/v251/fluent/fluent25.1.0/addons/afd/lib/hdfio.bin"
Done.

Reading from 48e045c6fbaf:"/mnt/pyfluent/NACA_Airfoil_6412.msh.h5" in NODE0 mode ...
  Reading mesh ...
     4072217 cells,     2 cell zones ...
        1875396 mixed cells,  zone id: 117
        2196821 mixed cells,  zone id: 122
    17982795 faces,     6 face zones ...
            829 polygonal wall faces,  zone id: 24
         111846 polygonal wall faces,  zone id: 21
            254 polygonal velocity-inlet faces,  zone id: 23
            254 polygonal pressure-outlet faces,  zone id: 22
        9651946 mixed interior faces,  zone id: 124
        8217666 mixed interior faces,  zone id: 119
    10413674 nodes,     4 node zones ...

Building...
     mesh
        distributing mesh
                parts....,
                faces....,
                nodes....,
                cells....,
        bandwidth reduction using Reverse Cuthill-McKee: 1007460/30522 = 33.0077
  Reading boundary layer flags ...
  Done.

     materials,
     interface,
     domains,
     zones,
        airfoil-faces-shadow
        Skipping thread 15 of domain 1 (not referenced by grid).
        Skipping thread 16 of domain 1 (not referenced by grid).
        Skipping thread 17 of domain 1 (not referenced by grid).
        Skipping thread 18 of domain 1 (not referenced by grid).
        Skipping thread 19 of domain 1 (not referenced by grid).
        Skipping thread 20 of domain 1 (not referenced by grid).
        Skipping thread 12 of domain 1 (not referenced by grid).
        surrounding-faces
        airfoil-faces
        inlet-fluid
        outlet-fluid
        interior--a419ce14-7279-4cad-8130-c4fcea5b4e0b-fluid
        interior--a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil
        a419ce14-7279-4cad-8130-c4fcea5b4e0b-airfoil
        a419ce14-7279-4cad-8130-c4fcea5b4e0b-fluid
     parallel,
Done.
Mesh is now scaled to meters.

 Domain Extents:
   x-coordinate: min (m) = -4.500000e+00, max (m) = 5.500000e+00
   y-coordinate: min (m) = -1.000000e+00, max (m) = 1.000000e+00
   z-coordinate: min (m) = -2.000000e+00, max (m) = 3.000000e+00
 Volume statistics:
   minimum volume (m3): 1.449715e-12
   maximum volume (m3): 1.479827e-01
     total volume (m3): 1.000000e+02
 Face area statistics:
   minimum face area (m2): 1.698896e-09
   maximum face area (m2): 6.993715e-01
 Checking mesh......................................
Done.

Note: Settings to improve the robustness of pathline and
      particle tracking have been automatically enabled.


Note: Enabling energy equation as required by material density method.

Initialize using the hybrid initialization method.

Checking case topology...
-This case combines farfield, inlets and outlets
-Pressure information is available at the boundaries

        iter            scalar-0                scalar-1

        1               1.000000e+00    0.000000e+00
        2               6.757056e-05    0.000000e+00
        3               2.115947e-05    0.000000e+00
        4               9.249542e-06    0.000000e+00
        5               4.333018e-06    0.000000e+00
        6               2.375263e-06    0.000000e+00
        7               1.222223e-06    0.000000e+00
        8               7.546930e-07    0.000000e+00
        9               4.229692e-07    0.000000e+00
        10              2.786517e-07    0.000000e+00

Hybrid initialization is done.

Writing to 48e045c6fbaf:"/mnt/pyfluent/NACA_Airfoil_6412_initialization.cas.h5" in NODE0 mode and compression level 1 ...
Grouping cells for Laplace smoothing ...
  Done.     4072217 cells,     2 zones ...
    18094641 faces,     7 zones ...
    10508610 nodes,     1 zone  ...
  Done.

  Writing boundary layer flags ...
  Done.
Done.

  iter  continuity  x-velocity  y-velocity  z-velocity      energy           k       omega     time/iter
     1  1.0000e+00  2.7421e-04  2.7236e-04  1.4056e-04  3.8083e-05  9.7775e-01  4.9402e-01  0:15:16   24
     2  6.6553e-01  2.3663e-04  4.6346e-04  9.2685e-05  3.6591e-05  9.5847e-01  4.9024e-01  0:14:23   23
     3  7.5075e-01  2.3586e-04  3.1198e-04  7.2858e-05  3.6963e-05  9.0247e-01  4.8389e-01  0:13:36   22
     4  7.6554e-01  2.1443e-04  2.1725e-04  6.5580e-05  3.5001e-05  7.1996e-01  4.7299e-01  0:12:51   21
     5  7.8208e-01  1.8411e-04  1.5302e-04  6.1577e-05  3.0255e-05  4.4751e-01  4.5395e-01  0:11:52   20
     6  7.7069e-01  1.5699e-04  1.1102e-04  5.8013e-05  2.5232e-05  2.2944e-01  4.2068e-01  0:10:59   19
     7  7.1406e-01  1.4846e-04  8.3758e-05  5.4477e-05  2.0975e-05  1.2287e-01  3.6508e-01  0:10:18   18
     8  6.3312e-01  1.4494e-04  6.6335e-05  5.0023e-05  1.8626e-05  6.4621e-02  2.8370e-01  0:09:36   17
     9  5.4326e-01  1.3880e-04  5.6236e-05  4.4854e-05  1.6710e-05  3.5177e-02  1.9121e-01  0:08:56   16
    10  4.6474e-01  1.2815e-04  4.8714e-05  3.9022e-05  1.5098e-05  2.3649e-02  1.1087e-01  0:08:18   15
    11  3.9910e-01  1.2049e-04  4.2707e-05  3.3061e-05  1.4290e-05  2.2138e-02  5.7937e-02  0:07:41   14

  iter  continuity  x-velocity  y-velocity  z-velocity      energy           k       omega     time/iter
    12  3.4386e-01  1.1409e-04  3.6625e-05  2.7246e-05  1.4558e-05  2.5660e-02  2.9312e-02  0:07:05   13
    13  2.9667e-01  1.0823e-04  3.1044e-05  2.2013e-05  1.5134e-05  2.8590e-02  1.5224e-02  0:06:31   12
    14  2.5985e-01  1.0060e-04  2.5957e-05  1.7744e-05  1.4903e-05  3.0026e-02  8.5020e-03  0:05:54   11
    15  2.3357e-01  9.2352e-05  2.1958e-05  1.4675e-05  1.3970e-05  2.9825e-02  5.2596e-03  0:05:19   10
    16  2.1280e-01  8.7288e-05  1.8921e-05  1.2686e-05  1.3124e-05  2.8313e-02  3.6212e-03  0:04:46    9
    17  1.9796e-01  8.4308e-05  1.6743e-05  1.1543e-05  1.2479e-05  2.6645e-02  2.7536e-03  0:04:14    8
    18  1.8749e-01  8.2697e-05  1.5284e-05  1.0888e-05  1.1834e-05  2.4919e-02  2.2037e-03  0:03:42    7
    19  1.7943e-01  7.9897e-05  1.4470e-05  1.0509e-05  1.0852e-05  2.2963e-02  1.8215e-03  0:03:10    6
    20  1.7087e-01  7.5169e-05  1.3974e-05  1.0292e-05  9.6215e-06  2.0551e-02  1.5688e-03  0:02:37    5
    21  1.6232e-01  6.8958e-05  1.3370e-05  9.9768e-06  8.3725e-06  1.7582e-02  1.3926e-03  0:02:05    4
    22  1.5111e-01  6.2162e-05  1.2361e-05  9.3193e-06  7.3062e-06  1.4961e-02  1.2516e-03  0:01:33    3

  iter  continuity  x-velocity  y-velocity  z-velocity      energy           k       omega     time/iter
    23  1.3799e-01  5.5439e-05  1.1085e-05  8.3213e-06  6.4264e-06  1.2894e-02  1.1331e-03  0:01:02    2
    24  1.2548e-01  4.9498e-05  9.6731e-06  7.1510e-06  5.7136e-06  1.1139e-02  1.0270e-03  0:00:31    1
    25  1.1410e-01  4.4105e-05  8.4225e-06  6.2170e-06  5.0967e-06  9.6205e-03  9.3127e-04  0:00:00    0

Writing to 48e045c6fbaf:"/mnt/pyfluent/NACA_Airfoil_6412_resolved.cas.h5" in NODE0 mode and compression level 1 ...
Grouping cells for Laplace smoothing ...
     4072217 cells,     2 zones ...
    18094641 faces,     7 zones ...
    10508610 nodes,     1 zone  ...
  Done.

  Writing boundary layer flags ...
  Done.
Done.

Writing to 48e045c6fbaf:"/mnt/pyfluent/NACA_Airfoil_6412_resolved.dat.h5" in NODE0 mode and compression level 1 ...
  Writing results.
Done.

Total running time of the script: (18 minutes 9.072 seconds)