Note
Go to the end to download the full example code.
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 = {
"fluent_image": f"{os.environ['FLUENT_DOCKER_IMAGE']}:{os.environ['FLUENT_IMAGE_TAG']}",
"host_mount_path": DATA_DIR,
"license_server": os.environ["ANSYSLMD_LICENSE_FILE"],
"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/v242/fluent/fluent24.2.0/addons/afd/lib/hdfio.bin"
Done.
Reading from 24203702884f:"/mnt/pyfluent/NACA_Airfoil_6412.msh.h5" in NODE0 mode ...
Reading mesh ...
4071450 cells, 2 cell zones ...
1874429 mixed cells, zone id: 113
2197021 mixed cells, zone id: 118
17742510 faces, 6 face zones ...
821 polygonal wall faces, zone id: 24
111648 polygonal wall faces, zone id: 21
254 polygonal velocity-inlet faces, zone id: 23
254 polygonal pressure-outlet faces, zone id: 22
9515305 mixed interior faces, zone id: 120
8114228 mixed interior faces, zone id: 115
10080893 nodes, 4 node zones ...
Building...
mesh
distributing mesh
parts....,
faces....,
nodes....,
cells....,
bandwidth reduction using Reverse Cuthill-McKee: 998809/33416 = 29.8901
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).
surrounding-faces
airfoil-faces
inlet-fluid
outlet-fluid
interior--ca178494-75a3-401c-938e-096668384bfe-fluid
interior--fluid
fluid
ca178494-75a3-401c-938e-096668384bfe-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): 8.468777e-13
maximum volume (m3): 1.422774e-01
total volume (m3): 1.000000e+02
Face area statistics:
minimum face area (m2): 2.280691e-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 1.000000e+00
2 6.645157e-05 3.378266e-07
3 2.000818e-05 1.336523e-07
4 1.179705e-05 1.067819e-07
5 5.258877e-06 3.525356e-08
6 2.720042e-06 3.793973e-08
7 1.356182e-06 1.184089e-08
8 1.018637e-06 1.410328e-08
9 5.315569e-07 4.750358e-09
10 3.906237e-07 4.863557e-09
Hybrid initialization is done.
Writing to 24203702884f:"/mnt/pyfluent/NACA_Airfoil_6412_initialization.cas.h5" in NODE0 mode and compression level 1 ...
Grouping cells for Laplace smoothing ...
Done. 4071450 cells, 2 zones ...
17854158 faces, 7 zones ...
10189562 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.7927e-04 2.7549e-04 1.4197e-04 3.8109e-05 9.7772e-01 4.9401e-01 0:15:08 24
2 6.3285e-01 2.3948e-04 4.6531e-04 9.3791e-05 3.6542e-05 9.5841e-01 4.9022e-01 0:14:19 23
3 6.7535e-01 2.3960e-04 3.1404e-04 7.3400e-05 3.7161e-05 9.0243e-01 4.8386e-01 0:13:33 22
4 6.7792e-01 2.1568e-04 2.1945e-04 6.6004e-05 3.5185e-05 7.2034e-01 4.7295e-01 0:12:56 21
5 6.8850e-01 1.8595e-04 1.5467e-04 6.1813e-05 3.0405e-05 4.4829e-01 4.5389e-01 0:11:59 20
6 6.8022e-01 1.5790e-04 1.1210e-04 5.8129e-05 2.5294e-05 2.3021e-01 4.2061e-01 0:11:06 19
7 6.3170e-01 1.4876e-04 8.4635e-05 5.4588e-05 2.0944e-05 1.2310e-01 3.6502e-01 0:10:16 18
8 5.6177e-01 1.4460e-04 6.6812e-05 4.9994e-05 1.8412e-05 6.4281e-02 2.8370e-01 0:09:37 17
9 4.8102e-01 1.3857e-04 5.6132e-05 4.4578e-05 1.6471e-05 3.4783e-02 1.9139e-01 0:08:58 16
10 4.1075e-01 1.2847e-04 4.8600e-05 3.8843e-05 1.4855e-05 2.3376e-02 1.1103e-01 0:08:20 15
11 3.5291e-01 1.2120e-04 4.2468e-05 3.3183e-05 1.4150e-05 2.1954e-02 5.8104e-02 0:07:43 14
iter continuity x-velocity y-velocity z-velocity energy k omega time/iter
12 3.0537e-01 1.1489e-04 3.6212e-05 2.7712e-05 1.4446e-05 2.5487e-02 2.9454e-02 0:07:09 13
13 2.6472e-01 1.0914e-04 3.0598e-05 2.2723e-05 1.5033e-05 2.8451e-02 1.5329e-02 0:06:30 12
14 2.3196e-01 1.0154e-04 2.5552e-05 1.8410e-05 1.4791e-05 2.9939e-02 8.5765e-03 0:05:54 11
15 2.0799e-01 9.3274e-05 2.1878e-05 1.5124e-05 1.3863e-05 2.9777e-02 5.3140e-03 0:05:19 10
16 1.8926e-01 8.8168e-05 1.9071e-05 1.2838e-05 1.3013e-05 2.8299e-02 3.6617e-03 0:04:45 9
17 1.7518e-01 8.5202e-05 1.6849e-05 1.1388e-05 1.2371e-05 2.6638e-02 2.7829e-03 0:04:12 8
18 1.6629e-01 8.3267e-05 1.5262e-05 1.0466e-05 1.1768e-05 2.4917e-02 2.2321e-03 0:03:39 7
19 1.6003e-01 8.0477e-05 1.4380e-05 9.9830e-06 1.0869e-05 2.2951e-02 1.8476e-03 0:03:07 6
20 1.5333e-01 7.5748e-05 1.3817e-05 9.7537e-06 9.7003e-06 2.0532e-02 1.5957e-03 0:02:35 5
21 1.4599e-01 6.9516e-05 1.3180e-05 9.6127e-06 8.4613e-06 1.7574e-02 1.4175e-03 0:02:03 4
22 1.3645e-01 6.2743e-05 1.2259e-05 9.2616e-06 7.3881e-06 1.4974e-02 1.2744e-03 0:01:32 3
iter continuity x-velocity y-velocity z-velocity energy k omega time/iter
23 1.2500e-01 5.6063e-05 1.1127e-05 8.5603e-06 6.5064e-06 1.2900e-02 1.1525e-03 0:01:01 2
24 1.1365e-01 5.0070e-05 9.7635e-06 7.5534e-06 5.7811e-06 1.1134e-02 1.0436e-03 0:00:31 1
25 1.0336e-01 4.4514e-05 8.4698e-06 6.4937e-06 5.1570e-06 9.6102e-03 9.4639e-04 0:00:00 0
Writing to 24203702884f:"/mnt/pyfluent/NACA_Airfoil_6412_resolved.cas.h5" in NODE0 mode and compression level 1 ...
Grouping cells for Laplace smoothing ...
4071450 cells, 2 zones ...
17854158 faces, 7 zones ...
10189562 nodes, 1 zone ...
Done.
Writing boundary layer flags ...
Done.
Done.
Writing to 24203702884f:"/mnt/pyfluent/NACA_Airfoil_6412_resolved.dat.h5" in NODE0 mode and compression level 1 ...
Writing results.
Done.
Total running time of the script: (17 minutes 57.462 seconds)