"""FAST - Copyright (c) 2016 ONERA ISAE."""
# This file is part of FAST-OAD_CS23 : A framework for rapid Overall Aircraft Design
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from openmdao.core.group import Group
import fastoad.api as oad
from fastoad.module_management.constants import ModelDomain
from fastga.models.aerodynamics.external.openvsp import ComputeAeroOpenVSP
from fastga.models.aerodynamics.components import ComputeMachInterpolation
# noinspection PyProtectedMember
from fastga.models.aerodynamics.external.openvsp.compute_aero_slipstream import (
ComputeSlipstreamOpenvspSubGroup,
)
from fastga.models.aerodynamics.external.vlm import ComputeAeroVLM
from .constants import (
SUBMODEL_CD0,
SUBMODEL_CL_ALPHA_VT,
SUBMODEL_HINGE_MOMENTS_TAIL,
SUBMODEL_MAX_L_D,
SUBMODEL_CM_ALPHA_FUSELAGE,
SUBMODEL_CY_RUDDER,
SUBMODEL_EFFECTIVE_EFFICIENCY_PROPELLER,
SUBMODEL_DOWNWASH,
SUBMODEL_CY_BETA,
SUBMODEL_CN_BETA,
DEFAULT_INPUT_AOA,
)
[docs]@oad.RegisterOpenMDAOSystem("fastga.aerodynamics.highspeed.legacy", domain=ModelDomain.AERODYNAMICS)
class AerodynamicsHighSpeed(Group):
"""Models for high speed aerodynamics."""
[docs] def initialize(self):
self.options.declare("propulsion_id", default="", types=str)
self.options.declare("use_openvsp", default=False, types=bool)
self.options.declare("compute_mach_interpolation", default=False, types=bool)
self.options.declare("compute_slipstream", default=False, types=bool)
self.options.declare("result_folder_path", default="", types=str)
self.options.declare("openvsp_exe_path", default="", types=str, allow_none=True)
self.options.declare("airfoil_folder_path", default=None, types=str, allow_none=True)
self.options.declare("wing_airfoil", default="naca23012.af", types=str, allow_none=True)
self.options.declare("htp_airfoil", default="naca0012.af", types=str, allow_none=True)
self.options.declare("vtp_airfoil", default="naca0012.af", types=str, allow_none=True)
self.options.declare("input_angle_of_attack", default=DEFAULT_INPUT_AOA, types=float)
# noinspection PyTypeChecker
[docs] def setup(self):
if not self.options["use_openvsp"]:
if self.options["compute_mach_interpolation"]:
self.add_subsystem(
"aero_vlm",
ComputeAeroVLM(
low_speed_aero=False,
result_folder_path=self.options["result_folder_path"],
compute_mach_interpolation=True,
airfoil_folder_path=self.options["airfoil_folder_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
input_angle_of_attack=self.options["input_angle_of_attack"],
),
promotes=["*"],
)
else:
self.add_subsystem(
"aero_vlm",
ComputeAeroVLM(
low_speed_aero=False,
result_folder_path=self.options["result_folder_path"],
compute_mach_interpolation=False,
airfoil_folder_path=self.options["airfoil_folder_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
input_angle_of_attack=self.options["input_angle_of_attack"],
),
promotes=["*"],
)
self.add_subsystem(
"mach_interpolation_roskam",
ComputeMachInterpolation(
airfoil_folder_path=self.options["airfoil_folder_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
),
promotes=["*"],
)
else:
if self.options["compute_mach_interpolation"]:
self.add_subsystem(
"aero_openvsp",
ComputeAeroOpenVSP(
low_speed_aero=False,
compute_mach_interpolation=True,
result_folder_path=self.options["result_folder_path"],
openvsp_exe_path=self.options["openvsp_exe_path"],
airfoil_folder_path=self.options["airfoil_folder_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
input_angle_of_attack=self.options["input_angle_of_attack"],
),
promotes=["*"],
)
else:
self.add_subsystem(
"aero_openvsp",
ComputeAeroOpenVSP(
low_speed_aero=False,
compute_mach_interpolation=False,
result_folder_path=self.options["result_folder_path"],
airfoil_folder_path=self.options["airfoil_folder_path"],
openvsp_exe_path=self.options["openvsp_exe_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
input_angle_of_attack=self.options["input_angle_of_attack"],
),
promotes=["*"],
)
self.add_subsystem(
"mach_interpolation_roskam",
ComputeMachInterpolation(
airfoil_folder_path=self.options["airfoil_folder_path"],
wing_airfoil_file=self.options["wing_airfoil"],
htp_airfoil_file=self.options["htp_airfoil"],
),
promotes=["*"],
)
options_downwash = {
"low_speed_aero": False,
}
self.add_subsystem(
"downwash",
oad.RegisterSubmodel.get_submodel(SUBMODEL_DOWNWASH, options=options_downwash),
promotes=["*"],
)
options_cd0 = {
"airfoil_folder_path": self.options["airfoil_folder_path"],
"low_speed_aero": False,
"wing_airfoil_file": self.options["wing_airfoil"],
"htp_airfoil_file": self.options["htp_airfoil"],
"propulsion_id": self.options["propulsion_id"],
}
self.add_subsystem(
"Cd0_all",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CD0, options=options_cd0),
promotes=["*"],
)
option_high_speed = {"low_speed_aero": False}
self.add_subsystem(
"Effective_efficiency_propeller",
oad.RegisterSubmodel.get_submodel(
SUBMODEL_EFFECTIVE_EFFICIENCY_PROPELLER, options=option_high_speed
),
promotes=["*"],
)
self.add_subsystem(
"L_D_max", oad.RegisterSubmodel.get_submodel(SUBMODEL_MAX_L_D), promotes=["*"]
)
self.add_subsystem(
"cmAlpha_fuse",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CM_ALPHA_FUSELAGE),
promotes=["*"],
)
self.add_subsystem(
"clAlpha_vt",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CL_ALPHA_VT, options=option_high_speed),
promotes=["*"],
)
self.add_subsystem(
"Cy_Delta_rudder",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CY_RUDDER, options=option_high_speed),
promotes=["*"],
)
self.add_subsystem(
"ch_ht", oad.RegisterSubmodel.get_submodel(SUBMODEL_HINGE_MOMENTS_TAIL), promotes=["*"]
)
self.add_subsystem(
"cy_beta",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CY_BETA, options=option_high_speed),
promotes=["*"],
)
self.add_subsystem(
"cn_beta",
oad.RegisterSubmodel.get_submodel(SUBMODEL_CN_BETA, options=option_high_speed),
promotes=["*"],
)
if self.options["compute_slipstream"]:
self.add_subsystem(
"aero_slipstream_openvsp_hs",
ComputeSlipstreamOpenvspSubGroup(
propulsion_id=self.options["propulsion_id"],
result_folder_path=self.options["result_folder_path"],
airfoil_folder_path=self.options["airfoil_folder_path"],
openvsp_exe_path=self.options["openvsp_exe_path"],
wing_airfoil_file=self.options["wing_airfoil"],
low_speed_aero=False,
),
promotes=["data:*"],
)