"""OpenAP Emission model."""
from typing import Any, Optional, Tuple
from openap import prop
from openap.backends import BackendType
Numeric = Any
from openap.extra import ndarrayconvert
from .base import EmissionBase
class Emission(EmissionBase):
"""Emission model based on ICAO emission databank."""
def __init__(
self,
ac: str,
eng: Optional[str] = None,
backend: Optional[BackendType] = None,
**kwargs,
):
"""Initialize Emission object.
Args:
ac: ICAO aircraft type (for example: A320).
eng: Engine type (for example: CFM56-5A3).
Leave empty to use the default engine specified
by in the aircraft database.
backend: Math backend to use. Defaults to NumpyBackend.
"""
super().__init__(ac, eng, backend=backend, **kwargs)
self.aircraft = prop.aircraft(ac, **kwargs)
self.n_eng = self.aircraft["engine"]["number"]
if eng is None:
eng = self.aircraft["engine"]["default"]
self.engine = prop.engine(eng)
def _fl2sl(
self, ffac: Numeric, tas: Numeric, alt: Numeric, dT: Numeric = 0
) -> Tuple[Numeric, Numeric]:
"""Convert to sea-level equivalent."""
b = self.backend
M = self.aero.tas2mach(tas * self.aero.kts, alt * self.aero.ft, dT=dT)
beta = b.exp(0.2 * (M**2))
theta = (self.aero.temperature(alt * self.aero.ft, dT=dT) / 288.15) / beta
delta = (1 - 0.0019812 * alt / 288.15) ** 5.255876 / b.power(beta, 3.5)
ratio = (theta**3.3) / (delta**1.02)
ff_sl = (ffac / self.n_eng) * theta**3.8 / delta * beta
return ff_sl, ratio
@ndarrayconvert
def co2(self, ffac: Numeric) -> Numeric:
"""Compute CO2 emission with given fuel flow.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
Returns:
CO2 emission from all engines (unit: g/s).
"""
return ffac * 3160
@ndarrayconvert
def h2o(self, ffac: Numeric) -> Numeric:
"""Compute H2O emission with given fuel flow.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
Returns:
H2O emission from all engines (unit: g/s).
"""
return ffac * 1230
@ndarrayconvert
def soot(self, ffac: Numeric) -> Numeric:
"""Compute soot emission with given fuel flow.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
Returns:
Soot emission from all engines (unit: g/s).
"""
return ffac * 0.03
@ndarrayconvert
def sox(self, ffac: Numeric) -> Numeric:
"""Compute SOx emission with given fuel flow.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
Returns:
SOx emission from all engines (unit: g/s).
"""
return ffac * 1.2
@ndarrayconvert
def nox(
self,
ffac: Numeric,
tas: Numeric,
alt: Numeric = 0,
dT: Numeric = 0,
) -> Numeric:
"""Compute NOx emission with given fuel flow, speed, and altitude.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
tas: Speed (unit: kt).
alt: Aircraft altitude (unit: ft). Defaults to 0.
dT: Temperature shift (unit: K or degC). Defaults to 0.
Returns:
NOx emission from all engines (unit: g/s).
"""
b = self.backend
ff_sl, ratio = self._fl2sl(ffac, tas, alt, dT=dT)
nox_sl = b.interp(
ff_sl,
[
self.engine["ff_idl"],
self.engine["ff_app"],
self.engine["ff_co"],
self.engine["ff_to"],
],
[
self.engine["ei_nox_idl"],
self.engine["ei_nox_app"],
self.engine["ei_nox_co"],
self.engine["ei_nox_to"],
],
)
omega = 10 ** (-3) * b.exp(-0.0001426 * (alt - 12900))
nox_fl = nox_sl * b.sqrt(1 / ratio) * b.exp(-19 * (omega - 0.00634))
nox_rate = nox_fl * ffac
return nox_rate
@ndarrayconvert
def co(
self,
ffac: Numeric,
tas: Numeric,
alt: Numeric = 0,
dT: Numeric = 0,
) -> Numeric:
"""Compute CO emission with given fuel flow, speed, and altitude.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
tas: Speed (unit: kt).
alt: Aircraft altitude (unit: ft). Defaults to 0.
dT: Temperature shift (unit: K or degC). Defaults to 0.
Returns:
CO emission from all engines (unit: g/s).
"""
b = self.backend
ff_sl, ratio = self._fl2sl(ffac, tas, alt, dT=dT)
co_sl = b.interp(
ff_sl,
[
self.engine["ff_idl"],
self.engine["ff_app"],
self.engine["ff_co"],
self.engine["ff_to"],
],
[
self.engine["ei_co_idl"],
self.engine["ei_co_app"],
self.engine["ei_co_co"],
self.engine["ei_co_to"],
],
)
co_fl = co_sl * ratio
co_rate = co_fl * ffac
return co_rate
@ndarrayconvert
def hc(
self,
ffac: Numeric,
tas: Numeric,
alt: Numeric = 0,
dT: Numeric = 0,
) -> Numeric:
"""Compute HC emission with given fuel flow, speed, and altitude.
Args:
ffac: Fuel flow for all engines (unit: kg/s).
tas: Speed (unit: kt).
alt: Aircraft altitude (unit: ft). Defaults to 0.
dT: Temperature shift (unit: K or degC). Defaults to 0.
Returns:
HC emission from all engines (unit: g/s).
"""
b = self.backend
ff_sl, ratio = self._fl2sl(ffac, tas, alt, dT=dT)
hc_sl = b.interp(
ff_sl,
[
self.engine["ff_idl"],
self.engine["ff_app"],
self.engine["ff_co"],
self.engine["ff_to"],
],
[
self.engine["ei_hc_idl"],
self.engine["ei_hc_app"],
self.engine["ei_hc_co"],
self.engine["ei_hc_to"],
],
)
hc_fl = hc_sl * ratio
hc_rate = hc_fl * ffac
return hc_rate