pyLOM.RL#
Module contents#
- class pyLOM.RL.BaseSolver[source]#
Bases:
ABC
Base class for all solvers. It defines the interface for the solvers.
- class pyLOM.RL.XFoilSolver(alpha: float, mach: float, Reynolds: float = None, check_selfintersection: bool = False, xfoil_params: dict = {})[source]#
Bases:
BaseSolver
XFoil solver for airfoil analysis. It uses the XFoil library to compute the lift and drag coefficients. Under the hood, it uses the XFoil class from aerosandbox. Requires XFoil to be on installed your machine; XFoil is available here: RobotLocomotion/xfoil And xfoil to be in your PATH. You can check this by running which xfoil in your terminal.
- Parameters:
alpha (float) – Angle of attack in degrees.
mach (float) – Mach number.
Reynolds (float, optional) – Reynolds number. If not provided, inviscid mode is used. Default is
None
.check_selfintersection (bool, optional) – If True, check for self-intersection of the airfoil when computing lift/drag. If the airfoil self-intersects, XFoil will return NON_CONVERGED_REWARD. Default is
False
.xfoil_params (dict, optional) – Additional parameters that are passed to the XFoil class. For example, you can set xfoil_params={“xfoil_repanel”: True} to repanel the airfoil. Default is
{}
.
- class pyLOM.RL.NeuralFoilSolver(alpha: float, Reynolds: float, model_size: str = 'xxxlarge')[source]#
Bases:
BaseSolver
NeuralFoil solver for airfoil analysis. It uses the NeuralFoil library to compute the lift and drag coefficients.
- class pyLOM.RL.DummySolver[source]#
Bases:
BaseSolver
Dummy solver for airfoil analysis. It returns a constant reward for all airfoils. This is useful for testing purposes.
- class pyLOM.RL.AerosandboxWingSolver(velocity, alpha, atmosphere, model_size='xxxlarge')[source]#
Bases:
BaseSolver
Aerosandbox solver for wing analysis. It uses the AeroBuildup component from the Aerosandbox library to compute the lift and drag coefficients. For more details, see https://aerosandbox.readthedocs.io/en/master/autoapi/aerosandbox/index.html#aerosandbox.AeroBuildup :param velocity: The flight velocity, expressed as a true airspeed. [m/s] :type velocity: float :param alpha: Angle of attack in degrees. :type alpha: float :param atmosphere: The atmosphere model to use. :type atmosphere: asb.Atmosphere :param model_size: Size of the model. Default is
xxxlarge
. Other options are “xxsmall”, “xsmall”, “small”, “medium”, “large”, “xlarge”, “xxlarge”. :type model_size: str, optional
- class pyLOM.RL.AVLSolver(velocity, alpha, atmosphere)[source]#
Bases:
BaseSolver
AVL solver for wing analysis. It uses the AVL (Athena Vortex Lattice) method to compute the lift and drag coefficients. To use this solver, you need to have AVL executable installed and available in your PATH, see https://web.mit.edu/drela/Public/web/avl/ :param velocity: The flight velocity, expressed as a true airspeed. [m/s] :type velocity: float :param alpha: Angle of attack in degrees. :type alpha: float :param atmosphere: The atmosphere model to use. :type atmosphere: asb.Atmosphere
- class pyLOM.RL.BaseParameterizer[source]#
Bases:
ABC
Base class for all parameterizers. It defines the interface for the parameterizers.
- abstract get_shape_from_params(params: ndarray) Airfoil [source]#
Create a shape from the given parameters.
- Parameters:
params (np.ndarray) – Parameters to create the shape.
- Returns:
Created shape.
- Return type:
asb.Airfoil
- abstract get_optimizable_bounds() Tuple[List, List] [source]#
Get the bounds of the optimizable parameters.
- Returns:
Lower and upper bounds of the parameters.
- Return type:
Tuple[List, List]
- class pyLOM.RL.AirfoilCSTParametrizer(upper_surface_bounds: Tuple[List, List], lower_surface_bounds: Tuple[List, List], TE_thickness_bounds: Tuple[List, List], leading_edge_weight: Tuple[List, List])[source]#
Bases:
BaseParameterizer
CST parameterization of airfoils. The CST method is a way to parameterize airfoils using a set of control points. Depending on the number of points in upper and lower surfaces, the number of parameters will be different.
- Parameters:
upper_surface_bounds (Tuple[List, List]) – Bounds for the upper surface parameters. The first list has the lower bounds and the second list has the upper bounds.The length of the lists should be equal to the number of parameters for the upper surface.
lower_surface_bounds (Tuple[List, List]) – Bounds for the lower surface parameters. The first list has the lower bounds and the second list has the upper bounds.The length of the lists should be equal to the number of parameters for the lower surface.
TE_thickness_bounds (Tuple[float, float]) – Bounds for the TE thickness. The first value is the lower bound and the second value is the upper bound.
leading_edge_weight (Tuple[float, float]) – Bounds for the leading edge weight. The first value is the lower bound and the second value is the upper bound.
- naca_4digit_airfoils = ['naca0006', 'naca0009', 'naca0012', 'naca0015', 'naca0018', 'naca1408', 'naca1410', 'naca1412', 'naca2412', 'naca2415', 'naca4412', 'naca4415', 'naca4420', 'naca6412', 'naca6415', 'naca7421', 'naca8409', 'naca8412', 'naca8415', 'naca9421']#
- get_shape_from_params(params)[source]#
Create a shape from the given parameters.
- Parameters:
params (np.ndarray) – Parameters to create the shape.
- Returns:
Created shape.
- Return type:
asb.Airfoil
- get_params_from_shape(airfoil: Airfoil) ndarray [source]#
Get the parameters from the given shape. :param shape: Shape to get the parameters from. :type shape: asb.Airfoil
- Returns:
Parameters of the shape.
- Return type:
np.ndarray
- class pyLOM.RL.WingParameterizer(airfoil: Airfoil, chord_bounds: Tuple[List], twist_bounds: Tuple[List], span_bounds: Tuple[List], sweep_bounds: Tuple[List], dihedral_bounds: Tuple[List])[source]#
Bases:
BaseParameterizer
- __init__(airfoil: Airfoil, chord_bounds: Tuple[List], twist_bounds: Tuple[List], span_bounds: Tuple[List], sweep_bounds: Tuple[List], dihedral_bounds: Tuple[List])[source]#
Initialize the WingParametrizerDust class.
- Parameters:
airfoil (asb.Airfoil) – The airfoil to be used for the wing sections.
chord (The bounds for the)
twist
span (and a region of the wing is created for each)
sweep
lists (and dihedral parameters are tuples with two)
same (the first list is the lower bound and the second list is the upper bound. If the upper and lower bounds are the)
pair (the parameter will not be considered for optimization. A section of the wing is created for each chord and twist)
span
sweep
triplet (and dihedral)
degrees. (the number of sections should be one more than the number of regions. The angles need to be in)
- get_shape_from_params(params)[source]#
Create a shape from the given parameters.
- Parameters:
params (np.ndarray) – Parameters to create the shape.
- Returns:
Created shape.
- Return type:
asb.Airfoil
- get_params_from_shape(wing)[source]#
Get the parameters from the given shape. :param shape: Shape to get the parameters from. :type shape: asb.Airfoil
- Returns:
Parameters of the shape.
- Return type:
np.ndarray
- pyLOM.RL.create_env(solver_name, parameterizer=None, operating_conditions=None, num_envs=1, episode_max_length=64, thickness_penalization_factor=0, initial_seed=None)[source]#
Create a reinforcement learning environment for shape optimization. Using these environments, the RL agents have been trained in https://arxiv.org/pdf/2505.02634.
- Parameters:
solver_name (str) – Name of the solver to use.
parameterizer – Parameterizer object that defines the shape to optimize (if None, a default will be used)
num_envs (int) – Number of parallel environments to create. If greater than 1, you need to wrap the code in
if __name__ == "__main__":
to avoid issues with multiprocessing. Ref: https://stable-baselines3.readthedocs.io/en/master/guide/vec_envs.html. Default is1
.episode_max_length (int) – Maximum episode length. Default is
64
.operating_conditions (Optional[AirfoilOperatingConditions]) – Operating conditions for the solver. Default is
None
.thickness_penalization_factor (float) – Penalty factor for thickness changes. Default is
0
.initial_seed (Optional[int]) – Initial random seed. Default is
None
.
- Returns:
The created environment
- Return type:
gym.Env
- class pyLOM.RL.AirfoilOperatingConditions(alpha: float = 2, Reynolds: float = 1000000.0, mach: float = 0.5)[source]#
Bases:
object
Configuration for airfoil operating conditions.
This class encapsulates the physical parameters used in airfoil simulations, including angle of attack, Reynolds number, and Mach number.
- Parameters:
- class pyLOM.RL.AirfoilParameterizerConfig(n_weights_per_side: int = 8, leading_edge_weight_bounds: Tuple[float, float] = (-0.05, 0.75), te_thickness_bounds: Tuple[float, float] = (0.0005, 0.01), upper_edge_bounds: Tuple[float, float] = (-1.5, 1.25), lower_edge_bounds: Tuple[float, float] = (-0.75, 1.5))[source]#
Bases:
object
Configuration for airfoil parameterization.
This class defines the parameters used to create an airfoil shape using the Class-Shape Transformation (CST) method. It controls the number of control points and their bounds for both upper and lower surfaces.
- Parameters:
n_weights_per_side (int) – Number of control points per surface side. Default is
8
.leading_edge_weight_bounds (Tuple[float, float]) – Min and max values for the leading edge weight parameter. Default is
(-0.05, 0.75)
.te_thickness_bounds (Tuple[float, float]) – Min and max values for trailing edge thickness. Default is
(0.0005, 0.01)
.upper_edge_bounds (Tuple[float, float]) – Min and max values for upper surface control points. Default is
(-1.5, 1.25)
.lower_edge_bounds (Tuple[float, float]) – Min and max values for lower surface control points. Default is
(-0.75, 1.5)
.
- create_parameterizer()[source]#
Creates an AirfoilCSTParametrizer based on this configuration.
This method instantiates a new AirfoilCSTParametrizer using the current configuration settings. The parameterizer can then be used to generate airfoil shapes for optimization.
- Returns:
A configured airfoil parameterizer instance.
- Return type:
- class pyLOM.RL.SolverFactory[source]#
Bases:
object
Factory for creating solver instances.
This class provides methods to create appropriate solver instances based on their name and configuration parameters. It acts as a factory that abstracts the details of solver instantiation.
- static create_solver(solver_name: str, conditions: AirfoilOperatingConditions | None = None) BaseSolver [source]#
Create a solver by name.
This method determines the type of solver (airfoil or wing) based on the name and delegates creation to the appropriate specialized factory method.
- Parameters:
solver_name (str) – The name of the solver to create.
conditions (Optional[AirfoilOperatingConditions]) – Configuration parameters for the solver. If None, default values will be used.
- Returns:
The created solver instance.
- Return type:
- Raises:
ValueError – If the solver name is not recognized.
- static create_airfoil_solver(solver_name: str, conditions: AirfoilOperatingConditions | None = None) BaseSolver [source]#
Create an airfoil solver instance.
This method creates and returns an airfoil solver instance based on the specified name and configured with the given conditions.
- Parameters:
solver_name (str) – The name of the airfoil solver to create.
conditions (Optional[AirfoilOperatingConditions]) – Configuration parameters for the solver. If None, default values will be used.
- Returns:
The created airfoil solver instance.
- Return type:
- Raises:
ValueError – If the solver name is not recognized as a valid airfoil solver.
- static create_wing_solver(solver_name: str, conditions: WingOperatingConditions | None = None)[source]#
Create a wing solver
- class pyLOM.RL.WingOperatingConditions(velocity: float = 150, altitude: float = 500, alpha: float = 2)[source]#
Bases:
object
Configuration for wing operating conditions
- Parameters:
- class pyLOM.RL.WingParameterizerConfig(airfoil_name: str = 'naca0012', chord_bounds: ~typing.List[~typing.List[float]] = <factory>, twist_bounds: ~typing.List[~typing.List[float]] = <factory>, span_bounds: ~typing.List[~typing.List[float]] = <factory>, sweep_bounds: ~typing.List[~typing.List[float]] = <factory>, dihedral_bounds: ~typing.List[~typing.List[float]] = <factory>)[source]#
Bases:
object
Configuration for wing parameterization
This class defines the parameters used to create a wing shape, including airfoil type, chord, twist, span, sweep, and dihedral angles. It provides methods to create a WingParameterizer instance based on these settings.
- Parameters:
airfoil_name (str) – Name of an airfoil from the UIUC airfoil dataset to use for the wing. If a custom asb.Airfoil wants to me used, pleas create the parameterizere directly with pyLOM.RL.WingParameterizer. Default is “naca0012”.
chord_bounds (List[List[float]]) – Bounds for the chord length. Default is [[0.75, 0.45], [1.25, 0.75]].
twist_bounds (List[List[float]]) – Bounds for the twist angle in degrees. Default is [[-2, -2], [2, 2]].
span_bounds (List[List[float]]) – Bounds for the span length. Default is [[1.5], [2]].
sweep_bounds (List[List[float]]) – Bounds for the sweep angle in degrees. Default is [[-5], [15]].
dihedral_bounds (List[List[float]]) – Bounds for the dihedral angle in degrees. Default is [[-2], [7]].
- pyLOM.RL.run_episode(rl_model, env, initial_shape=None, seed=None, keep_unconverged=False)[source]#
Runs a single episode of the RL agent in the given environment.
- Parameters:
rl_model – The RL model to evaluate.
env – The environment in which to run the episode.
initial_shape – An initial airfoil shape to start the episode with. Default:
None
, which means a random shape will be generated.seed – A seed for reproducibility. Default:
None
.keep_unconverged – If True, keeps the last state and reward even if the episode was truncated. Default:
False
.
- Returns:
A list of cumulative rewards at each step. states: A list of airfoil shapes at each step.
- Return type:
rewards
- pyLOM.RL.evaluate_airfoil_agent(agent, env, num_episodes=200, save_path=None)[source]#
Evaluates an RL agent on a set of airfoils from the UIUC airfoil database and prints a summary of the results.
- Parameters:
agent – The RL agent to evaluate.
env – The environment in which to run the episodes.
num_episodes – The number of airfoils to evaluate. Default: 200.
save_path – If provided, saves the results to a CSV file at this path. Default:
None
.
- Returns:
A list with the lists of cumulative rewards for each airfoil optimization. states: A list with lists of airfoil shapes for each step of the optimization of each airfoil.
- Return type:
all_rewards
- pyLOM.RL.evaluate_airfoil_agent_whole_uiuc(agent, env, save_path=None)[source]#
Evaluates an RL agent on all airfoils in the UIUC airfoil database and prints a summary of the results. :param agent: The RL agent to evaluate. :param env: The environment in which to run the episodes. :param save_path: If provided, saves the results to a CSV file at this path. Default:
None
.- Returns:
A list with the lists of cumulative rewards for each airfoil optimization. states: A list with lists of airfoil shapes for each step of the optimization of each airfoil.
- Return type:
all_rewards
- pyLOM.RL.evaluate_airfoil_agent_whole_uiuc_mpi(agent, env, save_results_path)[source]#
Evaluates an RL agent on all airfoils in the UIUC airfoil database using MPI for parallel processing and saves the results to a CSV file. If this function is used on a script, it should be run with mpiexec -n <num_processes> python <script_name>.py.
- Parameters:
agent – The RL agent to evaluate.
env – The environment in which to run the episodes.
save_results_path – If provided, saves the results to a CSV file at this path.
- pyLOM.RL.create_airfoil_optimization_progress_plot(airfoils, rewards, airfoil_name='Airfoil Shape', save_path=None)[source]#
Create a plot showing the evolution of airfoil shapes and their corresponding lift-to-drag ratios.
- Parameters:
airfoils (List[asb.Airfoil]) – List of airfoil objects representing the evolution.
rewards (List[float]) – List of lift-to-drag ratios corresponding to each airfoil.
airfoil_name (str) – Name of the airfoil for the plot title. Default:
'Airfoil Shape'
.save_path (Optional[str]) – Path to save the plot. If None, the plot will not be saved. Default:
None
.
- class pyLOM.RL.AirfoilEvolutionAnimation(*args, **kwargs)[source]#
Bases:
object
Generate an animation showing the evolution of airfoils and their corresponding lift-to-drag ratios. Manim is required to run this animation, and it is recommended to install it with conda install -c conda-forge manim.
- Properties:
airfoils: List of airfoil objects representing the evolution.
rewards: List of lift-to-drag ratios corresponding to each airfoil.
run_time: Duration of the animation in seconds. Default:
5
.title: Title of the animation. Default:
"Airfoil evolution"
.
Examples
To use in a notebook:
>>> import manim >>> from pyLOM.RL import AirfoilEvolutionAnimation
>>> %%manim -qm -v WARNING AirfoilEvolution >>> AirfoilEvolutionAnimation.airfoils = airfoils >>> AirfoilEvolutionAnimation.rewards = rewards >>> AirfoilEvolutionAnimation.title = "NACA0012 Evolution"
To use it in a script:
>>> from pyLOM.RL import AirfoilEvolutionAnimation >>> from manim import * >>> from main import config >>> # config.format = "gif" # Change output format to GIF >>> config.output_file = "airfoil_evolution.mp4" # Change output file name >>> config.quality = "production_quality" # Set quality to maximum (Full HD) >>> animation = AirfoilEvolutionAnimation() >>> animation.airfoils = airfoils >>> animation.rewards = rewards >>> animation.title = "Airfoil Evolution" >>> animation.render()
- class pyLOM.RL.WingEvolutionAnimation(*args, **kwargs)[source]#
Bases:
object
Generate an animation showing the evolution of wings and their corresponding lift-to-drag ratios. Manim is required to run this animation, and it is recommended to install it with conda install -c conda-forge manim.
- Properties:
wings: List of wing objects representing the evolution.
rewards: List of lift-to-drag ratios corresponding to each airplane.
run_time_per_update: Duration of each update in seconds. Default:
0.25
.
Examples
To use in a notebook:
>>> import manim >>> from pyLOM.RL import WingEvolutionAnimation
on a separete cell, define the wings and rewards:
>>> %%manim -qm -v WARNING AirfoilEvolution >>> WingEvolutionAnimation.wings = wings >>> WingEvolutionAnimation.rewards = rewards >>> WingEvolutionAnimation.run_time_per_update = 0.1
- pyLOM.RL.SB3_PPO#
alias of
PPO