"""
Computation of lift and drag increment due to high-lift devices
"""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 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 importlib.resources import open_text
import numpy as np
import openmdao.api as om
from scipy import interpolate
from . import resources
LIFT_EFFECTIVENESS_FILENAME = "interpolation of lift effectiveness.txt"
[docs]class ComputeDeltaHighLift(om.ExplicitComponent):
"""
Provides lift and drag increments due to high-lift devices
"""
[docs] def initialize(self):
self.options.declare("landing_flag", default=False, types=bool)
[docs] def setup(self):
if self.options["landing_flag"]:
self.add_input("data:mission:sizing:landing:flap_angle", val=np.nan, units="deg")
self.add_input("data:mission:sizing:landing:slat_angle", val=np.nan, units="deg")
self.add_input("data:aerodynamics:aircraft:landing:mach", val=np.nan)
self.add_output("data:aerodynamics:high_lift_devices:landing:CL")
self.add_output("data:aerodynamics:high_lift_devices:landing:CD")
else:
self.add_input("data:mission:sizing:takeoff:flap_angle", val=np.nan, units="deg")
self.add_input("data:mission:sizing:takeoff:slat_angle", val=np.nan, units="deg")
self.add_input("data:aerodynamics:aircraft:takeoff:mach", val=np.nan)
self.add_output("data:aerodynamics:high_lift_devices:takeoff:CL")
self.add_output("data:aerodynamics:high_lift_devices:takeoff:CD")
self.add_input("data:geometry:wing:sweep_0", val=np.nan, units="rad")
self.add_input("data:geometry:wing:sweep_100_outer", val=np.nan, units="rad")
self.add_input("data:geometry:flap:chord_ratio", val=np.nan)
self.add_input("data:geometry:flap:span_ratio", val=np.nan)
self.add_input("data:geometry:slat:chord_ratio", val=np.nan)
self.add_input("data:geometry:slat:span_ratio", val=np.nan)
[docs] def setup_partials(self):
self.declare_partials("*", "*", method="fd")
[docs] def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
if self.options["landing_flag"]:
flap_angle = inputs["data:mission:sizing:landing:flap_angle"]
slat_angle = inputs["data:mission:sizing:landing:slat_angle"]
mach = inputs["data:aerodynamics:aircraft:landing:mach"]
else:
flap_angle = inputs["data:mission:sizing:takeoff:flap_angle"]
slat_angle = inputs["data:mission:sizing:takeoff:slat_angle"]
mach = inputs["data:aerodynamics:aircraft:takeoff:mach"]
le_sweep_angle = inputs["data:geometry:wing:sweep_0"]
te_sweep_angle = inputs["data:geometry:wing:sweep_100_outer"]
flap_chord_ratio = inputs["data:geometry:flap:chord_ratio"]
flap_span_ratio = inputs["data:geometry:flap:span_ratio"]
slat_chord_ratio = inputs["data:geometry:slat:chord_ratio"]
slat_span_ratio = inputs["data:geometry:slat:span_ratio"]
if self.options["landing_flag"]:
outputs["data:aerodynamics:high_lift_devices:landing:CL"] = self._get_delta_cl(
slat_angle,
flap_angle,
slat_span_ratio,
flap_span_ratio,
slat_chord_ratio,
flap_chord_ratio,
mach,
le_sweep_angle,
te_sweep_angle,
)
outputs["data:aerodynamics:high_lift_devices:landing:CD"] = self._get_delta_cd(
slat_angle, flap_angle, slat_span_ratio, flap_span_ratio
)
else:
outputs["data:aerodynamics:high_lift_devices:takeoff:CL"] = self._get_delta_cl(
slat_angle,
flap_angle,
slat_span_ratio,
flap_span_ratio,
slat_chord_ratio,
flap_chord_ratio,
mach,
le_sweep_angle,
te_sweep_angle,
)
outputs["data:aerodynamics:high_lift_devices:takeoff:CD"] = self._get_delta_cd(
slat_angle, flap_angle, slat_span_ratio, flap_span_ratio
)
def _get_delta_cl(
self,
slat_angle,
flap_angle,
slat_span_ratio,
flap_span_ratio,
slat_chord_ratio,
flap_chord_ratio,
mach,
le_sweep_angle,
te_sweep_angle,
):
"""
Method based on Roskam book and Raymer book
:param slat_angle: in degrees
:param flap_angle: in degrees
:param slat_span_ratio: the ratio of the part of wing which is equipped with slat
:param flap_span_ratio: the ratio of the part of wing which is equipped with flap
:param slat_chord_ratio: average ratio of slat chord to clean chord
:param flap_chord_ratio: average ratio of flap chord to clean chord
:param mach:
:param le_sweep_angle: sweep angle at leading edge
:param te_sweep_angle: sweep angle at trailing edge
:return: increment of lift coefficient
"""
flap_angle = np.radians(flap_angle)
slat_angle = np.radians(slat_angle)
# ratio of chord with flap extended compared to clean chord
ratio_c_flap = 1.0 + flap_chord_ratio * np.cos(flap_angle)
alpha_flap = self._compute_alpha_flap(flap_angle * 57.3, flap_chord_ratio)
# cl created by the flap in 2D
delta_cl_flap = (
2.0 * np.pi / np.sqrt(1 - mach ** 2) * ratio_c_flap * alpha_flap * flap_angle
)
# ratio of chord with slat extended compared to clean chord
ratio_c_slat = 1.0 + slat_chord_ratio * np.cos(slat_angle)
# leading edge slat effectiveness
cl_delta = (
5.05503e-7
+ 0.00666 * slat_chord_ratio
+ 0.23758 * slat_chord_ratio ** 2
- 4.3639 * slat_chord_ratio ** 3
+ 51.16323 * slat_chord_ratio ** 4
- 320.10803 * slat_chord_ratio ** 5
+ 1142.23033 * slat_chord_ratio ** 6
- 2340.75209 * slat_chord_ratio ** 7
+ 2570.35947 * slat_chord_ratio ** 8
- 1173.73465 * slat_chord_ratio ** 9
)
# cl created by the slat in 2D
delta_cl_slat = cl_delta * slat_angle * 57.3 * ratio_c_slat
# cl due to flap and slat including 3D
delta_cl_total = delta_cl_flap * flap_span_ratio * np.cos(
te_sweep_angle
) + delta_cl_slat * slat_span_ratio * np.cos(
le_sweep_angle
) # this equation is from ref Raymer book
return delta_cl_total
def _get_delta_cd(self, slat_angle, flap_angle, slat_span_ratio, flap_span_ratio):
"""
:param slat_angle: in degrees
:param flap_angle: in degrees
:param slat_span_ratio: the ratio of the part of wing which is equipped with slat
:param flap_span_ratio: the ratio of the part of wing which is equipped with flap
:return: increment of drag coefficient
"""
cd0_slat = (
(
-0.00266
+ 0.06065 * slat_angle
- 0.03023 * slat_angle ** 2
+ 0.01055 * slat_angle ** 3
- 0.00176 * slat_angle ** 4
+ 1.77986e-4 * slat_angle ** 5
- 1.11754e-5 * slat_angle ** 6
+ 4.19082e-7 * slat_angle ** 7
- 8.53492e-9 * slat_angle ** 8
+ 7.24194e-11 * slat_angle ** 9
)
* slat_span_ratio
/ 100
)
cd0_flap = (
(
-0.01523
+ 0.05145 * flap_angle
- 9.53201e-4 * flap_angle ** 2
+ 7.5972e-5 * flap_angle ** 3
)
* flap_span_ratio
/ 100
)
total_cd0 = cd0_flap + cd0_slat
return total_cd0
def _compute_alpha_flap(self, flap_angle, ratio_cf_flap):
temp_array = []
with open_text(resources, LIFT_EFFECTIVENESS_FILENAME) as fichier:
for line in fichier:
temp_array.append([float(x) for x in line.split(",")])
x1 = []
y1 = []
x2 = []
y2 = []
x3 = []
y3 = []
x4 = []
y4 = []
x5 = []
y5 = []
for arr in temp_array:
x1.append(arr[0])
y1.append(arr[1])
x2.append(arr[2])
y2.append(arr[3])
x3.append(arr[4])
y3.append(arr[5])
x4.append(arr[6])
y4.append(arr[7])
x5.append(arr[8])
y5.append(arr[9])
tck1 = interpolate.splrep(x1, y1, s=0)
tck2 = interpolate.splrep(x2, y2, s=0)
tck3 = interpolate.splrep(x3, y3, s=0)
tck4 = interpolate.splrep(x4, y4, s=0)
tck5 = interpolate.splrep(x5, y5, s=0)
ynew1 = interpolate.splev(flap_angle, tck1, der=0)
ynew2 = interpolate.splev(flap_angle, tck2, der=0)
ynew3 = interpolate.splev(flap_angle, tck3, der=0)
ynew4 = interpolate.splev(flap_angle, tck4, der=0)
ynew5 = interpolate.splev(flap_angle, tck5, der=0)
zs = [0.15, 0.20, 0.25, 0.30, 0.40]
y_final = [ynew1, ynew2, ynew3, ynew4, ynew5]
tck6 = interpolate.splrep(zs, y_final, s=0)
return interpolate.splev(ratio_cf_flap, tck6, der=0)