Source code for fastga.models.performances.mission_vector.initialization.initialize_airspeed

#  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/>.

import numpy as np
import openmdao.api as om
from scipy.constants import g
from stdatm import Atmosphere

from fastga.models.performances.mission.mission_components import (
    POINTS_NB_CLIMB,
    POINTS_NB_CRUISE,
)


[docs]class InitializeAirspeed(om.ExplicitComponent): """Initializes the airspeeds at each time step."""
[docs] def initialize(self): self.options.declare( "number_of_points", default=1, desc="number of equilibrium to be treated" )
[docs] def setup(self): number_of_points = self.options["number_of_points"] self.add_input("data:TLAR:v_cruise", val=np.nan, units="m/s") self.add_input("data:geometry:wing:area", val=np.nan, units="m**2") self.add_input("data:aerodynamics:wing:cruise:induced_drag_coefficient", np.nan) self.add_input("data:aerodynamics:aircraft:cruise:CD0", np.nan) self.add_input("data:aerodynamics:wing:low_speed:CL_max_clean", val=np.nan) self.add_input("data:aerodynamics:aircraft:cruise:optimal_CL", np.nan) self.add_input( "mass", val=np.full(number_of_points, np.nan), shape=number_of_points, units="kg" ) self.add_input( "altitude", val=np.full(number_of_points, np.nan), shape=number_of_points, units="m" ) self.add_output("true_airspeed", val=np.full(number_of_points, 50.0), units="m/s") self.add_output("equivalent_airspeed", val=np.full(number_of_points, 50.0), units="m/s")
[docs] def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): v_tas_cruise = inputs["data:TLAR:v_cruise"] cd0 = inputs["data:aerodynamics:aircraft:cruise:CD0"] coeff_k_wing = inputs["data:aerodynamics:wing:cruise:induced_drag_coefficient"] cl_max_clean = inputs["data:aerodynamics:wing:low_speed:CL_max_clean"] wing_area = inputs["data:geometry:wing:area"] mass = inputs["mass"] altitude = inputs["altitude"] altitude_climb = altitude[0:POINTS_NB_CLIMB] altitude_cruise = altitude[POINTS_NB_CLIMB : POINTS_NB_CLIMB + POINTS_NB_CRUISE] altitude_descent = altitude[POINTS_NB_CLIMB + POINTS_NB_CRUISE :] # Computes the airspeed that gives the best climb rate # FIXME: VCAS constant-speed strategy is specific to ICE-propeller configuration, # FIXME: could be an input! c_l = np.sqrt(3 * cd0 / coeff_k_wing) atm_climb = Atmosphere(altitude_climb, altitude_in_feet=False) vs1 = np.sqrt((mass[0] * g) / (0.5 * atm_climb.density[0] * wing_area * cl_max_clean)) # Using the denomination in Gudmundsson v_y = np.sqrt((mass[0] * g) / (0.5 * atm_climb.density[0] * wing_area * c_l)) v_eas_climb = max(v_y, 1.3 * vs1) atm_climb.equivalent_airspeed = np.full_like(altitude_climb, v_eas_climb) true_airspeed_climb = atm_climb.true_airspeed atm_cruise = Atmosphere(altitude_cruise[0], altitude_in_feet=False) atm_cruise.true_airspeed = v_tas_cruise true_airspeed_cruise = np.full_like(altitude_cruise, v_tas_cruise) equivalent_airspeed_cruise = np.full_like(altitude_cruise, atm_cruise.equivalent_airspeed) cl_opt = inputs["data:aerodynamics:aircraft:cruise:optimal_CL"] mass_descent = mass[POINTS_NB_CLIMB + POINTS_NB_CRUISE + 1] atm_descent = Atmosphere(altitude_descent, altitude_in_feet=False) vs1 = np.sqrt( (mass_descent * g) / (0.5 * atm_descent.density[0] * wing_area * cl_max_clean) ) v_eas_descent = max( np.sqrt((mass_descent * g) / (0.5 * atm_descent.density[0] * wing_area * cl_opt)), 1.3 * vs1, ) atm_descent.equivalent_airspeed = np.full_like(altitude_descent, v_eas_descent) true_airspeed_descent = atm_descent.true_airspeed outputs["true_airspeed"] = np.concatenate( (true_airspeed_climb, true_airspeed_cruise, true_airspeed_descent) ) outputs["equivalent_airspeed"] = np.concatenate( ( atm_climb.equivalent_airspeed, equivalent_airspeed_cruise, atm_descent.equivalent_airspeed, ) )