diff --git a/python/fastsim/demos/demo.py b/python/fastsim/demos/demo.py index 71077af0..551fdcbf 100644 --- a/python/fastsim/demos/demo.py +++ b/python/fastsim/demos/demo.py @@ -122,11 +122,11 @@ # %% fig, ax = plt.subplots(2, 1, figsize=(9, 5)) ax[0].plot(cyc.time_s, sim_drive.fc_kw_in_ach, label='py') -ax[0].plot(cyc.time_s, sdr.fc_kw_in_ach, linestyle='--', label='rust') +ax[0].plot(rc.time_s, sdr.fc_kw_in_ach, linestyle='--', label='rust') ax[0].legend() ax[0].set_ylabel('Engine Input\nPower [kW]') -ax[1].plot(cyc.time_s, sim_drive.mph_ach) +ax[1].plot(rc.time_s, sdr.mph_ach) ax[1].set_xlabel('Cycle Time [s]') ax[1].set_ylabel('Speed [MPH]') @@ -143,7 +143,7 @@ 'Power[kW]' ) -ax[1].plot(cyc.time_s, sim_drive.mph_ach) +ax[1].plot(rc.time_s, sdr.mph_ach) ax[1].set_xlabel('Cycle Time [s]') ax[1].set_ylabel('Speed [MPH]') @@ -151,39 +151,10 @@ plt.show() # %% [markdown] -# ## Running sim_drive_step() with modified auxInKw +# ## Running sim_drive_step() with modified auxInKw using Rust # Note that auxInKw is the only variable setup to be externally modified # as of 1 July 2020 # ### Overriding at each time step - -# %% -## Running sim_drive_step() with modified auxInKw -# Note that auxInKw is the only variable setup to be externally modified -# as of 1 July 2020 - -t0 = time.perf_counter() - -veh = fsim.vehicle.Vehicle.from_vehdb(9) -cyc = fsim.cycle.Cycle.from_file('udds') -sim_drive = fsim.simdrive.SimDrive(cyc, veh) -sim_drive.init_for_step(init_soc=0.7935) - -while sim_drive.i < len(cyc.time_s): - sim_drive.aux_in_kw[sim_drive.i] = sim_drive.i / cyc.time_s[-1] * 10 - # above could be a function of some internal sim_drive state - sim_drive.sim_drive_step() - -plt.plot(cyc.time_s, sim_drive.fc_kw_out_ach, label='FC out') -plt.plot(cyc.time_s, sim_drive.ess_kw_out_ach, label='ESS out') -plt.xlabel('Time [s]') -plt.ylabel('Power [kW]') -plt.legend() -if SHOW_PLOTS: - plt.show() -print(f'Time to simulate: {time.perf_counter() - t0:.2e} s') - -# %% -## Running sim_drive_step() with modified auxInKw using Rust # Note that the aux load array **must** be set as a whole. We currently # cannot set just an index of an array via the Python bindings to Rust # at this time @@ -217,31 +188,6 @@ # %% [markdown] # ### Overriding using a constant value -# %% -## Running sim_drive_step() with modified auxInKw -# Note that auxInKw is the only variable setup to be externally modified -# as of 1 July 2020 - -t0 = time.perf_counter() - -veh = fsim.vehicle.Vehicle.from_vehdb(9) -cyc = fsim.cycle.Cycle.from_file('udds') -sim_drive = fsim.simdrive.SimDrive(cyc, veh) -auxInKwConst = 12 -sim_drive.sim_drive(None, np.ones(len(cyc.time_s))*auxInKwConst) - -plt.figure() -plt.plot(cyc.time_s, sim_drive.fc_kw_out_ach, label='FC out') -plt.plot(cyc.time_s, sim_drive.ess_kw_out_ach, label='ESS out') -plt.xlabel('Time [s]') -plt.ylabel('Power [kW]') -plt.legend() -if SHOW_PLOTS: - plt.show() - -print(f'Time to simulate: {time.perf_counter() - t0:.2e} s') - - # %% ## Running sim_drive_step() with modified auxInKw using Rust # Note that auxInKw is the only variable setup to be externally modified @@ -268,37 +214,6 @@ # # %% [markdown] # ### Overriding using a time trace -# %% -## Running sim_drive_step() with modified auxInKw -# Note that auxInKw is the only variable setup to be externally modified -# as of 1 July 2020 - -t0 = time.perf_counter() - -veh = fsim.vehicle.Vehicle.from_vehdb(9) -cyc = fsim.cycle.Cycle.from_file('udds') -sim_drive = fsim.simdrive.SimDrive(cyc, veh) - -# by assigning the value directly (this is faster than using positional -# args) -sim_drive.init_for_step( - 0.5, - aux_in_kw_override=cyc.time_s / cyc.time_s[-1] * 10 -) -while sim_drive.i < len(sim_drive.cyc.time_s): - sim_drive.sim_drive_step() - -plt.figure() -plt.plot(cyc.time_s, sim_drive.fc_kw_out_ach, label='FC out') -plt.plot(cyc.time_s, sim_drive.ess_kw_out_ach, label='ESS out') -plt.xlabel('Time [s]') -plt.ylabel('Power [kW]') -plt.legend() -if SHOW_PLOTS: - plt.show() - -print(f'Time to simulate: {time.perf_counter() - t0:.2e} s') - # %% ## Running sim_drive_step() with modified auxInKw using Rust # Note that auxInKw is the only variable setup to be externally modified @@ -331,29 +246,6 @@ print(f'Time to simulate: {time.perf_counter() - t0:.2e} s') -# %% by assigning positional arguments may require recompile if these -# arguments have not been passed, but this is the fastest approach after -# compilation - -veh = fsim.vehicle.Vehicle.from_vehdb(9) -cyc = fsim.cycle.Cycle.from_file('udds') - -t0 = time.perf_counter() - -sim_drive = fsim.simdrive.SimDrive(cyc, veh) -sim_drive.sim_drive(None, cyc.time_s / cyc.time_s[-1] * 10) - -plt.figure() -plt.plot(cyc.time_s, sim_drive.fc_kw_out_ach, label='FC out') -plt.plot(cyc.time_s, sim_drive.ess_kw_out_ach, label='ESS out') -plt.xlabel('Time [s]') -plt.ylabel('Power [kW]') -plt.legend() -if SHOW_PLOTS: - plt.show() - -print(f'Time to simulate: {time.perf_counter() - t0:.2e} s') - # %% by assigning positional arguments (using Rust) may require # recompile if these arguments have not been passed, but this is the # fastest approach after compilation @@ -482,56 +374,10 @@ def get_sim_drive_vec( # Includes example of how to load cycle from dict # %% -with fsim.utils.suppress_logging(): - veh = fsim.vehicle.Vehicle.from_vehdb(1) # load vehicle model - output = {} - - results_df = pd.DataFrame() - t_start = time.perf_counter() - for trp in list(drive_cycs_df.nrel_trip_id.unique()): - pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy() - pnts['time_local'] = pd.to_datetime(pnts['timestamp']) - - cyc = {} - cyc['cycGrade'] = np.zeros(len(pnts)) - cyc['mps'] = np.array( - pnts['speed_mph'] / fsim.params.MPH_PER_MPS) # MPH to MPS conversion - cyc['time_s'] = np.array( - np.cumsum( - (pnts['time_local'] - - pnts['time_local'].shift()).fillna(pd.Timedelta(seconds=0)).astype('timedelta64[s]') - ) - ) - cyc['road_type'] = np.zeros(len(pnts)) - # example of loading cycle from dict - cyc = fsim.cycle.Cycle.from_dict(cyc) - - sim_drive = fsim.simdrive.SimDrive(cyc, veh) - sim_drive.sim_drive() - - output['nrel_trip_id'] = trp - output['distance_mi'] = sum(sim_drive.dist_mi) - duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0] - output['avg_speed_mph'] = sum( - sim_drive.dist_mi) / (duration_sec / 3600.0) - #results_df = results_df.append(output, ignore_index=True) - results_df = pd.concat([results_df,pd.DataFrame(output,index=[0])],ignore_index=True) - output['mpgge'] = sim_drive.mpgge - - t_end = time.perf_counter() - - # results_df = results_df.astype(float) - - print(f'Simulations Complete. Total runtime = {t_end - t_start:.2f} s') - print(' Average time per cycle = {:.2f} s'.format(( - t_end - t_start) / len(drive_cycs_df.nrel_trip_id.unique()))) - -# %% ... and the Rust version with fsim.utils.suppress_logging(): veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # load vehicle model output = {} - - rust_results_df = pd.DataFrame() + results_df = pd.DataFrame() t_start = time.perf_counter() for trp in list(drive_cycs_df.nrel_trip_id.unique()): pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy() @@ -559,7 +405,7 @@ def get_sim_drive_vec( duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0] output['avg_speed_mph'] = sum( sim_drive.dist_mi) / (duration_sec / 3600.0) - rust_results_df = pd.concat([results_df, pd.DataFrame(output,index=[0])], ignore_index=True) + results_df = pd.concat([results_df, pd.DataFrame(output,index=[0])], ignore_index=True) #rust_results_df = results_df.append(output, ignore_index=True) output['mpgge'] = sim_drive.mpgge @@ -632,7 +478,7 @@ def get_sim_drive_vec( # %% load vehicle t0 = time.perf_counter() -veh = fsim.vehicle.Vehicle.from_vehdb(9) +veh = fsim.vehicle.Vehicle.from_vehdb(9).to_rust() # veh = veh print(f'Time to load vehicle: {time.perf_counter() - t0:.2e} s') @@ -641,13 +487,12 @@ def get_sim_drive_vec( t0 = time.perf_counter() cyc = fsim.cycle.Cycle.from_file("udds") microtrips = fsim.cycle.to_microtrips(cyc.to_dict()) -cyc = fsim.cycle.Cycle.from_dict(microtrips[1]) +cyc = fsim.cycle.Cycle.from_dict(microtrips[1]).to_rust() print(f'Time to load cycle: {time.perf_counter() - t0:.2e} s') - # %% simulate t0 = time.perf_counter() -sim_drive = fsim.simdrive.SimDrive(cyc, veh) +sim_drive = fsim.simdrive.RustSimDrive(cyc, veh) sim_drive.sim_drive() # sim_drive = fsim.simdrive.SimDriveClassic(cyc, veh) # sim_drive.sim_drive() @@ -688,7 +533,7 @@ def get_sim_drive_vec( # %% load vehicle t0 = time.perf_counter() # load from standalone vehicle file -veh = fsim.vehicle.Vehicle.from_file('2012_Ford_Fusion.csv') # load vehicle using name +veh = fsim.vehicle.Vehicle.from_file('2012_Ford_Fusion.csv').to_rust() # load vehicle using name print(f'Time to load veicle: {time.perf_counter() - t0:.2e} s') @@ -696,16 +541,16 @@ def get_sim_drive_vec( t0 = time.perf_counter() # load from cycle file path cyc1 = fsim.cycle.Cycle.from_file( - str(Path(fsim.simdrive.__file__).parent / 'resources/cycles/udds.csv')) -cyc2 = fsim.cycle.Cycle.from_file("us06") + str(Path(fsim.simdrive.__file__).parent / 'resources/cycles/udds.csv')).to_rust() +cyc2 = fsim.cycle.Cycle.from_file("us06").to_rust() cyc_combo = fsim.cycle.concat([cyc1.to_dict(), cyc2.to_dict()]) -cyc_combo = fsim.cycle.Cycle.from_dict(cyc_combo) +cyc_combo = fsim.cycle.Cycle.from_dict(cyc_combo).to_rust() print(f'Time to load cycles: {time.perf_counter() - t0:.2e} s') # %% simulate t0 = time.perf_counter() -sim_drive = fsim.simdrive.SimDrive(cyc_combo, veh) +sim_drive = fsim.simdrive.RustSimDrive(cyc_combo, veh) sim_drive.sim_drive() # sim_drive = fsim.simdrive.SimDriveClassic(cyc, veh) # sim_drive.sim_drive() @@ -742,12 +587,12 @@ def get_sim_drive_vec( # %% generate concatenated trip t0 = time.perf_counter() -cyc1 = fsim.cycle.Cycle.from_file("udds") -cyc2 = fsim.cycle.Cycle.from_file("us06") +cyc1 = fsim.cycle.Cycle.from_file("udds").to_rust() +cyc2 = fsim.cycle.Cycle.from_file("us06").to_rust() print('Cycle 1 and 2 equal?') print(fsim.cycle.equals(cyc1.to_dict(), cyc2.to_dict())) -cyc1 = fsim.cycle.Cycle.from_file("udds") -cyc2 = fsim.cycle.Cycle.from_file("udds") +cyc1 = fsim.cycle.Cycle.from_file("udds").to_rust() +cyc2 = fsim.cycle.Cycle.from_file("udds").to_rust() print('Cycle 1 and 2 equal?') print(fsim.cycle.equals(cyc1.to_dict(), cyc2.to_dict())) cyc2dict = cyc2.to_dict() @@ -761,9 +606,9 @@ def get_sim_drive_vec( # %% t0 = time.perf_counter() -cyc = fsim.cycle.Cycle.from_file("udds") -cyc10Hz = fsim.cycle.Cycle.from_dict(fsim.cycle.resample(cyc.to_dict(), new_dt=0.1)) -cyc10s = fsim.cycle.Cycle.from_dict(fsim.cycle.resample(cyc.to_dict(), new_dt=10)) +cyc = fsim.cycle.Cycle.from_file("udds").to_rust() +cyc10Hz = fsim.cycle.Cycle.from_dict(fsim.cycle.resample(cyc.to_dict(), new_dt=0.1)).to_rust() +cyc10s = fsim.cycle.Cycle.from_dict(fsim.cycle.resample(cyc.to_dict(), new_dt=10)).to_rust() plt.plot(cyc10Hz.time_s, cyc10Hz.mph, marker=',') plt.plot(cyc10s.time_s, cyc10s.mph, marker=',') @@ -782,26 +627,26 @@ def get_sim_drive_vec( t0 = time.perf_counter() # load vehicle using explicit path veh = fsim.vehicle.Vehicle.from_file(Path(fsim.simdrive.__file__).parent / - 'resources/vehdb/2012_Ford_Fusion.csv') + 'resources/vehdb/2012_Ford_Fusion.csv').to_rust() print(f'Time to load vehicle: {time.perf_counter() - t0:.2e} s') # %% generate concatenated trip t0 = time.perf_counter() -cyc_udds = fsim.cycle.Cycle.from_file("udds") +cyc_udds = fsim.cycle.Cycle.from_file("udds").to_rust() # Generate cycle with 0.1 s time steps cyc_udds_10Hz = fsim.cycle.Cycle.from_dict( - fsim.cycle.resample(cyc_udds.to_dict(), new_dt=0.1)) -cyc_us06 = fsim.cycle.Cycle.from_file("us06") + fsim.cycle.resample(cyc_udds.to_dict(), new_dt=0.1)).to_rust() +cyc_us06 = fsim.cycle.Cycle.from_file("us06").to_rust() cyc_combo = fsim.cycle.concat([cyc_udds_10Hz.to_dict(), cyc_us06.to_dict()]) cyc_combo = fsim.cycle.resample(cyc_combo, new_dt=1) -cyc_combo = fsim.cycle.Cycle.from_dict(cyc_combo) +cyc_combo = fsim.cycle.Cycle.from_dict(cyc_combo).to_rust() print(f'Time to load and concatenate cycles: {time.perf_counter() - t0:.2e} s') # %% simulate t0 = time.perf_counter() -sim_drive = fsim.simdrive.SimDrive(cyc_combo, veh) +sim_drive = fsim.simdrive.RustSimDrive(cyc_combo, veh) sim_drive.sim_drive() # sim_drive = fsim.simdrive.SimDriveClassic(cyc, veh) # sim_drive.sim_drive() @@ -838,7 +683,7 @@ def get_sim_drive_vec( # %% load vehicle t0 = time.perf_counter() -veh = fsim.vehicle.Vehicle.from_vehdb(1) +veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # veh = veh print(f'Time to load vehicle: {time.perf_counter() - t0:.2e} s') @@ -847,13 +692,13 @@ def get_sim_drive_vec( t0 = time.perf_counter() cyc = fsim.cycle.Cycle.from_file("udds") cyc = fsim.cycle.clip_by_times(cyc.to_dict(), t_end=300) -cyc = fsim.cycle.Cycle.from_dict(cyc) +cyc = fsim.cycle.Cycle.from_dict(cyc).to_rust() print(f'Time to load and clip cycle: {time.perf_counter() - t0:.2e} s') # %% simulate t0 = time.perf_counter() -sim_drive = fsim.simdrive.SimDrive(cyc, veh) +sim_drive = fsim.simdrive.RustSimDrive(cyc, veh) sim_drive.sim_drive() # sim_drive = fsim.simdrive.SimDriveClassic(cyc, veh) # sim_drive.sim_drive() diff --git a/python/fastsim/demos/demo_eu_vehicle_wltp.py b/python/fastsim/demos/demo_eu_vehicle_wltp.py index 81f4b3e3..307ab32b 100644 --- a/python/fastsim/demos/demo_eu_vehicle_wltp.py +++ b/python/fastsim/demos/demo_eu_vehicle_wltp.py @@ -42,8 +42,7 @@ def simdrive_get_mpg(cur_simdrive): def hybrid_eu_veh_wltp_fe_test(): WILLANS_FACTOR_gram_CO2__MJ = 724 # gCO2/MJ E10_HEAT_VALUE_kWh__liter = 8.64 # kWh/L - veh_2022_yaris = fsim.vehicle.Vehicle.from_file('2022_TOYOTA_Yaris_Hybrid_Mid.csv') - veh_2022_yaris_rust = fsim.vehicle.Vehicle.from_file('2022_TOYOTA_Yaris_Hybrid_Mid.csv', to_rust=True).to_rust() + veh_2022_yaris = fsim.vehicle.Vehicle.from_file('2022_TOYOTA_Yaris_Hybrid_Mid.csv', to_rust=True).to_rust() # Measured FE (L/100km) meas_fe_combined_liter__100km = 3.8 @@ -52,33 +51,22 @@ def hybrid_eu_veh_wltp_fe_test(): meas_fe_high_liter__100km = 3.5 meas_fe_extrahigh_liter__100km = 5 - wltp_low_cyc_3 = fsim.cycle.Cycle.from_file('wltc_low_3.csv') - wltp_low_cyc_3_rust = wltp_low_cyc_3.to_rust() - wltp_med_cyc_3b = fsim.cycle.Cycle.from_file('wltc_medium_3b.csv') - wltp_med_cyc_3b_rust = wltp_med_cyc_3b.to_rust() - wltp_high_cyc_3b = fsim.cycle.Cycle.from_file('wltc_high_3b.csv') - wltp_high_cyc_3b_rust = wltp_high_cyc_3b.to_rust() - wltp_extrahigh_cyc_3 = fsim.cycle.Cycle.from_file('wltc_extrahigh_3.csv') - wltp_extrahigh_cyc_3_rust = wltp_extrahigh_cyc_3.to_rust() - cyc_wltp_combined = fsim.cycle.Cycle.from_file("wltc_3b.csv") - cyc_wltp_combined_rust = cyc_wltp_combined.to_rust() - - sim = fsim.simdrive.SimDrive(cyc_wltp_combined, veh_2022_yaris) - sim_rust = fsim.simdrive.RustSimDrive(cyc_wltp_combined_rust,veh_2022_yaris_rust) + wltp_low_cyc_3 = fsim.cycle.Cycle.from_file('wltc_low_3.csv').to_rust() + wltp_med_cyc_3b = fsim.cycle.Cycle.from_file('wltc_medium_3b.csv').to_rust() + wltp_high_cyc_3b = fsim.cycle.Cycle.from_file('wltc_high_3b.csv').to_rust() + wltp_extrahigh_cyc_3 = fsim.cycle.Cycle.from_file('wltc_extrahigh_3.csv').to_rust() + cyc_wltp_combined = fsim.cycle.Cycle.from_file("wltc_3b.csv").to_rust() + + sim = fsim.simdrive.RustSimDrive(cyc_wltp_combined, veh_2022_yaris) sim.sim_drive() - sim_rust.sim_drive() - dist_miles_combined = sim.dist_mi.sum() - dist_miles_combined_rust = sum(sim_rust.dist_mi) - print(f"Distance modelled in miles: Pure Python FastSim:\t{dist_miles_combined:.2f}\t Rust backend FastSim:\t{dist_miles_combined_rust:.2f}") - energy_combined = sim.fs_kwh_out_ach.sum() - energy_combined_rust = sum(sim_rust.fs_kwh_out_ach) - print(f"Fuel Supply achieved in kilowatts-hours: Pure Python FastSim:\t{energy_combined:.2f}\t Rust backend FastSim:\t{energy_combined_rust:.2f}") + dist_miles_combined = np.array(sim.dist_mi).sum() + print(f"Distance modelled in miles:\t{dist_miles_combined:.2f}") + energy_combined = np.array(sim.fs_kwh_out_ach).sum() + print(f"Fuel Supply achieved in kilowatts-hours:\t{energy_combined:.2f}") fe_mpgge_combined = sim.mpgge - fe_mpgge_combined_rust = sim_rust.mpgge fe_l__100km_combined = utils.mpg_to_l__100km(fe_mpgge_combined) - fe_l__100km_combined_rust = utils.mpg_to_l__100km(fe_mpgge_combined_rust) - print(f"Fuel Consumption achieved in L/100km: Pure Python FastSim:\t{fe_l__100km_combined:.2f}\t Rust backend FastSim:\t{fe_l__100km_combined_rust:.2f}") + print(f"Fuel Consumption achieved in L/100km:\t{fe_l__100km_combined:.2f}") i0 = len(wltp_low_cyc_3.time_s) i1 = i0 + len(wltp_med_cyc_3b.time_s)-1 @@ -102,7 +90,7 @@ def hybrid_veh_fe_soc_correction(cur_veh, raw_simdrive, phase_slice_list): cur_energy_consumption_kwh = sum(np.array(sim.fs_kwh_out_ach)[cur_phase_slice]) cur_fe_mpgge = cur_dist_miles / (cur_energy_consumption_kwh/sim.props.kwh_per_gge) cur_fe_liter__100km = utils.mpg_to_l__100km(cur_fe_mpgge) - cur_dSOC = sim.soc[cur_phase_slice][-1] - sim.soc[cur_phase_slice][0] + cur_dSOC = np.array(sim.soc)[cur_phase_slice][-1] - np.array(sim.soc)[cur_phase_slice][0] cur_dE_wh = -cur_dSOC * cur_veh.ess_max_kwh * 1000 cur_dM_CO2_gram__100km = 0.0036 * cur_dE_wh * 1/cur_veh.alt_eff * WILLANS_FACTOR_gram_CO2__MJ * 1/cur_dist_km cur_dfe_liter__100km = cur_dE_wh/1000 * 1/cur_veh.alt_eff * 1/E10_HEAT_VALUE_kWh__liter * 100/cur_dist_km @@ -111,33 +99,27 @@ def hybrid_veh_fe_soc_correction(cur_veh, raw_simdrive, phase_slice_list): return fe_liter__100km_list fe_low3_l__100km, fe_med3b_l__100km, fe_high3b_l__100km, fe_extrahigh3_l__100km = hybrid_veh_fe_soc_correction(veh_2022_yaris, sim, wltp_3b_phase_slice_list) - fe_low3_l__100km_rust, fe_med3b_l__100km_rust, fe_high3b_l__100km_rust, fe_extrahigh3_l__100km_rust = hybrid_veh_fe_soc_correction(veh_2022_yaris_rust, sim_rust, wltp_3b_phase_slice_list) print("LOW") print(f" Target: {meas_fe_low_liter__100km} L/100km") print(f" Simulation: {fe_low3_l__100km:.2f} L/100km ({(fe_low3_l__100km - meas_fe_low_liter__100km)/meas_fe_low_liter__100km * 100:+.2f}%)") - print(f" Rust Simulation: {fe_low3_l__100km_rust:.2f} L/100km ({(fe_low3_l__100km_rust - meas_fe_low_liter__100km)/meas_fe_low_liter__100km * 100:+.2f}%)") print("MEDIUM") print(f" Target: {meas_fe_med_liter__100km} L/100km") print(f" Simulation: {fe_med3b_l__100km:.2f} L/100km ({(fe_med3b_l__100km - meas_fe_med_liter__100km)/meas_fe_med_liter__100km * 100:+.2f}%)") - print(f" Rust Simulation: {fe_med3b_l__100km_rust:.2f} L/100km ({(fe_med3b_l__100km_rust - meas_fe_med_liter__100km)/meas_fe_med_liter__100km * 100:+.2f}%)") print("HIGH") print(f" Target: {meas_fe_high_liter__100km} L/100km") print(f" Simulation: {fe_high3b_l__100km:.2f} L/100km ({(fe_high3b_l__100km - meas_fe_high_liter__100km)/meas_fe_high_liter__100km * 100:+.2f}%)") - print(f" Rust Simulation: {fe_high3b_l__100km_rust:.2f} L/100km ({(fe_high3b_l__100km_rust - meas_fe_high_liter__100km)/meas_fe_high_liter__100km * 100:+.2f}%)") print("EXTRA-HIGH") print(f" Target: {meas_fe_extrahigh_liter__100km} L/100km") print(f" Simulation: {fe_extrahigh3_l__100km:.6f} L/100km ({(fe_extrahigh3_l__100km - meas_fe_extrahigh_liter__100km)/meas_fe_extrahigh_liter__100km * 100:+.6f}%)") - print(f" Rust Simulation: {fe_extrahigh3_l__100km_rust:.6f} L/100km ({(fe_extrahigh3_l__100km_rust - meas_fe_extrahigh_liter__100km)/meas_fe_extrahigh_liter__100km * 100:+.6f}%)") print("COMBINED") print(f" Target: {meas_fe_combined_liter__100km} L/100km") print(f" Simulation: {fe_l__100km_combined:.6f} L/100km ({(fe_l__100km_combined - meas_fe_combined_liter__100km)/meas_fe_combined_liter__100km * 100:+.6f}%)") - print(f" Rust Simulation: {fe_l__100km_combined_rust:.2f} L/100km ({(fe_l__100km_combined_rust - meas_fe_combined_liter__100km)/meas_fe_combined_liter__100km * 100:+.2f}%)") if __name__ == '__main__': hybrid_eu_veh_wltp_fe_test() \ No newline at end of file diff --git a/python/fastsim/demos/stop_start_demo.py b/python/fastsim/demos/stop_start_demo.py index fc2c5add..1910e02f 100644 --- a/python/fastsim/demos/stop_start_demo.py +++ b/python/fastsim/demos/stop_start_demo.py @@ -53,9 +53,9 @@ # %% t0 = time.time() -sim_drive0 = simdrive.SimDrive(cyc, veh0) +sim_drive0 = simdrive.RustSimDrive(cyc.to_rust(), veh0.to_rust()) sim_drive0.sim_drive() -sim_drive1 = simdrive.SimDrive(cyc, veh1) +sim_drive1 = simdrive.RustSimDrive(cyc.to_rust(), veh1.to_rust()) sim_drive1.sim_drive() print(f"Elapsed time: {time.time() - t0:.3e} s") diff --git a/python/fastsim/demos/time_dilation_demo.py b/python/fastsim/demos/time_dilation_demo.py index 0c7a24a6..42b287aa 100644 --- a/python/fastsim/demos/time_dilation_demo.py +++ b/python/fastsim/demos/time_dilation_demo.py @@ -28,27 +28,29 @@ t0 = time.time() cyc = cycle.Cycle.from_dict(cyc_dict=cycle.clip_by_times( cycle.Cycle.from_file('longHaulDriveCycle').to_dict(), - t_end=18_000, t_start=1_800)) + t_end=18_000, t_start=1_800)).to_rust() print('Time to load cycle file: {:.3f} s'.format(time.time() - t0)) t0 = time.time() -veh = vehicle.Vehicle.from_file('Line_Haul_Conv.csv') +veh = vehicle.Vehicle.from_file('Line_Haul_Conv.csv').to_rust() veh.veh_kg *= 2 print('Time to load vehicle: {:.3f} s'.format(time.time() - t0)) t0 = time.time() -sd_fixed = simdrive.SimDrive(cyc, veh) +sd_fixed = simdrive.RustSimDrive(cyc, veh) sim_params = sd_fixed.sim_params +sim_params.reset_orphaned() # activate time dilation (aka missed trace correction) sim_params.missed_trace_correction=True # by setting `sim_params.max_time_dilation = 0.1`, we're ensuring that a simulation with 1 s # time steps will never exceed a 1.1 s time step to achieve trace matching sim_params.max_time_dilation = 0.1 +sd_fixed.sim_params = sim_params -sd_base = simdrive.SimDrive(cyc, veh) +sd_base = simdrive.RustSimDrive(cyc, veh) sd_fixed.sim_drive() sd_base.sim_drive() @@ -56,15 +58,15 @@ t_delta = time.time() - t0 print('Time to run sim_drive: {:.3f} s'.format(t_delta)) -print('Mean number of trace miss iterations: {:.3f}'.format(sd_fixed.trace_miss_iters.mean())) +print('Mean number of trace miss iterations: {:.3f}'.format(np.array(sd_fixed.trace_miss_iters).mean())) print('Distance percent error w.r.t. base cycle: {:.3%}'.format( - (sd_fixed.dist_m.sum() - cyc.dist_m.sum()) / cyc.dist_m.sum())) + (np.array(sd_fixed.dist_m).sum() - np.array(cyc.dist_m).sum()) / np.array(cyc.dist_m).sum())) # elevation delta based on dilated cycle secs -delta_elev_dilated = (sd_fixed.cyc.grade * sd_fixed.cyc.dt_s * sd_fixed.cyc.mps).sum() +delta_elev_dilated = (np.array(sd_fixed.cyc.grade) * np.array(sd_fixed.cyc.dt_s) * np.array(sd_fixed.cyc.mps)).sum() # elevation delta based on dilated cycle secs -delta_elev_achieved = (sd_fixed.cyc.grade * - sd_fixed.cyc.dt_s * sd_fixed.mps_ach).sum() +delta_elev_achieved = (np.array(sd_fixed.cyc.grade) * + np.array(sd_fixed.cyc.dt_s) * np.array(sd_fixed.mps_ach)).sum() # PLOTS @@ -95,11 +97,11 @@ # distance plt.figure() -plt.plot(cyc.time_s, (cyc.mps * cyc.dt_s).cumsum() / 1e3, label='trace') -plt.plot(sd_fixed.cyc.time_s, (sd_fixed.mps_ach * - sd_fixed.cyc.dt_s).cumsum() / 1e3, label='dilated', linestyle='--') -plt.plot(sd_base.cyc.time_s, (sd_base.mps_ach * - sd_base.cyc.dt_s).cumsum() / 1e3, label='base', linestyle='-.') +plt.plot(cyc.time_s, (np.array(cyc.mps) * np.array(cyc.dt_s)).cumsum() / 1e3, label='trace') +plt.plot(sd_fixed.cyc.time_s, (np.array(sd_fixed.mps_ach) * + np.array(sd_fixed.cyc.dt_s)).cumsum() / 1e3, label='dilated', linestyle='--') +plt.plot(sd_base.cyc.time_s, (np.array(sd_base.mps_ach) * + np.array(sd_base.cyc.dt_s)).cumsum() / 1e3, label='base', linestyle='-.') # plt.grid() plt.legend(loc='upper left') plt.xlabel('Time [s]') @@ -109,10 +111,10 @@ plt.show() plt.figure() -plt.plot((cyc.mps * cyc.dt_s).cumsum() / 1e3, label='trace') -plt.plot((sd_fixed.mps_ach * sd_fixed.cyc.dt_s).cumsum() / 1e3, +plt.plot((np.array(cyc.mps) * np.array(cyc.dt_s)).cumsum() / 1e3, label='trace') +plt.plot((np.array(sd_fixed.mps_ach) * np.array(sd_fixed.cyc.dt_s)).cumsum() / 1e3, label='dilated', linestyle='--') -plt.plot((sd_base.mps_ach * sd_base.cyc.dt_s).cumsum() / 1e3, +plt.plot((np.array(sd_base.mps_ach) * np.array(sd_base.cyc.dt_s)).cumsum() / 1e3, label='base', linestyle='-.') # plt.grid() plt.legend(loc='upper left') @@ -127,7 +129,7 @@ (np.interp( sd_fixed.cyc.time_s, cyc.time_s, - cyc.dist_m.cumsum()) - sd_fixed.dist_m.cumsum()) + np.array(cyc.dist_m).cumsum()) - np.array(sd_fixed.dist_m).cumsum()) / 1e3) # plt.grid() plt.xlabel('Time [s]') @@ -138,8 +140,8 @@ plt.show() plt.figure() -plt.plot((cyc.dist_m.cumsum() - - sd_fixed.dist_m.cumsum())) +plt.plot((np.array(cyc.dist_m).cumsum() - + np.array(sd_fixed.dist_m).cumsum())) # plt.grid() plt.xlabel('Index') plt.ylabel('Distance (trace - achieved) [m]') @@ -151,11 +153,11 @@ # elevation change plt.figure() -plt.plot(cyc.time_s, (cyc.grade * cyc.mps * cyc.dt_s).cumsum(), label='trace') -plt.plot(sd_fixed.cyc.time_s, (cyc.grade * cyc.dt_s * - sd_fixed.mps_ach).cumsum(), label='undilated', linestyle='--') -plt.plot(sd_fixed.cyc.time_s, (sd_fixed.cyc.grade * sd_fixed.cyc.dt_s * - sd_fixed.mps_ach).cumsum(), label='dilated', linestyle='-.') +plt.plot(cyc.time_s, (np.array(cyc.grade) * np.array(cyc.mps) * np.array(cyc.dt_s)).cumsum(), label='trace') +plt.plot(sd_fixed.cyc.time_s, (np.array(cyc.grade) * np.array(cyc.dt_s) * + np.array(sd_fixed.mps_ach)).cumsum(), label='undilated', linestyle='--') +plt.plot(sd_fixed.cyc.time_s, (np.array(sd_fixed.cyc.grade) * np.array(sd_fixed.cyc.dt_s) * + np.array(sd_fixed.mps_ach)).cumsum(), label='dilated', linestyle='-.') # plt.grid() plt.legend(loc='upper left') plt.xlabel('Time [s]') @@ -166,11 +168,11 @@ plt.figure() -plt.plot((cyc.grade * cyc.mps * - cyc.dt_s).cumsum(), label='trace') -plt.plot((cyc.grade * cyc.dt_s * sd_fixed.mps_ach).cumsum(), label='undilated', linestyle='--') -plt.plot((sd_fixed.cyc.grade * sd_fixed.cyc.dt_s * - sd_fixed.mps_ach).cumsum(), label='dilated', linestyle='-.') +plt.plot((np.array(cyc.grade) * np.array(cyc.mps) * + np.array(cyc.dt_s)).cumsum(), label='trace') +plt.plot((np.array(cyc.grade) * np.array(cyc.dt_s) * np.array(sd_fixed.mps_ach)).cumsum(), label='undilated', linestyle='--') +plt.plot((np.array(sd_fixed.cyc.grade) * np.array(sd_fixed.cyc.dt_s) * + np.array(sd_fixed.mps_ach)).cumsum(), label='dilated', linestyle='-.') # plt.grid() plt.legend(loc='upper left') plt.xlabel('Index') diff --git a/python/fastsim/demos/timing_demo.py b/python/fastsim/demos/timing_demo.py index a4d15d7f..7f1c48d9 100644 --- a/python/fastsim/demos/timing_demo.py +++ b/python/fastsim/demos/timing_demo.py @@ -56,7 +56,7 @@ veh_csv_path = fsim.package_root() / "resources/vehdb/2012_Ford_Fusion.csv" t0 = time.perf_counter() -veh_python = fsim.vehicle.Vehicle.from_file(str(veh_csv_path), to_rust=True) +veh_python = fsim.vehicle.Vehicle.from_file(str(veh_csv_path), to_rust=True).to_rust() print( 'Time to load vehicle with\n' + f'`vehicle.Vehicle.from_file(veh_csv_path)`: {time.perf_counter() - t0:.2e} s'