From 7f6b8a41a720b493f0d613ba7ce039f8b9162087 Mon Sep 17 00:00:00 2001 From: Harish Panneer Selvam Date: Mon, 7 Oct 2024 14:48:46 -0600 Subject: [PATCH 1/3] Update shifts_per_year calc for blank input --- t3co/run/run_scenario.py | 5 +++++ t3co/tco/opportunity_cost.py | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/t3co/run/run_scenario.py b/t3co/run/run_scenario.py index b59f0dd..a86c10c 100644 --- a/t3co/run/run_scenario.py +++ b/t3co/run/run_scenario.py @@ -535,6 +535,11 @@ def get_scenario_and_cycle( scenario = load_scenario(veh_no, scenario_inputs_path, a_vehicle, config) cyc = load_design_cycle_from_scenario(scenario, gl.OPTIMIZATION_DRIVE_CYCLES) + if isinstance(cyc, list): + scenario.constant_trip_distance_mi = sum([sum(cyc[i][0].mph * np.diff(np.array(cyc[i][0].time_s), append=0))*cyc[i][1]/3600 for i in range(len(cyc))]) + else: + scenario.constant_trip_distance_mi = sum(cyc.mph * np.diff(np.array(cyc.time_s), append=0))/3600 + return scenario, cyc diff --git a/t3co/tco/opportunity_cost.py b/t3co/tco/opportunity_cost.py index 2aef5f8..453adf7 100644 --- a/t3co/tco/opportunity_cost.py +++ b/t3co/tco/opportunity_cost.py @@ -1,6 +1,7 @@ # %% from __future__ import annotations +import ast import warnings from math import ceil from pathlib import Path @@ -71,9 +72,10 @@ def __init__( self.frac_of_fullcharge_bounds = list( np.float_(scenario.fdt_frac_full_charge_bounds.strip(" ][").split(",")) ) - self.shifts_per_year = list( - np.float_(scenario.shifts_per_year.strip(" ][").split(",")) - ) + if ('0' in str(scenario.shifts_per_year) or np.isnan(scenario.shifts_per_year)) and scenario.constant_trip_distance_mi: + self.shifts_per_year = [round(scenario.vmt[i] / scenario.constant_trip_distance_mi) for i in range(scenario.vehicle_life_yr)] + else: + self.shifts_per_year = ast.literal_eval(scenario.shifts_per_year) self.payload_cap_cost_multiplier = 0 From ede80b49a4b6f244a3786d2093d805979ecee7ca Mon Sep 17 00:00:00 2001 From: Harish Panneer Selvam Date: Mon, 7 Oct 2024 14:50:41 -0600 Subject: [PATCH 2/3] Update definition of shifts_per_year in md and fix typos --- docs/quick_start.md | 17 +++++++++++------ docs/scenario_inputs_descriptions.md | 2 +- t3co/sweep.py | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/quick_start.md b/docs/quick_start.md index 0596e98..407b6cc 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -34,8 +34,11 @@ python sweep.py --help ``` $ python sweep.py --help -usage: SWEEP [-h] [--config CONFIG] [--analysis-id ANALYSIS_ID] [--vehicles VEHICLES] [--scenarios SCENARIOS] [--selections [SELECTIONS ...]] [--eng-curves ENG_CURVES] [--lw-curves LW_CURVES] [--aero-curves AERO_CURVES] [--look-for LOOK_FOR] [--skip-all-opt] [--skip-input-validation] [--exclude [EXCLUDE ...]] [--algorithms [ALGORITHMS ...]] [--dst-dir DST_DIR] [--dir-mark DIR_MARK] [--file-mark FILE_MARK] [--skip-save-veh] [--x-tol X_TOL] [--f-tol F_TOL] [--n-max-gen N_MAX_GEN] [--pop-size POP_SIZE] [--nth-gen NTH_GEN] [--n-last N_LAST] - [--range-overshoot-tol RANGE_OVERSHOOT_TOL] [---missed-trace-correction] [--max-time-dilation MAX_TIME_DILATION] [--min-time-dilation MIN_TIME_DILATION] [--time-dilation-tol TIME_DILATION_TOL] [--write-tsv WRITE_TSV] +usage: SWEEP [-h] [--config CONFIG] [--analysis-id ANALYSIS_ID] [--vehicles VEHICLES] [--scenarios SCENARIOS] [--selections [SELECTIONS ...]] [--eng-curves ENG_CURVES] [--lw-curves LW_CURVES] + [--aero-curves AERO_CURVES] [--look-for LOOK_FOR] [--skip-all-opt] [--skip-input-validation] [--exclude [EXCLUDE ...]] [--algorithms [ALGORITHMS ...]] [--dst-dir DST_DIR] + [--dir-mark DIR_MARK] [--file-mark FILE_MARK] [--skip-save-veh] [--x-tol X_TOL] [--f-tol F_TOL] [--n-max-gen N_MAX_GEN] [--pop-size POP_SIZE] [--nth-gen NTH_GEN] [--n-last N_LAST] + [--range-overshoot-tol RANGE_OVERSHOOT_TOL] [---missed-trace-correction] [--max-time-dilation MAX_TIME_DILATION] [--min-time-dilation MIN_TIME_DILATION] + [--time-dilation-tol TIME_DILATION_TOL] [--write-tsv WRITE_TSV] The sweep.py module is the main script to run T3CO @@ -48,7 +51,8 @@ optional arguments: --scenarios SCENARIOS Input file for Scenario models (default: ./resources/inputs/demo/Demo_FY22_scenario_assumptions.csv) --selections [SELECTIONS ...] - Selections desired to run. Selections can be an int, or list of ints, or range expression. Ex: --selections 234 or --selections "[234,236,238]" or --selections "range(234, 150, 2)" (default: None) + Selections desired to run. Selections can be an int, or list of ints, or range expression. Ex: --selections 234 or --selections "[234,236,238]" or --selections "range(234, + 150, 2)" (default: None) --eng-curves ENG_CURVES Input file for engine efficiency improvement cost curves (default: ./resources/auxiliary/EngineEffImprovementCostCurve.csv) --lw-curves LW_CURVES @@ -63,8 +67,9 @@ optional arguments: --exclude [EXCLUDE ...] Overrides -look_for. a string for string matching to exclude runs, example -exclude 'FCEV' or -look_for '["FCEV", "HEV"]' (default: >{-<>-}<) --algorithms [ALGORITHMS ...], --algos [ALGORITHMS ...], --algo [ALGORITHMS ...] - Enter algorithm or list of algorithms, or "ensemble" to use all, to use for optimization: ['NSGA2', 'NelderMead', 'PatternSearch', 'PSO'] ex: -algos PatternSearch | -algos '["PatternSearch", "NSGA2"]' | -algos "ensemble" (default: NSGA2) - --dst-dir DST_DIR Directory to store T3CO results (default: ../results) + Enter algorithm or list of algorithms, or "ensemble" to use all, to use for optimization: ['NSGA2', 'NelderMead', 'PatternSearch', 'PSO'] ex: -algos PatternSearch | -algos + '["PatternSearch", "NSGA2"]' | -algos "ensemble" (default: NSGA2) + --dst-dir DST_DIR Directory to store T3CO results (default: ./results) --dir-mark DIR_MARK Name for results directory in addition to timestamp (default: ) --file-mark FILE_MARK Prefix to add to the result file names (default: ) @@ -72,7 +77,7 @@ optional arguments: --x-tol X_TOL Parameter space tolerance for optimization (default: 0.001) --f-tol F_TOL Objective space tolerance for optimzation (default: 0.001) --n-max-gen N_MAX_GEN - Cax number of optimizer iterations regardless of algorithm (default: 1000) + Max number of optimizer iterations regardless of algorithm (default: 1000) --pop-size POP_SIZE population of each generation (default: 25) --nth-gen NTH_GEN Period of generations in which to evaluate if convergence happens during optimization (default: 1) --n-last N_LAST Number of generations to look back for establishing convergence during optimization (default: 5) diff --git a/docs/scenario_inputs_descriptions.md b/docs/scenario_inputs_descriptions.md index 595f016..07d554e 100644 --- a/docs/scenario_inputs_descriptions.md +++ b/docs/scenario_inputs_descriptions.md @@ -64,7 +64,7 @@ fc_ice_base_cost_dol | Cost of Fuel Convertor | constraint_grade | Optimization constraint - Gradeability 1.25% grade and 6% grade | bool | | objective_tco | Boolean switch for minimizing TCO as optimization objective | bool | | constraint_c_rate | Optimization constraint - Charge Rate | bool | -| shifts_per_year | Number of shifts/drivecycle instances per year traveled by the vehicle as a vector of length equal to number of TCO years. if = 0, then it's calculated from vmt and daily distance | list\[int\] | +| shifts_per_year | Number of shift / drive cycle instances the vehicle travels per year as a vector of length equal to number of TCO years. If not specified, then it's calculated from vmt and drive cycle distance. NOTE: if the drive cycle includes the full duration of a shift, best practice is to leave this blank or 0 or \[0\]; otherwise , i.e. if it is a compressed or regulatory cycle, shifts per year should be specified. | list\[int\] | | motor_power_override_kw_fc_demand_on_pct | For PHEV, percentage motor power override as fraction | float | | soc_norm_init_for_accel_pct | Initial normalized SOC for acceleration test (only PHEV) | float | | soc_norm_init_for_grade_pct | Initial normalized SOC for gradeability test (only PHEV) | float | diff --git a/t3co/sweep.py b/t3co/sweep.py index 67c1727..dc4ba3a 100644 --- a/t3co/sweep.py +++ b/t3co/sweep.py @@ -1274,7 +1274,7 @@ def skip_scenario(sel: int, scenario_name: str, verbose: bool = False) -> bool: "--n-max-gen", default=1000, type=float, - help="Cax number of optimizer iterations regardless of algorithm", + help="Max number of optimizer iterations regardless of algorithm", ) parser.add_argument("--pop-size", default=25, help="population of each generation") parser.add_argument( From c39f410a5b2e70a0c88936a712ac02f7b4433421 Mon Sep 17 00:00:00 2001 From: Harish Panneer Selvam Date: Mon, 7 Oct 2024 15:03:56 -0600 Subject: [PATCH 3/3] Remove unnecessary comments in the codebase --- t3co/run/run_scenario.py | 3 - t3co/sweep.py | 2 - t3co/tco/opportunity_cost.py | 104 ++++---------------------------- t3co/tco/tco_stock_emissions.py | 5 -- t3co/tco/tcocalc.py | 26 +------- 5 files changed, 13 insertions(+), 127 deletions(-) diff --git a/t3co/run/run_scenario.py b/t3co/run/run_scenario.py index a86c10c..cbf1cd2 100644 --- a/t3co/run/run_scenario.py +++ b/t3co/run/run_scenario.py @@ -18,8 +18,6 @@ from t3co.run import Global as gl from t3co.tco import tco_analysis -# import importlib -# tco_analysis = importlib.reload(tco_analysis) # --------------------------------- \\ powertrain adjustment methods --------------------------------- # @@ -99,7 +97,6 @@ def from_dict(self, config_dict: dict) -> Self: Returns: Self: Config instance containining all values from T3CO Config CSV file """ - # config_dict['selections'] = np.array(ast.literal_eval(config_dict['selections'])) try: config_dict["selections"] = ast.literal_eval(config_dict["selections"]) except: # noqa: E722 diff --git a/t3co/sweep.py b/t3co/sweep.py index dc4ba3a..c5e8ecc 100644 --- a/t3co/sweep.py +++ b/t3co/sweep.py @@ -1346,9 +1346,7 @@ def skip_scenario(sel: int, scenario_name: str, verbose: bool = False) -> bool: lw_imp_curves = Path(args.lw_imp_curves) aero_drag_imp_curves = Path(args.aero_drag_imp_curves) write_tsv = args.write_tsv - # config = None else: - # args.analysis_id = ast.literal_eval(args.analysis_id) try: config = rs.Config() config.from_file(filename=args.config, analysis_id=args.analysis_id) diff --git a/t3co/tco/opportunity_cost.py b/t3co/tco/opportunity_cost.py index 453adf7..5bd7fc4 100644 --- a/t3co/tco/opportunity_cost.py +++ b/t3co/tco/opportunity_cost.py @@ -15,15 +15,6 @@ from t3co.run import Global as gl from t3co.run import run_scenario -# TODO: think about this stuff -# Thoughts about how to improve this: -# 1 - maybe $/lb should be in terms of profit and not raw shipping fees -# 2 - could consider scaling number of vehicles by some function of opportunity cost -# such that fungible goods are shipped at same rate. This would bump up capital -# expenses but lower lost revenue. At the other end, we could just lose some revenue. -# I would think they'd work out pretty similarly, but it'd be interesting to compare -# two approaches. - class OpportunityCost: """ @@ -44,52 +35,30 @@ def __init__( range_dict (dict, optional): dictionary containing primary_fuel_range_mi from fueleconomy.get_range_mi function. Defaults to None. """ - # maybe this should be on a profit basis (it's currently not) - ### All params below here are experimental and not to be used for now - # self.cost_per_lb_mi = kwargs.pop("cost_per_lb_mi", 0.0003) - # trip distance[mi] for typical point A to point B trip - # self.d_trip_mi = kwargs.pop('d_trip_mi', 500) - # self.d_trip_mi = scenario.vmt[0]/scenario.shifts_per_year self.payload_cap_cost_multiplier = None - # distance[mi] that can be traveled with a full battery. - # self.total_range_mi = kwargs.pop('d_fullbatt_mi', 300) + if range_dict: self.total_range_mi = range_dict["primary_fuel_range_mi"] - # print('primary_fuel_range_mi') else: self.total_range_mi = scenario.target_range_mi - # print(range_dict) - # self.cycle_distance_mi = range_dict['cycle_distance_mi'] - # average vehicle speed[mph] over trip, should come from FASTSim - # self.v_mean_mph = range_dict['mean_cyc_speed_mph'] - # driver hourly labor rate[$/hr]. - # self.free_dwell_time_hr = scenario.fdt_available_freetime_hr - # dwell time [hr] driven by non-charging needs (e.g. required work breaks) that can be used for charging. - # self.free_dwell_time_hr = kwargs.pop('free_dwell_time_hr', 3) - # fraction of dwell time that can actually be used for charging - # self.dwell_time_efficiency = kwargs.pop('dwell_time_efficiency', 1.) + if scenario.activate_tco_fueling_dwell_time_cost: self.frac_of_fullcharge_bounds = list( np.float_(scenario.fdt_frac_full_charge_bounds.strip(" ][").split(",")) ) - if ('0' in str(scenario.shifts_per_year) or np.isnan(scenario.shifts_per_year)) and scenario.constant_trip_distance_mi: - self.shifts_per_year = [round(scenario.vmt[i] / scenario.constant_trip_distance_mi) for i in range(scenario.vehicle_life_yr)] + if ( + "0" in str(scenario.shifts_per_year) + or np.isnan(scenario.shifts_per_year) + ) and scenario.constant_trip_distance_mi: + self.shifts_per_year = [ + round(scenario.vmt[i] / scenario.constant_trip_distance_mi) + for i in range(scenario.vehicle_life_yr) + ] else: self.shifts_per_year = ast.literal_eval(scenario.shifts_per_year) self.payload_cap_cost_multiplier = 0 - # rate[kW] at which battery is recharged - # self.charge_rate_kW = kwargs.pop("charge_rate_kW", 200) - # battery capacity [kilowatt-hours] - # self.battery_capacity_kWhr = kwargs.pop("batt_cap_kW_hr", 300) - # number of full battery trips that don't incur dwell time penalty - # battery is allowed `num_free_trips` charging events without penalty - # scenario.fdt_num_free_dwell_trips = kwargs.pop('num_free_trips', 1.) - # scenario.fdt_num_free_dwell_trips = scenario.fdt_num_free_dwell_trips - # number of weight weight bins - # self.num_bins = kwargs.pop("num_bins", 1_000) - if len(kwargs) > 0: warnings.warn(f"Invalid kwargs: {list(kwargs.keys())}") @@ -136,7 +105,6 @@ def set_kdes( # get probability of each vehicle weight self.p_of_weights = kernel(self.vehicle_weights_bins_lb) - # self.p_of_weights_normalized = probability_payload = pd.DataFrame( [self.vehicle_weights_bins_kg, self.p_of_weights], @@ -151,7 +119,6 @@ def set_kdes( ) ]["p_of_weights"].sum() self.p_of_weights_normalized = self.p_of_weights / normalization_factor - # print(f'plf_ref_veh_empty_mass_kg {scenario.plf_ref_veh_empty_mass_kg}') def set_payload_loss_factor( self, @@ -177,7 +144,6 @@ def set_payload_loss_factor( new_cargo_cieling_kg = ( scenario.gvwr_kg - empty_increase_kg + scenario.gvwr_credit_kg ) - # print(new_cargo_cieling_lb) # determine indices where lost cargo capacity is bounded in vehicle_weights # and get the corresponding indices for p_of_weights @@ -195,17 +161,11 @@ def set_payload_loss_factor( maxidx = ( np.where(self.vehicle_weights_bins_kg == a[a > 0][0] + scenario.gvwr_kg) )[0][0] - # print(f'Vehicle bin limits: {self.vehicle_weights_bins_kg[minidx]}, {self.vehicle_weights_bins_kg[maxidx]}') - - # print( f' PDF bounds: {minidx}, {maxidx}' ) - # print( f' PDF weight bounds: {self.vehicle_weights_bins_lb[minidx]}, {self.vehicle_weights_bins_lb[maxidx]}' ) estimated_lost_payload_per_bin_kg = self.p_of_weights_normalized[ minidx:maxidx ] * (self.vehicle_weights_bins_kg[minidx:maxidx] - new_cargo_cieling_kg) - # estimated_lost_payload_lb = sum(estimated_lost_payload_per_bin_lb) estimated_lost_payload_kg = np.trapz(estimated_lost_payload_per_bin_kg) - # print(f'estimated_lost_payload_kg: {estimated_lost_payload_kg}') # payload cost multiplier self.payload_cap_cost_multiplier = 1 + estimated_lost_payload_kg / ( @@ -275,24 +235,6 @@ def make_plots(save_dir: str = None) -> None: if plots: make_plots(plots_dir) - # Old Dwell time calculation - # def get_dwell_loss_factor(self, - # a_vehicle:fastsim.vehicle, - # scenario) : - # self.dwell_time_hr = max( - # 0, self.d_trip_mi / self.total_range_mi - scenario.fdt_num_free_dwell_trips) * \ - # (a_vehicle.ess_max_kwh / a_vehicle.ess_max_kw) - # # (nominal time + additional non-driving time to charge) / nominal time - - # # TODO: need to add separate labor and payload dwell penalties starting here - # self.net_fueling_dwell_time_hr_per_yr = max( - # 0, (self.dwell_time_hr - max(0, self.free_dwell_time_hr)) * self.dwell_time_efficiency) - - # # number of original trip time durations after correcting for EV time penalty - # # (e.g. 1.8 means 80% longer trip duration) - # self.dwell_time_factor = max(1, (self.d_trip_mi / self.v_mean_mph + self.net_fueling_dwell_time_hr_per_yr) / - # (self.d_trip_mi / self.v_mean_mph)) - def set_fueling_dwell_time_cost( self, a_vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario ) -> None: @@ -348,7 +290,6 @@ def set_fueling_dwell_time_cost( ) for i in range(scenario.vehicle_life_yr): - # self.shifts_per_year = (scenario.vmt[i])/ self.cycle_distance_mi self.d_trip_mi = scenario.vmt[i] / self.shifts_per_year[i] self.num_of_dwells = max( 0, @@ -359,8 +300,7 @@ def set_fueling_dwell_time_cost( - scenario.fdt_num_free_dwell_trips ), ) - # print(f'num_of_dwells: {self.num_of_dwells}\n vmt: {scenario.vmt[i]}') - # print(f'd_trip_mi: {self.d_trip_mi}') + if self.num_of_dwells != 0: self.remaining_dwells = self.num_of_dwells % 1 if self.remaining_dwells < self.frac_of_fullcharge_bounds[0]: @@ -375,7 +315,6 @@ def set_fueling_dwell_time_cost( self.num_of_dwells += 0 else: self.num_of_dwells += 1 - self.remaining_dwells - # else: if (self.num_of_dwells < 1 and not scenario.fdt_num_free_dwell_trips) or ( scenario.fuel_type @@ -414,24 +353,6 @@ def set_fueling_dwell_time_cost( self.total_fueling_dwell_time_hr += self.net_fueling_dwell_time_hr_per_yr[i] - # self.dwell_time_factor = max(1, (self.d_trip_mi / self.v_mean_mph + self.net_fueling_dwell_time_hr_per_yr[i]) / - # (self.d_trip_mi / self.v_mean_mph)) - - # def set_fueling_dwell_time_cost #Old calculation - # (self, - # a_vehicle:fastsim.vehicle, - # scenario): - - # self.dwell_time_hr = 0 if self.d_trip_mi< self.total_range_mi else \ - # max((self.d_trip_mi - self.total_range_mi)* (a_vehicle.ess_max_kwh / a_vehicle.ess_max_kw), scenario.dlf_min_charge_time_hr) - # self.time_full_charge_hr = self.total_range_mi * a_vehicle.ess_max_kwh / a_vehicle.ess_max_kw - # self.time_frac_charge_hr = self.time_full_charge_hr *(1- (self.dwell_time_hr/self.time_full_charge_hr - floor(self.dwell_time_hr/self.time_full_charge_hr) )) - # self.dwell_time_hr = self.dwell_time_hr if self.time_frac_charge_hr < self.time_available_charge_hr else (self.dwell_time_hr+ self.time_frac_charge_hr) - - # self.dwell_time_cost_Dol = self.dwell_time_hr/self.dwell_time_efficiency * self.labor_rate_dol_per_hr - # print(f'Dwell time hr per year: {self.dwell_time_hr}') - # print(f'Dwell cost dol: {self.dwell_time_cost_Dol}') - def set_M_R_downtime_cost( self, a_vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario ) -> None: @@ -469,9 +390,6 @@ def set_M_R_downtime_cost( * scenario.downtime_oppy_cost_dol_per_hr ) - # print(f'Total M&R downtime hr: {self.net_net_mr_downtime_hr_per_yr}') - # print(f'M&R Downtime cost dol: {self.net_MR_downtime_oppcosts_Dol}') - # %% def main(): diff --git a/t3co/tco/tco_stock_emissions.py b/t3co/tco/tco_stock_emissions.py index 15978b5..41c70fa 100644 --- a/t3co/tco/tco_stock_emissions.py +++ b/t3co/tco/tco_stock_emissions.py @@ -1,7 +1,3 @@ -# December 2018 -# Stock Model in Python -# C. Hunter - from typing import Tuple import pandas as pd @@ -181,7 +177,6 @@ def stockModel( residualCosts.to_csv(gl.TCO_INTERMEDIATES / "residual_costs.csv", index=False) downtimeCosts.to_csv(gl.TCO_INTERMEDIATES / "downtime_costs.csv", index=False) - # ownershipCosts = pd.concat([vehicleCosts, travelCosts, fuelCosts], sort=False) ownershipCosts = pd.concat( [ vehicleCosts, diff --git a/t3co/tco/tcocalc.py b/t3co/tco/tcocalc.py index 419e6c5..aabc3a5 100644 --- a/t3co/tco/tcocalc.py +++ b/t3co/tco/tcocalc.py @@ -174,8 +174,7 @@ def calculate_dollar_cost( pTaxCost = tax_rate_pct * msrp - # insurance_cost = calc_insurance_costs(scenario=scenario, msrp=msrp) - # residual_cost = calc_residual_cost(vehicle=veh, scenario=scenario, msrp=msrp) + cost_set = { "Glider": vehicle_glider_cost_dol, "Fuel converter": fcPrice, @@ -211,13 +210,11 @@ def calculate_opp_costs( """ oppcostobj = opportunity_cost.OpportunityCost(scenario, range_dict) if scenario.activate_tco_payload_cap_cost_multiplier: - # assert optvehicle.veh_pt_type in [gl.BEV, gl.HEV], "payload cap loss factor TCO element only available for BEVs and FCEV HEVs" assert gl.not_falsy(scenario.plf_ref_veh_empty_mass_kg) assert np.isnan(scenario.plf_ref_veh_empty_mass_kg) == False oppcostobj.set_payload_loss_factor(vehicle, scenario) if scenario.activate_tco_fueling_dwell_time_cost: - # assert optvehicle.veh_pt_type in [gl.BEV, gl.HEV], "payload cap loss factor TCO element only available for BEVs and FCEV HEVs" assert gl.not_falsy(scenario.downtime_oppy_cost_dol_per_hr) assert not np.isnan(scenario.fdt_num_free_dwell_trips) assert not np.isnan(scenario.fdt_dwpt_fraction_power_pct) @@ -237,7 +234,6 @@ def calculate_opp_costs( assert gl.not_falsy(scenario.mr_avg_tire_life_mi) oppcostobj.set_M_R_downtime_cost(vehicle, scenario) - # veh_opp_cost_set = {'payload_cap_cost_multiplier' : None, 'net_fueling_dwell_time_hr_per_yr' : 0., 'dwell_time_cost_Dol' : 0.} veh_opp_cost_set = { "payload_cap_cost_multiplier": oppcostobj.payload_cap_cost_multiplier, "daily_trip_distance_mi": oppcostobj.d_trip_mi, @@ -371,8 +367,6 @@ def fill_veh_expense_file( "Battery replacement", ], [vehicle, vocation, model_year, cost_set["Purchase tax"], "Purchase tax"], - # [vehicle, vocation, model_year, cost_set["Insurance"], "Insurance"], - # [vehicle, vocation, model_year, cost_set["Residual Cost"], "Residual Cost"], ] vexpdf = pd.DataFrame( data, columns=["Vehicle", "Vocation", "Model Year", "Cost [$/veh]", "Category"] @@ -414,9 +408,6 @@ def fill_trav_exp_tsv( ): l1 = [yr, region, vocation, vehicle_name, "maintenance", maint[i]] data.append(l1) - # data.append([yr, region, vocation, vehicle, "payload opp cost", np.nan]) - # data.append([yr, region, vocation, vehicle, "time opp cost", np.nan]) - # data.append([yr, region, vocation, vehicle, "labor opp cost", np.nan]) df = pd.DataFrame(data=data, columns=columns) @@ -448,10 +439,7 @@ def fill_downtimelabor_cost_tsv( "fueling_dwell_labor_cost_dol_per_yr" ] mr_downtime_oppy_cost_dol_per_yr = oppy_cost_set["mr_downtime_oppy_cost_dol_per_yr"] - # assert len(insurance_rates) >= veh_life_years, (f"vehLifeYears of {veh_life_years} & length of input insurance rates {len(insurance_rates)} do not align; " - # f"vehLifeYears life years & number of years in vmt should match\n" - # f"[vehLifeYears/[VMT_1,...,VMT_N]]:[{veh_life_years}/{insurance_rates}]") - # \ + for i in range(0, veh_life_years): # downtime_costs_Dol = fueling_downtime_oppy_cost_dol[i] + MR_downtime_cost_Dol[i] # i is age, give it a VMT value for each entry in VMT or defer to last VMT entry @@ -463,7 +451,6 @@ def fill_downtimelabor_cost_tsv( df = pd.DataFrame(data, columns=columns) - # print(f'insurance: {df}') return df @@ -487,7 +474,6 @@ def fill_market_share_tsv( veh_life_years = int(scenario.vehicle_life_yr) model_year = int(scenario.model_year) - # maint = list(np.float_(scenario.maint_oper_cost_dol_per_mi.strip('][').split(','))) data = [] columns = ["Vehicle", "Vocation", "Model Year", "Region", "Market Share [veh/veh]"] data.append([vehicle, vocation, model_year, reg, 1 / num_vs]) @@ -574,8 +560,6 @@ def fill_fuel_expense_tsv( ) data.append([yr, fuel_type, cat, cost]) - # scenario.scenario_gge_regional_temporal_fuel_price += f"fuel: {fuel_type}; region: {scenario.region}; year: {yr}; $_gge: {cost}" - df = pd.DataFrame(data, columns=columns) return df @@ -676,7 +660,6 @@ def fill_insurance_tsv( df = pd.DataFrame(data, columns=columns) - # print(f'insurance: {df}') return df @@ -703,10 +686,6 @@ def fill_residual_cost_tsc( residual_rate = find_residual_rates(vehicle, scenario) - # assert len(insurance_rates) >= veh_life_years, (f"vehicle_life_yr of {veh_life_years} & length of input insurance rates {len(insurance_rates)} do not align; " - # f"vehicle_life_yr life years & number of years in vmt should match\n" - # f"[vehicle_life_yr/[VMT_1,...,VMT_N]]:[{veh_life_years}/{insurance_rates}]") - MSRP = veh_cost_set["msrp"] for i in range(0, veh_life_years): if i == veh_life_years - 1: @@ -717,7 +696,6 @@ def fill_residual_cost_tsc( df = pd.DataFrame(data, columns=columns) - # print(f'residual: {df}') return df