Example #1
0
    def test_fuel_value_734(self):
        nn = 5
        p = om.Problem()
        tas = np.linspace(0, 100, nn)
        tas_kt = tas * 1.94384
        alt = 0

        ivc = p.model.add_subsystem('ivc',
                                    subsys=om.IndepVarComp(),
                                    promotes_outputs=['*'])
        ivc.add_output(name='tas', val=tas, units='m/s')
        ivc.add_output(name='alt', val=alt, units='m')
        p.model.connect('alt', ['atmos.h', 'propulsion.elevation'])
        p.model.connect('tas', ['propulsion.tas'])

        p.model.add_subsystem(name='atmos', subsys=USatm1976Comp(num_nodes=1))

        p.model.add_subsystem(name='propulsion',
                              subsys=PropulsionGroup(
                                  num_nodes=nn, airplane=self.airplane_734))

        p.model.connect('atmos.sos', 'propulsion.sos')
        p.model.connect('atmos.pres', ['propulsion.p_amb'])
        p.setup()
        p.run_model()

        ff = FuelFlow(ac='B734')
        reference_ff = [-1 * ff.takeoff(tas=v, alt=alt) for v in tas_kt]
        assert_near_equal(p.get_val('propulsion.m_dot'),
                          reference_ff,
                          tolerance=0.001)
 def __init__(self, aircraft_name, write_output: bool = False):
     self.write = write_output
     # General Variables
     self.aircraft_data = prop.aircraft(aircraft_name)
     self.dt = 1.0 / 60.0  # simulation timestep 60 per seconds
     aircraft_txt = open(f"./data/{aircraft_name}.json", 'r').read()
     self.aircraft = json.loads(aircraft_txt)
     eng_name = self.aircraft_data["engine"]["default"]
     self.ac_thrust = Thrust(ac=self.aircraft["Name"], eng=eng_name)
     # self.ac_thrust = Thrust(f"./data/{aircraft_name}_thrust.csv")
     # Performance Variables (all unit in SI except stated otherwise)
     self.lift_drag = LiftDrag(f"./data/{aircraft_name}_ld.csv")
     self.g = 9.81
     self.mass = self.aircraft_data["limits"]["MTOW"]
     self.thrust_lever = 1.0
     self.altitude = 0.0
     self.pressure = 0.0
     self.density = 0.0
     self.temp = 0.0
     self.cas = 0.0
     self.tas = 0.0
     self.v_y = 0.0  # vertical Speed
     self.vs = 0.0  # Vertical Speed [fpm]
     self.drag = 0.0
     self.thrust = 0.0
     self.lift = 0.0
     self.weight = 0.0
     self.t_d = 0.0  # thrust minus drag aka exceed thrust
     self.l_w = 0.0  # lift minus weight aka exceed lift
     self.pitch = 0.0
     self.fpa = 0.0
     self.aoa = 0.0
     self.Q = 0.0  # tas² * density
     self.acc_x = 0.0
     self.acc_y = 0.0
     self.distance_x = 0.0  # total distance[m]
     self.d_x = 0.0  # instantaneous X distance[m]
     self.d_y = 0.0  # instantaneous Y distance[m]
     self.phase = 0  # Current phase
     self.cd = 0.0
     self.cl = 0.0
     self.drag0 = self.aircraft["Drag0"]
     self.lift0 = self.aircraft["Lift0"]
     self.gear = False
     self.flaps = 0
     self.pitch_target = 0.0
     self.pitch_rate_of_change = 3.0  # rate of change of the pitch [°/sec]
     self.ac_fuelflow = FuelFlow(ac=self.aircraft["Name"], eng=eng_name)
     if self.write:
         self.output = open("output.csv", 'w+')
         self.output.write(self.__get_header())
         self.output.flush()
Example #3
0
    def __init__(self, ac):
        super(CruiseOptimizer, self).__init__()

        self.ac = ac
        self.aircraft = prop.aircraft(ac)
        self.thrust = Thrust(ac)
        self.fuelflow = FuelFlow(ac)
        self.drag = Drag(ac)

        # parameters to be optimized:
        #   Mach number, altitude
        self.x0 = np.array([0.3, 25000 * aero.ft])
        self.normfactor = calc_normfactor(self.x0)

        self.bounds = None
        self.update_bounds()
Example #4
0
class CruiseOptimizer(object):
    """Optimizer for cursie mach number and altitude."""
    def __init__(self, ac):
        super(CruiseOptimizer, self).__init__()

        self.ac = ac
        self.aircraft = prop.aircraft(ac)
        self.thrust = Thrust(ac)
        self.fuelflow = FuelFlow(ac)
        self.drag = Drag(ac)

        # parameters to be optimized:
        #   Mach number, altitude
        self.x0 = np.array([0.3, 25000 * aero.ft])
        self.normfactor = calc_normfactor(self.x0)

        self.bounds = None
        self.update_bounds()

    def update_bounds(self, **kwargs):
        machmin = kwargs.get('machmin', 0.5)
        machmax = kwargs.get('machmax', self.aircraft['limits']['MMO'])
        hmin = kwargs.get('hmin', 25000 * aero.ft)
        hmax = kwargs.get('hmax', self.aircraft['limits']['ceiling'])

        self.bounds = np.array([[machmin, machmax], [hmin, hmax]
                                ]) * self.normfactor.reshape(2, -1)

    def func_fuel(self, x, mass):
        mach, h = denormalize(x, self.normfactor)
        va = aero.mach2tas(mach, h)
        ff = self.fuelflow.enroute(mass, va / aero.kts, h / aero.ft)
        ff_m = ff / (va + 1e-3) * 1000
        # print("%.03f" % mach, "%d" % (h/aero.ft), "%.05f" % ff_m)
        return ff_m

    def func_time(self, x, mass):
        mach, h = denormalize(x, self.normfactor)
        va = aero.mach2tas(mach, h)
        va_inv = 1 / (va + 1e-4) * 1000
        # print("%.03f" % mach, "%d" % (h/aero.ft), "%.02f" % va)
        return va_inv

    def func_cons_lift(self, x, mass):
        mach, h = denormalize(x, self.normfactor)
        va = aero.mach2tas(mach, h)

        Tmax = self.thrust.cruise(va / aero.kts, h / aero.ft)

        qS = 0.5 * aero.density(h) * va**2 * self.aircraft['wing']['area']
        cd0 = self.drag.polar['clean']['cd0']
        k = self.drag.polar['clean']['k']

        mach_crit = self.drag.polar['mach_crit']
        if mach > mach_crit:
            cd0 += 20 * (mach - mach_crit)**4

        dL2 = qS**2 * (1 / k * (Tmax /
                                (qS + 1e-3) - cd0)) - (mass * aero.g0)**2
        return dL2

    def func_cons_thrust(self, x, mass):
        mach, h = denormalize(x, self.normfactor)
        va = aero.mach2tas(mach, h)

        D = self.drag.clean(mass, va / aero.kts, h / aero.ft)
        Tmax = self.thrust.cruise(va / aero.kts, h / aero.ft)

        dT = Tmax - D
        return dT

    def optimize(self, goal, mass):
        if goal == 'fuel':
            func = self.func_fuel
        elif goal == 'time':
            func = self.func_time
        else:
            raise RuntimeError('Optimization goal [%s] not avaiable.' % goal)

        x0 = self.x0 * self.normfactor
        res = minimize(
            func,
            x0,
            args=(mass, ),
            bounds=self.bounds,
            jac=lambda x, m: Jacobian(lambda x: func(x, m))(x),
            options={'maxiter': 200},
            constraints=(
                {
                    'type':
                    'ineq',
                    'args': (mass, ),
                    'fun':
                    lambda x, m: self.func_cons_thrust(x, m),
                    'jac':
                    lambda x, m: Jacobian(lambda x: self.func_cons_thrust(
                        x, m))(x)
                },
                {
                    'type':
                    'ineq',
                    'args': (mass, ),
                    'fun':
                    lambda x, m: self.func_cons_lift(x, m),
                    'jac':
                    lambda x, m: Jacobian(lambda x: self.func_cons_lift(x, m))
                    (x)
                },
            ))
        return res
class Performance():
    """Calulate Instantaneous performance of one object"""
    def __init__(self, aircraft_name, write_output: bool = False):
        self.write = write_output
        # General Variables
        self.aircraft_data = prop.aircraft(aircraft_name)
        self.dt = 1.0 / 60.0  # simulation timestep 60 per seconds
        aircraft_txt = open(f"./data/{aircraft_name}.json", 'r').read()
        self.aircraft = json.loads(aircraft_txt)
        eng_name = self.aircraft_data["engine"]["default"]
        self.ac_thrust = Thrust(ac=self.aircraft["Name"], eng=eng_name)
        # self.ac_thrust = Thrust(f"./data/{aircraft_name}_thrust.csv")
        # Performance Variables (all unit in SI except stated otherwise)
        self.lift_drag = LiftDrag(f"./data/{aircraft_name}_ld.csv")
        self.g = 9.81
        self.mass = self.aircraft_data["limits"]["MTOW"]
        self.thrust_lever = 1.0
        self.altitude = 0.0
        self.pressure = 0.0
        self.density = 0.0
        self.temp = 0.0
        self.cas = 0.0
        self.tas = 0.0
        self.v_y = 0.0  # vertical Speed
        self.vs = 0.0  # Vertical Speed [fpm]
        self.drag = 0.0
        self.thrust = 0.0
        self.lift = 0.0
        self.weight = 0.0
        self.t_d = 0.0  # thrust minus drag aka exceed thrust
        self.l_w = 0.0  # lift minus weight aka exceed lift
        self.pitch = 0.0
        self.fpa = 0.0
        self.aoa = 0.0
        self.Q = 0.0  # tas² * density
        self.acc_x = 0.0
        self.acc_y = 0.0
        self.distance_x = 0.0  # total distance[m]
        self.d_x = 0.0  # instantaneous X distance[m]
        self.d_y = 0.0  # instantaneous Y distance[m]
        self.phase = 0  # Current phase
        self.cd = 0.0
        self.cl = 0.0
        self.drag0 = self.aircraft["Drag0"]
        self.lift0 = self.aircraft["Lift0"]
        self.gear = False
        self.flaps = 0
        self.pitch_target = 0.0
        self.pitch_rate_of_change = 3.0  # rate of change of the pitch [°/sec]
        self.ac_fuelflow = FuelFlow(ac=self.aircraft["Name"], eng=eng_name)
        if self.write:
            self.output = open("output.csv", 'w+')
            self.output.write(self.__get_header())
            self.output.flush()

    def __get_Q(self):
        self.pressure, self.density, self.temp = aero.atmos(self.altitude)
        self.Q = self.density * (self.tas**2)

    def __calculate_FPA(self):
        self.fpa = math.degrees(math.atan2(self.d_y, self.d_x))
        self.aoa = self.pitch - self.fpa

    def __calculate_lift(self):
        if self.gear:
            self.cl += self.aircraft["Gear"]["Lift"]
        if self.flaps > 0:
            self.cl += self.aircraft["Flaps"][self.flaps - 1]["Lift"]

        self.lift = self.lift0\
            + (0.5 * self.Q * self.aircraft["WingSpan"] * self.cl)
        self.lift *= 1.5

    def __calculate_drag(self, new: bool = True):
        if self.gear:
            self.cd += self.aircraft["Gear"]["Drag"]
        if self.flaps > 0:
            self.cd += self.aircraft["Flaps"][self.flaps - 1]["Drag"]
        self.drag = self.drag0\
            + (0.5 * self.Q * self.aircraft["WingSpan"] * self.cd)

    def __change_pitch(self) -> None:
        """
        Change pitch in relation of pitch target change of pitch occure with
        a 3 degrees per seconds change.
        """
        if self.pitch == self.pitch_target:
            return
        if self.pitch > self.pitch_target:
            self.pitch -= self.pitch_rate_of_change * self.dt
        elif self.pitch < self.pitch_target:
            self.pitch += self.pitch_rate_of_change * self.dt

    def run(self) -> bool:
        """Calculate aircraft performance till thrust reduction altitude

        Args:
            target_alt (float, optional):
                The thrust reduction altitude in meters.
                Defaults to 457.2m (1500.0 feets)

        Returns:
            bool: True if the phase is still valid, else False
        """
        if self.distance_x == 0:
            self.aoa = self.pitch
        self.cl, self.cd = self.lift_drag.get_data(self.aoa)
        self.__get_Q()
        self.__change_pitch()
        self.__calculate_drag()
        self.__calculate_lift()
        self.g = local_gravity(50.0, self.altitude)
        self.weight = self.mass * self.g
        max_thrust = self.ac_thrust.takeoff(alt=self.altitude / aero.ft,
                                            tas=self.tas / aero.kts)
        idle_thrust = self.ac_thrust.descent_idle(tas=self.tas / aero.kts,
                                                  alt=self.altitude / aero.ft)
        self.thrust = interpolate(self.thrust_lever, 0.0, 1.0, idle_thrust,
                                  max_thrust)
        fuelflow = self.ac_fuelflow.at_thrust(acthr=self.thrust / 2.0,
                                              alt=self.altitude / aero.ft)
        self.mass -= fuelflow * self.dt * 2
        self.t_d = self.thrust - self.drag\
            - (self.weight * math.sin(math.radians(self.pitch)))
        self.l_w = self.lift\
            - (self.weight * math.cos(math.radians(self.pitch)))\
            + (self.thrust * math.sin(math.radians(self.pitch)))
        acc = self.t_d / self.mass
        self.acc_x = acc * math.cos(math.radians(self.pitch))
        self.acc_y = acc * math.sin(math.radians(self.pitch))
        v_acc = self.l_w / self.mass
        self.acc_y += v_acc * math.cos(math.radians(self.pitch))
        self.acc_x += v_acc * math.sin(math.radians(self.pitch))
        self.d_x = (self.tas * self.dt) + 0.5 * self.acc_x * (self.dt**2)
        self.d_y = (self.v_y * self.dt) + 0.5 * self.acc_y * (self.dt**2)
        self.tas += self.acc_x * self.dt
        self.cas = aero.tas2cas(self.tas, self.altitude)
        self.v_y += self.acc_y * self.dt
        if self.altitude <= 0:
            self.altitude = 0
            if self.d_y < 0:
                self.d_y = 0
            if self.v_y < 0:
                self.v_y = 0
                self.vs = 0
        self.altitude += self.d_y
        self.distance_x += self.d_x
        self.vs = self.v_y / aero.fpm
        self.__calculate_FPA()
        if self.write:
            self.output.write(str(self))
            self.output.flush()

    def __str__(self):
        return f"{self.mass},{self.altitude},{self.pressure},{self.density},"\
               f"{self.temp},{self.cas},{self.tas},{self.v_y},{self.vs},"\
               f"{self.drag},{self.thrust},{self.t_d},{self.pitch},"\
               f"{self.fpa},{self.aoa},{self.Q},{self.acc_x},{self.acc_y},"\
               f"{self.distance_x},{self.d_x},{self.d_y},{self.phase},"\
               f"{self.cd},{self.drag0},{self.gear},{self.flaps},{self.cl},"\
               f"{self.lift},{self.weight},{self.l_w},{self.thrust_lever},"\
               f"{self.altitude / aero.ft},{self.g},{self.pitch_target}\n"

    def __get_header(self):
        return "Mass,Altitude,Pressure,Density,Temperature,Cas,Tas,Vy,VS,"\
               "Drag,Thrust,T-D,Pitch,FPA,AOA,Q,AccelerationX,AccelerationY,"\
               "DistanceX,Dx,Dy,Phase,Cd,Cd0,Gear,Flaps,Cl,Lift,Weight,L-W,"\
               "Thrust Limit,Altitude FT,Gravity,Target Pitch\n"
Example #6
0
import numpy as np
import matplotlib.pyplot as plt
from openap import Emission, FuelFlow, prop
from mpl_toolkits.mplot3d import Axes3D

ac = "A320"

aircraft = prop.aircraft(ac)
fuelflow = FuelFlow(ac=ac)
emission = Emission(ac=ac)

tas = np.linspace(50, 500, 50)
alt = np.linspace(100, 35000, 50)
tas_, alt_ = np.meshgrid(tas, alt)
mass = aircraft["limits"]["MTOW"] * 0.85

ff = fuelflow.enroute(mass=mass, tas=tas_, alt=alt_, path_angle=0)

co2 = emission.co2(ff)
h2o = emission.h2o(ff)
nox = emission.nox(ff, tas=tas_, alt=alt_)
co = emission.co(ff, tas=tas_, alt=alt_)
hc = emission.hc(ff, tas=tas_, alt=alt_)

fig = plt.figure()
ax = fig.gca(projection="3d")
surf = ax.plot_surface(tas_, alt_, ff)
plt.title("fuel flow (kg/s)")
plt.xlabel("TAS (kt)")
plt.ylabel("Altitude (ft)")
plt.show()
Example #7
0
from openap import FuelFlow

fuel = FuelFlow(ac='A320', eng='CFM56-5B4')

print('-'*70)
FF = fuel.at_thrust(acthr=50000, alt=0)
print("fuel.at_thrust(acthr=50000, alt=0)")
print(FF)
print('-'*70)

FF = fuel.at_thrust(acthr=50000, alt=20000)
print("fuel.at_thrust(acthr=50000, alt=20000)")
print(FF)
print('-'*70)

FF = fuel.takeoff(tas=100, alt=0, throttle=1)
print("fuel.takeoff(tas=100, alt=0, throttle=1)")
print(FF)
print('-'*70)

FF = fuel.enroute(mass=60000, tas=200, alt=20000, path_angle=3)
print("fuel.enroute(mass=60000, tas=200, alt=20000, path_angle=3)")
print(FF)
print('-'*70)

FF = fuel.enroute(mass=60000, tas=230, alt=32000, path_angle=0)
print("fuel.enroute(mass=60000, tas=230, alt=32000, path_angle=0)")
print(FF)
print('-'*70)

FF = fuel.enroute(mass=[60000], tas=[230], alt=[32000], path_angle=[0])
Example #8
0
from openap import prop, FuelFlow, Emission, WRAP

available_acs = prop.available_aircraft(use_synonym=True)

for actype in available_acs:
    # print(actype)
    aircraft = prop.aircraft(ac=actype, use_synonym=True)
    wrap = WRAP(ac=actype, use_synonym=True)
    fuelflow = FuelFlow(ac=actype, use_synonym=True)
    emission = Emission(ac=actype, use_synonym=True)


available_acs = prop.available_aircraft(use_synonym=False)

for actype in available_acs:
    # print(actype)
    aircraft = prop.aircraft(ac=actype, use_synonym=False)
    wrap = WRAP(ac=actype, use_synonym=True)
    fuelflow = FuelFlow(ac=actype, use_synonym=True)
    emission = Emission(ac=actype, use_synonym=True)