# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 European Commission (JRC);
# Licensed under the EUPL (the 'Licence');
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
"""
Functions and `dsp` model to model the engine.
Sub-Modules:
.. currentmodule:: co2mpas.core.model.physical.engine
.. autosummary::
:nosignatures:
:toctree: engine/
fc
idle
thermal
"""
import math
import functools
import numpy as np
import schedula as sh
from co2mpas.defaults import dfl
from .idle import dsp as _idle
from .thermal import dsp as _thermal
from .fc import dsp as _fc
dsp = sh.BlueDispatcher(name='Engine', description='Models the vehicle engine.')
[docs]@sh.add_function(dsp, outputs=['fuel_type', 'is_hybrid'])
def define_fuel_type_and_is_hybrid(obd_fuel_type_code):
"""
Defines engine fuel type and if the vehicle is hybrid.
:param obd_fuel_type_code:
OBD fuel type of the vehicle [-].
:type obd_fuel_type_code: int
:return:
Engine fuel type and if the vehicle is hybrid.
:rtype: (str, bool)
"""
i = int(obd_fuel_type_code)
d = dfl.functions.define_fuel_type_and_is_hybrid
return d.fuel_type.get(i, sh.NONE), d.is_hybrid.get(i, sh.NONE)
[docs]@sh.add_function(dsp, outputs=['engine_mass'])
def calculate_engine_mass(ignition_type, engine_max_power):
"""
Calculates the engine mass [kg].
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:param engine_max_power:
Engine nominal power [kW].
:type engine_max_power: float
:return:
Engine mass [kg].
:rtype: float
"""
par = dfl.functions.calculate_engine_mass.PARAMS
_mass_coeff = par['mass_coeff']
m, q = par['mass_reg_coeff']
# Engine mass empirical formula based on web data found for engines weighted
# according DIN 70020-GZ
# kg
return (m * engine_max_power + q) * _mass_coeff[ignition_type]
[docs]@sh.add_function(dsp, outputs=['engine_heat_capacity'])
def calculate_engine_heat_capacity(engine_mass):
"""
Calculates the engine heat capacity [kg*J/K].
:param engine_mass:
Engine mass [kg].
:type engine_mass: float
:return:
Engine heat capacity [kg*J/K].
:rtype: float
"""
par = dfl.functions.calculate_engine_heat_capacity.PARAMS
mp, hc = par['heated_mass_percentage'], par['heat_capacity']
return engine_mass * np.sum([hc[k] * v for k, v in mp.items()])
[docs]@sh.add_function(dsp, outputs=['ignition_type'])
def default_ignition_type(engine_type):
"""
Returns the default ignition type according to the fuel type.
:param engine_type:
Engine type (positive turbo, positive natural aspiration, compression).
:type engine_type: str
:return:
Engine ignition type (positive or compression).
:rtype: str
"""
if 'compression' in engine_type:
return 'compression'
return 'positive'
[docs]@sh.add_function(dsp, outputs=['ignition_type'], weight=1)
def default_ignition_type_v1(fuel_type):
"""
Returns the default ignition type according to the fuel type.
:param fuel_type:
Fuel type (diesel, gasoline, LPG, NG, ethanol, methanol, biodiesel,
propane).
:type fuel_type: str
:return:
Engine ignition type (positive or compression).
:rtype: str
"""
if 'diesel' in fuel_type:
return 'compression'
return 'positive'
[docs]@sh.add_function(dsp, outputs=['full_bmep_curve'])
def define_full_bmep_curve(
full_load_speeds, full_load_curve, min_engine_on_speed,
engine_capacity, engine_stroke, idle_engine_speed, engine_max_speed):
"""
Defines the vehicle full bmep curve.
:param full_load_speeds:
T1 map speed vector [RPM].
:type full_load_speeds: numpy.array
:param full_load_curve:
Vehicle full load curve.
:type full_load_curve: function
:param min_engine_on_speed:
Minimum engine speed to consider the engine to be on [RPM].
:type min_engine_on_speed: float
:param engine_capacity:
Engine capacity [cm3].
:type engine_capacity: float
:param engine_stroke:
Engine stroke [mm].
:type engine_stroke: float
:param idle_engine_speed:
Idle engine speed and its standard deviation [RPM].
:type idle_engine_speed: (float, float)
:param engine_max_speed:
Maximum allowed engine speed [RPM].
:type engine_max_speed: float
:return:
Vehicle full bmep curve.
:rtype: function
"""
speeds = np.unique(np.append(
full_load_speeds, [idle_engine_speed[0], engine_max_speed]
))
from .fc import calculate_brake_mean_effective_pressures
p = calculate_brake_mean_effective_pressures(
speeds, full_load_curve(speeds), engine_capacity,
min_engine_on_speed)
s = calculate_mean_piston_speeds(speeds, engine_stroke)
return functools.partial(np.interp, xp=s, fp=p, left=0, right=0)
dsp.add_data('is_cycle_hot', dfl.values.is_cycle_hot)
[docs]@sh.add_function(dsp, outputs=['full_load_powers'])
def calculate_full_load_powers(full_load_torques, full_load_speeds):
"""
Calculates T1 map power vector [kW].
:param full_load_torques:
T1 map torque vector [N*m].
:type full_load_torques: numpy.array
:param full_load_speeds:
T1 map speed vector [RPM].
:type full_load_speeds: numpy.array
:return:
T1 map power vector [kW].
:rtype: numpy.array
"""
from ..wheels import calculate_wheel_powers
return calculate_wheel_powers(full_load_torques, full_load_speeds)
[docs]@sh.add_function(dsp, outputs=['full_load_torques'])
def calculate_full_load_speeds(full_load_powers, full_load_torques):
"""
Calculates T1 map speed vector [RPM].
:param full_load_powers:
T1 map power vector [kW].
:type full_load_powers: numpy.array
:param full_load_torques:
T1 map torque vector [N*m].
:type full_load_torques: numpy.array
:return:
T1 map speed vector [RPM].
:rtype: numpy.array
"""
from ..wheels import calculate_wheel_torques
return calculate_wheel_torques(full_load_powers, full_load_torques)
[docs]@sh.add_function(dsp, outputs=['engine_max_speed'], weight=20)
def default_engine_max_speed(
ignition_type, idle_engine_speed, engine_speed_at_max_power):
"""
Returns the default maximum allowed engine speed [RPM].
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:param idle_engine_speed:
Engine speed idle median and std [RPM].
:type idle_engine_speed: (float, float)
:param engine_speed_at_max_power:
Engine speed at engine nominal power [RPM].
:type engine_speed_at_max_power: float
:return:
Maximum allowed engine speed [RPM].
:rtype: float
"""
fl = dfl.functions.default_full_load_speeds_and_powers.FULL_LOAD
idl, r = idle_engine_speed[0], max(fl[ignition_type][0])
return idl + r * (engine_speed_at_max_power - idl)
[docs]@sh.add_function(dsp, outputs=['full_load_speeds', 'full_load_powers'])
def default_full_load_speeds_and_powers(
ignition_type, engine_max_power, engine_speed_at_max_power,
idle_engine_speed, engine_max_speed):
"""
Returns the defaults full load speeds and powers [RPM, kW].
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:param engine_max_power:
Engine nominal power [kW].
:type engine_max_power: float
:param engine_speed_at_max_power:
Engine speed at engine nominal power [RPM].
:type engine_speed_at_max_power: float
:param idle_engine_speed:
Engine speed idle median and std [RPM].
:type idle_engine_speed: (float, float)
:param engine_max_speed:
Maximum allowed engine speed [RPM].
:type engine_max_speed: float
:return:
T1 map speed [RPM] and power [kW] vectors.
:rtype: (numpy.array, numpy.array)
"""
from scipy.interpolate import InterpolatedUnivariateSpline as Spline
idl = idle_engine_speed[0]
full_load_speeds = np.unique(np.append(
[engine_speed_at_max_power], np.linspace(idl, engine_max_speed)
))
d = dfl.functions.default_full_load_speeds_and_powers
full_load_powers = Spline(*d.FULL_LOAD[ignition_type], k=1)(
(full_load_speeds - idl) / (engine_speed_at_max_power - idl)
) * engine_max_power
return full_load_speeds, full_load_powers
[docs]@sh.add_function(dsp, outputs=['engine_speed_at_max_power'])
def identify_engine_speed_at_max_power(full_load_speeds, full_load_powers):
"""
Identifies engine nominal speed at engine nominal power [RPM].
:param full_load_speeds:
T1 map speed vector [RPM].
:type full_load_speeds: numpy.array
:param full_load_powers:
T1 map power vector [kW].
:type full_load_powers: numpy.array
:return:
Engine speed at engine nominal power [RPM].
:rtype: float
"""
return full_load_speeds[np.argmax(full_load_powers)]
[docs]@sh.add_function(dsp, outputs=['engine_max_power'])
def calculate_engine_max_power(full_load_curve, engine_speed_at_max_power):
"""
Calculates engine nominal power [kW].
:param full_load_curve:
Vehicle full load curve.
:type full_load_curve: function
:param engine_speed_at_max_power:
Engine speed at engine nominal power [RPM].
:type engine_speed_at_max_power: float
:return:
Engine nominal power [kW].
:rtype: float
"""
return full_load_curve(engine_speed_at_max_power)
[docs]@sh.add_function(dsp, outputs=['full_load_curve'])
def define_full_load_curve(
full_load_speeds, full_load_powers, idle_engine_speed,
engine_max_speed):
"""
Calculates the full load curve.
:param full_load_speeds:
T1 map speed vector [RPM].
:type full_load_speeds: numpy.array
:param full_load_powers:
T1 map power vector [kW].
:type full_load_powers: numpy.array
:param idle_engine_speed:
Engine speed idle median and std [RPM].
:type idle_engine_speed: (float, float)
:param engine_max_speed:
Maximum allowed engine speed [RPM].
:type engine_max_speed: float
:return:
Vehicle full load curve.
:rtype: function
"""
xp = [idle_engine_speed[0] - idle_engine_speed[1], engine_max_speed]
xp.extend(full_load_speeds)
xp = np.unique(xp)
fp = np.interp(xp, full_load_speeds, full_load_powers)
return functools.partial(np.interp, xp=xp, fp=fp, left=0, right=0)
[docs]@sh.add_function(dsp, outputs=['engine_max_speed'])
def identify_engine_max_speed(full_load_speeds):
"""
Identifies the maximum allowed engine speed [RPM].
:param full_load_speeds:
T1 map speed vector [RPM].
:type full_load_speeds: numpy.array
:return:
Maximum allowed engine speed [RPM].
:rtype: float
"""
return np.max(full_load_speeds)
[docs]@sh.add_function(dsp, outputs=['engine_max_torque'])
def calculate_engine_max_torque(
engine_max_power, engine_speed_at_max_power, ignition_type):
"""
Calculates engine nominal torque [N*m].
:param engine_max_power:
Engine nominal power [kW].
:type engine_max_power: float
:param engine_speed_at_max_power:
Engine speed at engine nominal power [RPM].
:type engine_speed_at_max_power: float
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:return:
Engine nominal torque [N*m].
:rtype: float
"""
c = dfl.functions.calculate_engine_max_torque.PARAMS[ignition_type]
pi = math.pi
return engine_max_power / engine_speed_at_max_power * (30000.0 / pi * c)
[docs]@sh.add_function(dsp, outputs=['engine_max_power'])
def calculate_engine_max_power_v1(
engine_max_torque, engine_speed_at_max_power, ignition_type):
"""
Calculates engine nominal power [kW].
:param engine_max_torque:
Engine nominal torque [N*m].
:type engine_max_torque: float
:param engine_speed_at_max_power:
Engine speed at engine nominal power [RPM].
:type engine_speed_at_max_power: float
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:return:
Engine nominal power [kW].
:rtype: float
"""
c = calculate_engine_max_torque(1, engine_speed_at_max_power, ignition_type)
return engine_max_torque / c
dsp.add_dispatcher(
include_defaults=True,
dsp=_idle,
inputs=(
'idle_engine_speed_median', 'idle_engine_speed_std',
'min_engine_on_speed', 'stop_velocity', 'velocities',
'engine_speeds_out', 'idle_engine_speed',
),
outputs=(
'idle_engine_speed_median', 'idle_engine_speed_std',
'idle_engine_speed'
)
)
dsp.add_dispatcher(
include_defaults=True,
dsp=_thermal,
dsp_id='thermal',
inputs=(
'max_engine_coolant_temperature', 'initial_engine_temperature', 'times',
'engine_thermostat_temperature_window', 'engine_thermostat_temperature',
'engine_temperature_regression_model', 'idle_engine_speed', 'on_engine',
'engine_coolant_temperatures', 'gear_box_powers_out', 'accelerations',
'engine_speeds_out', 'velocities',
),
outputs=(
'engine_thermostat_temperature_window', 'engine_thermostat_temperature',
'engine_temperature_regression_model', 'max_engine_coolant_temperature',
'engine_temperature_derivatives', 'engine_coolant_temperatures',
'initial_engine_temperature',
)
)
[docs]@sh.add_function(
dsp,
inputs=[
'on_engine', 'idle_engine_speed', 'engine_speeds_out_hot',
'after_treatment_speeds_delta', 'clutch_tc_speeds_delta'
],
outputs=['engine_speeds_out']
)
def calculate_engine_speeds_out(
on_engine, idle_engine_speed, engine_speeds_out_hot, *delta_speeds):
"""
Calculates the engine speed [RPM].
:param on_engine:
If the engine is on [-].
:type on_engine: numpy.array
:param idle_engine_speed:
Idle engine speed and its standard deviation [RPM].
:type idle_engine_speed: (float, float)
:param engine_speeds_out_hot:
Engine speed at hot condition [RPM].
:type engine_speeds_out_hot: numpy.array
:return:
Engine speed [RPM].
:rtype: numpy.array
"""
speeds = engine_speeds_out_hot.copy()
s = speeds[on_engine]
for delta in delta_speeds:
s += delta[on_engine]
dn = idle_engine_speed[0]
s[s < dn] = dn
speeds[on_engine] = s
return speeds
[docs]@sh.add_function(dsp, outputs=['engine_inertia_powers_losses'])
def calculate_engine_inertia_powers_losses(
times, engine_speeds_out, engine_moment_inertia):
"""
Calculates the engine power losses due to inertia [kW].
:param times:
Time vector [s].
:type times: numpy.array
:param engine_moment_inertia:
Engine moment of inertia [kg*m2].
:type engine_moment_inertia: float
:param engine_speeds_out:
Engine speed [RPM].
:type engine_speeds_out: numpy.array
:return:
Engine power losses due to inertia [kW].
:rtype: numpy.array
"""
t = times[:, None] + np.array([-1, 1])
c = engine_moment_inertia / 2000 * (2 * math.pi / 60) ** 2 / 4
return c * np.diff(np.interp(t, times, engine_speeds_out)).ravel() ** 2
dsp.add_data('belt_efficiency', dfl.values.belt_efficiency)
dsp.add_function(
function=sh.bypass,
inputs=['belt_efficiency'],
outputs=['belt_mean_efficiency']
)
[docs]@sh.add_function(dsp, outputs=['gross_engine_powers_out'])
def calculate_gross_engine_powers_out(
clutch_tc_powers, belt_efficiency, on_engine, gear_box_type, on_idle,
alternator_powers, motor_p0_powers, motor_p1_powers,
motor_p2_planetary_powers):
"""
Calculates the gross engine power (pre-losses) [kW].
:param clutch_tc_powers:
Clutch or torque converter power [kW].
:type clutch_tc_powers: numpy.array
:param belt_efficiency:
Belt efficiency [-].
:type belt_efficiency: float
:param on_engine:
If the engine is on [-].
:type on_engine: numpy.array
:param gear_box_type:
Gear box type (manual or automatic or cvt).
:type gear_box_type: str
:param on_idle:
If the engine is on idle [-].
:type on_idle: numpy.array
:param alternator_powers:
Alternator power [kW].
:type alternator_powers: numpy.array
:param motor_p0_powers:
Power at motor P0 [kW].
:type motor_p0_powers: numpy.array
:param motor_p1_powers:
Power at motor P1 [kW].
:type motor_p1_powers: numpy.array
:param motor_p2_planetary_powers:
Power at planetary motor P2 [kW].
:type motor_p2_planetary_powers: numpy.array
:return:
Gross engine power (pre-losses) [kW].
:rtype: numpy.array
"""
p, b = np.zeros_like(clutch_tc_powers, dtype=float), on_engine
p[b] = clutch_tc_powers[b]
if gear_box_type == 'manual':
p[on_idle & (p < 0)] = 0.0
eff = np.where(motor_p0_powers[b] < 0, belt_efficiency, 1 / belt_efficiency)
p[b] -= alternator_powers[b] + motor_p0_powers[b] * eff
p[b] -= motor_p1_powers[b] + motor_p2_planetary_powers[b]
return p
[docs]@sh.add_function(dsp, outputs=['min_available_engine_powers_out'])
def calculate_min_available_engine_powers_out(
engine_stroke, engine_capacity, initial_friction_params,
engine_speeds_out):
"""
Calculates the minimum available engine power (i.e., engine motoring curve).
:param engine_stroke:
Engine stroke [mm].
:type engine_stroke: float
:param engine_capacity:
Engine capacity [cm3].
:type engine_capacity: float
:param initial_friction_params:
Engine initial friction params l & l2 [-].
:type initial_friction_params: float, float
:param engine_speeds_out:
Engine speed [RPM].
:type engine_speeds_out: numpy.array | float
:return:
Minimum available engine power [kW].
:rtype: numpy.array | float
"""
l, l2 = np.array(initial_friction_params) * (engine_capacity / 1200000.0)
l2 *= (engine_stroke / 30000.0) ** 2
return (l2 * engine_speeds_out * engine_speeds_out + l) * engine_speeds_out
[docs]@sh.add_function(dsp, outputs=['max_available_engine_powers_out'])
def calculate_max_available_engine_powers_out(
full_load_curve, engine_speeds_out):
"""
Calculates the maximum available engine power [kW].
:param full_load_curve:
Vehicle full load curve.
:type full_load_curve: function
:param engine_speeds_out:
Engine speed vector [RPM].
:type engine_speeds_out: numpy.array | float
:return:
Maximum available engine power [kW].
:rtype: numpy.array | float
"""
return full_load_curve(engine_speeds_out)
[docs]@sh.add_function(
dsp, outputs=['engine_powers_out', 'missing_powers', 'brake_powers']
)
def correct_engine_powers_out(
max_available_engine_powers_out, min_available_engine_powers_out,
gross_engine_powers_out, auxiliaries_power_losses,
engine_inertia_powers_losses):
"""
Corrects the engine powers out according to the available powers and
returns the missing and brake power [kW].
:param max_available_engine_powers_out:
Maximum available engine power [kW].
:type max_available_engine_powers_out: numpy.array
:param min_available_engine_powers_out:
Minimum available engine power [kW].
:type min_available_engine_powers_out: numpy.array
:param engine_inertia_powers_losses:
Engine power losses due to inertia [kW].
:type engine_inertia_powers_losses: numpy.array
:param auxiliaries_power_losses:
Engine power losses due to engine auxiliaries [kW].
:type auxiliaries_power_losses: numpy.array
:param gross_engine_powers_out:
Gross engine power (pre-losses) [kW].
:type gross_engine_powers_out: numpy.array
:return:
Engine, missing, and braking powers [kW].
:rtype: numpy.array, numpy.array, numpy.array
"""
ul, dl = max_available_engine_powers_out, min_available_engine_powers_out
p = gross_engine_powers_out + auxiliaries_power_losses
p += engine_inertia_powers_losses
up, dn = ul < p, dl > p
missing_powers, brake_powers = np.zeros_like(p), np.zeros_like(p)
missing_powers[up], brake_powers[dn] = p[up] - ul[up], dl[dn] - p[dn]
return np.where(up, ul, np.where(dn, dl, p)), missing_powers, brake_powers
[docs]@sh.add_function(dsp, outputs=['has_sufficient_power'])
def check_vehicle_has_sufficient_power(times, missing_powers):
"""
Checks if the vehicle has sufficient power.
:param times:
Time vector [s].
:type times: numpy.array
:param missing_powers:
Missing powers [kW].
:type missing_powers: numpy.array
:return:
The cycle's percentage in which the vehicle has sufficient power [%].
:rtype: float
"""
w = np.zeros_like(times, dtype=float)
t = (times[:-1] + times[1:]) / 2
# noinspection PyUnresolvedReferences
w[0], w[1:-1], w[-1] = t[0] - times[0], np.diff(t), times[-1] - t[-1]
return 1 - np.average(missing_powers != 0, weights=w)
[docs]@sh.add_function(dsp, outputs=['mean_piston_speeds'])
def calculate_mean_piston_speeds(engine_speeds_out, engine_stroke):
"""
Calculates mean piston speed [m/sec].
:param engine_speeds_out:
Engine speed vector [RPM].
:type engine_speeds_out: numpy.array
:param engine_stroke:
Engine stroke [mm].
:type engine_stroke: float
:return:
Mean piston speed vector [m/s].
:rtype: numpy.array | float
"""
return (engine_stroke / 30000.0) * engine_speeds_out
dsp.add_data('engine_is_turbo', dfl.values.engine_is_turbo)
[docs]@sh.add_function(dsp, outputs=['engine_type'])
def calculate_engine_type(ignition_type, engine_is_turbo):
"""
Calculates the engine type (gasoline turbo, gasoline natural aspiration,
diesel).
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:param engine_is_turbo:
If the engine is equipped with any kind of charging.
:type engine_is_turbo: bool
:return:
Engine type (positive turbo, positive natural aspiration, compression).
:rtype: str
"""
engine_type = ignition_type
if ignition_type == 'positive':
engine_type = 'turbo' if engine_is_turbo else 'natural aspiration'
engine_type = '%s %s' % (ignition_type, engine_type)
return engine_type
[docs]@sh.add_function(dsp, outputs=['engine_moment_inertia'])
def calculate_engine_moment_inertia(engine_capacity, ignition_type):
"""
Calculates engine moment of inertia [kg*m2].
:param engine_capacity:
Engine capacity [cm3].
:type engine_capacity: float
:param ignition_type:
Engine ignition type (positive or compression).
:type ignition_type: str
:return:
Engine moment of inertia [kg*m2].
:rtype: float
"""
par = dfl.functions.calculate_engine_moment_inertia.PARAMS[ignition_type]
return (0.05 + 0.1 * engine_capacity / 1000.0) * par
dsp.add_data(
'auxiliaries_torque_loss_factors',
dfl.values.auxiliaries_torque_loss_factors
)
dsp.add_data('auxiliaries_power_loss', dfl.values.auxiliaries_power_loss)
[docs]@sh.add_function(dsp, outputs=['auxiliaries_torque_loss'])
def calculate_auxiliaries_torque_loss(
auxiliaries_torque_loss_factors, engine_capacity):
"""
Calculates engine torque losses due to engine auxiliaries [N*m].
:param auxiliaries_torque_loss_factors:
Constant torque loss factors due to engine auxiliaries [N/m2, N*m].
:type auxiliaries_torque_loss_factors: (float, float)
:param engine_capacity:
Engine capacity [cm3].
:type engine_capacity: float
:return:
Engine torque losses due to engine auxiliaries [N*m].
:rtype: numpy.array
"""
m, q = auxiliaries_torque_loss_factors
return m * engine_capacity / 1000.0 + q
[docs]@sh.add_function(dsp, outputs=['auxiliaries_torque_losses'])
def calculate_auxiliaries_torque_losses(times, auxiliaries_torque_loss):
"""
Calculates engine torque losses due to engine auxiliaries [N*m].
:param times:
Time vector [s].
:type times: numpy.array
:param auxiliaries_torque_loss:
Constant torque loss due to engine auxiliaries [N*m].
:type auxiliaries_torque_loss: float
:return:
Engine torque losses due to engine auxiliaries [N*m].
:rtype: numpy.array
"""
return np.tile(auxiliaries_torque_loss, len(times))
[docs]@sh.add_function(dsp, outputs=['auxiliaries_power_losses'])
def calculate_auxiliaries_power_losses(
auxiliaries_torque_losses, engine_speeds_out, on_engine,
auxiliaries_power_loss):
"""
Calculates engine power losses due to engine auxiliaries [kW].
:param auxiliaries_torque_losses:
Engine torque losses due to engine auxiliaries [N*m].
:type auxiliaries_torque_losses: numpy.array
:param engine_speeds_out:
Engine speed [RPM].
:type engine_speeds_out: numpy.array
:param on_engine:
If the engine is on [-].
:type on_engine: numpy.array
:param auxiliaries_power_loss:
Constant power loss due to engine auxiliaries [kW].
:type auxiliaries_power_loss: float
:return:
Engine power losses due to engine auxiliaries [kW].
:rtype: numpy.array
"""
from ..wheels import calculate_wheel_powers
p = calculate_wheel_powers(auxiliaries_torque_losses, engine_speeds_out)
if auxiliaries_power_loss:
p[on_engine] += auxiliaries_power_loss
return p
dsp.add_dispatcher(
include_defaults=True,
dsp=_fc,
dsp_id='fc_model',
inputs=(
'engine_has_variable_valve_actuation', 'engine_max_speed', 'velocities',
'engine_thermostat_temperature', 'engine_thermostat_temperature_window',
'engine_n_cylinders', 'min_engine_on_speed', 'phases_integration_times',
'has_selective_catalytic_reduction', 'engine_has_cylinder_deactivation',
'engine_fuel_lower_heating_value', 'idle_engine_speed', 'co2_emissions',
'calibration_status', 'fuel_consumptions', 'engine_powers_out', 'times',
'engine_speeds_out', 'full_load_powers', 'full_bmep_curve', 'on_engine',
'full_load_speeds', 'engine_capacity', 'stop_velocity', 'has_lean_burn',
'initial_engine_temperature', 'active_cylinder_ratios', 'engine_stroke',
'has_exhausted_gas_recirculation', 'fuel_carbon_content', 'engine_type',
'engine_coolant_temperatures', 'mean_piston_speeds', 'phases_distances',
'co2_normalization_references', 'phases_co2_emissions', 'is_cycle_hot',
'engine_inertia_powers_losses', 'co2_params', 'fuel_type', {
'co2_params_calibrated': ('co2_params_calibrated', 'co2_params'),
'engine_idle_fuel_consumption': (
'engine_idle_fuel_consumption',
'idle_fuel_consumption_initial_guess'
)
}),
outputs=(
'active_lean_burns', 'co2_rescaling_scores', 'co2_params_initial_guess',
'after_treatment_temperature_threshold', 'engine_idle_fuel_consumption',
'identified_co2_emissions', 'co2_emissions_model', 'calibration_status',
'initial_friction_params', 'active_variable_valves', 'active_cylinders',
'fuel_carbon_content', 'fuel_consumptions', 'co2_emissions', 'fuel_map',
'extended_phases_integration_times', 'mean_piston_speeds', 'fmep_model',
'active_exhausted_gas_recirculations', 'extended_phases_co2_emissions',
'has_exhausted_gas_recirculation', 'engine_fuel_lower_heating_value',
'co2_params_calibrated'
),
inp_weight={'co2_params': dfl.EPS}
)