Skip to content

Engine Power Model

stefanosts edited this page Aug 6, 2016 · 1 revision

Inputs

Name Units Source / Comments Parameter
Engine Capacity cc Input engine_capacity
Stroke mm Input engine_stroke
Fuel - Input fuel_type
Aspiration Method - Input engine_is_turbo
Engine Speed RPM Calculated by Engine Speed Model engine_speeds_out
Engine Status - On/Off - Calculated by Start/Stop Model on_engine
Auxiliaries Power Loss kW Default Input auxiliaries_power_loss
Auxiliaries Torque Loss Nm Default Input auxiliaries_torque_loss
Idle Speed RPM Parametric Calculated Input idle_engine_speed
Nominal Power kW Input engine_max_power
Nominal Speed RPM Input engine_max_speed_at_max_power
Full Load Curve table Default Input full_load_curve
Powers Clutch / Torque Converter kW Calculated by Clutch / Torque Converter Model clutch_tc_powers
Alternator Powers Demand kW Calculated by Electrics Model alternator_powers_demand

Output

Engine Power [kW] / engine_powers_out

Source Code

def calculate_engine_moment_inertia(engine_capacity, fuel_type):

    w = {
        'gasoline': 1,
        'diesel': 2
    }[fuel_type]

    return (0.05 + 0.1 * engine_capacity / 1000.0) * w

def calculate_powers(torques, speeds):
    return torques * speeds * (pi / 30000.0)

def calculate_engine_type(fuel_type, engine_is_turbo):

    engine_type = fuel_type

    if fuel_type == 'gasoline':
        engine_type = 'turbo' if engine_is_turbo else 'natural aspiration'
        engine_type = '%s %s' % (fuel_type, engine_type)

    return engine_type

def select_initial_friction_params(engine_type):

    params = {
        'gasoline turbo': {
                'l': -2.49882, 'l2': -0.0025
        },
        'gasoline natural aspiration': {
                'l': -2.14063, 'l2': -0.00286
        },
        'diesel': {
                'l': -1.55291, 'l2': -0.0076
        }
    }

    return params[engine_type]['l'], params[engine_type]['l2']

def get_engine_motoring_curve(engine_stroke, engine_capacity, friction_params):

    l, l2 = np.array(friction_params) * (engine_capacity / 1200000.0)
    l2 *= (engine_stroke / 30000.0) ** 2

    def dn_limit(engine_speeds):
        return (l2 * engine_speeds * engine_speeds + l) * engine_speeds

    return dn_limit

def define_engine_power_correction_function(
        full_load_curve, engine_motoring_curve, engine_max_power,
        idle_engine_speed, engine_max_speed_at_max_power):

    def engine_power_correction_function(engine_speeds, engine_powers):

        n_norm = (engine_max_speed_at_max_power - idle_engine_speed[0])
        n_norm = (np.asarray(engine_speeds) - idle_engine_speed[0]) / n_norm

        up_limit = full_load_curve(n_norm) * engine_max_power
        dn_limit = engine_motoring_curve(engine_speeds)

        up, dn = up_limit < engine_powers, dn_limit > engine_powers
        
        ul, dl = up_limit, dn_limit
        p = engine_powers
        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, up_limit, np.where(dn, dn_limit, engine_powers)), missing_powers, brake_powers
    
    return engine_power_correction_function

def calculate_engine_powers_out(
        engine_moment_inertia, clutch_tc_powers, engine_speeds_out, on_engine,
        engine_power_correction_function, auxiliaries_power_loss, auxiliaries_power_losses,
        alternator_powers_demand=None):
       
    apl = np.zeros_like(clutch_tc_powers, dtype=float)
    apl[on_engine] += auxiliaries_power_loss
    
    p_on = clutch_tc_powers[on_engine] + auxiliaries_power_losses[on_engine] + apl[on_engine]

    if alternator_powers_demand is not None:
        p_on += np.abs(alternator_powers_demand[on_engine])

    p_on, mp_on, bp_on = engine_power_correction_function(engine_speeds_out[on_engine], p_on)
    
    p = np.zeros_like(clutch_tc_powers, dtype=float)
    p[on_engine] = p_on

    engine_speeds_delta = np.ediff1d(engine_speeds_out, to_end=0)
    engine_powers_on_inertia = engine_moment_inertia / 2000 * (2 * pi / 60) ** 2
    engine_powers_on_inertia *= engine_speeds_delta * engine_speeds_delta
    p += engine_powers_on_inertia

    mp = np.zeros_like(clutch_tc_powers, dtype=float)
    mp[on_engine] = mp_on
    bp = np.zeros_like(clutch_tc_powers, dtype=float)
    bp[on_engine] = bp_on

    return p, mp, bp