diff --git a/README.md b/README.md index 355ce35..3e70c69 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,6 @@ [![homepage](https://img.shields.io/badge/homepage-t3co-blue)](https://www.nrel.gov/transportation/t3co.html) [![github](https://img.shields.io/badge/github-t3co-blue.svg)](https://github.com/NREL/T3CO) [![PyPI version](https://badge.fury.io/py/t3co.svg)](https://badge.fury.io/py/t3co) ![GitHub License](https://img.shields.io/github/license/NREL/T3CO) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/t3co) - - - - - - # **T3CO** : Transportation Technology Total Cost of Ownership Tool ## Description @@ -21,6 +15,12 @@ To start, go to the [Overview](https://github.com/NREL/T3CO-private/blob/264a730 **T3CO** is a general framework allowing a user to determine the total cost of ownership (TCO) of a FASTSim vehicle (paired with a FASTSim DriveCycle(s) for determining fuel efficiency). The user can also determine performance of gradability, acceleration, and range. In addition to straight TCO computation there is also the option to optimize a vehicle powertrain such that it meets performance optional targets while also optionally minimizing TCO. ## Installation +**From PyPI** +```bash +pip install t3co +``` + +**From Github** First, clone the repository from **NREL** GitHub: @@ -42,14 +42,14 @@ This will install t3co with minimal dependencies such that t3co files can be edi to be compatible with the current code in T3CO. ## Demo -**Using the T3CO Config file** +**Using the [T3CO Config](https://github.com/NREL/T3CO/blob/c3df6421033cef7d35b7d7cd575ab94e85fcd9a9/t3co/resources/T3COConfig.csv) file** ```bash cd t3co python sweep.py --analysis-id 0 ``` -** or get some quick TCO results** +**Or get some quick TCO results** ```bash cd t3co @@ -76,18 +76,17 @@ pipx ensurepath Then from T3CO root directory ```bash pipx install pydoc-markdown -pydoc-markdown -I . -p . --render-toc > ../docs/content/CodeReference.md +pydoc-markdown -I . -p t3co --render-toc > docs/functions/CodeReference.md ``` for specific modules, specify the module name after `-m`: -`pydoc-markdown -I . -m sweep --render-toc > ../docs/content/sweep.md` +`pydoc-markdown -I . -m t3co/sweep --render-toc > docs/functions/sweep.md` This generates CodeReference.md including a Table of Contents from all python docstrings in the T3CO package ## Generate MKDocs server for documentation website (For Developers) Use the `mkdocs.yml` file to configure the documentation website on localhost. `mkdocs` and `mkdocstrings` should get installed along with other dependencies when running `pip install -e .` from the root directory. In case it throws an error, these packages can be installed separately: ```bash -pip install mkdocs -pip install mkdocstrings-python +pip install mkdocs mkdocstrings-python ``` **On Mac** diff --git a/docs/T3CO_Overview.md b/docs/T3CO_Overview.md index 7665aaf..82cc04a 100644 --- a/docs/T3CO_Overview.md +++ b/docs/T3CO_Overview.md @@ -1,22 +1,22 @@ -- [T3CO Introduction ](#t3co-introduction-) -- [Code Flow ](#code-flow-) +- [T3CO Introduction ](#t3co-introduction) +- [Code Flow ](#code-flow) - [**Generating TCO and performance**](#generating-tco-and-performance) -- [T3CO Input Files ](#t3co-input-files-) -- [Optimization Flow ](#optimization-flow-) -- [Performance Objectives ](#performance-objectives-) +- [T3CO Input Files ](#t3co-input-files) +- [Optimization Flow ](#optimization-flow) +- [Performance Constraints ](#performance-constraints) -## T3CO Introduction +## T3CO Introduction [NREL's Transportation Technology Total Cost of Ownership](https://www.nrel.gov/transportation/t3co.html) (T3CO) tool enables levelized assessments of the full life cycle costs of advanced technology commercial vehicles. -## Code Flow +## Code Flow Generally speaking, T3CO can be used in two ways. The first way is generating total cost of ownership (TCO) metrics and performance metrics for a vehicle. The second way is optimizing a vehicle's specifications to achieve the lowest total cost of ownership possible. Since optimization requires gathering TCO and performance metrics during each step of optimization, it essentially is an expanded version of the first way of using T3CO. So we'll look at the first way first. -### **Generating TCO and performance** +### **Generating TCO and performance** When generating [TCO](https://github.com/NREL/T3CO-private/blob/65cb44929caff7b6e10959364f4f18d10f888d1e/docs/models/TCO_calculations.md), there are a few main components of a vehicle's total cost of ownership: - MSRP, the cost of the vehicle at time of purchase @@ -33,19 +33,19 @@ The [Performance Constraints](#performance-constraints) determined for the vehic More on that below. -## T3CO Input Files +## T3CO Input Files There are three main files that form the basis of T3CO TCO calculations and T3CO optimizations. The first is the vehicle file, which is a [FASTSim input file](https://docs.rs/fastsim-core/0.1.6/fastsim_core/vehicle/struct.RustVehicle.html). The second type of file is the T3CO file, or [Scenario File](https://github.com/NREL/T3CO-private/blob/61aff5700c16ff54d69aa2c238f63553ec31f1da/docs/scenario_inputs_descriptions.md), which specifies the operating conditions that make up the TCO calculation for the vehicle. These are conditions such as $ per kilowatt for engine or motor size, operating years, operating regions, whether to optimize the vehicle or not, range, grade and acceleration performance targets, etc. The third file is the [Config File](https://github.com/NREL/T3CO-private/blob/61aff5700c16ff54d69aa2c238f63553ec31f1da/docs/config_inputs_descriptions.md), which provides an easier way to manage analyses with minimal command line inputs, containing overrides for major scenario input parameters. T3CO provides some readily available Vehicle and Scenario models to run. There are demo versions of the [Vehicle file](https://github.com/NREL/T3CO-private/blob/264a730de942671eb2345a5afca7e1afd6d67666/t3co/resources/inputs/demo/Demo_FY22_vehicle_model_assumptions.csv), [Scenario file](https://github.com/NREL/T3CO-private/blob/264a730de942671eb2345a5afca7e1afd6d67666/t3co/resources/inputs/demo/Demo_FY22_scenario_assumptions.csv), and the [Config file](https://github.com/NREL/T3CO-private/blob/264a730de942671eb2345a5afca7e1afd6d67666/t3co/resources/T3COConfig.csv) available in the `/t3co/resources/` folder. -## Optimization Flow +## Optimization Flow The **TCO & Performance** metrics described above are the core of the [optimization loop](https://github.com/NREL/T3CO-private/blob/7b56eb37bf5a57e6cd0ce761fc1708ee151c956f/docs/models/optimization.md). T3CO has the capability to take vehicle specifications, such as engine size, motor size, battery size, area of drag, vehicle weight, etc. and modify them in order to find the set of specifications that yields the lowest TCO while still meeting minimum performance requirements in acceleration, grade and range. Optimization is handled in the [optimization module](https://github.com/NREL/T3CO-private/blob/74a494bc783c1d0d5794d605584e9843b3a4cb2d/t3co/moopack/moo.py#L80), inheriting from the PyMoo module. -## Performance Constraints +## Performance Constraints - [Gradability](https://github.com/NREL/T3CO-private/blob/7b56eb37bf5a57e6cd0ce761fc1708ee151c956f/docs/models/acceleration_and_grade_tests.mdd) is the measure of the vehicle's max speed achieved at 1.25 and 6 percent grades, while the vehicle is operating at max allowable weight (including EV weight credit kilograms) - [Acceleration](https://github.com/NREL/T3CO-private/blob/7b56eb37bf5a57e6cd0ce761fc1708ee151c956f/docs/models/acceleration_and_grade_tests.md) is the measure of the seconds the vehicle takes to reach 30 miles per hour and 60 miles per hour, which can be at max allowable weight or just current vehicle weight. diff --git a/docs/functions/CodeReference.md b/docs/functions/CodeReference.md index 00a9828..3d744d6 100644 --- a/docs/functions/CodeReference.md +++ b/docs/functions/CodeReference.md @@ -1,152 +1,154 @@ # Table of Contents -* [.](#.) -* [..tco](#..tco) -* [..tco.tcocalc](#..tco.tcocalc) - * [find\_residual\_rates](#..tco.tcocalc.find_residual_rates) - * [calculate\_dollar\_cost](#..tco.tcocalc.calculate_dollar_cost) - * [calculate\_opp\_costs](#..tco.tcocalc.calculate_opp_costs) - * [fill\_fuel\_eff\_file](#..tco.tcocalc.fill_fuel_eff_file) - * [fill\_veh\_expense\_file](#..tco.tcocalc.fill_veh_expense_file) - * [fill\_trav\_exp\_tsv](#..tco.tcocalc.fill_trav_exp_tsv) - * [fill\_downtimelabor\_cost\_tsv](#..tco.tcocalc.fill_downtimelabor_cost_tsv) - * [fill\_market\_share\_tsv](#..tco.tcocalc.fill_market_share_tsv) - * [fill\_fuel\_expense\_tsv](#..tco.tcocalc.fill_fuel_expense_tsv) - * [fill\_annual\_tsv](#..tco.tcocalc.fill_annual_tsv) - * [fill\_reg\_sales\_tsv](#..tco.tcocalc.fill_reg_sales_tsv) - * [fill\_insurance\_tsv](#..tco.tcocalc.fill_insurance_tsv) - * [fill\_residual\_cost\_tsc](#..tco.tcocalc.fill_residual_cost_tsc) - * [fill\_survival\_tsv](#..tco.tcocalc.fill_survival_tsv) - * [fill\_fuel\_split\_tsv](#..tco.tcocalc.fill_fuel_split_tsv) -* [..tco.opportunity\_cost](#..tco.opportunity_cost) - * [OpportunityCost](#..tco.opportunity_cost.OpportunityCost) - * [\_\_init\_\_](#..tco.opportunity_cost.OpportunityCost.__init__) - * [set\_kdes](#..tco.opportunity_cost.OpportunityCost.set_kdes) - * [get\_payload\_loss\_factor](#..tco.opportunity_cost.OpportunityCost.get_payload_loss_factor) - * [get\_dwell\_time\_cost](#..tco.opportunity_cost.OpportunityCost.get_dwell_time_cost) - * [get\_M\_R\_downtime\_cost](#..tco.opportunity_cost.OpportunityCost.get_M_R_downtime_cost) - * [main](#..tco.opportunity_cost.main) -* [..tco.tco\_stock\_emissions](#..tco.tco_stock_emissions) - * [dropCols](#..tco.tco_stock_emissions.dropCols) - * [stockModel](#..tco.tco_stock_emissions.stockModel) -* [..tco.tco\_analysis](#..tco.tco_analysis) - * [get\_operating\_costs](#..tco.tco_analysis.get_operating_costs) - * [discounted\_costs](#..tco.tco_analysis.discounted_costs) - * [calc\_discountedTCO](#..tco.tco_analysis.calc_discountedTCO) - * [get\_tco\_of\_vehicle](#..tco.tco_analysis.get_tco_of_vehicle) -* [..tests.test\_tcos](#..tests.test_tcos) - * [remove](#..tests.test_tcos.remove) - * [RunCONVTCOTests](#..tests.test_tcos.RunCONVTCOTests) - * [compare](#..tests.test_tcos.RunCONVTCOTests.compare) -* [..tests](#..tests) -* [..tests.tco\_tests.t2co\_tco\_benchmark](#..tests.tco_tests.t2co_tco_benchmark) - * [veh\_no](#..tests.tco_tests.t2co_tco_benchmark.veh_no) -* [..tests.tco\_tests.t2co\_bev\_mpgge\_benchmark](#..tests.tco_tests.t2co_bev_mpgge_benchmark) - * [veh\_no](#..tests.tco_tests.t2co_bev_mpgge_benchmark.veh_no) -* [..tests.test\_moo](#..tests.test_moo) -* [..moopack](#..moopack) -* [..moopack.moo](#..moopack.moo) - * [T3COProblem](#..moopack.moo.T3COProblem) - * [setup\_opt\_records](#..moopack.moo.T3COProblem.setup_opt_records) - * [\_\_init\_\_](#..moopack.moo.T3COProblem.__init__) - * [compile\_reporting\_vars](#..moopack.moo.T3COProblem.compile_reporting_vars) - * [instantiate\_moo\_vehicles\_and\_scenario](#..moopack.moo.T3COProblem.instantiate_moo_vehicles_and_scenario) - * [cda\_percent\_delta\_knob](#..moopack.moo.T3COProblem.cda_percent_delta_knob) - * [weight\_delta\_percent\_knob](#..moopack.moo.T3COProblem.weight_delta_percent_knob) - * [fc\_peak\_eff\_knob](#..moopack.moo.T3COProblem.fc_peak_eff_knob) - * [get\_objs](#..moopack.moo.T3COProblem.get_objs) - * [adjust\_fc\_peak\_eff](#..moopack.moo.T3COProblem.adjust_fc_peak_eff) - * [sweep\_knob](#..moopack.moo.T3COProblem.sweep_knob) - * [get\_tco\_from\_moo\_advanced\_result](#..moopack.moo.T3COProblem.get_tco_from_moo_advanced_result) - * [T3CODisplay](#..moopack.moo.T3CODisplay) - * [\_\_init\_\_](#..moopack.moo.T3CODisplay.__init__) - * [run\_optimization](#..moopack.moo.run_optimization) -* [..objectives.accel](#..objectives.accel) - * [get\_accel](#..objectives.accel.get_accel) -* [..objectives.fueleconomy](#..objectives.fueleconomy) - * [get\_range\_mi](#..objectives.fueleconomy.get_range_mi) - * [get\_sim\_drive](#..objectives.fueleconomy.get_sim_drive) - * [get\_mpgge](#..objectives.fueleconomy.get_mpgge) -* [..objectives.gradeability](#..objectives.gradeability) - * [get\_gradeability](#..objectives.gradeability.get_gradeability) -* [..objectives](#..objectives) -* [..sweep](#..sweep) - * [save\_tco\_files](#..sweep.save_tco_files) - * [get\_knobs\_bounds\_curves](#..sweep.get_knobs_bounds_curves) - * [get\_objectives\_constraints](#..sweep.get_objectives_constraints) - * [run\_moo](#..sweep.run_moo) - * [check\_input\_files](#..sweep.check_input_files) - * [run\_vehicle\_scenarios](#..sweep.run_vehicle_scenarios) -* [..run.Global](#..run.Global) - * [DieselGalPerGasGal](#..run.Global.DieselGalPerGasGal) - * [kgH2\_per\_gge](#..run.Global.kgH2_per_gge) - * [mps\_to\_mph](#..run.Global.mps_to_mph) - * [m\_to\_mi](#..run.Global.m_to_mi) - * [get\_kwh\_per\_gge](#..run.Global.get_kwh_per_gge) - * [set\_tco\_intermediates](#..run.Global.set_tco_intermediates) - * [set\_tco\_results](#..run.Global.set_tco_results) - * [kg\_to\_lbs](#..run.Global.kg_to_lbs) - * [lbs\_to\_kgs](#..run.Global.lbs_to_kgs) - * [not\_falsy](#..run.Global.not_falsy) -* [..run](#..run) -* [..run.generateinputs](#..run.generateinputs) - * [generate](#..run.generateinputs.generate) -* [..run.run\_scenario](#..run.run_scenario) - * [set\_test\_weight](#..run.run_scenario.set_test_weight) - * [reset\_vehicle\_weight](#..run.run_scenario.reset_vehicle_weight) - * [limit\_cargo\_kg\_for\_moo\_hev\_bev](#..run.run_scenario.limit_cargo_kg_for_moo_hev_bev) - * [set\_max\_motor\_kw](#..run.run_scenario.set_max_motor_kw) - * [set\_max\_battery\_kwh](#..run.run_scenario.set_max_battery_kwh) - * [set\_max\_battery\_power\_kw](#..run.run_scenario.set_max_battery_power_kw) - * [set\_max\_fuel\_converter\_kw](#..run.run_scenario.set_max_fuel_converter_kw) - * [set\_fuel\_store\_kwh](#..run.run_scenario.set_fuel_store_kwh) - * [set\_cargo\_kg](#..run.run_scenario.set_cargo_kg) - * [Config](#..run.run_scenario.Config) - * [from\_file](#..run.run_scenario.Config.from_file) - * [from\_dict](#..run.run_scenario.Config.from_dict) - * [validate\_analysis\_id](#..run.run_scenario.Config.validate_analysis_id) - * [Scenario](#..run.run_scenario.Scenario) - * [originalcargo\_kg](#..run.run_scenario.Scenario.originalcargo_kg) - * [plf\_scenario\_vehicle\_cargo\_capacity\_kg](#..run.run_scenario.Scenario.plf_scenario_vehicle_cargo_capacity_kg) - * [from\_config](#..run.run_scenario.Scenario.from_config) - * [check\_phev\_init\_socs](#..run.run_scenario.check_phev_init_socs) - * [get\_phev\_util\_factor](#..run.run_scenario.get_phev_util_factor) - * [get\_objective\_simdrive](#..run.run_scenario.get_objective_simdrive) - * [run\_grade\_or\_accel](#..run.run_scenario.run_grade_or_accel) - * [create\_fastsim\_vehicle](#..run.run_scenario.create_fastsim_vehicle) - * [get\_vehicle](#..run.run_scenario.get_vehicle) - * [get\_scenario\_and\_cycle](#..run.run_scenario.get_scenario_and_cycle) - * [load\_scenario](#..run.run_scenario.load_scenario) - * [load\_design\_cycle\_from\_scenario](#..run.run_scenario.load_design_cycle_from_scenario) - * [load\_design\_cycle\_from\_path](#..run.run_scenario.load_design_cycle_from_path) - * [vehicle\_scenario\_sweep](#..run.run_scenario.vehicle_scenario_sweep) - * [run](#..run.run_scenario.run) - * [rerun](#..run.run_scenario.rerun) -* [..demos.opp\_cost\_demo](#..demos.opp_cost_demo) -* [..demos.hev\_sweep\_and\_moo](#..demos.hev_sweep_and_moo) - * [vnum](#..demos.hev_sweep_and_moo.vnum) -* [..demos.example\_load\_and\_run](#..demos.example_load_and_run) -* [..demos.t2co\_opt\_benchmark](#..demos.t2co_opt_benchmark) -* [..demos.Spencer](#..demos.Spencer) - - - -# . - - - -# ..tco - - - -# ..tco.tcocalc - - +* [t3co](#t3co) +* [t3co.tco](#t3co.tco) +* [t3co.tco.tcocalc](#t3co.tco.tcocalc) + * [find\_residual\_rates](#t3co.tco.tcocalc.find_residual_rates) + * [calculate\_dollar\_cost](#t3co.tco.tcocalc.calculate_dollar_cost) + * [calculate\_opp\_costs](#t3co.tco.tcocalc.calculate_opp_costs) + * [fill\_fuel\_eff\_file](#t3co.tco.tcocalc.fill_fuel_eff_file) + * [fill\_veh\_expense\_file](#t3co.tco.tcocalc.fill_veh_expense_file) + * [fill\_trav\_exp\_tsv](#t3co.tco.tcocalc.fill_trav_exp_tsv) + * [fill\_downtimelabor\_cost\_tsv](#t3co.tco.tcocalc.fill_downtimelabor_cost_tsv) + * [fill\_market\_share\_tsv](#t3co.tco.tcocalc.fill_market_share_tsv) + * [fill\_fuel\_expense\_tsv](#t3co.tco.tcocalc.fill_fuel_expense_tsv) + * [fill\_annual\_tsv](#t3co.tco.tcocalc.fill_annual_tsv) + * [fill\_reg\_sales\_tsv](#t3co.tco.tcocalc.fill_reg_sales_tsv) + * [fill\_insurance\_tsv](#t3co.tco.tcocalc.fill_insurance_tsv) + * [fill\_residual\_cost\_tsc](#t3co.tco.tcocalc.fill_residual_cost_tsc) + * [fill\_survival\_tsv](#t3co.tco.tcocalc.fill_survival_tsv) + * [fill\_fuel\_split\_tsv](#t3co.tco.tcocalc.fill_fuel_split_tsv) +* [t3co.tco.opportunity\_cost](#t3co.tco.opportunity_cost) + * [OpportunityCost](#t3co.tco.opportunity_cost.OpportunityCost) + * [\_\_init\_\_](#t3co.tco.opportunity_cost.OpportunityCost.__init__) + * [set\_kdes](#t3co.tco.opportunity_cost.OpportunityCost.set_kdes) + * [set\_payload\_loss\_factor](#t3co.tco.opportunity_cost.OpportunityCost.set_payload_loss_factor) + * [set\_dwell\_time\_cost](#t3co.tco.opportunity_cost.OpportunityCost.set_dwell_time_cost) + * [set\_M\_R\_downtime\_cost](#t3co.tco.opportunity_cost.OpportunityCost.set_M_R_downtime_cost) + * [main](#t3co.tco.opportunity_cost.main) +* [t3co.tco.tco\_stock\_emissions](#t3co.tco.tco_stock_emissions) + * [dropCols](#t3co.tco.tco_stock_emissions.dropCols) + * [stockModel](#t3co.tco.tco_stock_emissions.stockModel) +* [t3co.tco.tco\_analysis](#t3co.tco.tco_analysis) + * [get\_operating\_costs](#t3co.tco.tco_analysis.get_operating_costs) + * [discounted\_costs](#t3co.tco.tco_analysis.discounted_costs) + * [calc\_discountedTCO](#t3co.tco.tco_analysis.calc_discountedTCO) + * [get\_tco\_of\_vehicle](#t3co.tco.tco_analysis.get_tco_of_vehicle) +* [t3co.tests.test\_tcos](#t3co.tests.test_tcos) + * [remove](#t3co.tests.test_tcos.remove) + * [RunCONVTCOTests](#t3co.tests.test_tcos.RunCONVTCOTests) + * [compare](#t3co.tests.test_tcos.RunCONVTCOTests.compare) +* [t3co.tests](#t3co.tests) +* [t3co.tests.tco\_tests.t2co\_tco\_benchmark](#t3co.tests.tco_tests.t2co_tco_benchmark) + * [veh\_no](#t3co.tests.tco_tests.t2co_tco_benchmark.veh_no) +* [t3co.tests.tco\_tests.t2co\_bev\_mpgge\_benchmark](#t3co.tests.tco_tests.t2co_bev_mpgge_benchmark) + * [veh\_no](#t3co.tests.tco_tests.t2co_bev_mpgge_benchmark.veh_no) +* [t3co.tests.test\_moo](#t3co.tests.test_moo) +* [t3co.moopack](#t3co.moopack) +* [t3co.moopack.moo](#t3co.moopack.moo) + * [T3COProblem](#t3co.moopack.moo.T3COProblem) + * [setup\_opt\_records](#t3co.moopack.moo.T3COProblem.setup_opt_records) + * [\_\_init\_\_](#t3co.moopack.moo.T3COProblem.__init__) + * [compile\_reporting\_vars](#t3co.moopack.moo.T3COProblem.compile_reporting_vars) + * [instantiate\_moo\_vehicles\_and\_scenario](#t3co.moopack.moo.T3COProblem.instantiate_moo_vehicles_and_scenario) + * [cda\_percent\_delta\_knob](#t3co.moopack.moo.T3COProblem.cda_percent_delta_knob) + * [weight\_delta\_percent\_knob](#t3co.moopack.moo.T3COProblem.weight_delta_percent_knob) + * [fc\_peak\_eff\_knob](#t3co.moopack.moo.T3COProblem.fc_peak_eff_knob) + * [get\_objs](#t3co.moopack.moo.T3COProblem.get_objs) + * [adjust\_fc\_peak\_eff](#t3co.moopack.moo.T3COProblem.adjust_fc_peak_eff) + * [sweep\_knob](#t3co.moopack.moo.T3COProblem.sweep_knob) + * [get\_tco\_from\_moo\_advanced\_result](#t3co.moopack.moo.T3COProblem.get_tco_from_moo_advanced_result) + * [T3CODisplay](#t3co.moopack.moo.T3CODisplay) + * [\_\_init\_\_](#t3co.moopack.moo.T3CODisplay.__init__) + * [run\_optimization](#t3co.moopack.moo.run_optimization) +* [t3co.objectives.accel](#t3co.objectives.accel) + * [get\_accel](#t3co.objectives.accel.get_accel) +* [t3co.objectives.fueleconomy](#t3co.objectives.fueleconomy) + * [get\_range\_mi](#t3co.objectives.fueleconomy.get_range_mi) + * [get\_sim\_drive](#t3co.objectives.fueleconomy.get_sim_drive) + * [get\_mpgge](#t3co.objectives.fueleconomy.get_mpgge) +* [t3co.objectives.gradeability](#t3co.objectives.gradeability) + * [get\_gradeability](#t3co.objectives.gradeability.get_gradeability) +* [t3co.objectives](#t3co.objectives) +* [t3co.sweep](#t3co.sweep) + * [deug\_traces](#t3co.sweep.deug_traces) + * [save\_tco\_files](#t3co.sweep.save_tco_files) + * [get\_knobs\_bounds\_curves](#t3co.sweep.get_knobs_bounds_curves) + * [get\_objectives\_constraints](#t3co.sweep.get_objectives_constraints) + * [run\_moo](#t3co.sweep.run_moo) + * [check\_input\_files](#t3co.sweep.check_input_files) + * [run\_vehicle\_scenarios](#t3co.sweep.run_vehicle_scenarios) +* [t3co.run.Global](#t3co.run.Global) + * [DieselGalPerGasGal](#t3co.run.Global.DieselGalPerGasGal) + * [kgH2\_per\_gge](#t3co.run.Global.kgH2_per_gge) + * [mps\_to\_mph](#t3co.run.Global.mps_to_mph) + * [m\_to\_mi](#t3co.run.Global.m_to_mi) + * [get\_kwh\_per\_gge](#t3co.run.Global.get_kwh_per_gge) + * [set\_tco\_intermediates](#t3co.run.Global.set_tco_intermediates) + * [set\_tco\_results](#t3co.run.Global.set_tco_results) + * [kg\_to\_lbs](#t3co.run.Global.kg_to_lbs) + * [lbs\_to\_kgs](#t3co.run.Global.lbs_to_kgs) + * [not\_falsy](#t3co.run.Global.not_falsy) +* [t3co.run](#t3co.run) +* [t3co.run.generateinputs](#t3co.run.generateinputs) + * [generate](#t3co.run.generateinputs.generate) +* [t3co.run.run\_scenario](#t3co.run.run_scenario) + * [Config](#t3co.run.run_scenario.Config) + * [from\_file](#t3co.run.run_scenario.Config.from_file) + * [from\_dict](#t3co.run.run_scenario.Config.from_dict) + * [validate\_analysis\_id](#t3co.run.run_scenario.Config.validate_analysis_id) + * [Scenario](#t3co.run.run_scenario.Scenario) + * [originalcargo\_kg](#t3co.run.run_scenario.Scenario.originalcargo_kg) + * [plf\_scenario\_vehicle\_cargo\_capacity\_kg](#t3co.run.run_scenario.Scenario.plf_scenario_vehicle_cargo_capacity_kg) + * [from\_config](#t3co.run.run_scenario.Scenario.from_config) + * [check\_phev\_init\_socs](#t3co.run.run_scenario.check_phev_init_socs) + * [get\_phev\_util\_factor](#t3co.run.run_scenario.get_phev_util_factor) + * [get\_objective\_simdrive](#t3co.run.run_scenario.get_objective_simdrive) + * [run\_grade\_or\_accel](#t3co.run.run_scenario.run_grade_or_accel) + * [create\_fastsim\_vehicle](#t3co.run.run_scenario.create_fastsim_vehicle) + * [get\_vehicle](#t3co.run.run_scenario.get_vehicle) + * [get\_scenario\_and\_cycle](#t3co.run.run_scenario.get_scenario_and_cycle) + * [load\_scenario](#t3co.run.run_scenario.load_scenario) + * [load\_design\_cycle\_from\_scenario](#t3co.run.run_scenario.load_design_cycle_from_scenario) + * [load\_design\_cycle\_from\_path](#t3co.run.run_scenario.load_design_cycle_from_path) + * [set\_test\_weight](#t3co.run.run_scenario.set_test_weight) + * [reset\_vehicle\_weight](#t3co.run.run_scenario.reset_vehicle_weight) + * [limit\_cargo\_kg\_for\_moo\_hev\_bev](#t3co.run.run_scenario.limit_cargo_kg_for_moo_hev_bev) + * [set\_max\_motor\_kw](#t3co.run.run_scenario.set_max_motor_kw) + * [set\_max\_battery\_kwh](#t3co.run.run_scenario.set_max_battery_kwh) + * [set\_max\_battery\_power\_kw](#t3co.run.run_scenario.set_max_battery_power_kw) + * [set\_max\_fuel\_converter\_kw](#t3co.run.run_scenario.set_max_fuel_converter_kw) + * [set\_fuel\_store\_kwh](#t3co.run.run_scenario.set_fuel_store_kwh) + * [set\_cargo\_kg](#t3co.run.run_scenario.set_cargo_kg) + * [vehicle\_scenario\_sweep](#t3co.run.run_scenario.vehicle_scenario_sweep) + * [run](#t3co.run.run_scenario.run) + * [rerun](#t3co.run.run_scenario.rerun) +* [t3co.demos.opp\_cost\_demo](#t3co.demos.opp_cost_demo) +* [t3co.demos.hev\_sweep\_and\_moo](#t3co.demos.hev_sweep_and_moo) + * [vnum](#t3co.demos.hev_sweep_and_moo.vnum) +* [t3co.demos.example\_load\_and\_run](#t3co.demos.example_load_and_run) +* [t3co.demos.t2co\_opt\_benchmark](#t3co.demos.t2co_opt_benchmark) +* [t3co.demos.Spencer](#t3co.demos.Spencer) + + + +# t3co + + + +# t3co.tco + + + +# t3co.tco.tcocalc + + #### find\_residual\_rates ```python -def find_residual_rates(vehicle, scenario) +def find_residual_rates(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> float ``` This helper method gets the residual rates from ResidualValues.csv @@ -161,12 +163,13 @@ This helper method gets the residual rates from ResidualValues.csv - `residual_rates` _float_ - Residual rate as percentage of MSRP - + #### calculate\_dollar\_cost ```python -def calculate_dollar_cost(veh, scenario) +def calculate_dollar_cost(veh: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> dict ``` This helper method calculates the MSRP breakdown dictionary from @@ -189,12 +192,14 @@ This helper method calculates the MSRP breakdown dictionary from - `cost_set` _dict_ - Dictionary containing MSRP breakdown - + #### calculate\_opp\_costs ```python -def calculate_opp_costs(vehicle, scenario, range_dict) +def calculate_opp_costs(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + range_dict: dict) -> dict ``` This helper method calculates opportunity costs and generates veh_opp_cost_set from @@ -207,13 +212,20 @@ This helper method calculates opportunity costs and generates veh_opp_cost_set f - `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object of current selection - `range_dict` _dict_ - Dictionary containing range values from fueleconomy.get_range_mi() + + +**Returns**: + +- `veh_opp_cost_set` _dict_ - Dictionary containing opportunity cost results - + #### fill\_fuel\_eff\_file ```python -def fill_fuel_eff_file(vehicle, scenario, mpgge_dict) +def fill_fuel_eff_file(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + mpgge_dict: dict) -> pd.DataFrame ``` This helper method generates a dataframe of Fuel Efficiency [mi/gge] @@ -232,12 +244,13 @@ For HEV and CONV, mpgge - `fefdata` _pd.DataFrame_ - Dictionary containing Fuel Efficiency [mi/gge] - + #### fill\_veh\_expense\_file ```python -def fill_veh_expense_file(scenario, cost_set) +def fill_veh_expense_file(scenario: run_scenario.Scenario, + cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe of MSRP breakdown costs as Cost [$/veh] @@ -252,12 +265,13 @@ This helper method generates a dataframe of MSRP breakdown costs as Cost [$/veh] - `vexpdf` _pd.DataFrame_ - Dataframe containing MSRP components costs as Cost [$/veh] - + #### fill\_trav\_exp\_tsv ```python -def fill_trav_exp_tsv(vehicle, scenario) +def fill_trav_exp_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe containing maintenance costs in Cost [$/mi] @@ -272,12 +286,13 @@ This helper method generates a dataframe containing maintenance costs in Cost [$ - `df` _pd.DataFrame_ - Dataframe containing maintenance costs in Cost [$/mi] - + #### fill\_downtimelabor\_cost\_tsv ```python -def fill_downtimelabor_cost_tsv(scenario, oppy_cost_set) +def fill_downtimelabor_cost_tsv(scenario: run_scenario.Scenario, + oppy_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe containing fueling downtime and M&R downtime costs in Cost [$/Yr] @@ -292,12 +307,13 @@ This helper method generates a dataframe containing fueling downtime and M&R dow - `df` _pd.DataFrame_ - Dataframe containing fueling and MR downtime costs in Cost [$/Yr] - + #### fill\_market\_share\_tsv ```python -def fill_market_share_tsv(scenario, num_vs=1) +def fill_market_share_tsv(scenario: run_scenario.Scenario, + num_vs: int = 1) -> pd.DataFrame ``` This helper method generates a dataframe containing market share of current vehicle selection per vehicle sold @@ -312,12 +328,13 @@ This helper method generates a dataframe containing market share of current vehi - `df` _pd.DataFrame_ - Dataframe containing market share of current vehicle in Market Share [veh/veh] - + #### fill\_fuel\_expense\_tsv ```python -def fill_fuel_expense_tsv(vehicle, scenario) +def fill_fuel_expense_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe of fuel operating costs in Cost [$/gge] @@ -330,19 +347,19 @@ This helper method generates a dataframe of fuel operating costs in Cost [$/gge] **Raises**: -- `Exception` - Invalid fuel type +- `Exception` - Invalid fuel_type type **Returns**: - `df` _pd.DataFrame_ - Dataframe containing fuel operating costs in Cost [$/gge] - + #### fill\_annual\_tsv ```python -def fill_annual_tsv(scenario) +def fill_annual_tsv(scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe of annual vehicle miles traveled (vmt) - Annual Travel [mi/yr] @@ -356,12 +373,13 @@ This helper method generates a dataframe of annual vehicle miles traveled (vmt) - `df` _pd.DataFrame_ - Dataframe containing Annual Travel [mi/yr] - + #### fill\_reg\_sales\_tsv ```python -def fill_reg_sales_tsv(scenario, num_vs=1) +def fill_reg_sales_tsv(scenario: run_scenario.Scenario, + num_vs: int = 1) -> pd.DataFrame ``` This helper method generates a dataframe containing vehicle sales per year - Sales [veh] @@ -376,12 +394,13 @@ This helper method generates a dataframe containing vehicle sales per year - Sal - `df` _pd.DataFrame_ - Dataframe containing vehicle sales in Sales [veh] - + #### fill\_insurance\_tsv ```python -def fill_insurance_tsv(scenario, veh_cost_set) +def fill_insurance_tsv(scenario: run_scenario.Scenario, + veh_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe containing vehicle insurance costs as Cost [$/Yr] @@ -396,12 +415,14 @@ This helper method generates a dataframe containing vehicle insurance costs as C - `df` _pd.DataFrame_ - Dataframe containing insurance costs in Cost [$/Yr] - + #### fill\_residual\_cost\_tsc ```python -def fill_residual_cost_tsc(vehicle, scenario, veh_cost_set) +def fill_residual_cost_tsc(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + veh_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe of residual costs as Cost [$/Yr] @@ -417,12 +438,13 @@ This helper method generates a dataframe of residual costs as Cost [$/Yr] - `df` _pd.DataFrame_ - Dataframe containing vehicle residual costs as Cost [$/Yr] - + #### fill\_survival\_tsv ```python -def fill_survival_tsv(scenario, num_vs=1) +def fill_survival_tsv(scenario: run_scenario.Scenario, + num_vs=1) -> pd.DataFrame ``` This helper method generates a dataframe containing surviving vehicles as Surviving Vehicles [veh/veh] @@ -437,12 +459,14 @@ This helper method generates a dataframe containing surviving vehicles as Surviv - `df` _pd.DataFrame_ - Dataframe containing number of surviving vehicles on road in Surviving Vehicles [veh/veh] - + #### fill\_fuel\_split\_tsv ```python -def fill_fuel_split_tsv(vehicle, scenario, mpgge) +def fill_fuel_split_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + mpgge: dict) -> pd.DataFrame ``` This helper method generates a dataframe of fraction of travel in each fuel type as Fraction of Travel [mi/mi] @@ -458,11 +482,11 @@ This helper method generates a dataframe of fraction of travel in each fuel type - `df` _pd.DataFrame_ - Dataframe containing fraction of travel in each fuel type as Fraction of Travel [mi/mi] - + -# ..tco.opportunity\_cost +# t3co.tco.opportunity\_cost - + ## OpportunityCost Objects @@ -475,12 +499,14 @@ This class is used to calculate the different opportunity costs for a scenario a - Fueling Downtime Cost - Maintenance and Repair Downtime Cost - + #### \_\_init\_\_ ```python -def __init__(scenario, range_dict=None, **kwargs) +def __init__(scenario: run_scenario.Scenario, + range_dict: dict = None, + **kwargs) -> None ``` Initializes OpportunityCost object using Scenario object, range_dict (from fueleconomy module), and other arguments @@ -490,12 +516,14 @@ Initializes OpportunityCost object using Scenario object, range_dict (from fuele - `scenario` _run_scenario.Scenario_ - Scenario object - `range_dict` _dict, optional_ - dictionary containing primary_fuel_range_mi from fueleconomy.get_range_mi function. Defaults to None. - + #### set\_kdes ```python -def set_kdes(scenario, bw_method=0.15, verbose=False) +def set_kdes(scenario: run_scenario.Scenario, + bw_method: float = 0.15, + verbose: bool = False) -> None ``` This method sets tje kde kernel. This is time-consuming, only call this once, if possible. @@ -506,15 +534,15 @@ This method sets tje kde kernel. This is time-consuming, only call this once, if - `bw_method` _float, optional_ - kernel bandwidth method used by guassian_kde. Defaults to .15. - `verbose` _bool, optional_ - if True, prints process sets. Defaults to False. - + -#### get\_payload\_loss\_factor +#### set\_payload\_loss\_factor ```python -def get_payload_loss_factor(a_vehicle: fastsim.vehicle, - scenario, - plots=False, - plots_dir=None) +def set_payload_loss_factor(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + plots: bool = False, + plots_dir: str = None) -> None ``` This method runs teh kernel density estimation function set_kdes and calculates the payload capacity loss factor (payload_cap_cost_multiplier) of the new vehicle compared to a conventional vehicle's reference empty weight. @@ -526,12 +554,13 @@ This method runs teh kernel density estimation function set_kdes and calculates - `plots` _bool, optional_ - if True, creates histogram of KDE weight bins. Defaults to False. - `plots_dir` _str, optional_ - output diretory for saving plot figure. Defaults to None. - + -#### get\_dwell\_time\_cost +#### set\_dwell\_time\_cost ```python -def get_dwell_time_cost(a_vehicle: fastsim.vehicle, scenario) +def set_dwell_time_cost(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> None ``` This function calculates the fueling dwell time cost for a vehicle based on fuel fill rate/charging power and shifts_per_year @@ -541,12 +570,13 @@ This function calculates the fueling dwell time cost for a vehicle based on fuel - `a_vehicle` _fastsim.vehicle_ - FASTSim vehicle object of analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object for current selection - + -#### get\_M\_R\_downtime\_cost +#### set\_M\_R\_downtime\_cost ```python -def get_M_R_downtime_cost(a_vehicle: fastsim.vehicle, scenario) +def set_M_R_downtime_cost(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> None ``` This function calculates the Maintenance and Repair (M&R) downtime cost based on planned, unplanned, and tire replacement downtime inputs @@ -556,7 +586,7 @@ This function calculates the Maintenance and Repair (M&R) downtime cost based on - `a_vehicle` _fastsim.vehicle_ - FASTSim object of the analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object for the current selection - + #### main @@ -566,16 +596,16 @@ def main() Runs the opportunity cost module as a standalone code based on input vehicles and scenarios - + -# ..tco.tco\_stock\_emissions +# t3co.tco.tco\_stock\_emissions - + #### dropCols ```python -def dropCols(df) +def dropCols(df: pd.DataFrame) -> pd.DataFrame ``` This helper method drops columns if any row contains ['*'] @@ -589,25 +619,27 @@ This helper method drops columns if any row contains ['*'] - `df` _pd.DataFrame_ - Output dataframe with dropped dummy columns - + #### stockModel ```python -def stockModel(sales, - marketShares, - survival, - annualTravel, - fuelSplit, - fuelEfficiency, - emissions, - vehicleCosts=None, - travelCosts=None, - fuelCosts=None, - insuranceCosts=None, - residualCosts=None, - downtimeCosts=None, - write_files=False) +def stockModel( + sales: pd.DataFrame, + marketShares: pd.DataFrame, + survival: pd.DataFrame, + annualTravel: pd.DataFrame, + fuelSplit: pd.DataFrame, + fuelEfficiency: pd.DataFrame, + emissions: pd.DataFrame, + vehicleCosts: pd.DataFrame = None, + travelCosts: pd.DataFrame = None, + fuelCosts: pd.DataFrame = None, + insuranceCosts: pd.DataFrame = None, + residualCosts: pd.DataFrame = None, + downtimeCosts: pd.DataFrame = None, + write_files: bool = False +) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame] ``` This function generates the ownershipCosts dataframe from the dataframes for each cost category @@ -636,16 +668,17 @@ This function generates the ownershipCosts dataframe from the dataframes for eac - `emissions` _pd.DataFrame_ - Dataframe of total emissions - `ownershipCosts` _pd.DataFrame_ - Dataframe of all ownership costs for given selection - + -# ..tco.tco\_analysis +# t3co.tco.tco\_analysis - + #### get\_operating\_costs ```python -def get_operating_costs(ownershipCosts, TCO_switch="DIRECT") +def get_operating_costs(ownershipCosts, + TCO_switch: str = "DIRECT") -> pd.DataFrame ``` This function creates a dataframe of operating cost from ownershipCosts dataframe based on TCO_switch ('DIRECT' or 'EFFICIENCY') @@ -660,12 +693,13 @@ This function creates a dataframe of operating cost from ownershipCosts datafram - `operatingCosts_df` _pd.DataFrame_ - Dataframe containing operating cost categories based on TCO_switch - + #### discounted\_costs ```python -def discounted_costs(scenario, ownershipCosts) +def discounted_costs(scenario: run_scenario.Scenario, + ownershipCosts: pd.DataFrame) -> pd.DataFrame ``` This function calculates the yearly discounted costs for each category of ownershipCosts based on scenario.discount_rate_pct_per_yr @@ -680,17 +714,17 @@ This function calculates the yearly discounted costs for each category of owners - `ownershipCosts` _pd.DataFrame_ - ownershipCosts dataframe with additional 'Discounted Cost [$]' column - + #### calc\_discountedTCO ```python -def calc_discountedTCO(scenario, - discounted_costs_df, - veh_cost_set, - veh_opp_cost_set, - sim_drive, - TCO_switch="DIRECT") +def calc_discountedTCO(scenario: run_scenario.Scenario, + discounted_costs_df: pd.DataFrame, + veh_cost_set: dict, + veh_opp_cost_set: dict, + sim_drive: fastsim.simdrive.SimDrive, + TCO_switch: str = "DIRECT") -> Tuple[float, dict, dict] ``` This function calculates the discounted Total Cost of Ownerhip (discounted to account for time-value of money). @@ -712,12 +746,29 @@ There are two methods to calculate discounted TCO - 'DIRECT' and 'EFFICIENCY' - `oppy_cost_Dol_set` _dict_ - Dictionary containing discounted opportunity costs breakdown - `veh_oper_cost_set` _dict_ - Dictionary containing discounted operating costs breakdown - + #### get\_tco\_of\_vehicle ```python -def get_tco_of_vehicle(vehicle, range_cyc, scenario, write_tsv=False) +def get_tco_of_vehicle( + vehicle: fastsim.vehicle.Vehicle, + range_cyc: fastsim.cycle.Cycle, + scenario: run_scenario.Scenario, + write_tsv: bool = False +) -> Tuple[ + float, + float, + dict, + pd.DataFrame, + pd.DataFrame, + dict, + dict, + fastsim.simdrive.SimDrive, + dict, + dict, + dict, +] ``` This function calculates the Total Cost of Ownership of a vehicle and scenario for a given cycle. The three main components are: @@ -747,9 +798,9 @@ This function calculates the Total Cost of Ownership of a vehicle and scenario f - `veh_opp_cost_set` _dict_ - Dictionary containing opportunity costs breakdown - `tco_files` _dict_ - Dictionary containing TCO intermediate dataframes - + -# ..tests.test\_tcos +# t3co.tests.test\_tcos Testing module for TCO to ensure the TCO related results remain consistent over time @@ -757,7 +808,7 @@ Flow: code reads TCO tests vehicles and scenarios one at a time. Generates TCO output dictionaries and compares the results with the hard coded dictionaries below in comparison_dict. - + #### remove @@ -767,7 +818,7 @@ def remove(out) removes key-values from output dict that can't be compared very easily - + ## RunCONVTCOTests Objects @@ -775,7 +826,7 @@ removes key-values from output dict that can't be compared very easily class RunCONVTCOTests(unittest.TestCase) ``` - + #### compare @@ -794,15 +845,15 @@ Check all key-value pairs between dicts for equality None - + -# ..tests +# t3co.tests Package for testing modules compliant with unittest folder structure. - + -# ..tests.tco\_tests.t2co\_tco\_benchmark +# t3co.tests.tco\_tests.t2co\_tco\_benchmark Testing module for TCO to ensure the TCO related results remain consistent over time with previous model (Tech Targets c 2019) @@ -811,15 +862,15 @@ Flow: code reads TCO tests vehicles and scenarios one at a time. Generates TCO output dictionaries and compares the results with the hard coded dictionaries below in comparison_dict. - + #### veh\_no - + -# ..tests.tco\_tests.t2co\_bev\_mpgge\_benchmark +# t3co.tests.tco\_tests.t2co\_bev\_mpgge\_benchmark Testing module for TCO to ensure the TCO related results remain consistent over time with previous model (Tech Targets c 2019) @@ -828,31 +879,31 @@ Flow: code reads TCO tests vehicles and scenarios one at a time. Generates TCO output dictionaries and compares the results with the hard coded dictionaries below in comparison_dict. - + #### veh\_no - + -# ..tests.test\_moo +# t3co.tests.test\_moo Module for testing moo. Folder structure, file name, and code are written to be compliant with python's unittest package, but main() can be called via importing - + -# ..moopack +# t3co.moopack Sub-package contaning module that runs PyMOO optimization - + -# ..moopack.moo +# t3co.moopack.moo - + ## T3COProblem Objects @@ -862,7 +913,7 @@ class T3COProblem(ElementwiseProblem) Class for creating PyMoo problem. - + #### setup\_opt\_records @@ -872,19 +923,19 @@ def setup_opt_records() This method sets up the empty optimization record arrays - + #### \_\_init\_\_ ```python -def __init__(knobs_bounds, - vnum, - optimize_pt=gl.BEV, - obj_list=None, - constr_list=None, - verbose=False, - config=None, - **kwargs) +def __init__(knobs_bounds: dict, + vnum: float, + optimize_pt: str = gl.BEV, + obj_list: list = None, + constr_list: list = None, + verbose: bool = False, + config: run_scenario.Config = None, + **kwargs) -> None ``` This constructor initializes optimization input variables @@ -893,35 +944,35 @@ This constructor initializes optimization input variables - `knobs_bounds` _dict_ - Dictionary containing knobs bounds for optimization - `vnum` _float_ - Vehicle selection number -- `optimize_pt` _vehicle.veh_pt_type, optional_ - Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. +- `optimize_pt` _str, optional_ - Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. - `obj_list` _list, optional_ - List of objectives. Defaults to None. - `constr_list` _list, optional_ - List of constraints. Defaults to None. - `verbose` _bool, optional_ - if True, prints process steps. Defaults to False. - `config` _run_scenario.Config, optional_ - T3CO Config object containing analysis attributes and scenario attribute overrides. Defaults to None. - + #### compile\_reporting\_vars ```python -def compile_reporting_vars() +def compile_reporting_vars() -> None ``` This method creates an output dictionary containing optimization results - + #### instantiate\_moo\_vehicles\_and\_scenario ```python -def instantiate_moo_vehicles_and_scenario(vnum, config=None) +def instantiate_moo_vehicles_and_scenario(vnum: int, config=None) -> None ``` This method instantiates the multi-objective optimization problem vehicles and scenarios, starting with the baseline Conventional vehicle. **Arguments**: -- `vnum` _float_ - vehicle selection number +- `vnum` _int_ - vehicle selection number - `config` _run_scenario.Config, optional_ - T3CO Config object containing analysis attributes and scenario attribute overrides. Defaults to None. @@ -929,12 +980,13 @@ This method instantiates the multi-objective optimization problem vehicles and s - `TypeError` - Invalid optimize_pt selection - + #### cda\_percent\_delta\_knob ```python -def cda_percent_delta_knob(CdA_perc_reduction, optvehicle) +def cda_percent_delta_knob(CdA_perc_reduction: str, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the drag_coef based on aero improvement curve and glider_kg based on cda_cost_coeff_a and cda_cost_coeff_b @@ -944,12 +996,13 @@ This method sets the drag_coef based on aero improvement curve and glider_kg bas - `CdA_perc_reduction` _str_ - Name of aero improvement curve file - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object for optimization vehicle - + #### weight\_delta\_percent\_knob ```python -def weight_delta_percent_knob(wt_perc_reduction, optvehicle) +def weight_delta_percent_knob(wt_perc_reduction: float, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the knob from the lightweighting curve @@ -959,12 +1012,13 @@ This method sets the knob from the lightweighting curve - `wt_perc_reduction` _float_ - Weight reduction percentage value from lightweighting curve - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of the optimization vehicle - + #### fc\_peak\_eff\_knob ```python -def fc_peak_eff_knob(fc_peak_eff, optvehicle) +def fc_peak_eff_knob(fc_peak_eff: float, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the knob from the engine efficiency curve @@ -974,12 +1028,13 @@ This method sets the knob from the engine efficiency curve - `fc_peak_eff` _float_ - Fuel converter peak effiency override from engine efficiency improvement curve - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object for optimization vehicle - + #### get\_objs ```python -def get_objs(x, write_tsv=False) +def get_objs(x: dict, + write_tsv: bool = False) -> Tuple[np.array, np.array, dict] ``` This method gets called when PyMoo calls _evaluate. It initializes objectives and constraints and runs vehicle_scenario_sweep @@ -1003,12 +1058,13 @@ chromosome is a full gene, all values in x - `constraint_results_G` _np.array_ - Array of constraints - `rs_sweep` _dict_ - Output dictionary from vehicle_scenario_sweep - + #### adjust\_fc\_peak\_eff ```python -def adjust_fc_peak_eff(fc_peak_eff, scenario, optvehicle) +def adjust_fc_peak_eff(fc_peak_eff: float, scenario: run_scenario.Scenario, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method augments an advanced vehicle fc_eff_array based on new fc_peak_eff using baseline fc_eff_array @@ -1020,12 +1076,16 @@ This method augments an advanced vehicle fc_eff_array based on new fc_peak_eff u - `scenario` _run_scenario.Scenario_ - Scenario object of current selection - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of optimization vehicle - + #### sweep\_knob ```python -def sweep_knob(knob, definition=100, plot=False, optres=None, **kwargs) +def sweep_knob(knob: list, + definition: int = 100, + plot: bool = False, + optres: float = None, + **kwargs) -> list ``` This method sweeps the optimization knob of vehicle from lbound to ubound, return TCO plot optres to see if there's agreement from opt solution and your sweep @@ -1042,12 +1102,12 @@ This method sweeps the optimization knob of vehicle from lbound to ubound, retur - `tcos` _list_ - List of TCOs of length=definition - + #### get\_tco\_from\_moo\_advanced\_result ```python -def get_tco_from_moo_advanced_result(x) +def get_tco_from_moo_advanced_result(x: dict) -> dict ``` This method is a utility function to get detailed TCO information from optimized MOO result @@ -1061,7 +1121,7 @@ This method is a utility function to get detailed TCO information from optimized - `out` _dict_ - Dictionary containing TCO results for optimization runs - + ## T3CODisplay Objects @@ -1075,33 +1135,34 @@ This class contains the display object for Pymoo optimization printouts - pymoo. - `Output` _pymoo.util.display.output.Output_ - Pymoo minimize display object - + #### \_\_init\_\_ ```python -def __init__(**kwargs) +def __init__(**kwargs) -> None ``` This constructor initializes the pymoo.util.display.Display object - + #### run\_optimization ```python -def run_optimization(pop_size, - n_max_gen, - knobs_bounds, - vnum, - x_tol, - f_tol, - nth_gen, - n_last, - algo, - obj_list=None, - config=None, - **kwargs) +def run_optimization( + pop_size: int, + n_max_gen: int, + knobs_bounds: dict, + vnum: int, + x_tol: float, + f_tol: float, + nth_gen: int, + n_last: int, + algo: str, + obj_list: list = None, + config: run_scenario.Config = None, + **kwargs) -> Tuple[pymoo.core.result.Result, T3COProblem, bool] ``` This method creates and runs T3COProblem minimization @@ -1111,7 +1172,7 @@ This method creates and runs T3COProblem minimization - `pop_size` _int_ - Population size for optimization - `n_max_gen` _int_ - maximum number of generations for optimization - `knobs_bounds` _dict_ - Dictionary containing knobs and bounds -- `vnum` _float_ - vehicle selection number +- `vnum` _int_ - vehicle selection number - `x_tol` _float_ - tolerance in parameter space - `f_tol` _float_ - tolerance in objective space - `nth_gen` _int_ - number of generations to evaluate if convergence occurs @@ -1127,22 +1188,23 @@ This method creates and runs T3COProblem minimization - `problem` _moo.T3COProblem_ - T3COProblem ElementwiseProblem object - `OPTIMIZATION_SUCCEEDED` _bool_ - if True, pymoo.minimize succeeded - + -# ..objectives.accel +# t3co.objectives.accel Module for simulating acceleration performance. - + #### get\_accel ```python -def get_accel(analysis_vehicle, - scenario=None, - set_weight_to_max_kg=True, - verbose=False, - ess_init_soc=None) +def get_accel( + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario = None, + set_weight_to_max_kg: bool = True, + verbose=False, + ess_init_soc=None) -> Tuple[float, float, fastsim.vehicle.Vehicle] ``` This function runs a simdrive for getting 0-to-60 and 0-30 mph time with fully laden weight at GVWR (plus gvwr_credit_kg?) @@ -1163,19 +1225,19 @@ This function runs a simdrive for getting 0-to-60 and 0-30 mph time with fully l - `zero_to_thirty` _float_ - 0-30 mph acceleration time in sec - `accel_simdrive` _fastsim.simdrive.SimDrive_ - FASTSim.simdrive.SimDrive object for running the acceleration drivecycle - + -# ..objectives.fueleconomy +# t3co.objectives.fueleconomy Module containing functions for calculating fuel economy objectives. - + #### get\_range\_mi ```python def get_range_mi(mpgge_info: dict, vehicle: fastsim.vehicle.Vehicle, - scenario) -> dict + scenario: run_scenario.Scenario) -> dict ``` This funcion computes range [miles] from mpgge using vehicle powertrain type and energy (or fuel) store size. @@ -1201,7 +1263,7 @@ i.e. the CD range that PHEVs are commonly specified with - `range_dict` _dict_ - Dictionary containing different range results - + #### get\_sim\_drive @@ -1222,16 +1284,18 @@ This helper method returns a FASTSim SimDrive object using the vehicle, drive cy - `sim_drive` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive object - + #### get\_mpgge ```python -def get_mpgge(eff_range_cyc: fastsim.cycle.Cycle - | List[Tuple[fastsim.cycle.Cycle, float]], - v: fastsim.vehicle.Vehicle, - scenario, - diagnostic=False) +def get_mpgge( + eff_range_cyc: fastsim.cycle.Cycle + | List[Tuple[fastsim.cycle.Cycle, float]], + v: fastsim.vehicle.Vehicle, + scenario, + diagnostic=False +) -> Tuple[dict, List[fastsim.simdrive.SimDrive], List[dict]] ``` This helper method gets the composite mpgge fuel efficiency of vehicle for each efficiency_range Drive Cycle and weight. @@ -1262,20 +1326,22 @@ Also updates the vehicle's corresponding scenario object - `sim_drives` _List[fastsim.simdrive.SimDrive]_ - List of simdrives for charge depleting and charge sustaining cycles - `mpgges` _List[dict], optional_ - if diagnostic==True, returns additional - + -# ..objectives.gradeability +# t3co.objectives.gradeability - + #### get\_gradeability ```python -def get_gradeability(analysis_vehicle, - scenario=None, - verbose=False, - ess_init_soc=None, - set_weight_to_max_kg=True) +def get_gradeability( + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario = None, + verbose: bool = False, + ess_init_soc: float = None, + set_weight_to_max_kg: bool = True +) -> Tuple[float, float, fastsim.simdrive.SimDrive, fastsim.simdrive.SimDrive] ``` This function runs SimDrives to determine the gradeability at given speed and the grade vehicle is @@ -1297,22 +1363,41 @@ evaluated at how much it meets or exceeds target speed at the target grade. - `grade_6_simdrive` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive for gradeability test of 6% grade - `grade_125_simdrive` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive for gradeability test of 1.25% grade - + -# ..objectives +# t3co.objectives Sub-package contaning modules that calculate optimization objectives. - + + +# t3co.sweep + + + +#### deug\_traces + +```python +def deug_traces(vehicle: fastsim.vehicle.Vehicle, + cycles: List[fastsim.cycle.Cycle], + scenario: run_scenario.Scenario) -> None +``` + +This function gets a diagnostic trace of get_mpgge + +**Arguments**: -# ..sweep +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim Vehicle object +- `cycles` _List[fastsim.cycle.Cycle]_ - List of FASTSim drivecycle objects +- `scenario` _run_scenario.Scenario_ - Scenario object - + #### save\_tco\_files ```python -def save_tco_files(tco_files, resdir, scenario_name, sel, ts) +def save_tco_files(tco_files: dict, resdir: str, scenario_name: str, sel: str, + ts: str) -> None ``` This function saves the intermediary files as tsv @@ -1325,25 +1410,27 @@ This function saves the intermediary files as tsv - `sel` _str_ - selection(s) - `ts` _str_ - timestring - + #### get\_knobs\_bounds\_curves ```python -def get_knobs_bounds_curves(selection, vpttype, sdf, lw_imp_curves, aero_drag_imp_curves, - eng_eff_curves) +def get_knobs_bounds_curves(selection: int, vpttype: str, sdf: pd.DataFrame, + lw_imp_curves: pd.DataFrame, + aero_drag_imp_curves: pd.DataFrame, + eng_eff_curves: pd.DataFrame) -> Tuple[dict, dict] ``` This function fetches the knobs and constraints for running the optimization for a given selection **Arguments**: -- `selection` _float_ - selection number +- `selection` _int_ - selection number - `vpttype` _str_ - vehicle powertrain type = veh_pt_type -- `sdf` _DataFrame_ - scenario dataframe -- `lw_imp_curves` _DataFrame_ - light weighting curve dataframe -- `aero_drag_imp_curves` _DataFrame_ - aero drag curve dataframe -- `eng_eff_curves` _DataFrame_ - engine efficiency curve dataframe +- `sdf` _pd.DataFrame_ - scenario dataframe +- `lw_imp_curves` _pd.DataFrame_ - light weighting curve dataframe +- `aero_drag_imp_curves` _pd.DataFrame_ - aero drag curve dataframe +- `eng_eff_curves` _pd.DataFrame_ - engine efficiency curve dataframe **Returns**: @@ -1351,19 +1438,21 @@ This function fetches the knobs and constraints for running the optimization for - `knobs_bounds` _dict_ - dict of knobs and bounds - `curves` _dict_ - dict of lw, aero, and engine efficiency curve parameters - + #### get\_objectives\_constraints ```python -def get_objectives_constraints(selection, sdf, verbose=True) +def get_objectives_constraints(selection: int, + sdf: pd.DataFrame, + verbose: bool = True) -> Tuple[list, list] ``` This function appends to list of necessary variables based on the constraints and objectives selected **Arguments**: -- `selection` _float_ - selection number +- `selection` _int_ - selection number - `sdf` _DataFrame_ - scenario dataframe - `verbose` _bool, optional_ - if selected, function will print objectives and constraints. Defaults to True. @@ -1373,21 +1462,25 @@ This function appends to list of necessary variables based on the constraints an - `objectives` _list_ - list of selected objective variables - `constraints` _list_ - list of selected constraint variables - + #### run\_moo ```python -def run_moo(sel, sdf, optpt, algo, skip_opt, pop_size, n_max_gen, n_last, - nth_gen, x_tol, verbose, f_tol, resdir, lw_imp_curves, aero_drag_imp_curves, - eng_eff_imp_curves, config, **kwargs) +def run_moo( + sel: int, sdf: pd.DataFrame, optpt: str, algo: str, skip_opt: bool, + pop_size: float, n_max_gen: int, n_last: int, nth_gen: int, + x_tol: float, verbose: bool, f_tol: float, resdir: str, + lw_imp_curves: pd.DataFrame, aero_drag_imp_curves: pd.DataFrame, + eng_eff_imp_curves: pd.DataFrame, config: run_scenario.Scenario, + **kwargs) -> Tuple[pymoo.core.result.Result, moo.T3COProblem, bool] ``` This function calls get_objectives_constraints and get_knobs_bounds_curves, and then calls run_optimization to perform the multiobjective optimization **Arguments**: -- `sel` _float_ - selection number +- `sel` _int_ - selection number - `sdf` _DataFrame_ - scenario dataframe - `optpt` _str_ - vehicle powertrain type - `algo` _str_ - algorithm name @@ -1410,14 +1503,14 @@ This function calls get_objectives_constraints and get_knobs_bounds_curves, and - `moo_results` _pymoo.core.result.Result_ - optimization results object - `moo_problem` _T3COProblem_ - minimization problem that calculates TCO -- `moo_code` _Error_ - Error message +- `moo_code` _bool_ - Error message - + #### check\_input\_files ```python -def check_input_files(df, filetype, filepath) +def check_input_files(df: pd.DataFrame, filetype: str, filepath: str) -> None ``` This function contains assert statements that make sure input vehicle and scenario dataframes do not contain numm rows @@ -1428,13 +1521,15 @@ This function contains assert statements that make sure input vehicle and scenar - `filetype` _str_ - 'vehicle' or 'scenario' - `filepath` _str_ - filepath of the vehicle or scenario input files - + #### run\_vehicle\_scenarios ```python -def run_vehicle_scenarios(vehicles, scenarios, eng_eff_imp_curves_p, lw_imp_curves_p, - aero_drag_imp_curves_p, config, **kwargs) +def run_vehicle_scenarios(vehicles: str, scenarios: str, + eng_eff_imp_curves_p: str, lw_imp_curves_p: str, + aero_drag_imp_curves_p: str, + config: run_scenario.Config, **kwargs) -> None ``` This is the main function that runs T3CO for all the selections input @@ -1454,38 +1549,38 @@ This is the main function that runs T3CO for all the selections input - `Exception` - input validation error - `Exception` - optimization error - + -# ..run.Global +# t3co.run.Global Global constants Stores paths to directories used for input files, as well as constants referenced throughout the code base - + #### DieselGalPerGasGal energy equivalent gallons of diesel per 1 gallon gas - + #### kgH2\_per\_gge https://epact.energy.gov/fuel-conversion-factors for Hydrogen - + #### mps\_to\_mph 1 mps = 2.23694 mph - + #### m\_to\_mi 1 m = 0.000621371 mi - + #### get\_kwh\_per\_gge @@ -1500,7 +1595,7 @@ important to get from one location each time so we can track when and how it's u - `kwh_per_gge` _float_ - kWh per Gasoline Gallon Equivalent - + #### set\_tco\_intermediates @@ -1510,7 +1605,7 @@ def set_tco_intermediates() This function sets path for TCO_INTERMEDIATES to save tsv files - + #### set\_tco\_results @@ -1520,12 +1615,12 @@ def set_tco_results() This function sets path for TCO_RESULTS - + #### kg\_to\_lbs ```python -def kg_to_lbs(kgs) +def kg_to_lbs(kgs: float) -> float ``` This function converts kg to lb @@ -1539,12 +1634,12 @@ This function converts kg to lb - `(float)` - mass in pounds - + #### lbs\_to\_kgs ```python -def lbs_to_kgs(lbs) +def lbs_to_kgs(lbs: float) -> float ``` This function converts lb to kg @@ -1558,12 +1653,12 @@ This function converts lb to kg - `(float)` - mass in kg - + #### not\_falsy ```python -def not_falsy(var) +def not_falsy(var: float) -> bool ``` This function returns True to verify that var is NOT falsy: not in [None, np.nan, 0, False] @@ -1578,20 +1673,20 @@ This function returns True to verify that var is NOT falsy: not in [None, np.nan - `(bool)` - True if not in [None, 0, False] - + -# ..run +# t3co.run - + -# ..run.generateinputs +# t3co.run.generateinputs - + #### generate ```python -def generate(vocation, dst=gl.OPTIMIZATION_AND_TCO_RCRS) +def generate(vocation: str, dst: str = gl.OPTIMIZATION_AND_TCO_RCRS) ``` This function aggregates specifications from users for powertrains, desired ranges, component costs etc. into two @@ -1602,148 +1697,13 @@ csv files - FASTSimInputs and OtherInputs - `vocation` _str_ - Vocation type description - `dst` _str, optional_ - results directory file path. Defaults to gl.OPTIMIZATION_AND_TCO_RCRS. - + -# ..run.run\_scenario +# t3co.run.run\_scenario Module for loading vehicles, scenarios, running them and managing them - - -#### set\_test\_weight - -```python -def set_test_weight(vehicle, scenario) -``` - -assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit - -**Arguments**: - -- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object - - - -#### reset\_vehicle\_weight - -```python -def reset_vehicle_weight(vehicle) -``` - -This function resets vehicle mass after loaded weight tests are done for accel and grade - -**Arguments**: - -- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - - - -#### limit\_cargo\_kg\_for\_moo\_hev\_bev - -```python -def limit_cargo_kg_for_moo_hev_bev(opt_scenario, mooadvancedvehicle) -``` - -This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles - -**Arguments**: - -- `opt_scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object -- `mooadvancedvehicle` _fastsim.vehicle.Vehicle_ - pymoo optimization vehicle - - - -#### set\_max\_motor\_kw - -```python -def set_max_motor_kw(analysis_vehicle, scenario, max_motor_kw) -``` - -This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `scenario` _t3co.run_scenario.Scenario_ - T3CO Scenarion object -- `max_motor_kw` _float_ - max motor power /kW - - - -#### set\_max\_battery\_kwh - -```python -def set_max_battery_kwh(analysis_vehicle, max_ess_kwh) -``` - -This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `max_ess_kwh` _float_ - max energy storage system energy capacity /kWh - - - -#### set\_max\_battery\_power\_kw - -```python -def set_max_battery_power_kw(analysis_vehicle, max_ess_kw) -``` - -This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `max_ess_kw` _float_ - max energy storage system power /kW - - - -#### set\_max\_fuel\_converter\_kw - -```python -def set_max_fuel_converter_kw(analysis_vehicle, fc_max_out_kw) -``` - -This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `fc_max_out_kw` _float_ - max fuel converter power /kW - - - -#### set\_fuel\_store\_kwh - -```python -def set_fuel_store_kwh(analysis_vehicle, fs_kwh) -``` - -This helper method is used within T3COProblem to set fs_kwh to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `fs_kwh` _float_ - fuel storage energy capacity /kWh - - - -#### set\_cargo\_kg - -```python -def set_cargo_kg(analysis_vehicle, cargo_kg) -``` - -This helper method is used within T3COProblem to set cargo_kg to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `cargo_kg` _float_ - vehicle cargo capacity /kg - - + ## Config Objects @@ -1754,7 +1714,7 @@ class Config() New class to read T3COConfig file containing analysis attributes like vehicle and scenario paths, and scenario attribute overrides - + #### from\_file @@ -1774,7 +1734,7 @@ This method generates a Config dictionary from CSV file and calls Config.from_di - `Self.from_dict` - method that gets Config instance from config_dict - + #### from\_dict @@ -1793,12 +1753,12 @@ This method generates a Config instance from config_dict - `Self` - Config instance containining all values from T3CO Config CSV file - + #### validate\_analysis\_id ```python -def validate_analysis_id(filename: str, analysis_id: int = 0) +def validate_analysis_id(filename: str, analysis_id: int = 0) -> Self ``` This method validates that correct analysis id is input @@ -1812,7 +1772,7 @@ This method validates that correct analysis id is input - `Exception` - Error if analysis_id not found - + ## Scenario Objects @@ -1823,24 +1783,24 @@ class Scenario() Class object that contains all TCO parameters and performance target (range, grade, accel) information for a vehicle such that performance and TCO can be computed during optimization - + #### originalcargo\_kg if needed, should be assigned immediately after vehicle read in - + #### plf\_scenario\_vehicle\_cargo\_capacity\_kg includes cargo credit kg - + #### from\_config ```python -def from_config(config: Config = None) +def from_config(config: Config = None) -> Self ``` This method overrides certain scenario fields if use_config is True and config object is not None @@ -1849,12 +1809,13 @@ This method overrides certain scenario fields if use_config is True and config o - `config` _Config, optional_ - Config object. Defaults to None. - + #### check\_phev\_init\_socs ```python -def check_phev_init_socs(a_vehicle: vehicle.Vehicle, scenario: Scenario) +def check_phev_init_socs(a_vehicle: vehicle.Vehicle, + scenario: Scenario) -> None ``` This function checks that soc_norm_init_for_grade_pct and soc_norm_init_for_accel_pct are present only for PHEVs @@ -1864,12 +1825,13 @@ This function checks that soc_norm_init_for_grade_pct and soc_norm_init_for_acce - `a_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - `scenario` _Scenario_ - T3CO scenario object - + #### get\_phev\_util\_factor ```python -def get_phev_util_factor(scenario, v, mpgge) +def get_phev_util_factor(scenario: Scenario, v: fastsim.vehicle.Vehicle, + mpgge: dict) -> float ``` This function gets the PHEV utility factor derived from the computed range of the @@ -1878,7 +1840,7 @@ vehicle and the operational day range computed from shifts per year and the firs **Arguments**: - `scenario` _Scenario_ - T3CO scenario object -- `v` _fastsim.Vehicle.vehicle_ - FASTSim vehicle object +- `v` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - `mpgge` _dict_ - Miles per Gallon Gasoline Equivalent dictionary @@ -1886,12 +1848,14 @@ vehicle and the operational day range computed from shifts per year and the firs - `uf` _float_ - PHEV computed utility factor - + #### get\_objective\_simdrive ```python -def get_objective_simdrive(analysis_vehicle: vehicle.Vehicle, cycle) +def get_objective_simdrive( + analysis_vehicle: vehicle.Vehicle, + cycle: fastsim.cycle.Cycle) -> fastsim.simdrive.SimDrive ``` This function obtains the SimDrive for accel and grade test @@ -1906,12 +1870,14 @@ This function obtains the SimDrive for accel and grade test - `sd` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive object containing vehicle inputs and simulation output attributes - + #### run\_grade\_or\_accel ```python -def run_grade_or_accel(test, analysis_vehicle, sim_drive, ess_init_soc) +def run_grade_or_accel(test: str, analysis_vehicle: fastsim.vehicle.Vehicle, + sim_drive: fastsim.simdrive.SimDrive, + ess_init_soc: float) -> None ``` This function handles initial SOC considerations for grade and accel tests @@ -1936,12 +1902,12 @@ HEVs attempt SOC balancing but that is overrident by HEV test init SOC - `Exception` - if test not in ['accel', 'grade'] - + #### create\_fastsim\_vehicle ```python -def create_fastsim_vehicle(veh_dict=None) +def create_fastsim_vehicle(veh_dict: dict = None) -> fastsim.vehicle.Vehicle ``` This function creates and returns an empty FASTSim vehicle object with no attributes or @@ -1955,12 +1921,12 @@ This function creates and returns an empty FASTSim vehicle object with no attrib - `v` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - + #### get\_vehicle ```python -def get_vehicle(veh_no, veh_input_path) +def get_vehicle(veh_no: int, veh_input_path: str) -> fastsim.vehicle.Vehicle ``` This function loads vehicle object from vehicle number and input csv filepath @@ -1975,15 +1941,16 @@ This function loads vehicle object from vehicle number and input csv filepath - `veh` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - + #### get\_scenario\_and\_cycle ```python -def get_scenario_and_cycle(veh_no, - scenario_inputs_path, - a_vehicle=None, - config=None) +def get_scenario_and_cycle( + veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None) -> Tuple[Scenario, fastsim.cycle.Cycle] ``` This function uses helper methods load_scenario and load_design_cycle_from_scenario to get scenario object and cycle object corresponding to selected vehicle (by veh_no) @@ -2001,12 +1968,15 @@ This function uses helper methods load_scenario and load_design_cycle_from_scena - `scenario` _Scenario_ - T3CO scenario object selected - `cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object selected - + #### load\_scenario ```python -def load_scenario(veh_no, scenario_inputs_path, a_vehicle=None, config=None) +def load_scenario(veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None) -> Scenario ``` This function gets the Scenario object from scenario input CSV filepath, initializes some fields, and overrides some fields based on Config object @@ -2023,14 +1993,15 @@ This function gets the Scenario object from scenario input CSV filepath, initial - `scenario` _Scenario_ - Scenario object for given selection - + #### load\_design\_cycle\_from\_scenario ```python -def load_design_cycle_from_scenario(scenario, - cyc_file_path=gl.OPTIMIZATION_DRIVE_CYCLES - ) +def load_design_cycle_from_scenario( + scenario: Scenario, + cyc_file_path: str = gl.OPTIMIZATION_DRIVE_CYCLES +) -> fastsim.cycle.Cycle ``` This helper method loads the design cycle used for mpgge and range determination. @@ -2048,12 +2019,12 @@ If the drive cycles are a list of tuples, handle accordingly with eval. - `range_cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object for current Scenario object - + #### load\_design\_cycle\_from\_path ```python -def load_design_cycle_from_path(cyc_file_path) +def load_design_cycle_from_path(cyc_file_path: str) -> fastsim.cycle.Cycle ``` This helper method loads the Cycle object from the drivecycle filepath @@ -2067,13 +2038,156 @@ This helper method loads the Cycle object from the drivecycle filepath - `range_cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object for current Scenario object - + + +#### set\_test\_weight + +```python +def set_test_weight(vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario) -> None +``` + +assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit + +**Arguments**: + +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object + + + +#### reset\_vehicle\_weight + +```python +def reset_vehicle_weight(vehicle: fastsim.vehicle.Vehicle) -> None +``` + +This function resets vehicle mass after loaded weight tests are done for accel and grade + +**Arguments**: + +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object + + + +#### limit\_cargo\_kg\_for\_moo\_hev\_bev + +```python +def limit_cargo_kg_for_moo_hev_bev( + opt_scenario: Scenario, + mooadvancedvehicle: fastsim.vehicle.Vehicle) -> None +``` + +This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles + +**Arguments**: + +- `opt_scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object +- `mooadvancedvehicle` _fastsim.vehicle.Vehicle_ - pymoo optimization vehicle + + + +#### set\_max\_motor\_kw + +```python +def set_max_motor_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario, max_motor_kw: float) -> None +``` + +This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `scenario` _t3co.run_scenario.Scenario_ - T3CO Scenarion object +- `max_motor_kw` _float_ - max motor power /kW + + + +#### set\_max\_battery\_kwh + +```python +def set_max_battery_kwh(analysis_vehicle: fastsim.vehicle.Vehicle, + max_ess_kwh: float) -> None +``` + +This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `max_ess_kwh` _float_ - max energy storage system energy capacity /kWh + + + +#### set\_max\_battery\_power\_kw + +```python +def set_max_battery_power_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + max_ess_kw: float) -> None +``` + +This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `max_ess_kw` _float_ - max energy storage system power /kW + + + +#### set\_max\_fuel\_converter\_kw + +```python +def set_max_fuel_converter_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + fc_max_out_kw: float) -> None +``` + +This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `fc_max_out_kw` _float_ - max fuel converter power /kW + + + +#### set\_fuel\_store\_kwh + +```python +def set_fuel_store_kwh(analysis_vehicle: fastsim.vehicle.Vehicle, + fs_kwh: float) -> None +``` + +This helper method is used within T3COProblem to set fs_kwh to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `fs_kwh` _float_ - fuel storage energy capacity /kWh + + + +#### set\_cargo\_kg + +```python +def set_cargo_kg(analysis_vehicle: fastsim.vehicle.Vehicle, cargo_kg) +``` + +This helper method is used within T3COProblem to set cargo_kg to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `cargo_kg` _float_ - vehicle cargo capacity /kg + + #### vehicle\_scenario\_sweep ```python -def vehicle_scenario_sweep(vehicle, - scenario, +def vehicle_scenario_sweep(vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario, range_cyc, verbose=False, **kwargs) @@ -2093,15 +2207,15 @@ This function contains helper methods such as get_tco_of_vehicle, check_phev_ini - `out` _dict_ - output dictionary containing TCO elements - + #### run ```python -def run(veh_no, - vocation="blank", - vehicle_input_path=gl.FASTSIM_INPUTS, - scenario_inputs_path=gl.OTHER_INPUTS) +def run(veh_no: int, + vocation: str = "blank", + vehicle_input_path: str = gl.FASTSIM_INPUTS, + scenario_inputs_path: str = gl.OTHER_INPUTS) ``` This function runs vehicle_scenario_sweep based on vehicle and scenario objects read from input file paths @@ -2118,12 +2232,12 @@ This function runs vehicle_scenario_sweep based on vehicle and scenario objects - `out` _dict_ - output dictionary containing TCO results - + #### rerun ```python -def rerun(vehicle, vocation, scenario) +def rerun(vehicle: fastsim.vehicle.Vehicle, vocation: str, scenario: Scenario) ``` This function runs vehicle_scenario_sweep when given the vehicle and scenario objects @@ -2139,23 +2253,23 @@ This function runs vehicle_scenario_sweep when given the vehicle and scenario ob - `out` _dict_ - output dictionary containing TCO outputs - + -# ..demos.opp\_cost\_demo +# t3co.demos.opp\_cost\_demo - + -# ..demos.hev\_sweep\_and\_moo +# t3co.demos.hev\_sweep\_and\_moo - + #### vnum - + -# ..demos.example\_load\_and\_run +# t3co.demos.example\_load\_and\_run To run this as a script that drives all the t3co files as a module: The working directory for this script should be at the same depth as the t3co/ module. @@ -2228,11 +2342,11 @@ scenario_inputs_path=gl.OTHER_INPUTS, >>> res1 = run_scenario.run(1, 'Class8_long_haul', use_jit=use_jit) >>> print(f'classic time [s] {time.time()-start} | use jit? {use_jit}') - + -# ..demos.t2co\_opt\_benchmark +# t3co.demos.t2co\_opt\_benchmark - + -# ..demos.Spencer +# t3co.demos.Spencer diff --git a/docs/functions/Global.md b/docs/functions/Global.md index 19cd309..9a8ea9e 100644 --- a/docs/functions/Global.md +++ b/docs/functions/Global.md @@ -1,49 +1,49 @@ # Table of Contents -* [run.Global](#run.Global) - * [DieselGalPerGasGal](#run.Global.DieselGalPerGasGal) - * [kgH2\_per\_gge](#run.Global.kgH2_per_gge) - * [mps\_to\_mph](#run.Global.mps_to_mph) - * [m\_to\_mi](#run.Global.m_to_mi) - * [get\_kwh\_per\_gge](#run.Global.get_kwh_per_gge) - * [set\_tco\_intermediates](#run.Global.set_tco_intermediates) - * [set\_tco\_results](#run.Global.set_tco_results) - * [kg\_to\_lbs](#run.Global.kg_to_lbs) - * [lbs\_to\_kgs](#run.Global.lbs_to_kgs) - * [not\_falsy](#run.Global.not_falsy) - - - -# run.Global +* [t3co/run/Global](#t3co/run/Global) + * [DieselGalPerGasGal](#t3co/run/Global.DieselGalPerGasGal) + * [kgH2\_per\_gge](#t3co/run/Global.kgH2_per_gge) + * [mps\_to\_mph](#t3co/run/Global.mps_to_mph) + * [m\_to\_mi](#t3co/run/Global.m_to_mi) + * [get\_kwh\_per\_gge](#t3co/run/Global.get_kwh_per_gge) + * [set\_tco\_intermediates](#t3co/run/Global.set_tco_intermediates) + * [set\_tco\_results](#t3co/run/Global.set_tco_results) + * [kg\_to\_lbs](#t3co/run/Global.kg_to_lbs) + * [lbs\_to\_kgs](#t3co/run/Global.lbs_to_kgs) + * [not\_falsy](#t3co/run/Global.not_falsy) + + + +# t3co/run/Global Global constants Stores paths to directories used for input files, as well as constants referenced throughout the code base - + #### DieselGalPerGasGal energy equivalent gallons of diesel per 1 gallon gas - + #### kgH2\_per\_gge https://epact.energy.gov/fuel-conversion-factors for Hydrogen - + #### mps\_to\_mph 1 mps = 2.23694 mph - + #### m\_to\_mi 1 m = 0.000621371 mi - + #### get\_kwh\_per\_gge @@ -58,7 +58,7 @@ important to get from one location each time so we can track when and how it's u - `kwh_per_gge` _float_ - kWh per Gasoline Gallon Equivalent - + #### set\_tco\_intermediates @@ -68,7 +68,7 @@ def set_tco_intermediates() This function sets path for TCO_INTERMEDIATES to save tsv files - + #### set\_tco\_results @@ -78,12 +78,12 @@ def set_tco_results() This function sets path for TCO_RESULTS - + #### kg\_to\_lbs ```python -def kg_to_lbs(kgs) +def kg_to_lbs(kgs: float) -> float ``` This function converts kg to lb @@ -97,12 +97,12 @@ This function converts kg to lb - `(float)` - mass in pounds - + #### lbs\_to\_kgs ```python -def lbs_to_kgs(lbs) +def lbs_to_kgs(lbs: float) -> float ``` This function converts lb to kg @@ -116,12 +116,12 @@ This function converts lb to kg - `(float)` - mass in kg - + #### not\_falsy ```python -def not_falsy(var) +def not_falsy(var: float) -> bool ``` This function returns True to verify that var is NOT falsy: not in [None, np.nan, 0, False] diff --git a/docs/functions/accel.md b/docs/functions/accel.md index 6213d87..70f7435 100644 --- a/docs/functions/accel.md +++ b/docs/functions/accel.md @@ -1,24 +1,25 @@ # Table of Contents -* [objectives.accel](#objectives.accel) - * [get\_accel](#objectives.accel.get_accel) +* [t3co/objectives/accel](#t3co/objectives/accel) + * [get\_accel](#t3co/objectives/accel.get_accel) - + -# objectives.accel +# t3co/objectives/accel Module for simulating acceleration performance. - + #### get\_accel ```python -def get_accel(analysis_vehicle, - scenario=None, - set_weight_to_max_kg=True, - verbose=False, - ess_init_soc=None) +def get_accel( + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario = None, + set_weight_to_max_kg: bool = True, + verbose=False, + ess_init_soc=None) -> Tuple[float, float, fastsim.vehicle.Vehicle] ``` This function runs a simdrive for getting 0-to-60 and 0-30 mph time with fully laden weight at GVWR (plus gvwr_credit_kg?) diff --git a/docs/functions/fueleconomy.md b/docs/functions/fueleconomy.md index 6b397a9..67f7b05 100644 --- a/docs/functions/fueleconomy.md +++ b/docs/functions/fueleconomy.md @@ -1,23 +1,23 @@ # Table of Contents -* [objectives.fueleconomy](#objectives.fueleconomy) - * [get\_range\_mi](#objectives.fueleconomy.get_range_mi) - * [get\_sim\_drive](#objectives.fueleconomy.get_sim_drive) - * [get\_mpgge](#objectives.fueleconomy.get_mpgge) +* [t3co/objectives/fueleconomy](#t3co/objectives/fueleconomy) + * [get\_range\_mi](#t3co/objectives/fueleconomy.get_range_mi) + * [get\_sim\_drive](#t3co/objectives/fueleconomy.get_sim_drive) + * [get\_mpgge](#t3co/objectives/fueleconomy.get_mpgge) - + -# objectives.fueleconomy +# t3co/objectives/fueleconomy Module containing functions for calculating fuel economy objectives. - + #### get\_range\_mi ```python def get_range_mi(mpgge_info: dict, vehicle: fastsim.vehicle.Vehicle, - scenario) -> dict + scenario: run_scenario.Scenario) -> dict ``` This funcion computes range [miles] from mpgge using vehicle powertrain type and energy (or fuel) store size. @@ -43,7 +43,7 @@ i.e. the CD range that PHEVs are commonly specified with - `range_dict` _dict_ - Dictionary containing different range results - + #### get\_sim\_drive @@ -64,16 +64,18 @@ This helper method returns a FASTSim SimDrive object using the vehicle, drive cy - `sim_drive` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive object - + #### get\_mpgge ```python -def get_mpgge(eff_range_cyc: fastsim.cycle.Cycle - | List[Tuple[fastsim.cycle.Cycle, float]], - v: fastsim.vehicle.Vehicle, - scenario, - diagnostic=False) +def get_mpgge( + eff_range_cyc: fastsim.cycle.Cycle + | List[Tuple[fastsim.cycle.Cycle, float]], + v: fastsim.vehicle.Vehicle, + scenario, + diagnostic=False +) -> Tuple[dict, List[fastsim.simdrive.SimDrive], List[dict]] ``` This helper method gets the composite mpgge fuel efficiency of vehicle for each efficiency_range Drive Cycle and weight. diff --git a/docs/functions/generateinputs.md b/docs/functions/generateinputs.md index aee4524..ba283ef 100644 --- a/docs/functions/generateinputs.md +++ b/docs/functions/generateinputs.md @@ -1,18 +1,18 @@ # Table of Contents -* [run.generateinputs](#run.generateinputs) - * [generate](#run.generateinputs.generate) +* [t3co/run/generateinputs](#t3co/run/generateinputs) + * [generate](#t3co/run/generateinputs.generate) - + -# run.generateinputs +# t3co/run/generateinputs - + #### generate ```python -def generate(vocation, dst=gl.OPTIMIZATION_AND_TCO_RCRS) +def generate(vocation: str, dst: str = gl.OPTIMIZATION_AND_TCO_RCRS) ``` This function aggregates specifications from users for powertrains, desired ranges, component costs etc. into two diff --git a/docs/functions/gradeability.md b/docs/functions/gradeability.md index 94b6266..d52e0db 100644 --- a/docs/functions/gradeability.md +++ b/docs/functions/gradeability.md @@ -1,22 +1,24 @@ # Table of Contents -* [objectives.gradeability](#objectives.gradeability) - * [get\_gradeability](#objectives.gradeability.get_gradeability) +* [t3co/objectives/gradeability](#t3co/objectives/gradeability) + * [get\_gradeability](#t3co/objectives/gradeability.get_gradeability) - + -# objectives.gradeability +# t3co/objectives/gradeability - + #### get\_gradeability ```python -def get_gradeability(analysis_vehicle, - scenario=None, - verbose=False, - ess_init_soc=None, - set_weight_to_max_kg=True) +def get_gradeability( + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario = None, + verbose: bool = False, + ess_init_soc: float = None, + set_weight_to_max_kg: bool = True +) -> Tuple[float, float, fastsim.simdrive.SimDrive, fastsim.simdrive.SimDrive] ``` This function runs SimDrives to determine the gradeability at given speed and the grade vehicle is diff --git a/docs/functions/moo.md b/docs/functions/moo.md index c589edc..6f36118 100644 --- a/docs/functions/moo.md +++ b/docs/functions/moo.md @@ -1,27 +1,27 @@ # Table of Contents -* [moopack.moo](#moopack.moo) - * [T3COProblem](#moopack.moo.T3COProblem) - * [setup\_opt\_records](#moopack.moo.T3COProblem.setup_opt_records) - * [\_\_init\_\_](#moopack.moo.T3COProblem.__init__) - * [compile\_reporting\_vars](#moopack.moo.T3COProblem.compile_reporting_vars) - * [instantiate\_moo\_vehicles\_and\_scenario](#moopack.moo.T3COProblem.instantiate_moo_vehicles_and_scenario) - * [cda\_percent\_delta\_knob](#moopack.moo.T3COProblem.cda_percent_delta_knob) - * [weight\_delta\_percent\_knob](#moopack.moo.T3COProblem.weight_delta_percent_knob) - * [fc\_peak\_eff\_knob](#moopack.moo.T3COProblem.fc_peak_eff_knob) - * [get\_objs](#moopack.moo.T3COProblem.get_objs) - * [adjust\_fc\_peak\_eff](#moopack.moo.T3COProblem.adjust_fc_peak_eff) - * [sweep\_knob](#moopack.moo.T3COProblem.sweep_knob) - * [get\_tco\_from\_moo\_advanced\_result](#moopack.moo.T3COProblem.get_tco_from_moo_advanced_result) - * [T3CODisplay](#moopack.moo.T3CODisplay) - * [\_\_init\_\_](#moopack.moo.T3CODisplay.__init__) - * [run\_optimization](#moopack.moo.run_optimization) - - - -# moopack.moo - - +* [t3co/moopack/moo](#t3co/moopack/moo) + * [T3COProblem](#t3co/moopack/moo.T3COProblem) + * [setup\_opt\_records](#t3co/moopack/moo.T3COProblem.setup_opt_records) + * [\_\_init\_\_](#t3co/moopack/moo.T3COProblem.__init__) + * [compile\_reporting\_vars](#t3co/moopack/moo.T3COProblem.compile_reporting_vars) + * [instantiate\_moo\_vehicles\_and\_scenario](#t3co/moopack/moo.T3COProblem.instantiate_moo_vehicles_and_scenario) + * [cda\_percent\_delta\_knob](#t3co/moopack/moo.T3COProblem.cda_percent_delta_knob) + * [weight\_delta\_percent\_knob](#t3co/moopack/moo.T3COProblem.weight_delta_percent_knob) + * [fc\_peak\_eff\_knob](#t3co/moopack/moo.T3COProblem.fc_peak_eff_knob) + * [get\_objs](#t3co/moopack/moo.T3COProblem.get_objs) + * [adjust\_fc\_peak\_eff](#t3co/moopack/moo.T3COProblem.adjust_fc_peak_eff) + * [sweep\_knob](#t3co/moopack/moo.T3COProblem.sweep_knob) + * [get\_tco\_from\_moo\_advanced\_result](#t3co/moopack/moo.T3COProblem.get_tco_from_moo_advanced_result) + * [T3CODisplay](#t3co/moopack/moo.T3CODisplay) + * [\_\_init\_\_](#t3co/moopack/moo.T3CODisplay.__init__) + * [run\_optimization](#t3co/moopack/moo.run_optimization) + + + +# t3co/moopack/moo + + ## T3COProblem Objects @@ -31,7 +31,7 @@ class T3COProblem(ElementwiseProblem) Class for creating PyMoo problem. - + #### setup\_opt\_records @@ -41,19 +41,19 @@ def setup_opt_records() This method sets up the empty optimization record arrays - + #### \_\_init\_\_ ```python -def __init__(knobs_bounds, - vnum, - optimize_pt=gl.BEV, - obj_list=None, - constr_list=None, - verbose=False, - config=None, - **kwargs) +def __init__(knobs_bounds: dict, + vnum: float, + optimize_pt: str = gl.BEV, + obj_list: list = None, + constr_list: list = None, + verbose: bool = False, + config: run_scenario.Config = None, + **kwargs) -> None ``` This constructor initializes optimization input variables @@ -62,35 +62,35 @@ This constructor initializes optimization input variables - `knobs_bounds` _dict_ - Dictionary containing knobs bounds for optimization - `vnum` _float_ - Vehicle selection number -- `optimize_pt` _vehicle.veh_pt_type, optional_ - Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. +- `optimize_pt` _str, optional_ - Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. - `obj_list` _list, optional_ - List of objectives. Defaults to None. - `constr_list` _list, optional_ - List of constraints. Defaults to None. - `verbose` _bool, optional_ - if True, prints process steps. Defaults to False. - `config` _run_scenario.Config, optional_ - T3CO Config object containing analysis attributes and scenario attribute overrides. Defaults to None. - + #### compile\_reporting\_vars ```python -def compile_reporting_vars() +def compile_reporting_vars() -> None ``` This method creates an output dictionary containing optimization results - + #### instantiate\_moo\_vehicles\_and\_scenario ```python -def instantiate_moo_vehicles_and_scenario(vnum, config=None) +def instantiate_moo_vehicles_and_scenario(vnum: int, config=None) -> None ``` This method instantiates the multi-objective optimization problem vehicles and scenarios, starting with the baseline Conventional vehicle. **Arguments**: -- `vnum` _float_ - vehicle selection number +- `vnum` _int_ - vehicle selection number - `config` _run_scenario.Config, optional_ - T3CO Config object containing analysis attributes and scenario attribute overrides. Defaults to None. @@ -98,12 +98,13 @@ This method instantiates the multi-objective optimization problem vehicles and s - `TypeError` - Invalid optimize_pt selection - + #### cda\_percent\_delta\_knob ```python -def cda_percent_delta_knob(CdA_perc_reduction, optvehicle) +def cda_percent_delta_knob(CdA_perc_reduction: str, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the drag_coef based on aero improvement curve and glider_kg based on cda_cost_coeff_a and cda_cost_coeff_b @@ -113,12 +114,13 @@ This method sets the drag_coef based on aero improvement curve and glider_kg bas - `CdA_perc_reduction` _str_ - Name of aero improvement curve file - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object for optimization vehicle - + #### weight\_delta\_percent\_knob ```python -def weight_delta_percent_knob(wt_perc_reduction, optvehicle) +def weight_delta_percent_knob(wt_perc_reduction: float, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the knob from the lightweighting curve @@ -128,12 +130,13 @@ This method sets the knob from the lightweighting curve - `wt_perc_reduction` _float_ - Weight reduction percentage value from lightweighting curve - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of the optimization vehicle - + #### fc\_peak\_eff\_knob ```python -def fc_peak_eff_knob(fc_peak_eff, optvehicle) +def fc_peak_eff_knob(fc_peak_eff: float, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method sets the knob from the engine efficiency curve @@ -143,12 +146,13 @@ This method sets the knob from the engine efficiency curve - `fc_peak_eff` _float_ - Fuel converter peak effiency override from engine efficiency improvement curve - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object for optimization vehicle - + #### get\_objs ```python -def get_objs(x, write_tsv=False) +def get_objs(x: dict, + write_tsv: bool = False) -> Tuple[np.array, np.array, dict] ``` This method gets called when PyMoo calls _evaluate. It initializes objectives and constraints and runs vehicle_scenario_sweep @@ -172,12 +176,13 @@ chromosome is a full gene, all values in x - `constraint_results_G` _np.array_ - Array of constraints - `rs_sweep` _dict_ - Output dictionary from vehicle_scenario_sweep - + #### adjust\_fc\_peak\_eff ```python -def adjust_fc_peak_eff(fc_peak_eff, scenario, optvehicle) +def adjust_fc_peak_eff(fc_peak_eff: float, scenario: run_scenario.Scenario, + optvehicle: fastsim.vehicle.Vehicle) -> None ``` This method augments an advanced vehicle fc_eff_array based on new fc_peak_eff using baseline fc_eff_array @@ -189,12 +194,16 @@ This method augments an advanced vehicle fc_eff_array based on new fc_peak_eff u - `scenario` _run_scenario.Scenario_ - Scenario object of current selection - `optvehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of optimization vehicle - + #### sweep\_knob ```python -def sweep_knob(knob, definition=100, plot=False, optres=None, **kwargs) +def sweep_knob(knob: list, + definition: int = 100, + plot: bool = False, + optres: float = None, + **kwargs) -> list ``` This method sweeps the optimization knob of vehicle from lbound to ubound, return TCO plot optres to see if there's agreement from opt solution and your sweep @@ -211,12 +220,12 @@ This method sweeps the optimization knob of vehicle from lbound to ubound, retur - `tcos` _list_ - List of TCOs of length=definition - + #### get\_tco\_from\_moo\_advanced\_result ```python -def get_tco_from_moo_advanced_result(x) +def get_tco_from_moo_advanced_result(x: dict) -> dict ``` This method is a utility function to get detailed TCO information from optimized MOO result @@ -230,7 +239,7 @@ This method is a utility function to get detailed TCO information from optimized - `out` _dict_ - Dictionary containing TCO results for optimization runs - + ## T3CODisplay Objects @@ -244,33 +253,34 @@ This class contains the display object for Pymoo optimization printouts - pymoo. - `Output` _pymoo.util.display.output.Output_ - Pymoo minimize display object - + #### \_\_init\_\_ ```python -def __init__(**kwargs) +def __init__(**kwargs) -> None ``` This constructor initializes the pymoo.util.display.Display object - + #### run\_optimization ```python -def run_optimization(pop_size, - n_max_gen, - knobs_bounds, - vnum, - x_tol, - f_tol, - nth_gen, - n_last, - algo, - obj_list=None, - config=None, - **kwargs) +def run_optimization( + pop_size: int, + n_max_gen: int, + knobs_bounds: dict, + vnum: int, + x_tol: float, + f_tol: float, + nth_gen: int, + n_last: int, + algo: str, + obj_list: list = None, + config: run_scenario.Config = None, + **kwargs) -> Tuple[pymoo.core.result.Result, T3COProblem, bool] ``` This method creates and runs T3COProblem minimization @@ -280,7 +290,7 @@ This method creates and runs T3COProblem minimization - `pop_size` _int_ - Population size for optimization - `n_max_gen` _int_ - maximum number of generations for optimization - `knobs_bounds` _dict_ - Dictionary containing knobs and bounds -- `vnum` _float_ - vehicle selection number +- `vnum` _int_ - vehicle selection number - `x_tol` _float_ - tolerance in parameter space - `f_tol` _float_ - tolerance in objective space - `nth_gen` _int_ - number of generations to evaluate if convergence occurs diff --git a/docs/functions/opportunity_cost.md b/docs/functions/opportunity_cost.md index 68ec8c8..f2fa287 100644 --- a/docs/functions/opportunity_cost.md +++ b/docs/functions/opportunity_cost.md @@ -1,19 +1,19 @@ # Table of Contents -* [tco.opportunity\_cost](#tco.opportunity_cost) - * [OpportunityCost](#tco.opportunity_cost.OpportunityCost) - * [\_\_init\_\_](#tco.opportunity_cost.OpportunityCost.__init__) - * [set\_kdes](#tco.opportunity_cost.OpportunityCost.set_kdes) - * [get\_payload\_loss\_factor](#tco.opportunity_cost.OpportunityCost.get_payload_loss_factor) - * [get\_dwell\_time\_cost](#tco.opportunity_cost.OpportunityCost.get_dwell_time_cost) - * [get\_M\_R\_downtime\_cost](#tco.opportunity_cost.OpportunityCost.get_M_R_downtime_cost) - * [main](#tco.opportunity_cost.main) +* [t3co/tco/opportunity\_cost](#t3co/tco/opportunity_cost) + * [OpportunityCost](#t3co/tco/opportunity_cost.OpportunityCost) + * [\_\_init\_\_](#t3co/tco/opportunity_cost.OpportunityCost.__init__) + * [set\_kdes](#t3co/tco/opportunity_cost.OpportunityCost.set_kdes) + * [set\_payload\_loss\_factor](#t3co/tco/opportunity_cost.OpportunityCost.set_payload_loss_factor) + * [set\_dwell\_time\_cost](#t3co/tco/opportunity_cost.OpportunityCost.set_dwell_time_cost) + * [set\_M\_R\_downtime\_cost](#t3co/tco/opportunity_cost.OpportunityCost.set_M_R_downtime_cost) + * [main](#t3co/tco/opportunity_cost.main) - + -# tco.opportunity\_cost +# t3co/tco/opportunity\_cost - + ## OpportunityCost Objects @@ -26,12 +26,14 @@ This class is used to calculate the different opportunity costs for a scenario a - Fueling Downtime Cost - Maintenance and Repair Downtime Cost - + #### \_\_init\_\_ ```python -def __init__(scenario, range_dict=None, **kwargs) +def __init__(scenario: run_scenario.Scenario, + range_dict: dict = None, + **kwargs) -> None ``` Initializes OpportunityCost object using Scenario object, range_dict (from fueleconomy module), and other arguments @@ -41,12 +43,14 @@ Initializes OpportunityCost object using Scenario object, range_dict (from fuele - `scenario` _run_scenario.Scenario_ - Scenario object - `range_dict` _dict, optional_ - dictionary containing primary_fuel_range_mi from fueleconomy.get_range_mi function. Defaults to None. - + #### set\_kdes ```python -def set_kdes(scenario, bw_method=0.15, verbose=False) +def set_kdes(scenario: run_scenario.Scenario, + bw_method: float = 0.15, + verbose: bool = False) -> None ``` This method sets tje kde kernel. This is time-consuming, only call this once, if possible. @@ -57,15 +61,15 @@ This method sets tje kde kernel. This is time-consuming, only call this once, if - `bw_method` _float, optional_ - kernel bandwidth method used by guassian_kde. Defaults to .15. - `verbose` _bool, optional_ - if True, prints process sets. Defaults to False. - + -#### get\_payload\_loss\_factor +#### set\_payload\_loss\_factor ```python -def get_payload_loss_factor(a_vehicle: fastsim.vehicle, - scenario, - plots=False, - plots_dir=None) +def set_payload_loss_factor(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + plots: bool = False, + plots_dir: str = None) -> None ``` This method runs teh kernel density estimation function set_kdes and calculates the payload capacity loss factor (payload_cap_cost_multiplier) of the new vehicle compared to a conventional vehicle's reference empty weight. @@ -77,12 +81,13 @@ This method runs teh kernel density estimation function set_kdes and calculates - `plots` _bool, optional_ - if True, creates histogram of KDE weight bins. Defaults to False. - `plots_dir` _str, optional_ - output diretory for saving plot figure. Defaults to None. - + -#### get\_dwell\_time\_cost +#### set\_dwell\_time\_cost ```python -def get_dwell_time_cost(a_vehicle: fastsim.vehicle, scenario) +def set_dwell_time_cost(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> None ``` This function calculates the fueling dwell time cost for a vehicle based on fuel fill rate/charging power and shifts_per_year @@ -92,12 +97,13 @@ This function calculates the fueling dwell time cost for a vehicle based on fuel - `a_vehicle` _fastsim.vehicle_ - FASTSim vehicle object of analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object for current selection - + -#### get\_M\_R\_downtime\_cost +#### set\_M\_R\_downtime\_cost ```python -def get_M_R_downtime_cost(a_vehicle: fastsim.vehicle, scenario) +def set_M_R_downtime_cost(a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> None ``` This function calculates the Maintenance and Repair (M&R) downtime cost based on planned, unplanned, and tire replacement downtime inputs @@ -107,7 +113,7 @@ This function calculates the Maintenance and Repair (M&R) downtime cost based on - `a_vehicle` _fastsim.vehicle_ - FASTSim object of the analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object for the current selection - + #### main diff --git a/docs/functions/run_scenario.md b/docs/functions/run_scenario.md index f30957f..a822ad3 100644 --- a/docs/functions/run_scenario.md +++ b/docs/functions/run_scenario.md @@ -1,179 +1,44 @@ # Table of Contents -* [run.run\_scenario](#run.run_scenario) - * [set\_test\_weight](#run.run_scenario.set_test_weight) - * [reset\_vehicle\_weight](#run.run_scenario.reset_vehicle_weight) - * [limit\_cargo\_kg\_for\_moo\_hev\_bev](#run.run_scenario.limit_cargo_kg_for_moo_hev_bev) - * [set\_max\_motor\_kw](#run.run_scenario.set_max_motor_kw) - * [set\_max\_battery\_kwh](#run.run_scenario.set_max_battery_kwh) - * [set\_max\_battery\_power\_kw](#run.run_scenario.set_max_battery_power_kw) - * [set\_max\_fuel\_converter\_kw](#run.run_scenario.set_max_fuel_converter_kw) - * [set\_fuel\_store\_kwh](#run.run_scenario.set_fuel_store_kwh) - * [set\_cargo\_kg](#run.run_scenario.set_cargo_kg) - * [Config](#run.run_scenario.Config) - * [from\_file](#run.run_scenario.Config.from_file) - * [from\_dict](#run.run_scenario.Config.from_dict) - * [validate\_analysis\_id](#run.run_scenario.Config.validate_analysis_id) - * [Scenario](#run.run_scenario.Scenario) - * [originalcargo\_kg](#run.run_scenario.Scenario.originalcargo_kg) - * [plf\_scenario\_vehicle\_cargo\_capacity\_kg](#run.run_scenario.Scenario.plf_scenario_vehicle_cargo_capacity_kg) - * [from\_config](#run.run_scenario.Scenario.from_config) - * [check\_phev\_init\_socs](#run.run_scenario.check_phev_init_socs) - * [get\_phev\_util\_factor](#run.run_scenario.get_phev_util_factor) - * [get\_objective\_simdrive](#run.run_scenario.get_objective_simdrive) - * [run\_grade\_or\_accel](#run.run_scenario.run_grade_or_accel) - * [create\_fastsim\_vehicle](#run.run_scenario.create_fastsim_vehicle) - * [get\_vehicle](#run.run_scenario.get_vehicle) - * [get\_scenario\_and\_cycle](#run.run_scenario.get_scenario_and_cycle) - * [load\_scenario](#run.run_scenario.load_scenario) - * [load\_design\_cycle\_from\_scenario](#run.run_scenario.load_design_cycle_from_scenario) - * [load\_design\_cycle\_from\_path](#run.run_scenario.load_design_cycle_from_path) - * [vehicle\_scenario\_sweep](#run.run_scenario.vehicle_scenario_sweep) - * [run](#run.run_scenario.run) - * [rerun](#run.run_scenario.rerun) - - - -# run.run\_scenario +* [t3co/run/run\_scenario](#t3co/run/run_scenario) + * [Config](#t3co/run/run_scenario.Config) + * [from\_file](#t3co/run/run_scenario.Config.from_file) + * [from\_dict](#t3co/run/run_scenario.Config.from_dict) + * [validate\_analysis\_id](#t3co/run/run_scenario.Config.validate_analysis_id) + * [Scenario](#t3co/run/run_scenario.Scenario) + * [originalcargo\_kg](#t3co/run/run_scenario.Scenario.originalcargo_kg) + * [plf\_scenario\_vehicle\_cargo\_capacity\_kg](#t3co/run/run_scenario.Scenario.plf_scenario_vehicle_cargo_capacity_kg) + * [from\_config](#t3co/run/run_scenario.Scenario.from_config) + * [check\_phev\_init\_socs](#t3co/run/run_scenario.check_phev_init_socs) + * [get\_phev\_util\_factor](#t3co/run/run_scenario.get_phev_util_factor) + * [get\_objective\_simdrive](#t3co/run/run_scenario.get_objective_simdrive) + * [run\_grade\_or\_accel](#t3co/run/run_scenario.run_grade_or_accel) + * [create\_fastsim\_vehicle](#t3co/run/run_scenario.create_fastsim_vehicle) + * [get\_vehicle](#t3co/run/run_scenario.get_vehicle) + * [get\_scenario\_and\_cycle](#t3co/run/run_scenario.get_scenario_and_cycle) + * [load\_scenario](#t3co/run/run_scenario.load_scenario) + * [load\_design\_cycle\_from\_scenario](#t3co/run/run_scenario.load_design_cycle_from_scenario) + * [load\_design\_cycle\_from\_path](#t3co/run/run_scenario.load_design_cycle_from_path) + * [set\_test\_weight](#t3co/run/run_scenario.set_test_weight) + * [reset\_vehicle\_weight](#t3co/run/run_scenario.reset_vehicle_weight) + * [limit\_cargo\_kg\_for\_moo\_hev\_bev](#t3co/run/run_scenario.limit_cargo_kg_for_moo_hev_bev) + * [set\_max\_motor\_kw](#t3co/run/run_scenario.set_max_motor_kw) + * [set\_max\_battery\_kwh](#t3co/run/run_scenario.set_max_battery_kwh) + * [set\_max\_battery\_power\_kw](#t3co/run/run_scenario.set_max_battery_power_kw) + * [set\_max\_fuel\_converter\_kw](#t3co/run/run_scenario.set_max_fuel_converter_kw) + * [set\_fuel\_store\_kwh](#t3co/run/run_scenario.set_fuel_store_kwh) + * [set\_cargo\_kg](#t3co/run/run_scenario.set_cargo_kg) + * [vehicle\_scenario\_sweep](#t3co/run/run_scenario.vehicle_scenario_sweep) + * [run](#t3co/run/run_scenario.run) + * [rerun](#t3co/run/run_scenario.rerun) + + + +# t3co/run/run\_scenario Module for loading vehicles, scenarios, running them and managing them - - -#### set\_test\_weight - -```python -def set_test_weight(vehicle, scenario) -``` - -assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit - -**Arguments**: - -- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object - - - -#### reset\_vehicle\_weight - -```python -def reset_vehicle_weight(vehicle) -``` - -This function resets vehicle mass after loaded weight tests are done for accel and grade - -**Arguments**: - -- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - - - -#### limit\_cargo\_kg\_for\_moo\_hev\_bev - -```python -def limit_cargo_kg_for_moo_hev_bev(opt_scenario, mooadvancedvehicle) -``` - -This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles - -**Arguments**: - -- `opt_scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object -- `mooadvancedvehicle` _fastsim.vehicle.Vehicle_ - pymoo optimization vehicle - - - -#### set\_max\_motor\_kw - -```python -def set_max_motor_kw(analysis_vehicle, scenario, max_motor_kw) -``` - -This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `scenario` _t3co.run_scenario.Scenario_ - T3CO Scenarion object -- `max_motor_kw` _float_ - max motor power /kW - - - -#### set\_max\_battery\_kwh - -```python -def set_max_battery_kwh(analysis_vehicle, max_ess_kwh) -``` - -This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `max_ess_kwh` _float_ - max energy storage system energy capacity /kWh - - - -#### set\_max\_battery\_power\_kw - -```python -def set_max_battery_power_kw(analysis_vehicle, max_ess_kw) -``` - -This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `max_ess_kw` _float_ - max energy storage system power /kW - - - -#### set\_max\_fuel\_converter\_kw - -```python -def set_max_fuel_converter_kw(analysis_vehicle, fc_max_out_kw) -``` - -This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `fc_max_out_kw` _float_ - max fuel converter power /kW - - - -#### set\_fuel\_store\_kwh - -```python -def set_fuel_store_kwh(analysis_vehicle, fs_kwh) -``` - -This helper method is used within T3COProblem to set fs_kwh to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `fs_kwh` _float_ - fuel storage energy capacity /kWh - - - -#### set\_cargo\_kg - -```python -def set_cargo_kg(analysis_vehicle, cargo_kg) -``` - -This helper method is used within T3COProblem to set cargo_kg to optimization vehicle - -**Arguments**: - -- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object -- `cargo_kg` _float_ - vehicle cargo capacity /kg - - + ## Config Objects @@ -184,7 +49,7 @@ class Config() New class to read T3COConfig file containing analysis attributes like vehicle and scenario paths, and scenario attribute overrides - + #### from\_file @@ -204,7 +69,7 @@ This method generates a Config dictionary from CSV file and calls Config.from_di - `Self.from_dict` - method that gets Config instance from config_dict - + #### from\_dict @@ -223,12 +88,12 @@ This method generates a Config instance from config_dict - `Self` - Config instance containining all values from T3CO Config CSV file - + #### validate\_analysis\_id ```python -def validate_analysis_id(filename: str, analysis_id: int = 0) +def validate_analysis_id(filename: str, analysis_id: int = 0) -> Self ``` This method validates that correct analysis id is input @@ -242,7 +107,7 @@ This method validates that correct analysis id is input - `Exception` - Error if analysis_id not found - + ## Scenario Objects @@ -253,24 +118,24 @@ class Scenario() Class object that contains all TCO parameters and performance target (range, grade, accel) information for a vehicle such that performance and TCO can be computed during optimization - + #### originalcargo\_kg if needed, should be assigned immediately after vehicle read in - + #### plf\_scenario\_vehicle\_cargo\_capacity\_kg includes cargo credit kg - + #### from\_config ```python -def from_config(config: Config = None) +def from_config(config: Config = None) -> Self ``` This method overrides certain scenario fields if use_config is True and config object is not None @@ -279,12 +144,13 @@ This method overrides certain scenario fields if use_config is True and config o - `config` _Config, optional_ - Config object. Defaults to None. - + #### check\_phev\_init\_socs ```python -def check_phev_init_socs(a_vehicle: vehicle.Vehicle, scenario: Scenario) +def check_phev_init_socs(a_vehicle: vehicle.Vehicle, + scenario: Scenario) -> None ``` This function checks that soc_norm_init_for_grade_pct and soc_norm_init_for_accel_pct are present only for PHEVs @@ -294,12 +160,13 @@ This function checks that soc_norm_init_for_grade_pct and soc_norm_init_for_acce - `a_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - `scenario` _Scenario_ - T3CO scenario object - + #### get\_phev\_util\_factor ```python -def get_phev_util_factor(scenario, v, mpgge) +def get_phev_util_factor(scenario: Scenario, v: fastsim.vehicle.Vehicle, + mpgge: dict) -> float ``` This function gets the PHEV utility factor derived from the computed range of the @@ -308,7 +175,7 @@ vehicle and the operational day range computed from shifts per year and the firs **Arguments**: - `scenario` _Scenario_ - T3CO scenario object -- `v` _fastsim.Vehicle.vehicle_ - FASTSim vehicle object +- `v` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - `mpgge` _dict_ - Miles per Gallon Gasoline Equivalent dictionary @@ -316,12 +183,14 @@ vehicle and the operational day range computed from shifts per year and the firs - `uf` _float_ - PHEV computed utility factor - + #### get\_objective\_simdrive ```python -def get_objective_simdrive(analysis_vehicle: vehicle.Vehicle, cycle) +def get_objective_simdrive( + analysis_vehicle: vehicle.Vehicle, + cycle: fastsim.cycle.Cycle) -> fastsim.simdrive.SimDrive ``` This function obtains the SimDrive for accel and grade test @@ -336,12 +205,14 @@ This function obtains the SimDrive for accel and grade test - `sd` _fastsim.simdrive.SimDrive_ - FASTSim SimDrive object containing vehicle inputs and simulation output attributes - + #### run\_grade\_or\_accel ```python -def run_grade_or_accel(test, analysis_vehicle, sim_drive, ess_init_soc) +def run_grade_or_accel(test: str, analysis_vehicle: fastsim.vehicle.Vehicle, + sim_drive: fastsim.simdrive.SimDrive, + ess_init_soc: float) -> None ``` This function handles initial SOC considerations for grade and accel tests @@ -366,12 +237,12 @@ HEVs attempt SOC balancing but that is overrident by HEV test init SOC - `Exception` - if test not in ['accel', 'grade'] - + #### create\_fastsim\_vehicle ```python -def create_fastsim_vehicle(veh_dict=None) +def create_fastsim_vehicle(veh_dict: dict = None) -> fastsim.vehicle.Vehicle ``` This function creates and returns an empty FASTSim vehicle object with no attributes or @@ -385,12 +256,12 @@ This function creates and returns an empty FASTSim vehicle object with no attrib - `v` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - + #### get\_vehicle ```python -def get_vehicle(veh_no, veh_input_path) +def get_vehicle(veh_no: int, veh_input_path: str) -> fastsim.vehicle.Vehicle ``` This function loads vehicle object from vehicle number and input csv filepath @@ -405,15 +276,16 @@ This function loads vehicle object from vehicle number and input csv filepath - `veh` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object - + #### get\_scenario\_and\_cycle ```python -def get_scenario_and_cycle(veh_no, - scenario_inputs_path, - a_vehicle=None, - config=None) +def get_scenario_and_cycle( + veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None) -> Tuple[Scenario, fastsim.cycle.Cycle] ``` This function uses helper methods load_scenario and load_design_cycle_from_scenario to get scenario object and cycle object corresponding to selected vehicle (by veh_no) @@ -431,12 +303,15 @@ This function uses helper methods load_scenario and load_design_cycle_from_scena - `scenario` _Scenario_ - T3CO scenario object selected - `cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object selected - + #### load\_scenario ```python -def load_scenario(veh_no, scenario_inputs_path, a_vehicle=None, config=None) +def load_scenario(veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None) -> Scenario ``` This function gets the Scenario object from scenario input CSV filepath, initializes some fields, and overrides some fields based on Config object @@ -453,14 +328,15 @@ This function gets the Scenario object from scenario input CSV filepath, initial - `scenario` _Scenario_ - Scenario object for given selection - + #### load\_design\_cycle\_from\_scenario ```python -def load_design_cycle_from_scenario(scenario, - cyc_file_path=gl.OPTIMIZATION_DRIVE_CYCLES - ) +def load_design_cycle_from_scenario( + scenario: Scenario, + cyc_file_path: str = gl.OPTIMIZATION_DRIVE_CYCLES +) -> fastsim.cycle.Cycle ``` This helper method loads the design cycle used for mpgge and range determination. @@ -478,12 +354,12 @@ If the drive cycles are a list of tuples, handle accordingly with eval. - `range_cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object for current Scenario object - + #### load\_design\_cycle\_from\_path ```python -def load_design_cycle_from_path(cyc_file_path) +def load_design_cycle_from_path(cyc_file_path: str) -> fastsim.cycle.Cycle ``` This helper method loads the Cycle object from the drivecycle filepath @@ -497,13 +373,156 @@ This helper method loads the Cycle object from the drivecycle filepath - `range_cyc` _fastsim.cycle.Cycle_ - FASTSim cycle object for current Scenario object - + + +#### set\_test\_weight + +```python +def set_test_weight(vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario) -> None +``` + +assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit + +**Arguments**: + +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object + + + +#### reset\_vehicle\_weight + +```python +def reset_vehicle_weight(vehicle: fastsim.vehicle.Vehicle) -> None +``` + +This function resets vehicle mass after loaded weight tests are done for accel and grade + +**Arguments**: + +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object + + + +#### limit\_cargo\_kg\_for\_moo\_hev\_bev + +```python +def limit_cargo_kg_for_moo_hev_bev( + opt_scenario: Scenario, + mooadvancedvehicle: fastsim.vehicle.Vehicle) -> None +``` + +This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles + +**Arguments**: + +- `opt_scenario` _t3co.run_scenario.Scenario_ - T3CO scenario object +- `mooadvancedvehicle` _fastsim.vehicle.Vehicle_ - pymoo optimization vehicle + + + +#### set\_max\_motor\_kw + +```python +def set_max_motor_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario, max_motor_kw: float) -> None +``` + +This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `scenario` _t3co.run_scenario.Scenario_ - T3CO Scenarion object +- `max_motor_kw` _float_ - max motor power /kW + + + +#### set\_max\_battery\_kwh + +```python +def set_max_battery_kwh(analysis_vehicle: fastsim.vehicle.Vehicle, + max_ess_kwh: float) -> None +``` + +This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `max_ess_kwh` _float_ - max energy storage system energy capacity /kWh + + + +#### set\_max\_battery\_power\_kw + +```python +def set_max_battery_power_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + max_ess_kw: float) -> None +``` + +This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `max_ess_kw` _float_ - max energy storage system power /kW + + + +#### set\_max\_fuel\_converter\_kw + +```python +def set_max_fuel_converter_kw(analysis_vehicle: fastsim.vehicle.Vehicle, + fc_max_out_kw: float) -> None +``` + +This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `fc_max_out_kw` _float_ - max fuel converter power /kW + + + +#### set\_fuel\_store\_kwh + +```python +def set_fuel_store_kwh(analysis_vehicle: fastsim.vehicle.Vehicle, + fs_kwh: float) -> None +``` + +This helper method is used within T3COProblem to set fs_kwh to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `fs_kwh` _float_ - fuel storage energy capacity /kWh + + + +#### set\_cargo\_kg + +```python +def set_cargo_kg(analysis_vehicle: fastsim.vehicle.Vehicle, cargo_kg) +``` + +This helper method is used within T3COProblem to set cargo_kg to optimization vehicle + +**Arguments**: + +- `analysis_vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object +- `cargo_kg` _float_ - vehicle cargo capacity /kg + + #### vehicle\_scenario\_sweep ```python -def vehicle_scenario_sweep(vehicle, - scenario, +def vehicle_scenario_sweep(vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario, range_cyc, verbose=False, **kwargs) @@ -523,15 +542,15 @@ This function contains helper methods such as get_tco_of_vehicle, check_phev_ini - `out` _dict_ - output dictionary containing TCO elements - + #### run ```python -def run(veh_no, - vocation="blank", - vehicle_input_path=gl.FASTSIM_INPUTS, - scenario_inputs_path=gl.OTHER_INPUTS) +def run(veh_no: int, + vocation: str = "blank", + vehicle_input_path: str = gl.FASTSIM_INPUTS, + scenario_inputs_path: str = gl.OTHER_INPUTS) ``` This function runs vehicle_scenario_sweep based on vehicle and scenario objects read from input file paths @@ -548,12 +567,12 @@ This function runs vehicle_scenario_sweep based on vehicle and scenario objects - `out` _dict_ - output dictionary containing TCO results - + #### rerun ```python -def rerun(vehicle, vocation, scenario) +def rerun(vehicle: fastsim.vehicle.Vehicle, vocation: str, scenario: Scenario) ``` This function runs vehicle_scenario_sweep when given the vehicle and scenario objects diff --git a/docs/functions/sweep.md b/docs/functions/sweep.md index faaa8e4..d8d6896 100644 --- a/docs/functions/sweep.md +++ b/docs/functions/sweep.md @@ -1,23 +1,43 @@ # Table of Contents -* [sweep](#sweep) - * [save\_tco\_files](#sweep.save_tco_files) - * [get\_knobs\_bounds\_curves](#sweep.get_knobs_bounds_curves) - * [get\_objectives\_constraints](#sweep.get_objectives_constraints) - * [run\_moo](#sweep.run_moo) - * [check\_input\_files](#sweep.check_input_files) - * [run\_vehicle\_scenarios](#sweep.run_vehicle_scenarios) +* [t3co/sweep](#t3co/sweep) + * [deug\_traces](#t3co/sweep.deug_traces) + * [save\_tco\_files](#t3co/sweep.save_tco_files) + * [get\_knobs\_bounds\_curves](#t3co/sweep.get_knobs_bounds_curves) + * [get\_objectives\_constraints](#t3co/sweep.get_objectives_constraints) + * [run\_moo](#t3co/sweep.run_moo) + * [check\_input\_files](#t3co/sweep.check_input_files) + * [run\_vehicle\_scenarios](#t3co/sweep.run_vehicle_scenarios) - + -# sweep +# t3co/sweep - + + +#### deug\_traces + +```python +def deug_traces(vehicle: fastsim.vehicle.Vehicle, + cycles: List[fastsim.cycle.Cycle], + scenario: run_scenario.Scenario) -> None +``` + +This function gets a diagnostic trace of get_mpgge + +**Arguments**: + +- `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim Vehicle object +- `cycles` _List[fastsim.cycle.Cycle]_ - List of FASTSim drivecycle objects +- `scenario` _run_scenario.Scenario_ - Scenario object + + #### save\_tco\_files ```python -def save_tco_files(tco_files, resdir, scenario_name, sel, ts) +def save_tco_files(tco_files: dict, resdir: str, scenario_name: str, sel: str, + ts: str) -> None ``` This function saves the intermediary files as tsv @@ -30,25 +50,27 @@ This function saves the intermediary files as tsv - `sel` _str_ - selection(s) - `ts` _str_ - timestring - + #### get\_knobs\_bounds\_curves ```python -def get_knobs_bounds_curves(selection, vpttype, sdf, lw_imp_curves, aero_drag_imp_curves, - eng_eff_curves) +def get_knobs_bounds_curves(selection: int, vpttype: str, sdf: pd.DataFrame, + lw_imp_curves: pd.DataFrame, + aero_drag_imp_curves: pd.DataFrame, + eng_eff_curves: pd.DataFrame) -> Tuple[dict, dict] ``` This function fetches the knobs and constraints for running the optimization for a given selection **Arguments**: -- `selection` _float_ - selection number +- `selection` _int_ - selection number - `vpttype` _str_ - vehicle powertrain type = veh_pt_type -- `sdf` _DataFrame_ - scenario dataframe -- `lw_imp_curves` _DataFrame_ - light weighting curve dataframe -- `aero_drag_imp_curves` _DataFrame_ - aero drag curve dataframe -- `eng_eff_curves` _DataFrame_ - engine efficiency curve dataframe +- `sdf` _pd.DataFrame_ - scenario dataframe +- `lw_imp_curves` _pd.DataFrame_ - light weighting curve dataframe +- `aero_drag_imp_curves` _pd.DataFrame_ - aero drag curve dataframe +- `eng_eff_curves` _pd.DataFrame_ - engine efficiency curve dataframe **Returns**: @@ -56,19 +78,21 @@ This function fetches the knobs and constraints for running the optimization for - `knobs_bounds` _dict_ - dict of knobs and bounds - `curves` _dict_ - dict of lw, aero, and engine efficiency curve parameters - + #### get\_objectives\_constraints ```python -def get_objectives_constraints(selection, sdf, verbose=True) +def get_objectives_constraints(selection: int, + sdf: pd.DataFrame, + verbose: bool = True) -> Tuple[list, list] ``` This function appends to list of necessary variables based on the constraints and objectives selected **Arguments**: -- `selection` _float_ - selection number +- `selection` _int_ - selection number - `sdf` _DataFrame_ - scenario dataframe - `verbose` _bool, optional_ - if selected, function will print objectives and constraints. Defaults to True. @@ -78,21 +102,25 @@ This function appends to list of necessary variables based on the constraints an - `objectives` _list_ - list of selected objective variables - `constraints` _list_ - list of selected constraint variables - + #### run\_moo ```python -def run_moo(sel, sdf, optpt, algo, skip_opt, pop_size, n_max_gen, n_last, - nth_gen, x_tol, verbose, f_tol, resdir, lw_imp_curves, aero_drag_imp_curves, - eng_eff_imp_curves, config, **kwargs) +def run_moo( + sel: int, sdf: pd.DataFrame, optpt: str, algo: str, skip_opt: bool, + pop_size: float, n_max_gen: int, n_last: int, nth_gen: int, + x_tol: float, verbose: bool, f_tol: float, resdir: str, + lw_imp_curves: pd.DataFrame, aero_drag_imp_curves: pd.DataFrame, + eng_eff_imp_curves: pd.DataFrame, config: run_scenario.Scenario, + **kwargs) -> Tuple[pymoo.core.result.Result, moo.T3COProblem, bool] ``` This function calls get_objectives_constraints and get_knobs_bounds_curves, and then calls run_optimization to perform the multiobjective optimization **Arguments**: -- `sel` _float_ - selection number +- `sel` _int_ - selection number - `sdf` _DataFrame_ - scenario dataframe - `optpt` _str_ - vehicle powertrain type - `algo` _str_ - algorithm name @@ -115,14 +143,14 @@ This function calls get_objectives_constraints and get_knobs_bounds_curves, and - `moo_results` _pymoo.core.result.Result_ - optimization results object - `moo_problem` _T3COProblem_ - minimization problem that calculates TCO -- `moo_code` _Error_ - Error message +- `moo_code` _bool_ - Error message - + #### check\_input\_files ```python -def check_input_files(df, filetype, filepath) +def check_input_files(df: pd.DataFrame, filetype: str, filepath: str) -> None ``` This function contains assert statements that make sure input vehicle and scenario dataframes do not contain numm rows @@ -133,13 +161,15 @@ This function contains assert statements that make sure input vehicle and scenar - `filetype` _str_ - 'vehicle' or 'scenario' - `filepath` _str_ - filepath of the vehicle or scenario input files - + #### run\_vehicle\_scenarios ```python -def run_vehicle_scenarios(vehicles, scenarios, eng_eff_imp_curves_p, lw_imp_curves_p, - aero_drag_imp_curves_p, config, **kwargs) +def run_vehicle_scenarios(vehicles: str, scenarios: str, + eng_eff_imp_curves_p: str, lw_imp_curves_p: str, + aero_drag_imp_curves_p: str, + config: run_scenario.Config, **kwargs) -> None ``` This is the main function that runs T3CO for all the selections input diff --git a/docs/functions/tco_analysis.md b/docs/functions/tco_analysis.md index 6722fd0..728ba67 100644 --- a/docs/functions/tco_analysis.md +++ b/docs/functions/tco_analysis.md @@ -1,21 +1,22 @@ # Table of Contents -* [tco.tco\_analysis](#tco.tco_analysis) - * [get\_operating\_costs](#tco.tco_analysis.get_operating_costs) - * [discounted\_costs](#tco.tco_analysis.discounted_costs) - * [calc\_discountedTCO](#tco.tco_analysis.calc_discountedTCO) - * [get\_tco\_of\_vehicle](#tco.tco_analysis.get_tco_of_vehicle) +* [t3co/tco/tco\_analysis](#t3co/tco/tco_analysis) + * [get\_operating\_costs](#t3co/tco/tco_analysis.get_operating_costs) + * [discounted\_costs](#t3co/tco/tco_analysis.discounted_costs) + * [calc\_discountedTCO](#t3co/tco/tco_analysis.calc_discountedTCO) + * [get\_tco\_of\_vehicle](#t3co/tco/tco_analysis.get_tco_of_vehicle) - + -# tco.tco\_analysis +# t3co/tco/tco\_analysis - + #### get\_operating\_costs ```python -def get_operating_costs(ownershipCosts, TCO_switch="DIRECT") +def get_operating_costs(ownershipCosts, + TCO_switch: str = "DIRECT") -> pd.DataFrame ``` This function creates a dataframe of operating cost from ownershipCosts dataframe based on TCO_switch ('DIRECT' or 'EFFICIENCY') @@ -30,12 +31,13 @@ This function creates a dataframe of operating cost from ownershipCosts datafram - `operatingCosts_df` _pd.DataFrame_ - Dataframe containing operating cost categories based on TCO_switch - + #### discounted\_costs ```python -def discounted_costs(scenario, ownershipCosts) +def discounted_costs(scenario: run_scenario.Scenario, + ownershipCosts: pd.DataFrame) -> pd.DataFrame ``` This function calculates the yearly discounted costs for each category of ownershipCosts based on scenario.discount_rate_pct_per_yr @@ -50,17 +52,17 @@ This function calculates the yearly discounted costs for each category of owners - `ownershipCosts` _pd.DataFrame_ - ownershipCosts dataframe with additional 'Discounted Cost [$]' column - + #### calc\_discountedTCO ```python -def calc_discountedTCO(scenario, - discounted_costs_df, - veh_cost_set, - veh_opp_cost_set, - sim_drive, - TCO_switch="DIRECT") +def calc_discountedTCO(scenario: run_scenario.Scenario, + discounted_costs_df: pd.DataFrame, + veh_cost_set: dict, + veh_opp_cost_set: dict, + sim_drive: fastsim.simdrive.SimDrive, + TCO_switch: str = "DIRECT") -> Tuple[float, dict, dict] ``` This function calculates the discounted Total Cost of Ownerhip (discounted to account for time-value of money). @@ -82,12 +84,29 @@ There are two methods to calculate discounted TCO - 'DIRECT' and 'EFFICIENCY' - `oppy_cost_Dol_set` _dict_ - Dictionary containing discounted opportunity costs breakdown - `veh_oper_cost_set` _dict_ - Dictionary containing discounted operating costs breakdown - + #### get\_tco\_of\_vehicle ```python -def get_tco_of_vehicle(vehicle, range_cyc, scenario, write_tsv=False) +def get_tco_of_vehicle( + vehicle: fastsim.vehicle.Vehicle, + range_cyc: fastsim.cycle.Cycle, + scenario: run_scenario.Scenario, + write_tsv: bool = False +) -> Tuple[ + float, + float, + dict, + pd.DataFrame, + pd.DataFrame, + dict, + dict, + fastsim.simdrive.SimDrive, + dict, + dict, + dict, +] ``` This function calculates the Total Cost of Ownership of a vehicle and scenario for a given cycle. The three main components are: diff --git a/docs/functions/tco_stock_emissions.md b/docs/functions/tco_stock_emissions.md index 13c33cb..c0e38b9 100644 --- a/docs/functions/tco_stock_emissions.md +++ b/docs/functions/tco_stock_emissions.md @@ -1,19 +1,19 @@ # Table of Contents -* [tco.tco\_stock\_emissions](#tco.tco_stock_emissions) - * [dropCols](#tco.tco_stock_emissions.dropCols) - * [stockModel](#tco.tco_stock_emissions.stockModel) +* [t3co/tco/tco\_stock\_emissions](#t3co/tco/tco_stock_emissions) + * [dropCols](#t3co/tco/tco_stock_emissions.dropCols) + * [stockModel](#t3co/tco/tco_stock_emissions.stockModel) - + -# tco.tco\_stock\_emissions +# t3co/tco/tco\_stock\_emissions - + #### dropCols ```python -def dropCols(df) +def dropCols(df: pd.DataFrame) -> pd.DataFrame ``` This helper method drops columns if any row contains ['*'] @@ -27,25 +27,27 @@ This helper method drops columns if any row contains ['*'] - `df` _pd.DataFrame_ - Output dataframe with dropped dummy columns - + #### stockModel ```python -def stockModel(sales, - marketShares, - survival, - annualTravel, - fuelSplit, - fuelEfficiency, - emissions, - vehicleCosts=None, - travelCosts=None, - fuelCosts=None, - insuranceCosts=None, - residualCosts=None, - downtimeCosts=None, - write_files=False) +def stockModel( + sales: pd.DataFrame, + marketShares: pd.DataFrame, + survival: pd.DataFrame, + annualTravel: pd.DataFrame, + fuelSplit: pd.DataFrame, + fuelEfficiency: pd.DataFrame, + emissions: pd.DataFrame, + vehicleCosts: pd.DataFrame = None, + travelCosts: pd.DataFrame = None, + fuelCosts: pd.DataFrame = None, + insuranceCosts: pd.DataFrame = None, + residualCosts: pd.DataFrame = None, + downtimeCosts: pd.DataFrame = None, + write_files: bool = False +) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame] ``` This function generates the ownershipCosts dataframe from the dataframes for each cost category diff --git a/docs/functions/tcocalc.md b/docs/functions/tcocalc.md index 83ac6e0..345f78a 100644 --- a/docs/functions/tcocalc.md +++ b/docs/functions/tcocalc.md @@ -1,32 +1,33 @@ # Table of Contents -* [tco.tcocalc](#tco.tcocalc) - * [find\_residual\_rates](#tco.tcocalc.find_residual_rates) - * [calculate\_dollar\_cost](#tco.tcocalc.calculate_dollar_cost) - * [calculate\_opp\_costs](#tco.tcocalc.calculate_opp_costs) - * [fill\_fuel\_eff\_file](#tco.tcocalc.fill_fuel_eff_file) - * [fill\_veh\_expense\_file](#tco.tcocalc.fill_veh_expense_file) - * [fill\_trav\_exp\_tsv](#tco.tcocalc.fill_trav_exp_tsv) - * [fill\_downtimelabor\_cost\_tsv](#tco.tcocalc.fill_downtimelabor_cost_tsv) - * [fill\_market\_share\_tsv](#tco.tcocalc.fill_market_share_tsv) - * [fill\_fuel\_expense\_tsv](#tco.tcocalc.fill_fuel_expense_tsv) - * [fill\_annual\_tsv](#tco.tcocalc.fill_annual_tsv) - * [fill\_reg\_sales\_tsv](#tco.tcocalc.fill_reg_sales_tsv) - * [fill\_insurance\_tsv](#tco.tcocalc.fill_insurance_tsv) - * [fill\_residual\_cost\_tsc](#tco.tcocalc.fill_residual_cost_tsc) - * [fill\_survival\_tsv](#tco.tcocalc.fill_survival_tsv) - * [fill\_fuel\_split\_tsv](#tco.tcocalc.fill_fuel_split_tsv) - - - -# tco.tcocalc - - +* [t3co/tco/tcocalc](#t3co/tco/tcocalc) + * [find\_residual\_rates](#t3co/tco/tcocalc.find_residual_rates) + * [calculate\_dollar\_cost](#t3co/tco/tcocalc.calculate_dollar_cost) + * [calculate\_opp\_costs](#t3co/tco/tcocalc.calculate_opp_costs) + * [fill\_fuel\_eff\_file](#t3co/tco/tcocalc.fill_fuel_eff_file) + * [fill\_veh\_expense\_file](#t3co/tco/tcocalc.fill_veh_expense_file) + * [fill\_trav\_exp\_tsv](#t3co/tco/tcocalc.fill_trav_exp_tsv) + * [fill\_downtimelabor\_cost\_tsv](#t3co/tco/tcocalc.fill_downtimelabor_cost_tsv) + * [fill\_market\_share\_tsv](#t3co/tco/tcocalc.fill_market_share_tsv) + * [fill\_fuel\_expense\_tsv](#t3co/tco/tcocalc.fill_fuel_expense_tsv) + * [fill\_annual\_tsv](#t3co/tco/tcocalc.fill_annual_tsv) + * [fill\_reg\_sales\_tsv](#t3co/tco/tcocalc.fill_reg_sales_tsv) + * [fill\_insurance\_tsv](#t3co/tco/tcocalc.fill_insurance_tsv) + * [fill\_residual\_cost\_tsc](#t3co/tco/tcocalc.fill_residual_cost_tsc) + * [fill\_survival\_tsv](#t3co/tco/tcocalc.fill_survival_tsv) + * [fill\_fuel\_split\_tsv](#t3co/tco/tcocalc.fill_fuel_split_tsv) + + + +# t3co/tco/tcocalc + + #### find\_residual\_rates ```python -def find_residual_rates(vehicle, scenario) +def find_residual_rates(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> float ``` This helper method gets the residual rates from ResidualValues.csv @@ -41,12 +42,13 @@ This helper method gets the residual rates from ResidualValues.csv - `residual_rates` _float_ - Residual rate as percentage of MSRP - + #### calculate\_dollar\_cost ```python -def calculate_dollar_cost(veh, scenario) +def calculate_dollar_cost(veh: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> dict ``` This helper method calculates the MSRP breakdown dictionary from @@ -69,12 +71,14 @@ This helper method calculates the MSRP breakdown dictionary from - `cost_set` _dict_ - Dictionary containing MSRP breakdown - + #### calculate\_opp\_costs ```python -def calculate_opp_costs(vehicle, scenario, range_dict) +def calculate_opp_costs(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + range_dict: dict) -> dict ``` This helper method calculates opportunity costs and generates veh_opp_cost_set from @@ -87,13 +91,20 @@ This helper method calculates opportunity costs and generates veh_opp_cost_set f - `vehicle` _fastsim.vehicle.Vehicle_ - FASTSim vehicle object of analysis vehicle - `scenario` _run_scenario.Scenario_ - Scenario object of current selection - `range_dict` _dict_ - Dictionary containing range values from fueleconomy.get_range_mi() + + +**Returns**: + +- `veh_opp_cost_set` _dict_ - Dictionary containing opportunity cost results - + #### fill\_fuel\_eff\_file ```python -def fill_fuel_eff_file(vehicle, scenario, mpgge_dict) +def fill_fuel_eff_file(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + mpgge_dict: dict) -> pd.DataFrame ``` This helper method generates a dataframe of Fuel Efficiency [mi/gge] @@ -112,12 +123,13 @@ For HEV and CONV, mpgge - `fefdata` _pd.DataFrame_ - Dictionary containing Fuel Efficiency [mi/gge] - + #### fill\_veh\_expense\_file ```python -def fill_veh_expense_file(scenario, cost_set) +def fill_veh_expense_file(scenario: run_scenario.Scenario, + cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe of MSRP breakdown costs as Cost [$/veh] @@ -132,12 +144,13 @@ This helper method generates a dataframe of MSRP breakdown costs as Cost [$/veh] - `vexpdf` _pd.DataFrame_ - Dataframe containing MSRP components costs as Cost [$/veh] - + #### fill\_trav\_exp\_tsv ```python -def fill_trav_exp_tsv(vehicle, scenario) +def fill_trav_exp_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe containing maintenance costs in Cost [$/mi] @@ -152,12 +165,13 @@ This helper method generates a dataframe containing maintenance costs in Cost [$ - `df` _pd.DataFrame_ - Dataframe containing maintenance costs in Cost [$/mi] - + #### fill\_downtimelabor\_cost\_tsv ```python -def fill_downtimelabor_cost_tsv(scenario, oppy_cost_set) +def fill_downtimelabor_cost_tsv(scenario: run_scenario.Scenario, + oppy_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe containing fueling downtime and M&R downtime costs in Cost [$/Yr] @@ -172,12 +186,13 @@ This helper method generates a dataframe containing fueling downtime and M&R dow - `df` _pd.DataFrame_ - Dataframe containing fueling and MR downtime costs in Cost [$/Yr] - + #### fill\_market\_share\_tsv ```python -def fill_market_share_tsv(scenario, num_vs=1) +def fill_market_share_tsv(scenario: run_scenario.Scenario, + num_vs: int = 1) -> pd.DataFrame ``` This helper method generates a dataframe containing market share of current vehicle selection per vehicle sold @@ -192,12 +207,13 @@ This helper method generates a dataframe containing market share of current vehi - `df` _pd.DataFrame_ - Dataframe containing market share of current vehicle in Market Share [veh/veh] - + #### fill\_fuel\_expense\_tsv ```python -def fill_fuel_expense_tsv(vehicle, scenario) +def fill_fuel_expense_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe of fuel operating costs in Cost [$/gge] @@ -210,19 +226,19 @@ This helper method generates a dataframe of fuel operating costs in Cost [$/gge] **Raises**: -- `Exception` - Invalid fuel type +- `Exception` - Invalid fuel_type type **Returns**: - `df` _pd.DataFrame_ - Dataframe containing fuel operating costs in Cost [$/gge] - + #### fill\_annual\_tsv ```python -def fill_annual_tsv(scenario) +def fill_annual_tsv(scenario: run_scenario.Scenario) -> pd.DataFrame ``` This helper method generates a dataframe of annual vehicle miles traveled (vmt) - Annual Travel [mi/yr] @@ -236,12 +252,13 @@ This helper method generates a dataframe of annual vehicle miles traveled (vmt) - `df` _pd.DataFrame_ - Dataframe containing Annual Travel [mi/yr] - + #### fill\_reg\_sales\_tsv ```python -def fill_reg_sales_tsv(scenario, num_vs=1) +def fill_reg_sales_tsv(scenario: run_scenario.Scenario, + num_vs: int = 1) -> pd.DataFrame ``` This helper method generates a dataframe containing vehicle sales per year - Sales [veh] @@ -256,12 +273,13 @@ This helper method generates a dataframe containing vehicle sales per year - Sal - `df` _pd.DataFrame_ - Dataframe containing vehicle sales in Sales [veh] - + #### fill\_insurance\_tsv ```python -def fill_insurance_tsv(scenario, veh_cost_set) +def fill_insurance_tsv(scenario: run_scenario.Scenario, + veh_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe containing vehicle insurance costs as Cost [$/Yr] @@ -276,12 +294,14 @@ This helper method generates a dataframe containing vehicle insurance costs as C - `df` _pd.DataFrame_ - Dataframe containing insurance costs in Cost [$/Yr] - + #### fill\_residual\_cost\_tsc ```python -def fill_residual_cost_tsc(vehicle, scenario, veh_cost_set) +def fill_residual_cost_tsc(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + veh_cost_set: dict) -> pd.DataFrame ``` This helper method generates a dataframe of residual costs as Cost [$/Yr] @@ -297,12 +317,13 @@ This helper method generates a dataframe of residual costs as Cost [$/Yr] - `df` _pd.DataFrame_ - Dataframe containing vehicle residual costs as Cost [$/Yr] - + #### fill\_survival\_tsv ```python -def fill_survival_tsv(scenario, num_vs=1) +def fill_survival_tsv(scenario: run_scenario.Scenario, + num_vs=1) -> pd.DataFrame ``` This helper method generates a dataframe containing surviving vehicles as Surviving Vehicles [veh/veh] @@ -317,12 +338,14 @@ This helper method generates a dataframe containing surviving vehicles as Surviv - `df` _pd.DataFrame_ - Dataframe containing number of surviving vehicles on road in Surviving Vehicles [veh/veh] - + #### fill\_fuel\_split\_tsv ```python -def fill_fuel_split_tsv(vehicle, scenario, mpgge) +def fill_fuel_split_tsv(vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + mpgge: dict) -> pd.DataFrame ``` This helper method generates a dataframe of fraction of travel in each fuel type as Fraction of Travel [mi/mi] diff --git a/docs/index.md b/docs/index.md index c20359b..2d7d193 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,9 +1,13 @@ -# Description +![T3CO Logo](https://www.nrel.gov/transportation/assets/images/t3co-icon-web.jpg) + +# **T3CO** : Transportation Technology Total Cost of Ownership Tool + +## Description This repo houses T3CO (Transportation Technology Total Cost of Ownership), software for modeling total cost of ownership for commercial vehicles with advanced powertrains. To start, go to the [Overview](https://github.com/NREL/T3CO-private/blob/52252a06fd16cc7bae377f169b78d02c30887b96/docs/index.md) -# Usage +## Usage **T3CO** is a general framework allowing a user to determine the total cost of ownership (TCO) of a FASTSim vehicle (paired with a FASTSim DriveCycle(s) for determining fuel efficiency). The user can also determine performance of gradability, acceleration, and range. In addition to straight TCO computation there is also the option to optimize a vehicle powertrain such that it meets performance optional targets while also optionally minimizing TCO. diff --git a/docs/models/TCO_calculations.md b/docs/models/TCO_calculations.md index 7510056..ad5d094 100644 --- a/docs/models/TCO_calculations.md +++ b/docs/models/TCO_calculations.md @@ -1,7 +1,7 @@ # Contents - [Contents](#contents) - - [Overview ](#overview-) - - [Vehicle MSRP ](#vehicle-msrp-) + - [Overview ](#overview) + - [Vehicle MSRP ](#vehicle-msrp) - [MSRP Inputs](#msrp-inputs) - [MSRP Formula](#msrp-formula) - [MSRP Code](#msrp-code) @@ -16,7 +16,7 @@ ## Overview The Total Cost of Ownership is a core metric calculated by T3CO. It is made up of a few parts. The first is **MSRP**, or the purchase cost of the vehicle. Then there is fuel cost for each operational year. Then there are "other costs" as well as Payload Opportunity Costs. -## Vehicle MSRP +## Vehicle MSRP The vehicle MSRP is composed of a glider cost, powertrain costs from engine and/or motor, energy storage for liquid fuel or battery pack, the plug for PHEVs and EVs, the battery replacement cost (rarely used), & the Purchase tax. **example** @@ -35,7 +35,7 @@ The vehicle MSRP is composed of a glider cost, powertrain costs from engine and/ The Glider and Plug costs are straight inputs from the T3CO scenario file. Battery and Fuel Storage are computed on a `$/kWh` basis. Fuel converter and Motor & power electronics are computed on a `$/kW` also from the T3CO [scenario file](ScenarioFile.md). -##### MSRP Inputs +##### MSRP Inputs |column name|example value| bounds | |---|----|----| |`ess_cost_dol_per_kw`|`0`| `float` | diff --git a/docs/t3co_logo.png b/docs/t3co_logo.png new file mode 100644 index 0000000..e1e87f0 Binary files /dev/null and b/docs/t3co_logo.png differ diff --git a/docs/vehicle_inputs_descriptions.md b/docs/vehicle_inputs_descriptions.md new file mode 100644 index 0000000..6c22913 --- /dev/null +++ b/docs/vehicle_inputs_descriptions.md @@ -0,0 +1,68 @@ +# Vehicle Input Descriptions + +| vehicle parameter | description | data type | +|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|----------------| +| scenario_name | Vehicle name |  string | +| selection | Vehicle database ID |  int | +| veh_year | Vehicle year |  int | +| veh_pt_type | Vehicle powertrain type, one of [CONV, HEV, PHEV, BEV] |  string | +| drag_coef | Aerodynamic drag coefficient |  float | +| frontal_area_m2 | Frontal area, $m^2$ |  float | +| glider_kg | Vehicle mass excluding cargo, passengers, and powertrain components, $kg$ |  float | +| veh_cg_m | Vehicle center of mass height, $m$ NOTE: positive for FWD, negative for RWD, AWD, 4WD |  float | +| drive_axle_weight_frac | Fraction of weight on the drive axle while stopped |  float | +| wheel_base_m | Wheelbase, $m$ |  float | +| cargo_kg | Cargo mass including passengers, $kg$ |  float | +| veh_override_kg | Total vehicle mass, overrides mass calculation, $kg$ |  Option | +| comp_mass_multiplier | Component mass multiplier for vehicle mass calculation |  float | +| fs_max_kw | Fuel storage max power output, $kW$ |  float | +| fs_secs_to_peak_pwr | Fuel storage time to peak power, $s$ |  float | +| fs_kwh | Fuel storage energy capacity, $kWh$ |  float | +| fs_kwh_per_kg | Fuel specific energy, $\frac{kWh}{kg}$ |  float | +| fc_max_kw | Fuel converter peak continuous power, $kW$ |  float | +| fc_pwr_out_perc | Fuel converter output power percentage map, x values of fc_eff_map |  Array1 | +| fc_eff_map | Fuel converter efficiency map |  Array1 | +| fc_eff_type | Fuel converter efficiency type, one of [SI, ATKINSON, DIESEL, H2FC, HD_DIESEL] Used for calculating fc_eff_map, and other calculations if H2FC |  string | +| fc_sec_to_peak_pwr | Fuel converter time to peak power, $s$ |  float | +| fc_base_kg | Fuel converter base mass, $kg$ |  float | +| fc_kw_per_kg | Fuel converter specific power (power-to-weight ratio), $\frac{kW}{kg}$ |  float | +| min_fc_time_on | Minimum time fuel converter must be on before shutoff (for HEV, PHEV) |  float | +| idle_fc_kw | Fuel converter idle power, $kW$ |  float | +| mc_max_kw | Peak continuous electric motor power, $kW$ |  float | +| mc_pwr_out_perc | Electric motor output power percentage map, x values of mc_eff_map |  Array1 | +| mc_eff_map | Electric motor efficiency map |  Array1 | +| mc_sec_to_peak_pwr | Electric motor time to peak power, $s$ |  float | +| mc_pe_kg_per_kw | Motor power electronics mass per power output, $\frac{kg}{kW}$ |  float | +| mc_pe_base_kg | Motor power electronics base mass, $kg$ |  float | +| ess_max_kw | Traction battery maximum power output, $kW$ |  float | +| ess_max_kwh | Traction battery energy capacity, $kWh$ |  float | +| ess_kg_per_kwh | Traction battery mass per energy, $\frac{kg}{kWh}$ |  float | +| ess_base_kg | Traction battery base mass, $kg$ |  float | +| ess_round_trip_eff | Traction battery round-trip efficiency |  float | +| ess_life_coef_a | Traction battery cycle life coefficient A, see reference |  float | +| ess_life_coef_b | Traction battery cycle life coefficient B, see reference |  float | +| min_soc | Traction battery minimum state of charge |  float | +| max_soc | Traction battery maximum state of charge |  float | +| ess_dischg_to_fc_max_eff_perc | ESS discharge effort toward max FC efficiency |  float | +| ess_chg_to_fc_max_eff_perc | ESS charge effort toward max FC efficiency |  float | +| wheel_inertia_kg_m2 | Mass moment of inertia per wheel, $kg \cdot m^2$ |  float | +| num_wheels | Number of wheels |  float | +| wheel_rr_coef | Rolling resistance coefficient |  float | +| wheel_radius_m | Wheel radius, $m$ |  float | +| wheel_coef_of_fric | Wheel coefficient of friction |  float | +| max_accel_buffer_mph | Speed where the battery reserved for accelerating is zero |  float | +| max_accel_buffer_perc_of_useable_soc | Percent of usable battery energy reserved to help accelerate |  float | +| perc_high_acc_buf | Percent SOC buffer for high accessory loads during cycles with long idle time |  float | +| mph_fc_on | Speed at which the fuel converter must turn on, $mph$ |  float | +| kw_demand_fc_on | Power demand above which to require fuel converter on, $kW$ |  float | +| max_regen | Maximum brake regeneration efficiency |  float | +| stop_start | Stop/start micro-HEV flag |  bool | +| force_aux_on_fc | Force auxiliary power load to come from fuel converter |  bool | +| alt_eff | Alternator efficiency |  float | +| chg_eff | Charger efficiency |  float | +| aux_kw | Auxiliary load power, $kW$ |  float | +| trans_kg | Transmission mass, $kg$ |  float | +| trans_eff | Transmission efficiency |  float | +| ess_to_fuel_ok_error | Maximum acceptable ratio of change in ESS energy to expended fuel energy (used in hybrid SOC balancing), $\frac{\Delta E_{ESS}}{\Delta E_{fuel}}$ |  float | +| fc_peak_eff_override | Fuel converter efficiency peak override, scales entire curve |  Option | +| mc_peak_eff_override | Motor efficiency peak override, scales entire curve |  Option | diff --git a/mkdocs.yml b/mkdocs.yml index fc69b07..f8399fb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,28 +1,47 @@ site_name: T3CO site_description: Transportation Technology Total Cost of Ownership -repo_url: https://github.com/NREL/T3CO-private +repo_url: https://github.com/NREL/T3CO +edit_uri: https://github.com/NREL/T3CO/tree/main/docs +site_author: Harish Panneer Selvam plugins: - search - mkdocstrings - markdown_extensions: - toc: permalink: true - + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + theme: - name: readthedocs + name: material + favicon: t3co_logo.png highlightjs: true hljs_languages: - python - yaml features: - search.highlight + - content.action.view + - search.suggest + icon: + repo: fontawesome/brands/github + edit: material/pencil + view: material/eye nav: - Home: index.md - Installation: installation.md + - Inputs: + - Vehicle: vehicle_inputs_descriptions.md + - Scenario: scenario_inputs_descriptions.md + - Config: config_inputs_descriptions.md - Code Reference: - CodeFlow: CodeFlow.md - T3CO Modules: diff --git a/pyproject.toml b/pyproject.toml index 8e16ed4..ca3863a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ NREL's Transportation Technology Total Cost of Ownership tool readme = "README.md" license = {file = "LICENSE"} classifiers = [ - "Development Status :: 5 - Production/Stable", + "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Intended Audience :: Education", diff --git a/t3co/moopack/moo.py b/t3co/moopack/moo.py index 0a59517..84856cf 100644 --- a/t3co/moopack/moo.py +++ b/t3co/moopack/moo.py @@ -1,6 +1,7 @@ import copy import logging import time +from typing import Tuple import warnings from time import gmtime, strftime @@ -17,7 +18,9 @@ # from pymoo.algorithms.so_local_search import LocalSearch from pymoo.algorithms.soo.nonconvex.pso import PSO +import pymoo.core from pymoo.core.problem import ElementwiseProblem +import pymoo.core.result from pymoo.operators.sampling.lhs import LatinHypercubeSampling as LHS # pymoo stuff @@ -25,7 +28,7 @@ from pymoo.termination.default import DefaultMultiObjectiveTermination as MODT from pymoo.termination.ftol import MultiObjectiveSpaceTermination from pymoo.util.display.output import Output - +import pymoo from t3co.run import Global as gl from t3co.run import run_scenario @@ -172,22 +175,22 @@ def setup_opt_records(self): def __init__( self, - knobs_bounds, - vnum, - optimize_pt=gl.BEV, - obj_list=None, - constr_list=None, - verbose=False, - config=None, + knobs_bounds: dict, + vnum: float, + optimize_pt: str = gl.BEV, + obj_list: list = None, + constr_list: list = None, + verbose: bool = False, + config: run_scenario.Config = None, **kwargs, - ): + ) -> None: """ This constructor initializes optimization input variables Args: knobs_bounds (dict): Dictionary containing knobs bounds for optimization vnum (float): Vehicle selection number - optimize_pt (vehicle.veh_pt_type, optional): Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. + optimize_pt (str, optional): Vehicle powertrain type - Conv, BEV, HEV, PHEV. Defaults to gl.BEV. obj_list (list, optional): List of objectives. Defaults to None. constr_list (list, optional): List of constraints. Defaults to None. verbose (bool, optional): if True, prints process steps. Defaults to False. @@ -358,7 +361,7 @@ def __init__( f"Possible unused/invalid kwargs provided:\n {list(kwargs.keys())}" ) - def compile_reporting_vars(self): + def compile_reporting_vars(self) -> None: """ This method creates an output dictionary containing optimization results """ @@ -372,7 +375,9 @@ def compile_reporting_vars(self): "r_sec_to_ach_30mph_ldd": self.r_accel_30l, "r_sec_to_ach_60mph_ldd": self.r_accel_60l, "r_ach_ranges_mi": self.r_ranges, - "target_mph_grade_6s": [self.opt_scenario.min_speed_at_6pct_grade_in_5min_mph] + "target_mph_grade_6s": [ + self.opt_scenario.min_speed_at_6pct_grade_in_5min_mph + ] * len(self.r_grade_6s), "target_mph_grade_125s": [ self.opt_scenario.min_speed_at_125pct_grade_in_5min_mph @@ -382,7 +387,8 @@ def compile_reporting_vars(self): * len(self.r_grade_6s), "target_sec_to_60mph_ldd": [self.opt_scenario.max_time_0_to_60mph_at_gvwr_s] * len(self.r_grade_6s), - "target_range_mi": [self.opt_scenario.target_range_mi] * len(self.r_grade_6s), + "target_range_mi": [self.opt_scenario.target_range_mi] + * len(self.r_grade_6s), "r_ach_fuel_efficiencies": self.r_fuel_efficiencies, "accel_30_constraint_vals": self.accel_30_constraint, "accel_60_constraint_vals": self.accel_60_constraint, @@ -402,12 +408,12 @@ def compile_reporting_vars(self): } self.reporting_vars = pd.DataFrame(data=d) - def instantiate_moo_vehicles_and_scenario(self, vnum, config=None): + def instantiate_moo_vehicles_and_scenario(self, vnum: int, config=None) -> None: """ This method instantiates the multi-objective optimization problem vehicles and scenarios, starting with the baseline Conventional vehicle. Args: - vnum (float): vehicle selection number + vnum (int): vehicle selection number config (run_scenario.Config, optional): T3CO Config object containing analysis attributes and scenario attribute overrides. Defaults to None. Raises: @@ -429,7 +435,9 @@ def instantiate_moo_vehicles_and_scenario(self, vnum, config=None): self.opt_scenario.fuel_type = "diesel" # save baseline values for optimization diffs - self.opt_scenario.originalGliderPrice = self.opt_scenario.vehicle_glider_cost_dol + self.opt_scenario.originalGliderPrice = ( + self.opt_scenario.vehicle_glider_cost_dol + ) self.opt_scenario.originalglider_kg = self.moobasevehicle.glider_kg self.opt_scenario.originalIceDolPerKw = self.opt_scenario.fc_ice_cost_dol_per_kw self.opt_scenario.origfc_eff_map = self.moobasevehicle.fc_eff_map.copy() @@ -464,7 +472,9 @@ def instantiate_moo_vehicles_and_scenario(self, vnum, config=None): # self.oppcostobj = opportunity_cost.OpportunityCost(self.opt_scenario) # --------- optimizer parameter application methods --------- - def cda_percent_delta_knob(self, CdA_perc_reduction, optvehicle): + def cda_percent_delta_knob( + self, CdA_perc_reduction: str, optvehicle: fastsim.vehicle.Vehicle + ) -> None: """ This method sets the drag_coef based on aero improvement curve and glider_kg based on cda_cost_coeff_a and cda_cost_coeff_b @@ -518,14 +528,18 @@ def get_mass_per_CdA_delta(x): ) # glider cost penalty due to CdA improvement CdA_cost = get_cost_per_CdA_delta(CdA_perc_reduction) - self.opt_scenario.vehicle_glider_cost_dol = self.opt_scenario.vehicle_glider_cost_dol + CdA_cost + self.opt_scenario.vehicle_glider_cost_dol = ( + self.opt_scenario.vehicle_glider_cost_dol + CdA_cost + ) # mass adjustments. Add CdA mass FIRST, if applicable. Then limit cargo_kg if overweight from battery. optvehicle.glider_kg = optvehicle.glider_kg + get_mass_per_CdA_delta( CdA_perc_reduction ) optvehicle.set_veh_mass() - def weight_delta_percent_knob(self, wt_perc_reduction, optvehicle): + def weight_delta_percent_knob( + self, wt_perc_reduction: float, optvehicle: fastsim.vehicle.Vehicle + ) -> None: """ This method sets the knob from the lightweighting curve @@ -546,13 +560,15 @@ def weight_delta_percent_knob(self, wt_perc_reduction, optvehicle): if wt_delta_kg not in x_new: x_new = np.append(x_new, wt_delta_kg) y_new = np.append(y_new, wt_delta_cost_per_kg) - self.opt_scenario.vehicle_glider_cost_dol = self.opt_scenario.vehicle_glider_cost_dol + np.trapz( - y_new, x_new + self.opt_scenario.vehicle_glider_cost_dol = ( + self.opt_scenario.vehicle_glider_cost_dol + np.trapz(y_new, x_new) ) optvehicle.glider_kg = optvehicle.glider_kg - wt_delta_kg optvehicle.set_veh_mass() - def fc_peak_eff_knob(self, fc_peak_eff, optvehicle): + def fc_peak_eff_knob( + self, fc_peak_eff: float, optvehicle: fastsim.vehicle.Vehicle + ) -> None: """ This method sets the knob from the engine efficiency curve @@ -568,10 +584,12 @@ def fc_peak_eff_knob(self, fc_peak_eff, optvehicle): ) self.adjust_fc_peak_eff(fc_peak_eff, self.opt_scenario, optvehicle) - def get_objs(self, x, write_tsv=False): + def get_objs( + self, x: dict, write_tsv: bool = False + ) -> Tuple[np.array, np.array, dict]: """ This method gets called when PyMoo calls _evaluate. It initializes objectives and constraints and runs vehicle_scenario_sweep - + x optimization knobs = [max motor kw, battery kwh, drag coeff % improvement] Function for running FE cycles and accel tests then returning fuel consumption and zero-to-sixty times. @@ -598,7 +616,9 @@ def get_objs(self, x, write_tsv=False): optvehicle = self.mooadvancedvehicle # reset glider price and weight for light-weighting and/or CdA percent improvement - self.opt_scenario.vehicle_glider_cost_dol = self.opt_scenario.originalGliderPrice + self.opt_scenario.vehicle_glider_cost_dol = ( + self.opt_scenario.originalGliderPrice + ) optvehicle.glider_kg = self.opt_scenario.originalglider_kg wt_delta_perc_guess = x_dict.pop(KNOB_WTDELTAPERC, None) @@ -752,7 +772,10 @@ def get_objs(self, x, write_tsv=False): if GRADE125 in self.constr_list: # todo, -abs() for all of these? g125c = ( - -(g125_acvhd - self.opt_scenario.min_speed_at_125pct_grade_in_5min_mph) + -( + g125_acvhd + - self.opt_scenario.min_speed_at_125pct_grade_in_5min_mph + ) / self.opt_scenario.min_speed_at_125pct_grade_in_5min_mph ) constr_perc[GRADE125] = g125c @@ -806,7 +829,8 @@ def get_objs(self, x, write_tsv=False): ) # pos return, failed else: range_mi_cv = range_achvd - ( - self.opt_scenario.target_range_mi * (1 + self.range_overshoot_tol) + self.opt_scenario.target_range_mi + * (1 + self.range_overshoot_tol) ) constraint_results_G.append(range_mi_cv) @@ -883,7 +907,7 @@ def get_objs(self, x, write_tsv=False): return np.array(obj_arr_F), np.array(constraint_results_G), rs_sweep - def _evaluate(self, x, out, *args, **kwargs): + def _evaluate(self, x: dict, out: dict, *args, **kwargs) -> None: """ This method runs T3COProblem.get_objs() when running Pymoo optimization @@ -897,7 +921,12 @@ def _evaluate(self, x, out, *args, **kwargs): if len(constr_arr) > 0: out["G"] = constr_arr - def adjust_fc_peak_eff(self, fc_peak_eff, scenario, optvehicle): + def adjust_fc_peak_eff( + self, + fc_peak_eff: float, + scenario: run_scenario.Scenario, + optvehicle: fastsim.vehicle.Vehicle, + ) -> None: """ This method augments an advanced vehicle fc_eff_array based on new fc_peak_eff using baseline fc_eff_array @@ -914,7 +943,14 @@ def adjust_fc_peak_eff(self, fc_peak_eff, scenario, optvehicle): optvehicle.set_derived() # ------------------------------------ utility functions ------------------------------------ - def sweep_knob(self, knob, definition=100, plot=False, optres=None, **kwargs): + def sweep_knob( + self, + knob: list, + definition: int = 100, + plot: bool = False, + optres: float = None, + **kwargs, + ) -> list: """ This method sweeps the optimization knob of vehicle from lbound to ubound, return TCO \ plot optres to see if there's agreement from opt solution and your sweep @@ -956,12 +992,18 @@ def sweep_knob(self, knob, definition=100, plot=False, optres=None, **kwargs): sixty_mph_times.append([z60l, x]) for res in sixty_mph_times: z60l, x = res - if z60l > self.opt_scenario.max_time_0_to_60mph_at_gvwr_s and x < opt_res_kw: + if ( + z60l > self.opt_scenario.max_time_0_to_60mph_at_gvwr_s + and x < opt_res_kw + ): largest_infeasible_60s_size = x failed_60_s_time = z60l for res in sixty_mph_times: z30l, x = res - if z30l > self.opt_scenario.max_time_0_to_30mph_at_gvwr_s and x < opt_res_kw: + if ( + z30l > self.opt_scenario.max_time_0_to_30mph_at_gvwr_s + and x < opt_res_kw + ): largest_infeasible_30s_size = x failed_30_s_time = z30l @@ -1013,7 +1055,7 @@ def sweep_knob(self, knob, definition=100, plot=False, optres=None, **kwargs): self.obj_list = temp_obj_list return tcos - def get_tco_from_moo_advanced_result(self, x): + def get_tco_from_moo_advanced_result(self, x: dict) -> dict: """ This method is a utility function to get detailed TCO information from optimized MOO result @@ -1064,14 +1106,14 @@ class T3CODisplay(Output): Output (pymoo.util.display.output.Output): Pymoo minimize display object """ - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: """ This constructor initializes the pymoo.util.display.Display object """ super().__init__(**kwargs) self.term = MultiObjectiveSpaceTermination() - def _do(self, problem, evaluator, algorithm): + def _do(self, problem: T3COProblem, evaluator: float, algorithm: str) -> None: """ This constructor creates the output printouts @@ -1121,19 +1163,19 @@ def _do(self, problem, evaluator, algorithm): def run_optimization( - pop_size, - n_max_gen, - knobs_bounds, - vnum, - x_tol, - f_tol, - nth_gen, - n_last, - algo, - obj_list=None, - config=None, + pop_size: int, + n_max_gen: int, + knobs_bounds: dict, + vnum: int, + x_tol: float, + f_tol: float, + nth_gen: int, + n_last: int, + algo: str, + obj_list: list = None, + config: run_scenario.Config = None, **kwargs, -): +) -> Tuple[pymoo.core.result.Result, T3COProblem, bool]: """ This method creates and runs T3COProblem minimization @@ -1141,7 +1183,7 @@ def run_optimization( pop_size (int): Population size for optimization n_max_gen (int): maximum number of generations for optimization knobs_bounds (dict): Dictionary containing knobs and bounds - vnum (float): vehicle selection number + vnum (int): vehicle selection number x_tol (float): tolerance in parameter space f_tol (float): tolerance in objective space nth_gen (int): number of generations to evaluate if convergence occurs @@ -1274,4 +1316,4 @@ def run_optimization( # print("Exception type : %s " % ex_type.__name__) # print("Exception message : %s" %ex_value) -# print("Stack trace : %s" %stack_trace) \ No newline at end of file +# print("Stack trace : %s" %stack_trace) diff --git a/t3co/objectives/accel.py b/t3co/objectives/accel.py index 51f9ded..d6a12fd 100644 --- a/t3co/objectives/accel.py +++ b/t3co/objectives/accel.py @@ -1,7 +1,11 @@ """Module for simulating acceleration performance.""" + # %% +from __future__ import annotations + import time from pathlib import Path +from typing import Tuple import numpy as np from fastsim import cycle @@ -9,15 +13,16 @@ from t3co.run import Global as gl from t3co.run import run_scenario +import fastsim def get_accel( - analysis_vehicle, - scenario=None, - set_weight_to_max_kg=True, + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario = None, + set_weight_to_max_kg: bool = True, verbose=False, ess_init_soc=None, -): +) -> Tuple[float, float, fastsim.vehicle.Vehicle]: """ This function runs a simdrive for getting 0-to-60 and 0-30 mph time with fully laden weight at GVWR (plus gvwr_credit_kg?) @@ -72,7 +77,7 @@ def get_accel( <= accel_simdrive.sim_params.trace_miss_dist_tol ) - def test_accel(speed_mph_target): + def test_accel(speed_mph_target: float) -> float: """ This function gets the time it takes to reach target speed diff --git a/t3co/objectives/fueleconomy.py b/t3co/objectives/fueleconomy.py index de19083..3eb29fc 100644 --- a/t3co/objectives/fueleconomy.py +++ b/t3co/objectives/fueleconomy.py @@ -1,4 +1,5 @@ """Module containing functions for calculating fuel economy objectives.""" + # %% from __future__ import annotations @@ -13,22 +14,24 @@ from t3co.run import run_scenario -def get_range_mi(mpgge_info:dict, vehicle:fastsim.vehicle.Vehicle, scenario) -> dict: +def get_range_mi( + mpgge_info: dict, vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario +) -> dict: """ This funcion computes range [miles] from mpgge using vehicle powertrain type and energy (or fuel) store size. Considerations: - - at some point each vehicle powertrain type could employ the concept - of a "first fuel" or "primary fuel" - so return a primary fuel-based range for all - powertrains. + - at some point each vehicle powertrain type could employ the concept + of a "first fuel" or "primary fuel" - so return a primary fuel-based range for all + powertrains. - PHEVs have two fuels (generally diesel and electricity). So return two ranges: -- One for determining range during optimization - i.e. the CD range that PHEVs are commonly specified with + i.e. the CD range that PHEVs are commonly specified with (e.g. PHEV-50 = PHEV with 50 mi AER "All-Electric Range" ~= CD range) -- One that represents the "true" total PHEV range (CD + CS using both ESS and FS) Args: - mpgge_info (dict): Dictionary containing MPGGE breakdown + mpgge_info (dict): Dictionary containing MPGGE breakdown vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object of analysis vehicle scenario (run_scenario.Scenario): Scenario object of current selection @@ -38,48 +41,64 @@ def get_range_mi(mpgge_info:dict, vehicle:fastsim.vehicle.Vehicle, scenario) -> range_dict = {} kwh_per_gge = gl.get_kwh_per_gge() if vehicle.veh_pt_type == gl.BEV: - assert vehicle.fs_kwh == 0 and vehicle.fc_max_kw == 0, "Error! BEV vehicle has non-zero ICE attributes - vehicle mass calculation may be off" + assert ( + vehicle.fs_kwh == 0 and vehicle.fc_max_kw == 0 + ), "Error! BEV vehicle has non-zero ICE attributes - vehicle mass calculation may be off" mpgge = mpgge_info["mpgge"] # use fuel efficiency from battery - range_mi = vehicle.ess_max_kwh * (vehicle.max_soc - vehicle.min_soc) * mpgge / kwh_per_gge - range_dict['primary_fuel_range_mi'] = range_mi + range_mi = ( + vehicle.ess_max_kwh + * (vehicle.max_soc - vehicle.min_soc) + * mpgge + / kwh_per_gge + ) + range_dict["primary_fuel_range_mi"] = range_mi elif vehicle.veh_pt_type == gl.CONV: - assert vehicle.ess_max_kwh == 0 and vehicle.mc_max_kw == 0, "Error! CONV vehicle has non-zero BEV attributes - vehicle mass calculation may be off" + assert ( + vehicle.ess_max_kwh == 0 and vehicle.mc_max_kw == 0 + ), "Error! CONV vehicle has non-zero BEV attributes - vehicle mass calculation may be off" mpgge = mpgge_info["mpgge"] range_mi = (vehicle.fs_kwh / kwh_per_gge) * mpgge - range_dict['primary_fuel_range_mi'] = range_mi + range_dict["primary_fuel_range_mi"] = range_mi elif vehicle.veh_pt_type == gl.HEV: mpgge = mpgge_info["mpgge"] - elec_range_mi = vehicle.ess_max_kwh * (vehicle.max_soc - vehicle.min_soc) * mpgge / kwh_per_gge + elec_range_mi = ( + vehicle.ess_max_kwh + * (vehicle.max_soc - vehicle.min_soc) + * mpgge + / kwh_per_gge + ) conv_range_mi = (vehicle.fs_kwh / kwh_per_gge) * mpgge range_mi = elec_range_mi + conv_range_mi - range_dict['primary_fuel_range_mi'] = range_mi + range_dict["primary_fuel_range_mi"] = range_mi elif vehicle.veh_pt_type == gl.PHEV: # https://github.nrel.gov/AVCI/FASTSim_TCO_Truck/issues/24#issuecomment-39958 # charge depleting range [miles] # CDrangeMiles = MIN( ESSmaxKWh*(CDmaxSOC- CDminSOC)/ CDelectricityKWhperMile , maxFuelStorKWh/33.7/ CDfuelGGEperMile ) cd_range_mi = min( - vehicle.ess_max_kwh * (vehicle.max_soc - vehicle.min_soc) / mpgge_info['cd_electric_kwh__mi'], - vehicle.fs_kwh / kwh_per_gge * mpgge_info['cd_fuel_mpgge'] + vehicle.ess_max_kwh + * (vehicle.max_soc - vehicle.min_soc) + / mpgge_info["cd_electric_kwh__mi"], + vehicle.fs_kwh / kwh_per_gge * mpgge_info["cd_fuel_mpgge"], ) # charge sustaining range [miles] - # note, CS range in this way of thinking, is essentially what range is *left over* after you've exhausted the battery to min SOC + # note, CS range in this way of thinking, is essentially what range is *left over* after you've exhausted the battery to min SOC # and switch into CS mode from CD mode, thus we subtract cd_gge_used from the GGE fuel stores of the vehicle - cd_gge_used = cd_range_mi / mpgge_info['cd_fuel_mpgge'] + cd_gge_used = cd_range_mi / mpgge_info["cd_fuel_mpgge"] gge_capacity = vehicle.fs_kwh / kwh_per_gge - cs_range_mi = (gge_capacity - cd_gge_used) * mpgge_info['cs_fuel_mpgge'] + cs_range_mi = (gge_capacity - cd_gge_used) * mpgge_info["cs_fuel_mpgge"] true_range_mi = cd_range_mi + cs_range_mi - range_dict= { + range_dict = { "cd_aer_phev_range_mi": cd_range_mi, - "cs_phev_range_mi" : cs_range_mi, + "cs_phev_range_mi": cs_range_mi, "true_phev_range_mi": true_range_mi, "primary_fuel_range_mi": cd_range_mi, - } + } # if sim_drive: # range_dict["cycle_distance_mi"] = sum(sim_drive.cyc.mps * np.diff(sim_drive.cyc.time_s)[0]) * gl.m_to_mi - # range_dict["mean_cyc_speed_mph"] = sum(sim_drive.cyc.mps)/max(sim_drive.cyc.time_s) * gl.mps_to_mph + # range_dict["mean_cyc_speed_mph"] = sum(sim_drive.cyc.mps)/max(sim_drive.cyc.time_s) * gl.mps_to_mph # elif range_cyc: # range_dict["cycle_distance_mi"] = sum(range_cyc.mps * np.diff(range_cyc.time_s)[0]) * gl.m_to_mi - # range_dict["mean_cyc_speed_mph"] = sum(range_cyc.mps)/max(range_cyc.time_s) * gl.mps_to_mph + # range_dict["mean_cyc_speed_mph"] = sum(range_cyc.mps)/max(range_cyc.time_s) * gl.mps_to_mph return range_dict @@ -97,7 +116,7 @@ def get_sim_drive(erc, v, scenario): """ sim_drive = fastsim.simdrive.SimDrive(erc, v) sim_drive = sim_drive.to_rust() - + sim_params = sim_drive.sim_params sim_params.reset_orphaned() # sim_params.verbose = False @@ -115,8 +134,13 @@ def get_sim_drive(erc, v, scenario): return sim_drive -def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle, float]], - v:fastsim.vehicle.Vehicle, scenario, diagnostic=False): + +def get_mpgge( + eff_range_cyc: fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle, float]], + v: fastsim.vehicle.Vehicle, + scenario, + diagnostic=False, +) -> Tuple[dict, List[fastsim.simdrive.SimDrive], List[dict]]: """ This helper method gets the composite mpgge fuel efficiency of vehicle for each efficiency_range Drive Cycle and weight. It runs the vehicle using efficiency range cycle(s) and returns mpgge based on the powertrain type @@ -139,22 +163,34 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle Returns: mpgge_comp (dict): Dictionary containing MPGGE breakdowns sim_drives (List[fastsim.simdrive.SimDrive]): List of simdrives for charge depleting and charge sustaining cycles - mpgges (List[dict], optional): if diagnostic==True, returns additional - + mpgges (List[dict], optional): if diagnostic==True, returns additional + """ if not isinstance(eff_range_cyc, list): eff_range_cyc = [(eff_range_cyc, 1)] if v.veh_pt_type == gl.BEV: - assert v.mc_max_kw > 0, "motor size is 0 kw in BEV - will lead to faulty results" - assert v.fs_kwh == 0 and v.fc_max_kw == 0, "Error! BEV vehicle has non-zero ICE attributes - vehicle mass calculation may be off" + assert ( + v.mc_max_kw > 0 + ), "motor size is 0 kw in BEV - will lead to faulty results" + assert ( + v.fs_kwh == 0 and v.fc_max_kw == 0 + ), "Error! BEV vehicle has non-zero ICE attributes - vehicle mass calculation may be off" elif v.veh_pt_type == gl.CONV: - assert v.fc_max_kw > 0, "engine size is 0 kw in CONV - will lead to faulty results" - assert v.ess_max_kwh == 0 and v.mc_max_kw == 0, "Error! CONV vehicle has non-zero BEV attributes - vehicle mass calculation may be off" + assert ( + v.fc_max_kw > 0 + ), "engine size is 0 kw in CONV - will lead to faulty results" + assert ( + v.ess_max_kwh == 0 and v.mc_max_kw == 0 + ), "Error! CONV vehicle has non-zero BEV attributes - vehicle mass calculation may be off" elif v.veh_pt_type == gl.PHEV: - assert v.fc_max_kw > 0, "engine size is 0 kw in CONV - will lead to faulty results" - assert v.mc_max_kw > 0, "motor size is 0 kw in BEV - will lead to faulty results" + assert ( + v.fc_max_kw > 0 + ), "engine size is 0 kw in CONV - will lead to faulty results" + assert ( + v.mc_max_kw > 0 + ), "motor size is 0 kw in BEV - will lead to faulty results" elif v.veh_pt_type == gl.HEV: pass else: @@ -164,59 +200,72 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle weights = [] sim_drives = [] for cycle_weight in eff_range_cyc: - # efficiency-range cycle, weight - erc, w = cycle_weight + # efficiency-range cycle, weight + erc, w = cycle_weight if v.veh_pt_type == gl.PHEV: # get two copies of cycle, rename cd_erc = erc.copy() cs_erc = erc.copy() - cd_erc.name = 'CD_' + erc.name - + cd_erc.name = "CD_" + erc.name + # # Charge Depleting Cycle first # ess_max_kwh_orig = v.ess_max_kwh - ess_max_kw_orig = v.ess_max_kw - veh_kg_orig = v.veh_kg + ess_max_kw_orig = v.ess_max_kw + veh_kg_orig = v.veh_kg # infinite battery hack (with no extra weight) to simulate charge depleting behavior v.veh_override_kg = veh_kg_orig - run_scenario.set_max_battery_kwh(v, 50e3) + run_scenario.set_max_battery_kwh(v, 50e3) run_scenario.set_max_battery_power_kw(v, 1000) # don't want extra weight from huge battery sim_drive_cd = get_sim_drive(cd_erc, v, scenario) - assert sim_drive_cd.veh.veh_kg == veh_kg_orig, f'sim_drive.veh.veh_kg == veh_kg_orig / {round(sim_drive_cd.veh.veh_kg)} == {round(veh_kg_orig)}' - assert sim_drive_cd.veh.ess_max_kwh == v.ess_max_kwh, f'sim_drive.veh.ess_max_kwh == v.ess_max_kwh / {round(sim_drive_cd.veh.ess_max_kwh)} == {round(v.ess_max_kwh)}' + assert ( + sim_drive_cd.veh.veh_kg == veh_kg_orig + ), f"sim_drive.veh.veh_kg == veh_kg_orig / {round(sim_drive_cd.veh.veh_kg)} == {round(veh_kg_orig)}" + assert ( + sim_drive_cd.veh.ess_max_kwh == v.ess_max_kwh + ), f"sim_drive.veh.ess_max_kwh == v.ess_max_kwh / {round(sim_drive_cd.veh.ess_max_kwh)} == {round(v.ess_max_kwh)}" sim_drive_cd.sim_drive(init_soc=v.max_soc) v.veh_override_kg = None - + # # Charge Sustaining Cycle second # # reset battery to inputs for charge sustaining behavior - run_scenario.set_max_battery_kwh(v, ess_max_kwh_orig) - run_scenario.set_max_battery_power_kw(v, ess_max_kw_orig) - # we're supposed to run this as a "hybrid" so set + run_scenario.set_max_battery_kwh(v, ess_max_kwh_orig) + run_scenario.set_max_battery_power_kw(v, ess_max_kw_orig) + # we're supposed to run this as a "hybrid" so set # veh_pt_type to gl.HEV so that FASTSim does SOC balancing, run as an HEV, basically v.veh_pt_type = gl.HEV sim_drive_cs = get_sim_drive(cs_erc, v, scenario) sim_drive_cs.sim_drive() - # CS calcs - assert sim_drive_cs.props.kwh_per_gge == gl.get_kwh_per_gge(), "fuel LHV not consistent between T3CO and FASTSim" - cs_fuel_kwh_out_ach = np.sum(sim_drive_cs.fs_kwh_out_ach) + assert ( + sim_drive_cs.props.kwh_per_gge == gl.get_kwh_per_gge() + ), "fuel LHV not consistent between T3CO and FASTSim" + cs_fuel_kwh_out_ach = np.sum(sim_drive_cs.fs_kwh_out_ach) cs_fuel_kwh__mi = cs_fuel_kwh_out_ach / np.sum(sim_drive_cs.dist_mi) # CD calcs # sim_drive_cd.fs_kwh_out_ach[i] = sim_drive_cd.fs_kw_out_ach[i] * sim_drive_cd.cyc.dt_s[i] * (1 / 3.6e3) - assert sim_drive_cd.props.kwh_per_gge == gl.get_kwh_per_gge(), "fuel LHV not consistent between T3CO and FASTSim" - cd_fuel_kwh_out_ach = np.sum(sim_drive_cd.fs_kwh_out_ach) - cd_elec_kwh_out_ach = np.sum(np.array(sim_drive_cd.ess_kw_out_ach) * np.array(sim_drive_cd.cyc.dt_s) / 3.6e3) - cd_elec_mpgge = np.sum(sim_drive_cd.dist_mi) / (cd_elec_kwh_out_ach / gl.get_kwh_per_gge()) + assert ( + sim_drive_cd.props.kwh_per_gge == gl.get_kwh_per_gge() + ), "fuel LHV not consistent between T3CO and FASTSim" + cd_fuel_kwh_out_ach = np.sum(sim_drive_cd.fs_kwh_out_ach) + cd_elec_kwh_out_ach = np.sum( + np.array(sim_drive_cd.ess_kw_out_ach) + * np.array(sim_drive_cd.cyc.dt_s) + / 3.6e3 + ) + cd_elec_mpgge = np.sum(sim_drive_cd.dist_mi) / ( + cd_elec_kwh_out_ach / gl.get_kwh_per_gge() + ) cd_electric_kwh__mi = cd_elec_kwh_out_ach / np.sum(sim_drive_cd.dist_mi) cd_fuel_kwh__mi = cd_fuel_kwh_out_ach / np.sum(sim_drive_cd.dist_mi) - + v.veh_pt_type = gl.PHEV v.set_derived() assert v.veh_kg == veh_kg_orig @@ -231,15 +280,15 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle # desired outputs and have stricter checks mpgge = { #### Charge depleting #### - 'cd_electric_mpgge': cd_elec_mpgge, - 'cd_grid_electric_mpgge': cd_elec_mpgge * v.chg_eff, # can be used for TCO CD mpgge electric - 'cd_fuel_mpgge': sim_drive_cd.mpgge, - 'cd_fuel_mpgde': sim_drive_cd.mpgge / gl.DieselGalPerGasGal, + "cd_electric_mpgge": cd_elec_mpgge, + "cd_grid_electric_mpgge": cd_elec_mpgge + * v.chg_eff, # can be used for TCO CD mpgge electric + "cd_fuel_mpgge": sim_drive_cd.mpgge, + "cd_fuel_mpgde": sim_drive_cd.mpgge / gl.DieselGalPerGasGal, "cd_electric_kwh__mi": cd_electric_kwh__mi, "cd_fuel_kwh__mi": cd_fuel_kwh__mi, - 'cd_fuel_used_kwh': cd_fuel_kwh_out_ach, - 'cd_elec_used_kwh': cd_elec_kwh_out_ach, - + "cd_fuel_used_kwh": cd_fuel_kwh_out_ach, + "cd_elec_used_kwh": cd_elec_kwh_out_ach, #### Charge sustaining #### "cs_fuel_mpgge": sim_drive_cs.mpgge, "cs_fuel_mpgde": sim_drive_cs.mpgge / gl.DieselGalPerGasGal, @@ -261,14 +310,21 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle if v.veh_pt_type in [gl.CONV, gl.HEV]: mpgge_both = sim_drive.mpgge else: - mpgge_both = sim_drive.mpgge + (1/sim_drive.electric_kwh_per_mi) * gl.get_kwh_per_gge() + mpgge_both = ( + sim_drive.mpgge + + (1 / sim_drive.electric_kwh_per_mi) * gl.get_kwh_per_gge() + ) mpgge = { # combine ICE and electric PT components for overall mpgge "mpgge": mpgge_both, - "grid_mpgge": mpgge_both * sim_drive.veh.chg_eff, + "grid_mpgge": mpgge_both * sim_drive.veh.chg_eff, "mpgde": mpgge_both / gl.DieselGalPerGasGal, # TODO, have this checked - "kwh_per_mi": (sum(sim_drive.fs_kwh_out_ach) + ((sim_drive.roadway_chg_kj + sim_drive.ess_dischg_kj) / 3.6e3)) / sum(sim_drive.dist_mi), + "kwh_per_mi": ( + sum(sim_drive.fs_kwh_out_ach) + + ((sim_drive.roadway_chg_kj + sim_drive.ess_dischg_kj) / 3.6e3) + ) + / sum(sim_drive.dist_mi), } sim_drives.append(sim_drive) @@ -276,167 +332,327 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle weights.append(w) if v.veh_pt_type == gl.PHEV: - cs_fuel_mpgge_i = np.array([m['cs_fuel_mpgge'] for m in mpgges]) - cs_fuel_mpgde_i = np.array([m['cs_fuel_mpgde'] for m in mpgges]) - cs_fuel_kwh__mi_i = np.array([m['cs_fuel_kwh__mi'] for m in mpgges]) - - cd_fuel_used_kwh_i = [m['cd_fuel_used_kwh'] for m in mpgges] - cd_battery_used_kwh_i = [m['cd_elec_used_kwh'] for m in mpgges] - cd_fuel_mpgge_i = np.array([m['cd_fuel_mpgge'] for m in mpgges]) - cd_fuel_mpgde_i = np.array([m['cd_fuel_mpgde'] for m in mpgges]) - cd_electric_mpgge_i = np.array([m['cd_electric_mpgge'] for m in mpgges]) - cd_grid_electric_mpgge_i = np.array([m['cd_grid_electric_mpgge'] for m in mpgges]) - cd_electric_kwh__mi_i = np.array([m['cd_electric_kwh__mi'] for m in mpgges]) - cd_fuel_kwh__mi_i = np.array([m['cd_fuel_kwh__mi'] for m in mpgges]) - + cs_fuel_mpgge_i = np.array([m["cs_fuel_mpgge"] for m in mpgges]) + cs_fuel_mpgde_i = np.array([m["cs_fuel_mpgde"] for m in mpgges]) + cs_fuel_kwh__mi_i = np.array([m["cs_fuel_kwh__mi"] for m in mpgges]) + + cd_fuel_used_kwh_i = [m["cd_fuel_used_kwh"] for m in mpgges] + cd_battery_used_kwh_i = [m["cd_elec_used_kwh"] for m in mpgges] + cd_fuel_mpgge_i = np.array([m["cd_fuel_mpgge"] for m in mpgges]) + cd_fuel_mpgde_i = np.array([m["cd_fuel_mpgde"] for m in mpgges]) + cd_electric_mpgge_i = np.array([m["cd_electric_mpgge"] for m in mpgges]) + cd_grid_electric_mpgge_i = np.array( + [m["cd_grid_electric_mpgge"] for m in mpgges] + ) + cd_electric_kwh__mi_i = np.array([m["cd_electric_kwh__mi"] for m in mpgges]) + cd_fuel_kwh__mi_i = np.array([m["cd_fuel_kwh__mi"] for m in mpgges]) + mpgge_comp = { # Charge sustaining - 'cs_fuel_mpgge': np.sum(weights) / np.sum(np.divide(weights, cs_fuel_mpgge_i, out=np.zeros_like(cs_fuel_mpgge_i), where=cs_fuel_mpgge_i!=0, casting='unsafe')), - 'cs_fuel_mpgde': np.sum(weights) / np.sum(np.divide(weights, cs_fuel_mpgde_i, out=np.zeros_like(cs_fuel_mpgde_i), where=cs_fuel_mpgde_i!=0, casting='unsafe')), - 'cs_fuel_kwh__mi': np.sum(weights) / np.sum(np.divide(weights, cs_fuel_kwh__mi_i, out=np.zeros_like(cs_fuel_kwh__mi_i), where=cs_fuel_kwh__mi_i!=0, casting='unsafe')), - + "cs_fuel_mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + cs_fuel_mpgge_i, + out=np.zeros_like(cs_fuel_mpgge_i), + where=cs_fuel_mpgge_i != 0, + casting="unsafe", + ) + ), + "cs_fuel_mpgde": np.sum(weights) + / np.sum( + np.divide( + weights, + cs_fuel_mpgde_i, + out=np.zeros_like(cs_fuel_mpgde_i), + where=cs_fuel_mpgde_i != 0, + casting="unsafe", + ) + ), + "cs_fuel_kwh__mi": np.sum(weights) + / np.sum( + np.divide( + weights, + cs_fuel_kwh__mi_i, + out=np.zeros_like(cs_fuel_kwh__mi_i), + where=cs_fuel_kwh__mi_i != 0, + casting="unsafe", + ) + ), # Charge depleting - 'cd_fuel_used_kwh_total': sum(cd_fuel_used_kwh_i), - 'cd_battery_used_kwh': sum(cd_battery_used_kwh_i), - 'cd_fuel_mpgge': np.sum(weights) / np.sum(np.divide(weights, cd_fuel_mpgge_i, out=np.zeros_like(cd_fuel_mpgge_i), where=cd_fuel_mpgge_i!=0, casting='unsafe')), - 'cd_fuel_mpgde': np.sum(weights) / np.sum(np.divide(weights, cd_fuel_mpgde_i, out=np.zeros_like(cd_fuel_mpgde_i), where=cd_fuel_mpgde_i!=0, casting='unsafe')), - 'cd_electric_mpgge': np.sum(weights) / np.sum(np.divide(weights, cd_electric_mpgge_i, out=np.zeros_like(cd_electric_mpgge_i), where=cd_electric_mpgge_i!=0, casting='unsafe')), - 'cd_grid_electric_mpgge': np.sum(weights) / np.sum(np.divide(weights, cd_grid_electric_mpgge_i, out=np.zeros_like(cd_grid_electric_mpgge_i), where=cd_grid_electric_mpgge_i!=0, casting='unsafe')), - 'cd_electric_kwh__mi': np.sum(weights) / np.sum(np.divide(weights, cd_electric_kwh__mi_i, out=np.zeros_like(cd_electric_kwh__mi_i), where=cd_electric_kwh__mi_i!=0, casting='unsafe')), - 'cd_fuel_kwh__mi': np.sum(weights) / np.sum(np.divide(weights, cd_fuel_kwh__mi_i, out=np.zeros_like(cd_fuel_kwh__mi_i), where=cd_fuel_kwh__mi_i!=0, casting='unsafe')), + "cd_fuel_used_kwh_total": sum(cd_fuel_used_kwh_i), + "cd_battery_used_kwh": sum(cd_battery_used_kwh_i), + "cd_fuel_mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_fuel_mpgge_i, + out=np.zeros_like(cd_fuel_mpgge_i), + where=cd_fuel_mpgge_i != 0, + casting="unsafe", + ) + ), + "cd_fuel_mpgde": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_fuel_mpgde_i, + out=np.zeros_like(cd_fuel_mpgde_i), + where=cd_fuel_mpgde_i != 0, + casting="unsafe", + ) + ), + "cd_electric_mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_electric_mpgge_i, + out=np.zeros_like(cd_electric_mpgge_i), + where=cd_electric_mpgge_i != 0, + casting="unsafe", + ) + ), + "cd_grid_electric_mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_grid_electric_mpgge_i, + out=np.zeros_like(cd_grid_electric_mpgge_i), + where=cd_grid_electric_mpgge_i != 0, + casting="unsafe", + ) + ), + "cd_electric_kwh__mi": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_electric_kwh__mi_i, + out=np.zeros_like(cd_electric_kwh__mi_i), + where=cd_electric_kwh__mi_i != 0, + casting="unsafe", + ) + ), + "cd_fuel_kwh__mi": np.sum(weights) + / np.sum( + np.divide( + weights, + cd_fuel_kwh__mi_i, + out=np.zeros_like(cd_fuel_kwh__mi_i), + where=cd_fuel_kwh__mi_i != 0, + casting="unsafe", + ) + ), } # also report: AveCombinedkWhperMile = UF*(CDelectricityKWhperMile + CDfuelKWhpermile) + (1-UF)*CSfuelKWhperMile uf = run_scenario.get_phev_util_factor(scenario, v, mpgge) - mpgge_comp['ave_combined_kwh__mile'] = uf * (mpgge_comp['cd_electric_kwh__mi'] + mpgge_comp['cd_fuel_kwh__mi']) + (1-uf) * mpgge_comp['cs_fuel_kwh__mi'] + mpgge_comp["ave_combined_kwh__mile"] = ( + uf * (mpgge_comp["cd_electric_kwh__mi"] + mpgge_comp["cd_fuel_kwh__mi"]) + + (1 - uf) * mpgge_comp["cs_fuel_kwh__mi"] + ) else: - mpgge_i = np.array([m['mpgge'] for m in mpgges]) - grid_mpgge_i = np.array([m['grid_mpgge'] for m in mpgges]) - mpgde_i = np.array([m['mpgde'] for m in mpgges]) - kwh_per_m_i = np.array([m['kwh_per_mi'] for m in mpgges]) + mpgge_i = np.array([m["mpgge"] for m in mpgges]) + grid_mpgge_i = np.array([m["grid_mpgge"] for m in mpgges]) + mpgde_i = np.array([m["mpgde"] for m in mpgges]) + kwh_per_m_i = np.array([m["kwh_per_mi"] for m in mpgges]) mpgge_comp = { - 'mpgge': np.sum(weights) / np.sum(np.divide(weights, mpgge_i, out=np.zeros_like(mpgge_i), where=mpgge_i!=0, casting='unsafe')), - 'grid_mpgge': np.sum(weights) / np.sum(np.divide(weights, grid_mpgge_i, out=np.zeros_like(grid_mpgge_i), where=grid_mpgge_i!=0, casting='unsafe')), - 'mpgde': np.sum(weights) / np.sum(np.divide(weights, mpgde_i, out=np.zeros_like(mpgde_i), where=mpgde_i!=0, casting='unsafe')), + "mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + mpgge_i, + out=np.zeros_like(mpgge_i), + where=mpgge_i != 0, + casting="unsafe", + ) + ), + "grid_mpgge": np.sum(weights) + / np.sum( + np.divide( + weights, + grid_mpgge_i, + out=np.zeros_like(grid_mpgge_i), + where=grid_mpgge_i != 0, + casting="unsafe", + ) + ), + "mpgde": np.sum(weights) + / np.sum( + np.divide( + weights, + mpgde_i, + out=np.zeros_like(mpgde_i), + where=mpgde_i != 0, + casting="unsafe", + ) + ), # energy consumption kWh/mi is wt-averaged normally (doesn't require inverting / harmonic averaging) - 'kwh_per_mi': np.sum(weights) / np.sum(np.divide(weights, kwh_per_m_i, out=np.zeros_like(kwh_per_m_i), where=kwh_per_m_i!=0, casting='unsafe')), + "kwh_per_mi": np.sum(weights) + / np.sum( + np.divide( + weights, + kwh_per_m_i, + out=np.zeros_like(kwh_per_m_i), + where=kwh_per_m_i != 0, + casting="unsafe", + ) + ), } - if diagnostic: return mpgge_comp, sim_drives, mpgges + if diagnostic: + return mpgge_comp, sim_drives, mpgges return mpgge_comp, sim_drives -# %% -if __name__=='__main__': - - - vehicle_input_path =Path(gl.T3CO_INPUTS_DIR / "tda_example/TDA_FY22_vehicle_model_assumptions.csv").resolve() - scenario_inputs_path=Path(gl.T3CO_INPUTS_DIR / "tda_example/TDA_FY22_scenario_assumptions.csv").resolve() +# %% +if __name__ == "__main__": + vehicle_input_path = Path( + gl.T3CO_INPUTS_DIR / "tda_example/TDA_FY22_vehicle_model_assumptions.csv" + ).resolve() + scenario_inputs_path = Path( + gl.T3CO_INPUTS_DIR / "tda_example/TDA_FY22_scenario_assumptions.csv" + ).resolve() # load the generated file of vehicles, drive cycles, and tech targets PHEV = 365 v = run_scenario.get_vehicle(PHEV, vehicle_input_path) scenario, cycle = run_scenario.get_scenario_and_cycle(PHEV, scenario_inputs_path) # cycle = cycle[2][0] - cyc_file_path = gl.OPTIMIZATION_DRIVE_CYCLES / 'regional_haul.csv' + cyc_file_path = gl.OPTIMIZATION_DRIVE_CYCLES / "regional_haul.csv" cycle = run_scenario.load_design_cycle_from_path(cyc_file_path) - mpgge_comp, sim_drives, mpgges = get_mpgge(cycle, v, scenario, diagnostic=True) get_range_mi(mpgge_comp, v, scenario) - print('phev_utility_factor_override', scenario.phev_utility_factor_override) - print('phev_utility_factor_computed', scenario.phev_utility_factor_computed) + print("phev_utility_factor_override", scenario.phev_utility_factor_override) + print("phev_utility_factor_computed", scenario.phev_utility_factor_computed) - fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(9,11)) + fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(9, 11)) x = range(0, len(cycle.time_s)) - ax1.tick_params(axis='x', colors='white') - ax1.tick_params(axis='y', colors='white') - ax1.plot(x, cycle.mps, label='cycle MPS') - ax1.plot(x, sim_drives[0].mps_ach , label='MPS ach') - ax1.set_title("drive cycle MPS and MPS achieved", color='white') + ax1.tick_params(axis="x", colors="white") + ax1.tick_params(axis="y", colors="white") + ax1.plot(x, cycle.mps, label="cycle MPS") + ax1.plot(x, sim_drives[0].mps_ach, label="MPS ach") + ax1.set_title("drive cycle MPS and MPS achieved", color="white") fig.legend() - x = range(0, len(cycle.time_s)) - ax2.tick_params(axis='x', colors='white') - ax2.tick_params(axis='y', colors='white') - ax2.plot(x, sim_drives[0].mc_mech_kw_out_ach , label='CD mc_mech_kw_out_ach ') - ax2.plot(x, sim_drives[1].mc_mech_kw_out_ach , label='CS mc_mech_kw_out_ach ') - ax2.set_title("CD & CS motor kw out", color='white') + ax2.tick_params(axis="x", colors="white") + ax2.tick_params(axis="y", colors="white") + ax2.plot(x, sim_drives[0].mc_mech_kw_out_ach, label="CD mc_mech_kw_out_ach ") + ax2.plot(x, sim_drives[1].mc_mech_kw_out_ach, label="CS mc_mech_kw_out_ach ") + ax2.set_title("CD & CS motor kw out", color="white") fig.legend() x = range(0, len(cycle.time_s)) - ax3.tick_params(axis='x', colors='white') - ax3.tick_params(axis='y', colors='white') - ax3.plot(x, sim_drives[0].fc_kw_out_ach, label='CD fc_kw_out_ach') - ax3.plot(x, sim_drives[1].fc_kw_out_ach, label='CS fc_kw_out_ach') - ax3.set_title("CD & CS fuel converter kw out", color='white') + ax3.tick_params(axis="x", colors="white") + ax3.tick_params(axis="y", colors="white") + ax3.plot(x, sim_drives[0].fc_kw_out_ach, label="CD fc_kw_out_ach") + ax3.plot(x, sim_drives[1].fc_kw_out_ach, label="CS fc_kw_out_ach") + ax3.set_title("CD & CS fuel converter kw out", color="white") fig.legend() # next plot - fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, figsize=(18,18)) + fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, figsize=(18, 18)) CD = 0 CS = 1 x = range(0, len(cycle.time_s)) - ax1.tick_params(axis='x', colors='white') - ax1.tick_params(axis='y', colors='white') - ax1.plot(x, sim_drives[0].mc_mech_kw_out_ach, dashes=[6, 2], label='CD mc_mech_kw_out_ach ') - ax1.plot(x, sim_drives[0].fc_kw_out_ach, label='CD fc_kw_out_ach') - ax1.plot(x, np.array(sim_drives[0].mc_mech_kw_out_ach) + np.array(sim_drives[0].fc_kw_out_ach), label='CD fc_kw_out_ach + mc_mech_kw_out_ach') - ax1.set_title("CD motor and FC kw out", color='white') + ax1.tick_params(axis="x", colors="white") + ax1.tick_params(axis="y", colors="white") + ax1.plot( + x, + sim_drives[0].mc_mech_kw_out_ach, + dashes=[6, 2], + label="CD mc_mech_kw_out_ach ", + ) + ax1.plot(x, sim_drives[0].fc_kw_out_ach, label="CD fc_kw_out_ach") + ax1.plot( + x, + np.array(sim_drives[0].mc_mech_kw_out_ach) + + np.array(sim_drives[0].fc_kw_out_ach), + label="CD fc_kw_out_ach + mc_mech_kw_out_ach", + ) + ax1.set_title("CD motor and FC kw out", color="white") fig.legend() x = range(0, len(cycle.time_s)) - ax2.tick_params(axis='x', colors='white') - ax2.tick_params(axis='y', colors='white') + ax2.tick_params(axis="x", colors="white") + ax2.tick_params(axis="y", colors="white") mk_kwh_out = np.array(sim_drives[0].mc_mech_kw_out_ach) / 3600 fc_kwh_out = np.array(sim_drives[0].fc_kw_out_ach) / 3600 - mc_kwh_cummultive = np.cumsum(np.array(sim_drives[0].mc_mech_kw_out_ach))/3600 - fc_kwh_cummultive = np.cumsum(np.array(sim_drives[0].fc_kw_out_ach))/3600 - ax2.plot(x, mc_kwh_cummultive, dashes=[6, 2], label='CD MC mech_KWH_out cummulative') - ax2.plot(x, fc_kwh_cummultive, label='CD FC KWH_out cummulative') - ax2.plot(x, mc_kwh_cummultive + fc_kwh_cummultive, label=f'CD ALL KWH_out cummulative kwh') - ax2.set_title(f"CD KWH_out cummulative {round(sum(mk_kwh_out + fc_kwh_out))}" , color='white') + mc_kwh_cummultive = np.cumsum(np.array(sim_drives[0].mc_mech_kw_out_ach)) / 3600 + fc_kwh_cummultive = np.cumsum(np.array(sim_drives[0].fc_kw_out_ach)) / 3600 + ax2.plot( + x, mc_kwh_cummultive, dashes=[6, 2], label="CD MC mech_KWH_out cummulative" + ) + ax2.plot(x, fc_kwh_cummultive, label="CD FC KWH_out cummulative") + ax2.plot( + x, + mc_kwh_cummultive + fc_kwh_cummultive, + label=f"CD ALL KWH_out cummulative kwh", + ) + ax2.set_title( + f"CD KWH_out cummulative {round(sum(mk_kwh_out + fc_kwh_out))}", color="white" + ) fig.legend() x = range(0, len(cycle.time_s)) - ax3.tick_params(axis='x', colors='white') - ax3.tick_params(axis='y', colors='white') - ax3.plot(x, sim_drives[1].mc_mech_kw_out_ach, dashes=[6, 2], label='CS mc_mech_kw_out_ach ') - ax3.plot(x, sim_drives[1].fc_kw_out_ach, label='CS fc_kw_out_ach') - ax3.plot(x, np.array(sim_drives[1].mc_mech_kw_out_ach) + np.array(sim_drives[1].fc_kw_out_ach), label='CS fc_kw_out_ach + mc_mech_kw_out_ach') - ax3.set_title("CS motor and FC kw out", color='white') + ax3.tick_params(axis="x", colors="white") + ax3.tick_params(axis="y", colors="white") + ax3.plot( + x, + sim_drives[1].mc_mech_kw_out_ach, + dashes=[6, 2], + label="CS mc_mech_kw_out_ach ", + ) + ax3.plot(x, sim_drives[1].fc_kw_out_ach, label="CS fc_kw_out_ach") + ax3.plot( + x, + np.array(sim_drives[1].mc_mech_kw_out_ach) + + np.array(sim_drives[1].fc_kw_out_ach), + label="CS fc_kw_out_ach + mc_mech_kw_out_ach", + ) + ax3.set_title("CS motor and FC kw out", color="white") fig.legend() x = range(0, len(cycle.time_s)) - ax4.tick_params(axis='x', colors='white') - ax4.tick_params(axis='y', colors='white') + ax4.tick_params(axis="x", colors="white") + ax4.tick_params(axis="y", colors="white") mk_kwh_out = np.array(sim_drives[1].mc_mech_kw_out_ach) / 3600 fc_kwh_out = np.array(sim_drives[1].fc_kw_out_ach) / 3600 - mc_kwh_cummultive = np.cumsum(np.array(sim_drives[1].mc_mech_kw_out_ach))/3600 - fc_kwh_cummultive = np.cumsum(np.array(sim_drives[1].fc_kw_out_ach))/3600 - ax4.plot(x, mc_kwh_cummultive, dashes=[6, 2], label='CS MC mech_KWH_out cummulative') - ax4.plot(x, fc_kwh_cummultive, label='CS FC KWH_out cummulative') - ax4.plot(x, mc_kwh_cummultive + fc_kwh_cummultive, label=f'CS ALL KWH_out cummulative kwh') - ax4.set_title(f"CS KWH_out cummulative {round(sum(mk_kwh_out + fc_kwh_out))}", color='white') + mc_kwh_cummultive = np.cumsum(np.array(sim_drives[1].mc_mech_kw_out_ach)) / 3600 + fc_kwh_cummultive = np.cumsum(np.array(sim_drives[1].fc_kw_out_ach)) / 3600 + ax4.plot( + x, mc_kwh_cummultive, dashes=[6, 2], label="CS MC mech_KWH_out cummulative" + ) + ax4.plot(x, fc_kwh_cummultive, label="CS FC KWH_out cummulative") + ax4.plot( + x, + mc_kwh_cummultive + fc_kwh_cummultive, + label=f"CS ALL KWH_out cummulative kwh", + ) + ax4.set_title( + f"CS KWH_out cummulative {round(sum(mk_kwh_out + fc_kwh_out))}", color="white" + ) fig.legend() - cd_elec_kwh_out_ach = round(sum(np.array(sim_drives[CD].ess_kw_out_ach) / 3600),1) - cd_fuel_kwh_out_ach = round(sum(sim_drives[CD].fs_kwh_out_ach),1) - cs_elec_kwh_out_ach = round(sum(np.array(sim_drives[CS].ess_kw_out_ach) / 3600),1) - cs_fuel_kwh_out_ach = round(sum(sim_drives[CS].fs_kwh_out_ach),1) - - print(f'total CD Mode electricity used (from ess_kw_out) {cd_elec_kwh_out_ach}') - print(f'total CD Mode fuel used (from fs_kwh_out) {cd_fuel_kwh_out_ach}') - print(f'total CS Mode electricity used (from ess_kw_out) {cs_elec_kwh_out_ach}') - print(f'total CS Mode fuel used (from fs_kwh_out) {cs_fuel_kwh_out_ach}') - cd_elec_mpgge = round(sum(sim_drives[CD].dist_mi) / (cd_elec_kwh_out_ach / gl.get_kwh_per_gge()),1) - print(f'CD mode cd_fuel_mpgge {round(sim_drives[CD].mpgge,1)}') - print(f'CD mode cd_electric_mpgge {cd_elec_mpgge}') - print(f'CD mode cd_grid_electric_mpgge {cd_elec_mpgge*v.chg_eff}') - print(f'CS mode cs_fuel_mpgge {round(sim_drives[CS].mpgge,1)}') - + cd_elec_kwh_out_ach = round(sum(np.array(sim_drives[CD].ess_kw_out_ach) / 3600), 1) + cd_fuel_kwh_out_ach = round(sum(sim_drives[CD].fs_kwh_out_ach), 1) + cs_elec_kwh_out_ach = round(sum(np.array(sim_drives[CS].ess_kw_out_ach) / 3600), 1) + cs_fuel_kwh_out_ach = round(sum(sim_drives[CS].fs_kwh_out_ach), 1) + + print(f"total CD Mode electricity used (from ess_kw_out) {cd_elec_kwh_out_ach}") + print(f"total CD Mode fuel used (from fs_kwh_out) {cd_fuel_kwh_out_ach}") + print(f"total CS Mode electricity used (from ess_kw_out) {cs_elec_kwh_out_ach}") + print(f"total CS Mode fuel used (from fs_kwh_out) {cs_fuel_kwh_out_ach}") + cd_elec_mpgge = round( + sum(sim_drives[CD].dist_mi) / (cd_elec_kwh_out_ach / gl.get_kwh_per_gge()), 1 + ) + print(f"CD mode cd_fuel_mpgge {round(sim_drives[CD].mpgge,1)}") + print(f"CD mode cd_electric_mpgge {cd_elec_mpgge}") + print(f"CD mode cd_grid_electric_mpgge {cd_elec_mpgge*v.chg_eff}") + print(f"CS mode cs_fuel_mpgge {round(sim_drives[CS].mpgge,1)}") + # # %% # sel=328 # selections = [sel] @@ -458,7 +674,7 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle # get_range_mi(mpgge_comp, v, scenario) # cd_elec_kwh_out_ach = round(sum(np.array(sim_drives[CD].ess_kw_out_ach) / 3600),1) - # cd_fuel_kwh_out_ach = round(sum(sim_drives[CD].fs_kwh_out_ach),1) + # cd_fuel_kwh_out_ach = round(sum(sim_drives[CD].fs_kwh_out_ach),1) # cs_elec_kwh_out_ach = round(sum(np.array(sim_drives[CS].ess_kw_out_ach) / 3600),1) # cs_fuel_kwh_out_ach = round(sum(sim_drives[CS].fs_kwh_out_ach),1) # print(f'total CD Mode electricity used (from ess_kw_out) {cd_elec_kwh_out_ach}') @@ -466,9 +682,9 @@ def get_mpgge(eff_range_cyc:fastsim.cycle.Cycle | List[Tuple[fastsim.cycle.Cycle # print(f'total CS Mode electricity used (from ess_kw_out) {cs_elec_kwh_out_ach}') # print(f'total CS Mode fuel used (from fs_kwh_out) {cs_fuel_kwh_out_ach}') # print('++++') - + # cd_elec_mpgge = round(sum(sim_drives[CD].dist_mi) / (cd_elec_kwh_out_ach / gl.get_kwh_per_gge()),1) - + # print(f'CD mode cd_fuel_mpgge {round(sim_drives[CD].mpgge,1)}') # print(f'CD mode cd_electric_mpgge {cd_elec_mpgge}') # print(f'CD mode cd_grid_electric_mpgge {cd_elec_mpgge*v.chg_eff}') diff --git a/t3co/objectives/gradeability.py b/t3co/objectives/gradeability.py index 208c274..cbe410b 100644 --- a/t3co/objectives/gradeability.py +++ b/t3co/objectives/gradeability.py @@ -1,9 +1,12 @@ # %% +from __future__ import annotations import time from pathlib import Path +from typing import Tuple import numpy as np +import fastsim from fastsim import cycle from fastsim import parameters as params @@ -12,12 +15,12 @@ def get_gradeability( - analysis_vehicle, - scenario=None, - verbose=False, - ess_init_soc=None, - set_weight_to_max_kg=True, -): + analysis_vehicle: fastsim.vehicle.Vehicle, + scenario:run_scenario.Scenario=None, + verbose:bool=False, + ess_init_soc:float=None, + set_weight_to_max_kg:bool=True, +)->Tuple[float, float, fastsim.simdrive.SimDrive, fastsim.simdrive.SimDrive]: """ This function runs SimDrives to determine the gradeability at given speed and the grade vehicle is evaluated at how much it meets or exceeds target speed at the target grade. @@ -50,7 +53,7 @@ def get_gradeability( print(f"f'{Path(__file__).name}:: Vehicle load time: {time.time() - t0:.3f} s") # load the cycles - def get_grade_perf(target_grade): + def get_grade_perf(target_grade: float)-> Tuple[float,fastsim.simdrive.SimDrive]: """ This function obtains the maximum speed achieved on gradeability test for target grade diff --git a/t3co/run/Global.py b/t3co/run/Global.py index 90cd39a..cb051f4 100644 --- a/t3co/run/Global.py +++ b/t3co/run/Global.py @@ -173,7 +173,7 @@ def set_tco_results(): KG_2_LB = 2.20462 -def kg_to_lbs(kgs): +def kg_to_lbs(kgs:float)->float: """ This function converts kg to lb @@ -186,7 +186,7 @@ def kg_to_lbs(kgs): return kgs * KG_2_LB -def lbs_to_kgs(lbs): +def lbs_to_kgs(lbs:float)->float: """ This function converts lb to kg @@ -199,7 +199,7 @@ def lbs_to_kgs(lbs): return lbs / KG_2_LB -def not_falsy(var): +def not_falsy(var:float)->bool: """ This function returns True to verify that var is NOT falsy: not in [None, np.nan, 0, False] diff --git a/t3co/run/generateinputs.py b/t3co/run/generateinputs.py index 6f62956..0c26f04 100644 --- a/t3co/run/generateinputs.py +++ b/t3co/run/generateinputs.py @@ -5,7 +5,7 @@ from t3co.run import Global as gl -def generate(vocation, dst=gl.OPTIMIZATION_AND_TCO_RCRS): +def generate(vocation: str, dst: str=gl.OPTIMIZATION_AND_TCO_RCRS): """ This function aggregates specifications from users for powertrains, desired ranges, component costs etc. into two csv files - FASTSimInputs and OtherInputs diff --git a/t3co/run/run_scenario.py b/t3co/run/run_scenario.py index 75c3ffb..0e7a7a5 100644 --- a/t3co/run/run_scenario.py +++ b/t3co/run/run_scenario.py @@ -1,14 +1,16 @@ """Module for loading vehicles, scenarios, running them and managing them""" - import ast from dataclasses import dataclass, field from pathlib import Path +from typing import Tuple +import fastsim import numpy as np import pandas as pd from fastsim import cycle, simdrive, vehicle import os + # for debugging convenience from typing_extensions import Self @@ -19,149 +21,6 @@ # import importlib # tco_analysis = importlib.reload(tco_analysis) -# ---------------------------------- powertrain adjustment methods ---------------------------------- # - - -def set_test_weight(vehicle, scenario): - """ - assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit - - Args: - vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - scenario (t3co.run_scenario.Scenario): T3CO scenario object - """ - # June 15,16 confirming that the test weight of vehicle should be GVWRKg + gvwr_credit_kg - vehicle.veh_override_kg = scenario.gvwr_kg + scenario.gvwr_credit_kg - vehicle.set_veh_mass() - assert ( - vehicle.veh_kg > 0 - ), "vehicle weight [kg] cannot be zero, check Scenario values for gvwr_kg and gvwr_credit_kg" - - -def reset_vehicle_weight(vehicle): - """ - This function resets vehicle mass after loaded weight tests are done for accel and grade - - Args: - vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - """ - vehicle.veh_override_kg = 0 - vehicle.set_veh_mass() - - -def limit_cargo_kg_for_moo_hev_bev(opt_scenario, mooadvancedvehicle): - """ - This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles - - Args: - opt_scenario (t3co.run_scenario.Scenario): T3CO scenario object - mooadvancedvehicle (fastsim.vehicle.Vehicle): pymoo optimization vehicle - """ - # limit cargo to a value <= its original mass, decrease it if vehicle is overweight - max_allowable_weight_kg = opt_scenario.gvwr_kg + opt_scenario.gvwr_credit_kg - cargo_limited = max_allowable_weight_kg - ( - mooadvancedvehicle.veh_kg - mooadvancedvehicle.cargo_kg - ) - cargo_limited = max(cargo_limited, 0) - # TODO socialize the fact that this next line makes it impossible to add cargo capacity relative to baseline - # lightweighting and such can improve energy efficiency but not increase cargo - mooadvancedvehicle.cargo_kg = min(cargo_limited, opt_scenario.originalcargo_kg) - mooadvancedvehicle.set_veh_mass() - - -# helper methods to ensure users call proper vehicle initialization methods to adjust vehicle powertrain and mass -def set_max_motor_kw(analysis_vehicle, scenario, max_motor_kw): - """ - This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - scenario (t3co.run_scenario.Scenario): T3CO Scenarion object - max_motor_kw (float): max motor power /kW - """ - # old comments that may be needed again: - # Scaling motor and ESS power with ESS capacity results in more reasonable - # zero-to-sixty response to battery capacity and is generally consistent - # with how things are done. We need to firm up the functional form of this, - # which came from Aaron Brooker for light duty. - # veh.mc_max_kw = 24.46 * (veh.ess_max_kwh ** (-.475) * veh.ess_max_kwh) - analysis_vehicle.mc_max_kw = max_motor_kw - # TODO: for HEV (at least), battery power could be significantly lower than motor power, - # and the following variable assignment will be pretty far off - - analysis_vehicle.ess_max_kw = ( - analysis_vehicle.mc_max_kw / analysis_vehicle.get_mcPeakEff() - ) - - # PHEV adjustment - if analysis_vehicle.veh_pt_type == gl.PHEV: - if scenario.motor_power_override_kw_fc_demand_on_pct != -1: - analysis_vehicle.kw_demand_fc_on = ( - max_motor_kw * scenario.motor_power_override_kw_fc_demand_on_pct - ) - - analysis_vehicle.set_derived() - - -def set_max_battery_kwh(analysis_vehicle, max_ess_kwh): - """ - This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - max_ess_kwh (float): max energy storage system energy capacity /kWh - """ - analysis_vehicle.ess_max_kwh = max_ess_kwh - analysis_vehicle.set_derived() - - -def set_max_battery_power_kw(analysis_vehicle, max_ess_kw): - """ - This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - max_ess_kw (float): max energy storage system power /kW - """ - analysis_vehicle.ess_max_kw = max_ess_kw - analysis_vehicle.set_derived() - - -def set_max_fuel_converter_kw(analysis_vehicle, fc_max_out_kw): - """ - This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - fc_max_out_kw (float): max fuel converter power /kW - """ - analysis_vehicle.fc_max_kw = fc_max_out_kw - analysis_vehicle.set_derived() - - -def set_fuel_store_kwh(analysis_vehicle, fs_kwh): - """ - This helper method is used within T3COProblem to set fs_kwh to optimization vehicle - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - fs_kwh (float): fuel storage energy capacity /kWh - """ - analysis_vehicle.fs_kwh = fs_kwh - analysis_vehicle.set_derived() - - -def set_cargo_kg(analysis_vehicle, cargo_kg): - """ - This helper method is used within T3COProblem to set cargo_kg to optimization vehicle - - Args: - analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object - cargo_kg (float): vehicle cargo capacity /kg - """ - analysis_vehicle.cargo_kg = cargo_kg - analysis_vehicle.set_veh_mass() - # --------------------------------- \\ powertrain adjustment methods --------------------------------- # @dataclass @@ -210,7 +69,7 @@ class Config: fdt_frac_full_charge_bounds: list = field(default_factory=list) activate_mr_downtime_cost: bool = False - def __init__(self): + def __init__(self) -> None: pass def from_file(self, filename: str, analysis_id: int) -> Self: @@ -248,7 +107,7 @@ def from_dict(self, config_dict: dict) -> Self: config_dict["selections"] = int(config_dict["selections"]) self.__dict__.update(config_dict) - def validate_analysis_id(self, filename: str, analysis_id: int = 0): + def validate_analysis_id(self, filename: str, analysis_id: int = 0) -> Self: """ This method validates that correct analysis id is input @@ -425,7 +284,7 @@ class Scenario: mr_avg_tire_life_mi: float = 0 mr_tire_replace_downtime_hr_per_event: float = 0 - def from_config(self, config: Config = None): + def from_config(self, config: Config = None) -> Self: """ This method overrides certain scenario fields if use_config is True and config object is not None @@ -472,7 +331,7 @@ def from_config(self, config: Config = None): # PHEV utility methods -def check_phev_init_socs(a_vehicle: vehicle.Vehicle, scenario: Scenario): +def check_phev_init_socs(a_vehicle: vehicle.Vehicle, scenario: Scenario) -> None: """ This function checks that soc_norm_init_for_grade_pct and soc_norm_init_for_accel_pct are present only for PHEVs @@ -505,14 +364,16 @@ def check_phev_init_socs(a_vehicle: vehicle.Vehicle, scenario: Scenario): ), f"INPUT ERROR, user specifed ess_init_soc_accel {scenario.ess_init_soc_accel}, & soc_norm_init_for_accel_pct {scenario.soc_norm_init_for_accel_pct} for PHEV; the question of which one to use is ambiguous" -def get_phev_util_factor(scenario, v, mpgge): +def get_phev_util_factor( + scenario: Scenario, v: fastsim.vehicle.Vehicle, mpgge: dict +) -> float: """ This function gets the PHEV utility factor derived from the computed range of the vehicle and the operational day range computed from shifts per year and the first vmt year Args: scenario (Scenario): T3CO scenario object - v (fastsim.Vehicle.vehicle): FASTSim vehicle object + v (fastsim.vehicle.Vehicle): FASTSim vehicle object mpgge (dict): Miles per Gallon Gasoline Equivalent dictionary Returns: @@ -535,7 +396,9 @@ def get_phev_util_factor(scenario, v, mpgge): # utility methods sim drives -def get_objective_simdrive(analysis_vehicle: vehicle.Vehicle, cycle): +def get_objective_simdrive( + analysis_vehicle: vehicle.Vehicle, cycle: fastsim.cycle.Cycle +) -> fastsim.simdrive.SimDrive: """ This function obtains the SimDrive for accel and grade test @@ -560,7 +423,12 @@ def get_objective_simdrive(analysis_vehicle: vehicle.Vehicle, cycle): return sd -def run_grade_or_accel(test, analysis_vehicle, sim_drive, ess_init_soc): +def run_grade_or_accel( + test: str, + analysis_vehicle: fastsim.vehicle.Vehicle, + sim_drive: fastsim.simdrive.SimDrive, + ess_init_soc: float, +) -> None: """ This function handles initial SOC considerations for grade and accel tests @@ -599,7 +467,7 @@ def run_grade_or_accel(test, analysis_vehicle, sim_drive, ess_init_soc): # utility methods to create fastsim vehicles -def create_fastsim_vehicle(veh_dict=None): +def create_fastsim_vehicle(veh_dict: dict = None) -> fastsim.vehicle.Vehicle: """ This function creates and returns an empty FASTSim vehicle object with no attributes or @@ -621,7 +489,7 @@ def create_fastsim_vehicle(veh_dict=None): return v -def get_vehicle(veh_no, veh_input_path): +def get_vehicle(veh_no: int, veh_input_path: str) -> fastsim.vehicle.Vehicle: """ This function loads vehicle object from vehicle number and input csv filepath @@ -642,7 +510,12 @@ def get_vehicle(veh_no, veh_input_path): # \\ end \\ utility methods to create fastsim vehicles -def get_scenario_and_cycle(veh_no, scenario_inputs_path, a_vehicle=None, config=None): +def get_scenario_and_cycle( + veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None, +) -> Tuple[Scenario, fastsim.cycle.Cycle]: """ This function uses helper methods load_scenario and load_design_cycle_from_scenario \ to get scenario object and cycle object corresponding to selected vehicle (by veh_no) @@ -663,7 +536,12 @@ def get_scenario_and_cycle(veh_no, scenario_inputs_path, a_vehicle=None, config= return scenario, cyc -def load_scenario(veh_no, scenario_inputs_path, a_vehicle=None, config=None): +def load_scenario( + veh_no: int, + scenario_inputs_path: str, + a_vehicle: fastsim.vehicle.Vehicle = None, + config: Config = None, +) -> Scenario: """ This function gets the Scenario object from scenario input CSV filepath, initializes some fields,\ and overrides some fields based on Config object @@ -764,8 +642,8 @@ def load_scenario(veh_no, scenario_inputs_path, a_vehicle=None, config=None): def load_design_cycle_from_scenario( - scenario, cyc_file_path=gl.OPTIMIZATION_DRIVE_CYCLES -): + scenario: Scenario, cyc_file_path: str = gl.OPTIMIZATION_DRIVE_CYCLES +) -> fastsim.cycle.Cycle: """ This helper method loads the design cycle used for mpgge and range determination. It can also be used standalone to get cycles not in standard gl.OPTIMIZATION_DRIVE_CYCLES location, @@ -802,7 +680,7 @@ def load_design_cycle_from_scenario( return range_cyc -def load_design_cycle_from_path(cyc_file_path): +def load_design_cycle_from_path(cyc_file_path: str) -> fastsim.cycle.Cycle: """ This helper method loads the Cycle object from the drivecycle filepath @@ -822,7 +700,169 @@ def load_design_cycle_from_path(cyc_file_path): return range_cyc -def vehicle_scenario_sweep(vehicle, scenario, range_cyc, verbose=False, **kwargs): +# ---------------------------------- powertrain adjustment methods ---------------------------------- # + + +def set_test_weight(vehicle: fastsim.vehicle.Vehicle, scenario: Scenario) -> None: + """ + assign standardized vehicle mass for accel and grade test using GVWR and GVWR Credit + + Args: + vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + scenario (t3co.run_scenario.Scenario): T3CO scenario object + """ + # June 15,16 confirming that the test weight of vehicle should be GVWRKg + gvwr_credit_kg + vehicle.veh_override_kg = scenario.gvwr_kg + scenario.gvwr_credit_kg + vehicle.set_veh_mass() + assert ( + vehicle.veh_kg > 0 + ), "vehicle weight [kg] cannot be zero, check Scenario values for gvwr_kg and gvwr_credit_kg" + + +def reset_vehicle_weight(vehicle: fastsim.vehicle.Vehicle) -> None: + """ + This function resets vehicle mass after loaded weight tests are done for accel and grade + + Args: + vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + """ + vehicle.veh_override_kg = 0 + vehicle.set_veh_mass() + + +def limit_cargo_kg_for_moo_hev_bev( + opt_scenario: Scenario, mooadvancedvehicle: fastsim.vehicle.Vehicle +) -> None: + """ + This helper method is used within T3COProblem to assign limited cargo capacity based on GVWR + GVWRCredit and optimization vehicle mass for advanced vehicles + + Args: + opt_scenario (t3co.run_scenario.Scenario): T3CO scenario object + mooadvancedvehicle (fastsim.vehicle.Vehicle): pymoo optimization vehicle + """ + # limit cargo to a value <= its original mass, decrease it if vehicle is overweight + max_allowable_weight_kg = opt_scenario.gvwr_kg + opt_scenario.gvwr_credit_kg + cargo_limited = max_allowable_weight_kg - ( + mooadvancedvehicle.veh_kg - mooadvancedvehicle.cargo_kg + ) + cargo_limited = max(cargo_limited, 0) + # TODO socialize the fact that this next line makes it impossible to add cargo capacity relative to baseline + # lightweighting and such can improve energy efficiency but not increase cargo + mooadvancedvehicle.cargo_kg = min(cargo_limited, opt_scenario.originalcargo_kg) + mooadvancedvehicle.set_veh_mass() + + +# helper methods to ensure users call proper vehicle initialization methods to adjust vehicle powertrain and mass +def set_max_motor_kw( + analysis_vehicle: fastsim.vehicle.Vehicle, scenario: Scenario, max_motor_kw: float +) -> None: + """ + This helper method is used within T3COProblem to set max_motor_kw to optimization vehicle and set kw_demand_fc_on if PHEV + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + scenario (t3co.run_scenario.Scenario): T3CO Scenarion object + max_motor_kw (float): max motor power /kW + """ + # old comments that may be needed again: + # Scaling motor and ESS power with ESS capacity results in more reasonable + # zero-to-sixty response to battery capacity and is generally consistent + # with how things are done. We need to firm up the functional form of this, + # which came from Aaron Brooker for light duty. + # veh.mc_max_kw = 24.46 * (veh.ess_max_kwh ** (-.475) * veh.ess_max_kwh) + analysis_vehicle.mc_max_kw = max_motor_kw + # TODO: for HEV (at least), battery power could be significantly lower than motor power, + # and the following variable assignment will be pretty far off + + analysis_vehicle.ess_max_kw = ( + analysis_vehicle.mc_max_kw / analysis_vehicle.get_mcPeakEff() + ) + + # PHEV adjustment + if analysis_vehicle.veh_pt_type == gl.PHEV: + if scenario.motor_power_override_kw_fc_demand_on_pct != -1: + analysis_vehicle.kw_demand_fc_on = ( + max_motor_kw * scenario.motor_power_override_kw_fc_demand_on_pct + ) + + analysis_vehicle.set_derived() + + +def set_max_battery_kwh( + analysis_vehicle: fastsim.vehicle.Vehicle, max_ess_kwh: float +) -> None: + """ + This helper method is used within T3COProblem to set max_ess_kwh to optimization vehicle + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + max_ess_kwh (float): max energy storage system energy capacity /kWh + """ + analysis_vehicle.ess_max_kwh = max_ess_kwh + analysis_vehicle.set_derived() + + +def set_max_battery_power_kw( + analysis_vehicle: fastsim.vehicle.Vehicle, max_ess_kw: float +) -> None: + """ + This helper method is used within T3COProblem to set max_ess_kwx to optimization vehicle + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + max_ess_kw (float): max energy storage system power /kW + """ + analysis_vehicle.ess_max_kw = max_ess_kw + analysis_vehicle.set_derived() + + +def set_max_fuel_converter_kw( + analysis_vehicle: fastsim.vehicle.Vehicle, fc_max_out_kw: float +) -> None: + """ + This helper method is used within T3COProblem to set fc_max_out_kw to optimization vehicle + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + fc_max_out_kw (float): max fuel converter power /kW + """ + analysis_vehicle.fc_max_kw = fc_max_out_kw + analysis_vehicle.set_derived() + + +def set_fuel_store_kwh( + analysis_vehicle: fastsim.vehicle.Vehicle, fs_kwh: float +) -> None: + """ + This helper method is used within T3COProblem to set fs_kwh to optimization vehicle + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + fs_kwh (float): fuel storage energy capacity /kWh + """ + analysis_vehicle.fs_kwh = fs_kwh + analysis_vehicle.set_derived() + + +def set_cargo_kg(analysis_vehicle: fastsim.vehicle.Vehicle, cargo_kg): + """ + This helper method is used within T3COProblem to set cargo_kg to optimization vehicle + + Args: + analysis_vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object + cargo_kg (float): vehicle cargo capacity /kg + """ + analysis_vehicle.cargo_kg = cargo_kg + analysis_vehicle.set_veh_mass() + + +def vehicle_scenario_sweep( + vehicle: fastsim.vehicle.Vehicle, + scenario: Scenario, + range_cyc, + verbose=False, + **kwargs, +): """ This function contains helper methods such as get_tco_of_vehicle, check_phev_init_socs, get_accel, and get_gradeability\ and returns a dictionary of all TCO related outputs @@ -977,10 +1017,10 @@ def vehicle_scenario_sweep(vehicle, scenario, range_cyc, verbose=False, **kwargs def run( - veh_no, - vocation="blank", - vehicle_input_path=gl.FASTSIM_INPUTS, - scenario_inputs_path=gl.OTHER_INPUTS, + veh_no: int, + vocation: str = "blank", + vehicle_input_path: str = gl.FASTSIM_INPUTS, + scenario_inputs_path: str = gl.OTHER_INPUTS, ): """ This function runs vehicle_scenario_sweep based on vehicle and scenario objects read from input file paths @@ -1009,7 +1049,7 @@ def run( return out -def rerun(vehicle, vocation, scenario): +def rerun(vehicle: fastsim.vehicle.Vehicle, vocation: str, scenario: Scenario): """ This function runs vehicle_scenario_sweep when given the vehicle and scenario objects diff --git a/t3co/sweep.py b/t3co/sweep.py index 6ab23d4..a79a9fd 100644 --- a/t3co/sweep.py +++ b/t3co/sweep.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # coding: utf-8 -#%% +# %% +from typing import List, Tuple +import fastsim import pandas as pd import numpy as np import csv @@ -13,8 +15,10 @@ import logging import re import os - -from t3co.run import Global as gl +import pymoo +import pymoo.core +import pymoo.core.result +from t3co.run import Global as gl, run_scenario from t3co.moopack import moo from t3co.run import run_scenario as rs from t3co.objectives import fueleconomy as fe @@ -79,14 +83,28 @@ KNOB_MIN = 1 -def deug_traces(vehicle, cycles, scenario): +def deug_traces( + vehicle: fastsim.vehicle.Vehicle, + cycles: List[fastsim.cycle.Cycle], + scenario: run_scenario.Scenario, +) -> None: + """ + This function gets a diagnostic trace of get_mpgge + + Args: + vehicle (fastsim.vehicle.Vehicle): FASTSim Vehicle object + cycles (List[fastsim.cycle.Cycle]): List of FASTSim drivecycle objects + scenario (run_scenario.Scenario): Scenario object + """ mpgge_comp, sim_drives, mpgges = fe.get_mpgge( cycles, vehicle, scenario, diganostic=True ) # save the sim_drives to file somehow -def save_tco_files(tco_files, resdir, scenario_name, sel, ts): +def save_tco_files( + tco_files: dict, resdir: str, scenario_name: str, sel: str, ts: str +) -> None: """ This function saves the intermediary files as tsv @@ -136,18 +154,23 @@ def save_tco_files(tco_files, resdir, scenario_name, sel, ts): def get_knobs_bounds_curves( - selection, vpttype, sdf, lw_imp_curves, aero_drag_imp_curves, eng_eff_curves -): + selection: int, + vpttype: str, + sdf: pd.DataFrame, + lw_imp_curves: pd.DataFrame, + aero_drag_imp_curves: pd.DataFrame, + eng_eff_curves: pd.DataFrame, +) -> Tuple[dict, dict]: """ This function fetches the knobs and constraints for running the optimization for a given selection Args: - selection (float): selection number + selection (int): selection number vpttype (str): vehicle powertrain type = veh_pt_type - sdf (DataFrame): scenario dataframe - lw_imp_curves (DataFrame): light weighting curve dataframe - aero_drag_imp_curves (DataFrame): aero drag curve dataframe - eng_eff_curves (DataFrame): engine efficiency curve dataframe + sdf (pd.DataFrame): scenario dataframe + lw_imp_curves (pd.DataFrame): light weighting curve dataframe + aero_drag_imp_curves (pd.DataFrame): aero drag curve dataframe + eng_eff_curves (pd.DataFrame): engine efficiency curve dataframe Returns: knobs_bounds (dict): dict of knobs and bounds @@ -271,12 +294,14 @@ def get_knobs_bounds_curves( return knobs_bounds, curves -def get_objectives_constraints(selection, sdf, verbose=True): +def get_objectives_constraints( + selection: int, sdf: pd.DataFrame, verbose: bool = True +) -> Tuple[list, list]: """ This function appends to list of necessary variables based on the constraints and objectives selected Args: - selection (float): selection number + selection (int): selection number sdf (DataFrame): scenario dataframe verbose (bool, optional): if selected, function will print objectives and constraints. Defaults to True. @@ -314,30 +339,30 @@ def get_objectives_constraints(selection, sdf, verbose=True): def run_moo( - sel, - sdf, - optpt, - algo, - skip_opt, - pop_size, - n_max_gen, - n_last, - nth_gen, - x_tol, - verbose, - f_tol, - resdir, - lw_imp_curves, - aero_drag_imp_curves, - eng_eff_imp_curves, - config, + sel: int, + sdf: pd.DataFrame, + optpt: str, + algo: str, + skip_opt: bool, + pop_size: float, + n_max_gen: int, + n_last: int, + nth_gen: int, + x_tol: float, + verbose: bool, + f_tol: float, + resdir: str, + lw_imp_curves: pd.DataFrame, + aero_drag_imp_curves: pd.DataFrame, + eng_eff_imp_curves: pd.DataFrame, + config: run_scenario.Scenario, **kwargs, -): +) -> Tuple[pymoo.core.result.Result, moo.T3COProblem, bool]: """ This function calls get_objectives_constraints and get_knobs_bounds_curves, and then calls run_optimization to perform the multiobjective optimization Args: - sel (float): selection number + sel (int): selection number sdf (DataFrame): scenario dataframe optpt (str): vehicle powertrain type algo (str): algorithm name @@ -358,7 +383,7 @@ def run_moo( Returns: moo_results (pymoo.core.result.Result): optimization results object moo_problem (T3COProblem): minimization problem that calculates TCO - moo_code (Error): Error message + moo_code (bool): Error message """ objectives, constraints = get_objectives_constraints(sel, sdf) @@ -390,7 +415,7 @@ def run_moo( return moo_results, moo_problem, moo_code -def check_input_files(df, filetype, filepath): +def check_input_files(df: pd.DataFrame, filetype: str, filepath: str) -> None: """ This function contains assert statements that make sure input vehicle and scenario dataframes do not contain numm rows @@ -400,12 +425,23 @@ def check_input_files(df, filetype, filepath): filepath (str): filepath of the vehicle or scenario input files """ blank_lines = [i for i in df.index.isnull().cumsum() if i != 0] - assert df.index.isnull().any() == False, f"\n\n{filetype} file selection column cannot have blank values\nlines: {blank_lines}\npath: {filepath}\n\n\n\n" # noqa: E712 - assert df['scenario_name'].isnull().any() == False, f"\n\n{filetype} file scenario_name column cannot have blank values\nlines: {blank_lines}\npath: {filepath}\n\n\n\n" # noqa: E712 + assert ( + df.index.isnull().any() == False + ), f"\n\n{filetype} file selection column cannot have blank values\nlines: {blank_lines}\npath: {filepath}\n\n\n\n" # noqa: E712 + assert ( + df["scenario_name"].isnull().any() == False + ), f"\n\n{filetype} file scenario_name column cannot have blank values\nlines: {blank_lines}\npath: {filepath}\n\n\n\n" # noqa: E712 + def run_vehicle_scenarios( - vehicles, scenarios, eng_eff_imp_curves_p, lw_imp_curves_p, aero_drag_imp_curves_p, config, **kwargs -): + vehicles: str, + scenarios: str, + eng_eff_imp_curves_p: str, + lw_imp_curves_p: str, + aero_drag_imp_curves_p: str, + config: run_scenario.Config, + **kwargs, +) -> None: """ This is the main function that runs T3CO for all the selections input @@ -464,8 +500,8 @@ def run_vehicle_scenarios( f_tol = kwargs.pop("f_tol", 3.0) # objective space tolerance verbose = kwargs.pop("verbose", False) look_for = kwargs.pop("look_for", [""]) - assert ( - isinstance(look_for,list) + assert isinstance( + look_for, list ), "look_for should have been input or cast as a list at this point" selections = kwargs.pop( "selections", -1 @@ -491,7 +527,7 @@ def run_vehicle_scenarios( selections = range(len(vdf)) if args.dst_dir is None and config.dst_dir is None: - resdir = Path(os.path.abspath(__file__)).parents[1]/ f"results{dir_mark}" + resdir = Path(os.path.abspath(__file__)).parents[1] / f"results{dir_mark}" elif args.dst_dir is not None: resdir = Path(args.dst_dir) else: @@ -521,7 +557,9 @@ def run_vehicle_scenarios( # list of report dataframes to write final output at each iteration reports = [] - def input_validation(sel, optpt, algo, config): + def input_validation( + sel: float, optpt: str, algo: str, config: run_scenario.Scenario + ): """ This function obtains the vehicle, scenario, and cycle object for a given selection and runs optimization to validate inputs @@ -570,7 +608,14 @@ def input_validation(sel, optpt, algo, config): ) return None - def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): + def optimize( + sel: float, + scenario_name: str, + optpt: str, + algo: str, + skip_opt: bool, + write_tsv: bool = False, + ) -> None: """ This function runs the optimization for a given selection if skip_opt = False @@ -626,9 +671,7 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): report_vehicle = moo_problem.mooadvancedvehicle report_scenario = moo_problem.opt_scenario else: - input_vehicle = rs.get_vehicle( - sel, veh_input_path=gl.FASTSIM_INPUTS - ) + input_vehicle = rs.get_vehicle(sel, veh_input_path=gl.FASTSIM_INPUTS) report_vehicle = None report_scenario, design_cycle = rs.get_scenario_and_cycle( sel, gl.OTHER_INPUTS, a_vehicle=input_vehicle, config=config @@ -647,9 +690,7 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): # TODO, is moo_problem.moobasevehicle really the right vehicle here? num_results = 1 moo_code = "NA" - input_vehicle = rs.get_vehicle( - sel, veh_input_path=gl.FASTSIM_INPUTS - ) + input_vehicle = rs.get_vehicle(sel, veh_input_path=gl.FASTSIM_INPUTS) report_scenario, design_cycle = rs.get_scenario_and_cycle( sel, gl.OTHER_INPUTS, a_vehicle=input_vehicle, config=config ) @@ -682,9 +723,9 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): ) for v_input_k in input_vehicle.__dict__.keys(): if "value_props" not in v_input_k: - report_i[ - "input_vehicle_value_" + v_input_k - ] = input_vehicle.__getattribute__(v_input_k) + report_i["input_vehicle_value_" + v_input_k] = ( + input_vehicle.__getattribute__(v_input_k) + ) # we want place-holder blank values for optimization columns even if we're not optimizing report_i["optimized_vehicle_value_" + v_input_k] = None @@ -715,9 +756,9 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): moo.OPTIMIZATION_FAILED_TO_CONVERGE, ]: if moo_code == moo.EXCEPTION_THROWN: - report_i[ - "n_gen" - ] = "Code Exception thrown" # TODO, get stacktrace information and add to this + report_i["n_gen"] = ( + "Code Exception thrown" # TODO, get stacktrace information and add to this + ) elif moo_code == moo.OPTIMIZATION_FAILED_TO_CONVERGE: report_i["n_gen"] = "Optimization Failed to converge" report_i = {k: str(v) for k, v in report_i.items()} @@ -777,9 +818,9 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): report_i["final_fs_kwh"] = x_dixt.get(moo.KNOB_fs_kwh) for v_input_k in report_vehicle.__dict__.keys(): if "value_props" not in v_input_k: - report_i[ - "optimized_vehicle_value_" + v_input_k - ] = report_vehicle.__getattribute__(v_input_k) + report_i["optimized_vehicle_value_" + v_input_k] = ( + report_vehicle.__getattribute__(v_input_k) + ) n_gens_used = moo_results.history[-1].n_gen report_i["fvals_over_gens"] = [ @@ -840,9 +881,9 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): ) report_i["minSpeed6PercentGradeIn5minAch"] = outdict["grade_6_mph_ach"] - report_i[ - "target_minSpeed6PercentGradeIn5min" - ] = report_scenario.min_speed_at_6pct_grade_in_5min_mph + report_i["target_minSpeed6PercentGradeIn5min"] = ( + report_scenario.min_speed_at_6pct_grade_in_5min_mph + ) report_i["delta_6PercentGrade"] = ( outdict["grade_6_mph_ach"] - report_scenario.min_speed_at_6pct_grade_in_5min_mph @@ -851,30 +892,36 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): report_i["minSpeed1point25PercentGradeIn5minAch"] = outdict[ "grade_1_25_mph_ach" ] - report_i[ - "target_minSpeed1point25PercentGradeIn5min" - ] = report_scenario.min_speed_at_125pct_grade_in_5min_mph + report_i["target_minSpeed1point25PercentGradeIn5min"] = ( + report_scenario.min_speed_at_125pct_grade_in_5min_mph + ) report_i["delta_1point25PercentGrade"] = ( outdict["grade_1_25_mph_ach"] - report_scenario.min_speed_at_125pct_grade_in_5min_mph ) report_i["max0to60secAtGVWRAch"] = outdict["zero_to_60_loaded"] - report_i["target_max0to60secAtGVWR"] = report_scenario.max_time_0_to_60mph_at_gvwr_s + report_i["target_max0to60secAtGVWR"] = ( + report_scenario.max_time_0_to_60mph_at_gvwr_s + ) if ( outdict["zero_to_60_loaded"] is not None ): # cannot calculate if it is none (but for some reason, range and grade are handled when none) report_i["delta_0to60sec"] = ( - outdict["zero_to_60_loaded"] - report_scenario.max_time_0_to_60mph_at_gvwr_s + outdict["zero_to_60_loaded"] + - report_scenario.max_time_0_to_60mph_at_gvwr_s ) report_i["max0to30secAtGVWRAch"] = outdict["zero_to_30_loaded"] - report_i["target_max0to30secAtGVWR"] = report_scenario.max_time_0_to_30mph_at_gvwr_s + report_i["target_max0to30secAtGVWR"] = ( + report_scenario.max_time_0_to_30mph_at_gvwr_s + ) if ( outdict["zero_to_30_loaded"] is not None ): # cannot calculate if it is none (but for some reason, range and grade are handled when none) report_i["delta_0to30sec"] = ( - outdict["zero_to_30_loaded"] - report_scenario.max_time_0_to_30mph_at_gvwr_s + outdict["zero_to_30_loaded"] + - report_scenario.max_time_0_to_30mph_at_gvwr_s ) report_i.update(mpgge) @@ -978,12 +1025,12 @@ def optimize(sel, scenario_name, optpt, algo, skip_opt, write_tsv=False): print("writing to ", resdir / RES_FILE) - def skip_scenario(sel, scenario_name, verbose=False): + def skip_scenario(sel: int, scenario_name: str, verbose: bool = False) -> bool: """ This function checks if given selection is present in exclude or look_for selections Args: - sel (float): _description_ + sel (int): _description_ scenario_name (str): scenario name verbose (bool, optional): if selected, prints out scenarios that are skipped. Defaults to False. @@ -1143,11 +1190,7 @@ def skip_scenario(sel, scenario_name, verbose=False): default=1000, help="max number of optimizer iterations regardless of algorithm", ) - parser.add_argument( - "--pop-size", - default=25, - help="population of each generation" - ) + parser.add_argument("--pop-size", default=25, help="population of each generation") parser.add_argument( "--nth-gen", default=1, @@ -1187,49 +1230,46 @@ def skip_scenario(sel, scenario_name, verbose=False): # input files parser.add_argument( "--vehicles", - default=gl.SWEEP_PATH.parents[0]/"resources/inputs/demo/Demo_FY22_vehicle_model_assumptions.csv", + default=gl.SWEEP_PATH.parents[0] + / "resources/inputs/demo/Demo_FY22_vehicle_model_assumptions.csv", help="input file for vehicles", ) parser.add_argument( "--scenarios", - default=gl.SWEEP_PATH.parents[0]/"resources/inputs/demo/Demo_FY22_scenario_assumptions.csv", + default=gl.SWEEP_PATH.parents[0] + / "resources/inputs/demo/Demo_FY22_scenario_assumptions.csv", help="input file for scenarios", ) parser.add_argument( "--eng-curves", - default=gl.SWEEP_PATH.parents[0]/ "resources/auxiliary/eng_imp_cost_curves_for_demo.csv", + default=gl.SWEEP_PATH.parents[0] + / "resources/auxiliary/eng_imp_cost_curves_for_demo.csv", help="input file for engine efficiency curves", ) parser.add_argument( "--lw-curves", - default=gl.SWEEP_PATH.parents[0]/"resources/auxiliary/matlltwt_imp_cost_curves_for_demo.csv", + default=gl.SWEEP_PATH.parents[0] + / "resources/auxiliary/matlltwt_imp_cost_curves_for_demo.csv", help="input file for lightweighting curves", ) parser.add_argument( "--aero-curves", - default=gl.SWEEP_PATH.parents[0]/"resources/auxiliary/aero_imp_cost_curves_for_demo.csv", + default=gl.SWEEP_PATH.parents[0] + / "resources/auxiliary/aero_imp_cost_curves_for_demo.csv", help="input file for aerodynamics improvement curves", ) - parser.add_argument( - "--delete-me", - default=True - ) - parser.add_argument( - "--write-tsv", - default=False - ) + parser.add_argument("--delete-me", default=True) + parser.add_argument("--write-tsv", default=False) parser.add_argument( "--config", - default=gl.SWEEP_PATH.parents[0]/"resources/T3COConfig.csv", + default=gl.SWEEP_PATH.parents[0] / "resources/T3COConfig.csv", help="input config file", ) parser.add_argument( - "--analysis-id", - default='0', - help="analysis selection from input config file" + "--analysis-id", default="0", help="analysis selection from input config file" ) - print(f'gl.SWEEP_PATH: {gl.SWEEP_PATH}') + print(f"gl.SWEEP_PATH: {gl.SWEEP_PATH}") args = parser.parse_args() # selections can be an int, or list of ints, or range expression @@ -1259,11 +1299,11 @@ def skip_scenario(sel, scenario_name, verbose=False): config = rs.Config() config.validate_analysis_id(filename=args.config) selections = config.selections - vehicles = gl.SWEEP_PATH.parents[0]/config.vehicle_file - scenarios = gl.SWEEP_PATH.parents[0]/config.scenario_file - eng_eff_imp_curves = gl.SWEEP_PATH.parents[0]/config.eng_eff_imp_curves - lw_imp_curves = gl.SWEEP_PATH.parents[0]/config.lw_imp_curves - aero_drag_imp_curves = gl.SWEEP_PATH.parents[0]/config.aero_drag_imp_curves + vehicles = gl.SWEEP_PATH.parents[0] / config.vehicle_file + scenarios = gl.SWEEP_PATH.parents[0] / config.scenario_file + eng_eff_imp_curves = gl.SWEEP_PATH.parents[0] / config.eng_eff_imp_curves + lw_imp_curves = gl.SWEEP_PATH.parents[0] / config.lw_imp_curves + aero_drag_imp_curves = gl.SWEEP_PATH.parents[0] / config.aero_drag_imp_curves write_tsv = config.write_tsv look_for = args.look_for @@ -1318,7 +1358,13 @@ def skip_scenario(sel, scenario_name, verbose=False): ) run_vehicle_scenarios( - vehicles, scenarios, eng_eff_imp_curves, lw_imp_curves, aero_drag_imp_curves, config=config, **kwargs + vehicles, + scenarios, + eng_eff_imp_curves, + lw_imp_curves, + aero_drag_imp_curves, + config=config, + **kwargs, ) # %% diff --git a/t3co/tco/opportunity_cost.py b/t3co/tco/opportunity_cost.py index b0258e9..a012e08 100644 --- a/t3co/tco/opportunity_cost.py +++ b/t3co/tco/opportunity_cost.py @@ -1,4 +1,5 @@ # %% +from __future__ import annotations import warnings from math import ceil @@ -8,7 +9,6 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd -from scipy.integrate import trapz from scipy.stats import gaussian_kde import os from t3co.run import Global as gl @@ -32,7 +32,9 @@ class OpportunityCost: - Maintenance and Repair Downtime Cost """ - def __init__(self, scenario, range_dict=None, **kwargs): + def __init__( + self, scenario: run_scenario.Scenario, range_dict: dict = None, **kwargs + ) -> None: """ Initializes OpportunityCost object using Scenario object, range_dict (from fueleconomy module), and other arguments @@ -101,11 +103,19 @@ def __init__(self, scenario, range_dict=None, **kwargs): # weight distribution file to load self.wt_dist_file = kwargs.pop( "wt_dist_file", - Path(os.path.abspath(__file__)).parents[1] / "resources" / "auxiliary" / "tractorweightvars.csv", + Path(os.path.abspath(__file__)).parents[1] + / "resources" + / "auxiliary" + / "tractorweightvars.csv", ) self.df_veh_wt = pd.read_csv(self.wt_dist_file, index_col=0) - def set_kdes(self, scenario, bw_method=0.15, verbose=False): + def set_kdes( + self, + scenario: run_scenario.Scenario, + bw_method: float = 0.15, + verbose: bool = False, + ) -> None: """ This method sets tje kde kernel. This is time-consuming, only call this once, if possible. @@ -139,7 +149,9 @@ def set_kdes(self, scenario, bw_method=0.15, verbose=False): [self.vehicle_weights_bins_kg, self.p_of_weights], index=["vehicle_weights_bins_kg", "p_of_weights"], ).T - probability_payload.to_csv(Path(self.wt_dist_file).parents[0]/"payload_pdf.csv") + probability_payload.to_csv( + Path(self.wt_dist_file).parents[0] / "payload_pdf.csv" + ) normalization_factor = probability_payload[ probability_payload["vehicle_weights_bins_kg"].between( scenario.plf_ref_veh_empty_mass_kg, scenario.gvwr_kg @@ -148,13 +160,13 @@ def set_kdes(self, scenario, bw_method=0.15, verbose=False): 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 get_payload_loss_factor( + def set_payload_loss_factor( self, - a_vehicle: fastsim.vehicle, - scenario, - plots=False, - plots_dir=None, - ): + a_vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + plots: bool = False, + plots_dir: str = None, + ) -> None: """ This method runs teh kernel density estimation function set_kdes and calculates the payload capacity loss factor (payload_cap_cost_multiplier) \ of the new vehicle compared to a conventional vehicle's reference empty weight. @@ -168,9 +180,7 @@ def get_payload_loss_factor( self.set_kdes(scenario, verbose=False) new_empty_weight_kg = a_vehicle.veh_kg - a_vehicle.cargo_kg - empty_increase_kg = ( - new_empty_weight_kg - scenario.plf_ref_veh_empty_mass_kg - ) + empty_increase_kg = new_empty_weight_kg - scenario.plf_ref_veh_empty_mass_kg new_cargo_cieling_kg = ( scenario.gvwr_kg - empty_increase_kg + scenario.gvwr_credit_kg ) @@ -201,7 +211,7 @@ def get_payload_loss_factor( 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 = trapz(estimated_lost_payload_per_bin_kg) + 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 @@ -221,7 +231,7 @@ def get_payload_loss_factor( scenario.gvwr_kg + scenario.gvwr_credit_kg - new_empty_weight_kg ) - def make_plots(save_dir=None): + def make_plots(save_dir: str = None) -> None: """ This function generates a histogram of the payload KDE weight distribution @@ -290,7 +300,9 @@ def make_plots(save_dir=None): # self.dwell_time_factor = max(1, (self.d_trip_mi / self.v_mean_mph + self.net_dwell_time_hr) / # (self.d_trip_mi / self.v_mean_mph)) - def get_dwell_time_cost(self, a_vehicle: fastsim.vehicle, scenario): + def set_dwell_time_cost( + self, a_vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario + ) -> None: """ This function calculates the fueling dwell time cost for a vehicle based on fuel fill rate/charging power and shifts_per_year @@ -371,7 +383,9 @@ def get_dwell_time_cost(self, a_vehicle: fastsim.vehicle, scenario): self.num_of_dwells += 1 - self.remaining_dwells # else: - if (self.num_of_dwells < 1 and not self.num_free_trips) or (scenario.fuel_type): + if (self.num_of_dwells < 1 and not self.num_free_trips) or ( + scenario.fuel_type + ): self.net_dwell_time_hr.append( scenario.vmt[i] * (1 - scenario.fdt_dwpt_fraction_power_pct) @@ -386,17 +400,23 @@ def get_dwell_time_cost(self, a_vehicle: fastsim.vehicle, scenario): self.net_dwell_time_hr.append( self.shifts_per_year[i] * max( - 0, (self.dwell_time_hr - max(0, scenario.fdt_available_freetime_hr)) + 0, + ( + self.dwell_time_hr + - max(0, scenario.fdt_available_freetime_hr) + ), ) ) - self.dwell_time_cost_Dol.append(self.net_dwell_time_hr[i] * self.labor_rate_dol_per_hr) + self.dwell_time_cost_Dol.append( + self.net_dwell_time_hr[i] * self.labor_rate_dol_per_hr + ) self.total_dwell_time_hr += self.net_dwell_time_hr[i] # self.dwell_time_factor = max(1, (self.d_trip_mi / self.v_mean_mph + self.net_dwell_time_hr[i]) / # (self.d_trip_mi / self.v_mean_mph)) - # def get_dwell_time_cost #Old calculation + # def set_dwell_time_cost #Old calculation # (self, # a_vehicle:fastsim.vehicle, # scenario): @@ -411,7 +431,9 @@ def get_dwell_time_cost(self, a_vehicle: fastsim.vehicle, scenario): # print(f'Dwell time hr per year: {self.dwell_time_hr}') # print(f'Dwell cost dol: {self.dwell_time_cost_Dol}') - def get_M_R_downtime_cost(self, a_vehicle: fastsim.vehicle, scenario): + def set_M_R_downtime_cost( + self, a_vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario + ) -> None: """ This function calculates the Maintenance and Repair (M&R) downtime cost based on planned, unplanned, and tire replacement downtime inputs @@ -420,7 +442,8 @@ def get_M_R_downtime_cost(self, a_vehicle: fastsim.vehicle, scenario): scenario (run_scenario.Scenario): Scenario object for the current selection """ self.planned_downtime_hr = [ - scenario.mr_planned_downtime_hr_per_yr for _ in range(scenario.vehicle_life_yr) + scenario.mr_planned_downtime_hr_per_yr + for _ in range(scenario.vehicle_life_yr) ] # regular maintenance and inspections self.unplanned_downtime_hr = [ scenario.mr_unplanned_downtime_hr_per_mi[i] * scenario.vmt[i] @@ -478,13 +501,13 @@ def main(): print("oc.base_vehicle_cargo_lb", gl.kg_to_lbs(oc.base_vehicle_cargo_kg)) print("oc.original_empty_lb", gl.kg_to_lbs(oc.reference_vehicle_empty_kg)) - plf = oc.get_payload_loss_factor(v, plots=True) + plf = oc.set_payload_loss_factor(v, plots=True) print(plf) - oc.get_dwell_time_cost(v, s) + oc.set_dwell_time_cost(v, s) print(oc.dwell_time_cost) print(oc.net_dwell_time_hr) print(oc.__dict__["payload_cap_cost_multiplier"]) - oc.get_M_R_downtime_cost(v, s) + oc.set_M_R_downtime_cost(v, s) # %% diff --git a/t3co/tco/tco_analysis.py b/t3co/tco/tco_analysis.py index c9bf55b..990652d 100644 --- a/t3co/tco/tco_analysis.py +++ b/t3co/tco/tco_analysis.py @@ -1,5 +1,10 @@ +from __future__ import annotations + +from typing import Tuple +import fastsim +import pandas as pd from t3co.objectives import fueleconomy -from t3co.run import Global as gl +from t3co.run import Global as gl, run_scenario from t3co.tco import tco_stock_emissions from t3co.tco import tcocalc as tcocalc @@ -10,7 +15,7 @@ STD_VAR_NAMES = "stdVarNames" -def get_operating_costs(ownershipCosts, TCO_switch="DIRECT"): +def get_operating_costs(ownershipCosts, TCO_switch: str = "DIRECT") -> pd.DataFrame: """ This function creates a dataframe of operating cost from ownershipCosts dataframe based on TCO_switch ('DIRECT' or 'EFFICIENCY') @@ -47,7 +52,9 @@ def get_operating_costs(ownershipCosts, TCO_switch="DIRECT"): return operatingCosts_df -def discounted_costs(scenario, ownershipCosts): +def discounted_costs( + scenario: run_scenario.Scenario, ownershipCosts: pd.DataFrame +) -> pd.DataFrame: """ This function calculates the yearly discounted costs for each category of ownershipCosts based on scenario.discount_rate_pct_per_yr @@ -68,13 +75,13 @@ def discounted_costs(scenario, ownershipCosts): def calc_discountedTCO( - scenario, - discounted_costs_df, - veh_cost_set, - veh_opp_cost_set, - sim_drive, - TCO_switch="DIRECT", -): + scenario: run_scenario.Scenario, + discounted_costs_df: pd.DataFrame, + veh_cost_set: dict, + veh_opp_cost_set: dict, + sim_drive: fastsim.simdrive.SimDrive, + TCO_switch: str = "DIRECT", +) -> Tuple[float, dict, dict]: """ This function calculates the discounted Total Cost of Ownerhip (discounted to account for time-value of money). There are two methods to calculate discounted TCO - 'DIRECT' and 'EFFICIENCY' @@ -172,7 +179,24 @@ def calc_discountedTCO( return discountedTCO, oppy_cost_Dol_set, veh_oper_cost_set -def get_tco_of_vehicle(vehicle, range_cyc, scenario, write_tsv=False): +def get_tco_of_vehicle( + vehicle: fastsim.vehicle.Vehicle, + range_cyc: fastsim.cycle.Cycle, + scenario: run_scenario.Scenario, + write_tsv: bool = False, +) -> Tuple[ + float, + float, + dict, + pd.DataFrame, + pd.DataFrame, + dict, + dict, + fastsim.simdrive.SimDrive, + dict, + dict, + dict, +]: """ This function calculates the Total Cost of Ownership of a vehicle and scenario for a given cycle. The three main components are: - Opportunity Costs @@ -181,7 +205,7 @@ def get_tco_of_vehicle(vehicle, range_cyc, scenario, write_tsv=False): Args: vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object of selected vehicle - range_cyc (fastsim.cycle.Cycle): FASTSim range cycle object + range_cyc (fastsim.cycle.Cycle): FASTSim range cycle object scenario (run_scenario.Scenario): Scenario object for current selection write_tsv (bool, optional): if True, save intermediate files as TSV. Defaults to False. diff --git a/t3co/tco/tco_stock_emissions.py b/t3co/tco/tco_stock_emissions.py index 1150b0f..2640883 100644 --- a/t3co/tco/tco_stock_emissions.py +++ b/t3co/tco/tco_stock_emissions.py @@ -1,13 +1,14 @@ -#December 2018 -#Stock Model in Python +# December 2018 +# Stock Model in Python # C. Hunter +from typing import Tuple import pandas as pd from t3co.run import Global as gl -def dropCols(df): +def dropCols(df: pd.DataFrame) -> pd.DataFrame: """ This helper method drops columns if any row contains ['*'] @@ -24,21 +25,21 @@ def dropCols(df): def stockModel( - sales, - marketShares, - survival, - annualTravel, - fuelSplit, - fuelEfficiency, - emissions, - vehicleCosts=None, - travelCosts=None, - fuelCosts=None, - insuranceCosts=None, - residualCosts=None, - downtimeCosts=None, - write_files=False, -): + sales: pd.DataFrame, + marketShares: pd.DataFrame, + survival: pd.DataFrame, + annualTravel: pd.DataFrame, + fuelSplit: pd.DataFrame, + fuelEfficiency: pd.DataFrame, + emissions: pd.DataFrame, + vehicleCosts: pd.DataFrame = None, + travelCosts: pd.DataFrame = None, + fuelCosts: pd.DataFrame = None, + insuranceCosts: pd.DataFrame = None, + residualCosts: pd.DataFrame = None, + downtimeCosts: pd.DataFrame = None, + write_files: bool = False, +) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: """ This function generates the ownershipCosts dataframe from the dataframes for each cost category diff --git a/t3co/tco/tcocalc.py b/t3co/tco/tcocalc.py index ca6e73a..6675259 100644 --- a/t3co/tco/tcocalc.py +++ b/t3co/tco/tcocalc.py @@ -1,14 +1,17 @@ +from __future__ import annotations + import numpy as np import pandas as pd from t3co.run import Global as gl from t3co.run import run_scenario from t3co.tco import opportunity_cost +import fastsim KG_2_LB = 2.20462 -def kg_to_lbs(kgs): +def kg_to_lbs(kgs: float) -> float: return kgs * KG_2_LB @@ -19,8 +22,8 @@ def kg_to_lbs(kgs): def find_residual_rates( - vehicle, scenario -): # finds residual rate at end of vehicle life + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario +) -> float: # finds residual rate at end of vehicle life """ This helper method gets the residual rates from ResidualValues.csv @@ -42,7 +45,9 @@ def find_residual_rates( return residual_rates -def calculate_dollar_cost(veh, scenario): +def calculate_dollar_cost( + veh: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario +) -> dict: """ This helper method calculates the MSRP breakdown dictionary from - Glider @@ -101,7 +106,9 @@ def calculate_dollar_cost(veh, scenario): fcPrice = scenario.fc_fuelcell_cost_dol_per_kw * fc_max_kw # TODO, what should 9 map too?? elif veh.fc_eff_type == 9: - fcPrice = (scenario.fc_cng_ice_cost_dol_per_kw * fc_max_kw) + fc_ice_base_cost_dol + fcPrice = ( + scenario.fc_cng_ice_cost_dol_per_kw * fc_max_kw + ) + fc_ice_base_cost_dol else: fcPrice = (fc_ice_cost_dol_per_kw * fc_max_kw) + fc_ice_base_cost_dol @@ -121,7 +128,9 @@ def calculate_dollar_cost(veh, scenario): fuelStorPrice = 0 elif veh.veh_pt_type == gl.HEV and scenario.fuel_type[0] == "hydrogen": fuelStorPrice = scenario.fs_h2_cost_dol_per_kwh * veh.fs_kwh - elif veh.veh_pt_type in [gl.CONV, gl.HEV, gl.PHEV] and scenario.fuel_type[0] == "cng": + elif ( + veh.veh_pt_type in [gl.CONV, gl.HEV, gl.PHEV] and scenario.fuel_type[0] == "cng" + ): fuelStorPrice = scenario.fs_cng_cost_dol_per_kwh * veh.fs_kwh elif veh.veh_pt_type in [gl.CONV, gl.HEV, gl.PHEV]: fuelStorPrice = scenario.fs_cost_dol_per_kwh * veh.fs_kwh @@ -159,7 +168,14 @@ def calculate_dollar_cost(veh, scenario): elif veh_pt_type == gl.HEV: msrp = vehicle_glider_cost_dol + fuelStorPrice + fcPrice + mcPrice + essPrice elif veh_pt_type == gl.PHEV: - msrp = vehicle_glider_cost_dol + fuelStorPrice + fcPrice + mcPrice + essPrice + plugPrice + msrp = ( + vehicle_glider_cost_dol + + fuelStorPrice + + fcPrice + + mcPrice + + essPrice + + plugPrice + ) elif veh_pt_type == gl.BEV: msrp = vehicle_glider_cost_dol + mcPrice + essPrice + plugPrice @@ -183,7 +199,9 @@ def calculate_dollar_cost(veh, scenario): return cost_set -def calculate_opp_costs(vehicle, scenario, range_dict): +def calculate_opp_costs( + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario, range_dict: dict +) -> dict: """ This helper method calculates opportunity costs and generates veh_opp_cost_set from - Payload Lost Capacity Cost/Multiplier @@ -194,13 +212,16 @@ def calculate_opp_costs(vehicle, scenario, range_dict): vehicle (fastsim.vehicle.Vehicle): FASTSim vehicle object of analysis vehicle scenario (run_scenario.Scenario): Scenario object of current selection range_dict (dict): Dictionary containing range values from fueleconomy.get_range_mi() + + Returns: + veh_opp_cost_set (dict): Dictionary containing opportunity cost results """ 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.get_payload_loss_factor(vehicle, scenario) + 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" @@ -214,14 +235,14 @@ def calculate_opp_costs(vehicle, scenario, range_dict): and len(oppcostobj.shifts_per_year) >= scenario.vehicle_life_yr ), f"Provide scenario.shifts_per_year as a vector of length > scenario.vehicle_life_yr. Currently {len(oppcostobj.shifts_per_year)}" assert gl.not_falsy(scenario.fdt_frac_full_charge_bounds) - oppcostobj.get_dwell_time_cost(vehicle, scenario) + oppcostobj.set_dwell_time_cost(vehicle, scenario) if scenario.activate_mr_downtime_cost: assert gl.not_falsy(scenario.mr_planned_downtime_hr_per_yr) assert any(np.isnan(scenario.mr_unplanned_downtime_hr_per_mi)) == False assert np.isnan(scenario.mr_tire_replace_downtime_hr_per_event) == False assert gl.not_falsy(scenario.mr_avg_tire_life_mi) - oppcostobj.get_M_R_downtime_cost(vehicle, scenario) + oppcostobj.set_M_R_downtime_cost(vehicle, scenario) # veh_opp_cost_set = {'payload_cap_cost_multiplier' : None, 'net_dwell_time_hr' : 0., 'dwell_time_cost_Dol' : 0.} veh_opp_cost_set = { @@ -237,7 +258,9 @@ def calculate_opp_costs(vehicle, scenario, range_dict): return veh_opp_cost_set -def fill_fuel_eff_file(vehicle, scenario, mpgge_dict): +def fill_fuel_eff_file( + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario, mpgge_dict: dict +) -> pd.DataFrame: """ This helper method generates a dataframe of Fuel Efficiency [mi/gge] For PHEV, cd_grid_electric_mpgge, cd_fuel_mpgge, and cs_fuel_mpgge @@ -313,7 +336,9 @@ def fill_fuel_eff_file(vehicle, scenario, mpgge_dict): return fefdata -def fill_veh_expense_file(scenario, cost_set): +def fill_veh_expense_file( + scenario: run_scenario.Scenario, cost_set: dict +) -> pd.DataFrame: """ This helper method generates a dataframe of MSRP breakdown costs as Cost [$/veh] @@ -360,7 +385,9 @@ def fill_veh_expense_file(scenario, cost_set): return vexpdf -def fill_trav_exp_tsv(vehicle, scenario): +def fill_trav_exp_tsv( + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario +) -> pd.DataFrame: """ This helper method generates a dataframe containing maintenance costs in Cost [$/mi] @@ -400,7 +427,9 @@ def fill_trav_exp_tsv(vehicle, scenario): return df -def fill_downtimelabor_cost_tsv(scenario, oppy_cost_set): +def fill_downtimelabor_cost_tsv( + scenario: run_scenario.Scenario, oppy_cost_set: dict +) -> pd.DataFrame: """ This helper method generates a dataframe containing fueling downtime and M&R downtime costs in Cost [$/Yr] @@ -434,7 +463,9 @@ def fill_downtimelabor_cost_tsv(scenario, oppy_cost_set): return df -def fill_market_share_tsv(scenario, num_vs=1): +def fill_market_share_tsv( + scenario: run_scenario.Scenario, num_vs: int = 1 +) -> pd.DataFrame: """ This helper method generates a dataframe containing market share of current vehicle selection per vehicle sold @@ -464,7 +495,9 @@ def fill_market_share_tsv(scenario, num_vs=1): return df -def fill_fuel_expense_tsv(vehicle, scenario): +def fill_fuel_expense_tsv( + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario +) -> pd.DataFrame: """ This helper method generates a dataframe of fuel operating costs in Cost [$/gge] @@ -482,7 +515,12 @@ def fill_fuel_expense_tsv(vehicle, scenario): fuels = scenario.fuel_type if vehicle.veh_pt_type in [gl.CONV, gl.HEV]: - assert scenario.fuel_type[0].lower() in ["cng", "gasoline", "diesel", "hydrogen"] + assert scenario.fuel_type[0].lower() in [ + "cng", + "gasoline", + "diesel", + "hydrogen", + ] elif vehicle.veh_pt_type in [gl.BEV]: assert scenario.fuel_type[0].lower() in ["electricity"] elif vehicle.veh_pt_type == gl.PHEV: @@ -539,7 +577,7 @@ def fill_fuel_expense_tsv(vehicle, scenario): return df -def fill_annual_tsv(scenario): +def fill_annual_tsv(scenario: run_scenario.Scenario) -> pd.DataFrame: """ This helper method generates a dataframe of annual vehicle miles traveled (vmt) - Annual Travel [mi/yr] @@ -571,7 +609,9 @@ def fill_annual_tsv(scenario): return df -def fill_reg_sales_tsv(scenario, num_vs=1): +def fill_reg_sales_tsv( + scenario: run_scenario.Scenario, num_vs: int = 1 +) -> pd.DataFrame: """ This helper method generates a dataframe containing vehicle sales per year - Sales [veh] @@ -599,7 +639,9 @@ def fill_reg_sales_tsv(scenario, num_vs=1): return df -def fill_insurance_tsv(scenario, veh_cost_set): +def fill_insurance_tsv( + scenario: run_scenario.Scenario, veh_cost_set: dict +) -> pd.DataFrame: """ This helper method generates a dataframe containing vehicle insurance costs as Cost [$/Yr] @@ -634,7 +676,11 @@ def fill_insurance_tsv(scenario, veh_cost_set): return df -def fill_residual_cost_tsc(vehicle, scenario, veh_cost_set): +def fill_residual_cost_tsc( + vehicle: fastsim.vehicle.Vehicle, + scenario: run_scenario.Scenario, + veh_cost_set: dict, +) -> pd.DataFrame: """ This helper method generates a dataframe of residual costs as Cost [$/Yr] @@ -671,7 +717,7 @@ def fill_residual_cost_tsc(vehicle, scenario, veh_cost_set): return df -def fill_survival_tsv(scenario, num_vs=1): +def fill_survival_tsv(scenario: run_scenario.Scenario, num_vs=1) -> pd.DataFrame: """ This helper method generates a dataframe containing surviving vehicles as Surviving Vehicles [veh/veh] @@ -694,7 +740,9 @@ def fill_survival_tsv(scenario, num_vs=1): return df -def fill_fuel_split_tsv(vehicle, scenario, mpgge): +def fill_fuel_split_tsv( + vehicle: fastsim.vehicle.Vehicle, scenario: run_scenario.Scenario, mpgge: dict +) -> pd.DataFrame: """ This helper method generates a dataframe of fraction of travel in each fuel type as Fraction of Travel [mi/mi]