Alpha Sweep

Contents

Alpha Sweep#

This example demonstrates how to configure and manage a series of simulations to perform an angle of attack (alpha) sweep for the ONERA M6 wing using the Flow360 Python API. It covers setting up a baseline simulation configuration, modifying the angle of attack across a specified range, submitting each case, retrieving results, and performing basic post-processing to calculate and plot aerodynamic coefficients.

 1import os
 2from typing import List
 3
 4from pylab import plot, show, xlabel, ylabel
 5
 6import flow360 as fl
 7from flow360.examples import OM6wing
 8
 9OM6wing.get_files()
10
11project = fl.Project.from_volume_mesh(OM6wing.mesh_filename, name="Alpha sweep results from Python")
12
13vm = project.volume_mesh
14
15with fl.SI_unit_system:
16    params = fl.SimulationParams(
17        reference_geometry=fl.ReferenceGeometry(
18            area=1.15315084119231,
19            moment_center=[0, 0, 0],
20            moment_length=[1.47602, 0.801672958512342, 1.47602],
21        ),
22        operating_condition=fl.AerospaceCondition(velocity_magnitude=286, alpha=3.06 * fl.u.deg),
23        time_stepping=fl.Steady(max_steps=500),
24        models=[
25            fl.Wall(surfaces=vm["1"]),
26            fl.SlipWall(surfaces=vm["2"]),
27            fl.Freestream(surfaces=vm["3"]),
28        ],
29    )
30
31
32# ": List[fl.Case]" is just for type hints
33case_list: List[fl.Case] = []
34alpha_range = range(-6, 15, 2)
35for alpha in alpha_range:
36    params.operating_condition.alpha = alpha * fl.u.deg
37    case = project.run_case(params, f"alpha-sweep-OM6wing-alpha={alpha}")
38    case_list.append(case)
39
40project.print_project_tree()
41
42# wait for all cases to finish processing
43[case.wait() for case in case_list]
44
45
46# calculate average using dataframe structure and pandas functions
47def average_last_10_percent(df, column):
48    last_10_percent = df.tail(int(len(df) * 0.1))
49    average = last_10_percent[column].mean()
50    return average
51
52
53CL_list = []
54CD_list = []
55
56for case in case_list:
57    total_forces = case.results.total_forces
58
59    average_CL = average_last_10_percent(total_forces.as_dataframe(), "CL")
60    CL_list.append(average_CL)
61
62    average_CD = average_last_10_percent(total_forces.as_dataframe(), "CD")
63    CD_list.append(average_CD)
64
65# download all data:
66results_folder = "alpha_sweep_example"
67for case in case_list:
68    results = case.results
69    results.download(
70        total_forces=True,
71        nonlinear_residuals=True,
72        destination=os.path.join(results_folder, case.name),
73    )
74
75# plot CL / CD
76plot(CD_list, CL_list)
77xlabel("CD")
78ylabel("CL")
79show()

Notes#

  • The script iterates through a predefined range of angles of attack, updating the operating_condition.alpha within the SimulationParams object for each iteration.

  • Each angle of attack is submitted as an individual simulation case using project.run_case, allowing for parallel processing and organized results management within a single project structure.

  • Basic post-processing is shown, calculating the mean lift (CL) and drag (CD) coefficients from the converged portion (last 10%) of the simulation history to generate an aerodynamic polar plot (CL vs. CD).