diff --git a/python/fastsim/__init__.py b/python/fastsim/__init__.py index a5a90645..350bac73 100644 --- a/python/fastsim/__init__.py +++ b/python/fastsim/__init__.py @@ -5,6 +5,7 @@ import sys import logging import traceback +from typing import Dict from fastsim import parameters as params from fastsim import utils @@ -21,11 +22,15 @@ def package_root() -> Path: return Path(__file__).parent +DEFAULT_LOGGING_CONFIG = dict( + format = "%(asctime)s.%(msecs)03d | %(filename)s:%(lineno)s | %(levelname)s: %(message)s", + datefmt = "%Y-%m-%d %H:%M:%S", +) + + + # Set up logging -logging.basicConfig( - format="%(asctime)s.%(msecs)03d | %(filename)s:%(lineno)s | %(levelname)s: %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", -) +logging.basicConfig(**DEFAULT_LOGGING_CONFIG) logger = logging.getLogger(__name__) from pkg_resources import get_distribution diff --git a/python/fastsim/demos/demo.py b/python/fastsim/demos/demo.py index 68af706f..71077af0 100644 --- a/python/fastsim/demos/demo.py +++ b/python/fastsim/demos/demo.py @@ -482,92 +482,94 @@ def get_sim_drive_vec( # Includes example of how to load cycle from dict # %% -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]') +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() + 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) + # 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()))) + 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 -veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # load vehicle model -output = {} - -rust_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]') +with fsim.utils.suppress_logging(): + veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # load vehicle model + output = {} + + rust_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).to_rust() - - sim_drive = fsim.simdrive.RustSimDrive(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) - rust_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 - -t_end = time.perf_counter() + cyc['road_type'] = np.zeros(len(pnts)) + # example of loading cycle from dict + cyc = fsim.cycle.Cycle.from_dict(cyc).to_rust() + + sim_drive = fsim.simdrive.RustSimDrive(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) + rust_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 + + t_end = time.perf_counter() -# results_df = results_df.astype(float) + # 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()))) + 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()))) # %% [markdown] # ### Results @@ -889,12 +891,13 @@ def get_sim_drive_vec( # values. # %% -if "default" in fsim.fastsimrust.enabled_features(): - from fastsim.fastsimrust import abc_to_drag_coeffs - test_veh = fsim.vehicle.Vehicle.from_vehdb(5, to_rust=True).to_rust() - (drag_coef, wheel_rr_coef) = abc_to_drag_coeffs(test_veh, 25.91, 0.1943, 0.01796, simdrive_optimize=True) - - print(f'Drag Coefficient: {drag_coef:.3g}') - print(f'Wheel Rolling Resistance Coefficient: {wheel_rr_coef:.3g}') +with fsim.utils.suppress_logging(): + if "default" in fsim.fastsimrust.enabled_features(): + from fastsim.fastsimrust import abc_to_drag_coeffs + test_veh = fsim.vehicle.Vehicle.from_vehdb(5, to_rust=True).to_rust() + (drag_coef, wheel_rr_coef) = abc_to_drag_coeffs(test_veh, 25.91, 0.1943, 0.01796, simdrive_optimize=True) + + print(f'Drag Coefficient: {drag_coef:.3g}') + print(f'Wheel Rolling Resistance Coefficient: {wheel_rr_coef:.3g}') # %% diff --git a/python/fastsim/demos/stop_start_demo.py b/python/fastsim/demos/stop_start_demo.py index d8e7de02..fc2c5add 100644 --- a/python/fastsim/demos/stop_start_demo.py +++ b/python/fastsim/demos/stop_start_demo.py @@ -62,54 +62,54 @@ # %% if SHOW_PLOTS: - fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True, figsize=(9,5)) - ax0.plot(cyc.time_s, sim_drive0.fc_kw_in_ach, - label='base') - ax0.plot(cyc.time_s, sim_drive1.fc_kw_in_ach, - label='stop-start', linestyle='--') - # ax.plot(cyc.time_s, dfco_fcKwOutAchPos, label='dfco', linestyle='--', color='blue') - ax0.legend(loc='upper left') - ax0.set_ylabel('Fuel Power [kW]') - - ax2 = ax1.twinx() - ax2.yaxis.label.set_color('red') - ax2.tick_params(axis='y', colors='red') - ax2.plot(cyc.time_s, sim_drive1.can_pwr_all_elec, - color='red') - ax2.set_ylabel('SS active') - ax2.grid() - - ax1.plot(cyc.time_s, cyc.mph) - ax1.yaxis.label.set_color('blue') - ax1.tick_params(axis='y', colors='blue') - ax1.set_ylabel('Speed [mph]') - ax1.set_ylim([0, 35]) - ax1.set_xlabel('Time [s]') - - # %% - fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True, figsize=(9,5)) - ax0.plot(cyc.time_s, (sim_drive0.fc_kw_in_ach * cyc.dt_s).cumsum() / 1e3, - label='base') - ax0.plot(cyc.time_s, (sim_drive1.fc_kw_in_ach * cyc.dt_s).cumsum() / 1e3, - label='stop-start') - ax0.legend(loc='upper left') - ax0.set_ylabel('Fuel Energy [MJ]') - - ax2 = ax1.twinx() - ax2.yaxis.label.set_color('red') - ax2.tick_params(axis='y', colors='red') - ax2.plot(cyc.time_s, sim_drive1.can_pwr_all_elec, - color='red', alpha=0.25) - ax2.set_ylabel('SS active') - ax2.set_xlim(ax0.get_xlim()) - ax2.set_yticks([0, 1]) - ax2.grid() - - ax1.plot(cyc.time_s, cyc.mph) - ax1.yaxis.label.set_color('blue') - ax1.tick_params(axis='y', colors='blue') - ax1.set_ylabel('Speed [mph]') - ax1.set_xlabel('Time [s]') + fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True, figsize=(9,5)) + ax0.plot(cyc.time_s, sim_drive0.fc_kw_in_ach, + label='base') + ax0.plot(cyc.time_s, sim_drive1.fc_kw_in_ach, + label='stop-start', linestyle='--') + # ax.plot(cyc.time_s, dfco_fcKwOutAchPos, label='dfco', linestyle='--', color='blue') + ax0.legend(loc='upper left') + ax0.set_ylabel('Fuel Power [kW]') + + ax2 = ax1.twinx() + ax2.yaxis.label.set_color('red') + ax2.tick_params(axis='y', colors='red') + ax2.plot(cyc.time_s, sim_drive1.can_pwr_all_elec, + color='red') + ax2.set_ylabel('SS active') + ax2.grid() + + ax1.plot(cyc.time_s, cyc.mph) + ax1.yaxis.label.set_color('blue') + ax1.tick_params(axis='y', colors='blue') + ax1.set_ylabel('Speed [mph]') + ax1.set_ylim([0, 35]) + ax1.set_xlabel('Time [s]') + + # %% + fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True, figsize=(9,5)) + ax0.plot(cyc.time_s, (sim_drive0.fc_kw_in_ach * cyc.dt_s).cumsum() / 1e3, + label='base') + ax0.plot(cyc.time_s, (sim_drive1.fc_kw_in_ach * cyc.dt_s).cumsum() / 1e3, + label='stop-start') + ax0.legend(loc='upper left') + ax0.set_ylabel('Fuel Energy [MJ]') + + ax2 = ax1.twinx() + ax2.yaxis.label.set_color('red') + ax2.tick_params(axis='y', colors='red') + ax2.plot(cyc.time_s, sim_drive1.can_pwr_all_elec, + color='red', alpha=0.25) + ax2.set_ylabel('SS active') + ax2.set_xlim(ax0.get_xlim()) + ax2.set_yticks([0, 1]) + ax2.grid() + + ax1.plot(cyc.time_s, cyc.mph) + ax1.yaxis.label.set_color('blue') + ax1.tick_params(axis='y', colors='blue') + ax1.set_ylabel('Speed [mph]') + ax1.set_xlabel('Time [s]') diff = ((sim_drive0.fc_kw_out_ach * cyc.dt_s).sum() - (sim_drive1.fc_kw_out_ach * cyc.dt_s).sum()) / ( diff --git a/python/fastsim/utils/utilities.py b/python/fastsim/utils/utilities.py index 2828060f..a70f9832 100644 --- a/python/fastsim/utils/utilities.py +++ b/python/fastsim/utils/utilities.py @@ -117,8 +117,28 @@ def set_log_level(level: str | int) -> int: Previous log level """ # Map string name to logging level + + allowed_args = [ + ("CRITICAL", 50), + ("ERROR", 40), + ("WARNING", 30), + ("INFO", 20), + ("DEBUG", 10), + ("NOTSET", 0), + # no logging of anything ever! + ("NONE", logging.CRITICAL + 1), + ] + allowed_str_args = [a[0] for a in allowed_args] + allowed_int_args = [a[1] for a in allowed_args] + + err_str = f"Invalid arg: '{level}'. See doc string:\n{set_log_level.__doc__}" + if isinstance(level, str): - level = logging._nameToLevel[level] + assert level.upper() in allowed_str_args, err_str + level = logging._nameToLevel[level.upper()] + else: + assert level in allowed_int_args, err_str + # Extract previous log level and set new log level fastsim_logger = logging.getLogger("fastsim") previous_level = fastsim_logger.level @@ -453,4 +473,4 @@ def copy_demo_files(path_for_copies: Path=Path("demos")): file_content = prepend + file_content file.seek(0) file.writelines(file_content) - print(f"Saved {dest_file.name} to {dest_file}") \ No newline at end of file + print(f"Saved {dest_file.name} to {dest_file}")