@sh.add_function(dsp, outputs=['hybrid_modes'])
def predict_hybrid_modes(
start_stop_hybrid, ems_data, drive_battery_model, times, motive_powers,
accelerations, after_treatment_warm_up_duration,
after_treatment_cooling_duration, start_stop_activation_time,
min_time_engine_on_after_start, is_cycle_hot):
"""
Predicts the hybrid mode status (0: EV, 1: Parallel, 2: Serial).
:param start_stop_hybrid:
Start stop model for hybrid electric vehicles.
:type start_stop_hybrid: StartStopHybrid
:param ems_data:
EMS decision data.
:type ems_data: dict
:param drive_battery_model:
Drive battery current model.
:type drive_battery_model: DriveBatteryModel
:param times:
Time vector [s].
:type times: numpy.array
:param motive_powers:
Motive power [kW].
:type motive_powers: numpy.array
:param accelerations:
Acceleration [m/s2].
:type accelerations: numpy.array
:param after_treatment_warm_up_duration:
After treatment warm up duration [s].
:type after_treatment_warm_up_duration: float
:param after_treatment_cooling_duration:
After treatment cooling duration [s].
:type after_treatment_cooling_duration: float
:param min_time_engine_on_after_start:
Minimum time of engine on after a start [s].
:type min_time_engine_on_after_start: float
:param start_stop_activation_time:
Start-stop activation time threshold [s].
:type start_stop_activation_time: float
:param is_cycle_hot:
Is an hot cycle?
:type is_cycle_hot: bool
:return:
Hybrid mode status (0: EV, 1: Parallel, 2: Serial).
:rtype: numpy.array
"""
r = start_stop_hybrid.reference(ems_data)
ele, par, ser = r['electric'], r['parallel'], r['serial']
current_bat = {
i: v['current_bat'].ravel() for i, v in enumerate((ele, par, ser, ele))
}
starter_bat = {
i: v['power_start'].ravel() for i, v in enumerate((par, ser, ser), 1)
}
starter_bat[0] = np.where(
r['hybrid_modes'] == 1, *(v['power_stop'].T for v in (par, ser))
).ravel()
from ..electrics.motors.starter import calculate_starter_currents as func
nom_volt = drive_battery_model.service.nominal_voltage
starter_bat = {k: func(v, nom_volt) for k, v in starter_bat.items()}
# noinspection PyUnresolvedReferences
hybrid_modes = r['force_on_engine'].astype(int)
drive_battery_model.reset()
soc, t0 = drive_battery_model.init_soc, start_stop_activation_time
it = enumerate(zip(
times, motive_powers, accelerations, hybrid_modes, r['k_reference'],
r['hybrid_modes'].ravel()
))
t_after_treatment = times[0]
if is_cycle_hot:
t_after_treatment += after_treatment_cooling_duration
for i, (t, motive_power, acc, mode, k_ref, mode_ref) in it:
pre_mode = hybrid_modes.take(i - 1, mode='clip')
j = int(bool(pre_mode))
if not mode:
if t < t0:
mode = pre_mode
elif k_ref[j] > start_stop_hybrid(soc):
mode = mode_ref
starter_curr = 0
if bool(pre_mode) ^ bool(mode) and i:
if mode:
t0 = t + min_time_engine_on_after_start
if t >= t_after_treatment:
if not hybrid_modes[i]:
mode = 3
j = np.searchsorted(
times, t + after_treatment_warm_up_duration
) + 1
hybrid_modes[i:j][hybrid_modes[i:j] == 0] = 3
else:
t_after_treatment = t + after_treatment_cooling_duration
starter_curr = starter_bat[mode][i]
soc = drive_battery_model(
current_bat[mode][i], t, motive_power, acc, bool(mode), starter_curr
)
hybrid_modes[i] = mode
return np.minimum(hybrid_modes, 2)