diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec81a707..9be2c7237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ - Added `simulation` section under `plant_config['plant']` that has information such as number of timesteps in the simulation, time step interval in seconds, simulation start time, and time zone. - Added `"custom_electrolyzer_cost"` model, an electrolyzer cost model that allows for user-defined capex and opex values - Made `pipe` and `cable` substance-agnostic rather than hard-coded for `hydrogen` and `electricity` +- Change finance handling to use `finance_subgroups` and `finance_groups` defined in the `plant_config` rather than previous `financial_groups` in the `tech_config` and `technologies_to_include_in_metrics` in `plant_config` ## 0.3.0 [May 2 2025] diff --git a/docs/_toc.yml b/docs/_toc.yml index 6b197d90c..8a403b637 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -17,9 +17,15 @@ parts: - file: user_guide/postprocessing_results - file: user_guide/how_to_interface_with_user_defined_model - file: user_guide/specifying_finance_parameters + sections: + - file: user_guide/cost_years + - file: finance_models/finance_index + sections: + - file: finance_models/ProFastComp - caption: Technology Models chapters: + - file: technology_models/technology_overview - file: technology_models/feedstocks - file: technology_models/run_of_river - file: technology_models/direct_ocean_capture diff --git a/docs/finance_models/ProFastComp.md b/docs/finance_models/ProFastComp.md new file mode 100644 index 000000000..d73040015 --- /dev/null +++ b/docs/finance_models/ProFastComp.md @@ -0,0 +1,229 @@ + +(profastcomp:profastcompmodel)= +# ProFastComp +The `ProFastComp` finance model calculates levelized cost of commodity using [ProFAST](https://github.com/NREL/ProFAST). + +The inputs, outputs, and naming convention for the `ProFastComp` model are outlined in this doc page. + + +(profastcomp:overview)= +## Finance parameters overview +The main inputs for `ProFastComp` model include: +- required: financial parameters (`params` section). These can be input in the `ProFastComp` format or the `ProFAST` format. These two formats are described in the following sections: + - [ProFastComp format](profastcomp:direct_opt) + - [ProFAST format](profastcomp:pf_params_opt) +- required: default capital item parameters (`capital_items` section). These parameters can be overridden for specific technologies if specified in the `tech_config`. Example usage of overriding values in the `tech_config` is outlined [here](profastcomp:tech_specific_finance) +- optional: information to export the ProFAST config to a .yaml file + +```yaml +finance_parameters: + finance_model: "ProFastComp" + model_inputs: #inputs for the finance_model + save_profast_to_file: True #optional, will save ProFAST entries to .yaml file in the folder specified in the driver_config (`driver_config["general"]["folder_output"]`) + profast_output_description: "profast_config" #required if `save_profast_to_file` is True, used to name the output file. + params: #Financial parameters section + capital_items: #Required: section for default parameters for capital items + depr_type: "MACRS" #Required: depreciation method for capital items, can be "MACRS" or "Straight line" + depr_period: 5 #Required: depreciation period for capital items + refurb: [0.] #Optional: replacement schedule as a fraction of the capital cost. Defaults to [0.] + fixed_costs: #Optional section for default parameters for fixed cost items + escalation: #escalation rate for fixed costs, will default to `inflation_rate` specific in the params section + unit: "$/year" #optional unit of the cost. Defaults to $/year + usage: 1.0 #usage multiplier, most commonly is set to 1 and defaults to 1.0 + +``` + +(profastcomp:direct_opt)= +## Providing Finance Parameters: ProFastComp Format +Below is an example inputting financial parameters directly in the `finance_parameters` section of `plant_config`: + +```yaml +finance_parameters: + finance_model: "ProFastComp" #finance model + model_inputs: #inputs for finance_model + params: #Financing parameters + analysis_start_year: 2032 #year that financial analysis starts + installation_time: 36 #installation period in months + # Inflation parameters + inflation_rate: 0.0 # 0 for nominal analysis + # Finance parameters + discount_rate: 0.09 + debt_equity_ratio: 2.62 + property_tax_and_insurance: 0.03 + total_income_tax_rate: 0.257 + capital_gains_tax_rate: 0.15 + sales_tax_rate: 0.07375 + debt_interest_rate: 0.07 + debt_type: "Revolving debt" #"Revolving debt" or "One time loan" + loan_period_if_used: 0 #loan period if debt_type is 'One time loan' + cash_onhand_months: 1 + admin_expense: 0.00 #administrative expense as a fraction of sales + #default parameters for capital items unless specified in tech_config + capital_items: + depr_type: "MACRS" #depreciation method for capital items, can be "MACRS" or "Straight line" + depr_period: 5 #depreciation period for capital items in years. + refurb: [0.] #refurbishment schedule, values represent the replacement cost as a fraction of the CapEx + + # To adjust costs for technologies to target_dollar_year + cost_adjustment_parameters: + target_dollar_year: 2022 + cost_year_adjustment_inflation: 0.025 +``` + +This approach also relies on data from `plant_config`: +- `plant_life`: used as the `operating life` ProFAST parameter + + +```{note} +`inflation_rate` is used to populate the escalation and inflation rates in ProFAST entries with a value of 0 corresponding to a *nominal analysis*. +``` + +(profastcomp:pf_params_opt)= +## Providing Finance Parameters: ProFAST format + +```{note} +To avoid errors, please check that `plant_config['plant']['plant_life']` is equal to `plant_config['finance_parameters']['model_inputs']['params']['operating life']`. Or remove `operating life` from the finance parameter inputs.` + + +| plant config parameter | equivalent `params` parameter | +| -------- | ------- | +| `plant['plant']['plant_life']` | `operating life` | +``` + +Below is an example of the `finance_parameters` section of `plant_config` if using ProFAST input format to specify financial parameters: + +```yaml +finance_parameters: + finance_model: "ProFastComp" + model_inputs: + params: !include "profast_params.yaml" #Finance information + capital_items: #default parameters for capital items unless specified in tech_config + depr_type: "MACRS" ##depreciation method for capital items, can be "MACRS" or "Straight line" + depr_period: 5 #depreciation period for capital items + refurb: [0.] + cost_adjustment_parameters: + target_dollar_year: 2022 + cost_year_adjustment_inflation: 0.025 # used to adjust costs for technologies to target_dollar_year +``` + +Below is an example of a valid ProFAST params config that may be specified in the `finance_parameters['model_inputs']['params]` section of `plant_config`: +```yaml +# Installation information +maintenance: + value: 0.0 + escalation: 0.0 +non depr assets: 250000 #such as land cost +end of proj sale non depr assets: 250000 #such as land cost +installation cost: + value: 0.0 + depr type: "Straight line" + depr period: 4 + depreciable: False +# Incentives information +incidental revenue: + value: 0.0 + escalation: 0.0 +annual operating incentive: + value: 0.0 + decay: 0.0 + sunset years: 0 + taxable: true +one time cap inct: + value: 0.0 + depr type: "MACRS" + depr period: 5 + depreciable: True +# Sales information +analysis start year: 2032 +operating life: 30 #if included, should equal plant_config['plant']['plant_life'] +installation months: 36 +demand rampup: 0 +# Take or pay specification +TOPC: + unit price: 0.0 + decay: 0.0 + support utilization: 0.0 + sunset years: 0 +# Other operating expenses +credit card fees: 0.0 +sales tax: 0.0 +road tax: + value: 0.0 + escalation: 0.0 +labor: + value: 0.0 + rate: 0.0 + escalation: 0.0 +rent: + value: 0.0 + escalation: 0.0 +license and permit: + value: 0.0 + escalation: 0.0 +admin expense: 0.0 +property tax and insurance: 0.015 +# Financing information +sell undepreciated cap: True +capital gains tax rate: 0.15 +total income tax rate: 0.2574 +leverage after tax nominal discount rate: 0.0948 +debt equity ratio of initial financing: 1.72 +debt interest rate: 0.046 +debt type: "Revolving debt" +general inflation rate: 0.0 +cash onhand: 1 # number of months with cash on-hand +tax loss carry forward years: 0 +tax losses monetized: True +loan period if used: 0 +``` + +(profastcomp:tech_specific_finance)= +## Override defaults for specific technologies + +Capital item entries can be overridden for individual technologies. +This means that specific technologies can have different financial parameters defined in `tech_config` than the defaults set in the `plant_config`. + +### **Override depreciation period:** + +Suppose the default depreciation period for capital items is 5 years (set in the `plant_config['finance_parameters']['model_inputs]['capital_items']['depr_period']`), but we want the depreciation period for the electrolyzer to be 7 years. This can be done in the `tech_config` as shown below: +```yaml +technologies: + electrolyzer: + model_inputs: + finance_parameters: + capital_items: + depr_period: 7 +``` + + +### **Custom refurbishment period:** + +Suppose the default refurbishment schedule for capital items is `[0.]` (set in the `plant_config['finance_parameters']['model_inputs]['capital_items']['refurb']`), but we want our battery to be replaced in 15-years and the replacement cost is equal to the capital cost. This can be accomplished in the tech_config as shown below: +```yaml +technologies: + battery: + model_inputs: + finance_parameters: + capital_items: + refurbishment_period_years: 15 + replacement_cost_percent: 1.0 +``` + +(profastcomp:outputs)= +## Output values and naming convention +``ProFastComp`` outputs the following data following the naming convention detailed below: +- `LCO`: levelized cost of commodity in USD/commodity unit, e.g. `LCOH_produced` for hydrogen produced. +- `wacc_`: weighted average cost of capital as a fraction. +- `crf_`: capital recovery factor as a fraction. +- `irr_`: internal rate of return as a fraction. +- `profit_index_` +- `investor_payback_period_`: time until initial investment costs are recovered in years. +- `price_`: first year price of commodity in same units as levelized cost. + +**Naming convention**: +- ``: + - if `commodity_desc` is **not** provided, then `` this is just `commodity`. For example, `wacc_hydrogen` if the `commodity` is `"hydrogen"`. + - if `commodity_desc` is provided, then `` is `_`. For example, `wacc_hydrogen_produced` if the `commodity` is `"hydrogen"` and `commodity_desc` is `"produced"` +- ``: + - if `commodity_desc` is **not** provided, then `` is the upper-case first letter of the `commodity`. For example, `LCOH` if the `commodity` is `"hydrogen"` + - if `commodity_desc` is provided, then `` is the upper-case first letter of the `commodity` followed by the `commodity_desc` descriptor. For example, `LCOH_produced` if the `commodity` is `"hydrogen"` and the `commodity_desc` is `"produced"`. diff --git a/docs/finance_models/finance_index.md b/docs/finance_models/finance_index.md new file mode 100644 index 000000000..5df3e83e9 --- /dev/null +++ b/docs/finance_models/finance_index.md @@ -0,0 +1,21 @@ + +(finance:overview)= +# Finance Models Overview + +**General finance models** compute finance metrics and are not specific to individual technologies. +These models live in the `h2integrate/finances/` folder and accept `driver_config`, `tech_config`, `plant_config`, `commodity_type`, and a `description` as the inputs and options. + +- `driver_config` (dict): the `folder_outputs` specified here may be used by the finance model if the finance model outputs data to a file. +- `tech_config` (dict): the technology configs for the technologies to include in the finance calculations +- `plant_config` (dict): contains the `finance_parameters` for the finance model (see [Finance Parameters](financeparameters:specifiyingfinanceparameters)). +- `commodity_type` (str): the name of the commodity to use in the finance calculation. +- `description` (str, optional): an additional description to use for naming outputs of the finance model. + +```{note} +The `commodity_type` and `description` are used in the finance model naming convention. Specifics on the output naming convention for each finance model can be found in their docs. +``` + +(finance:supportedmodels)= +## Currently supported general finance models + +- [``ProFastComp``](profastcomp:profastcompmodel): calculates levelized cost of commodity using ProFAST. diff --git a/docs/technology_models/atb_costs_pv.md b/docs/technology_models/atb_costs_pv.md index 7b5868024..10c12b04a 100644 --- a/docs/technology_models/atb_costs_pv.md +++ b/docs/technology_models/atb_costs_pv.md @@ -11,6 +11,7 @@ As mentioned on the [Utility-Scale PV ATB page](https://atb.nrel.gov/electricity - The `"atb_utility_pv_cost"` model has costs input in `$/kW-AC` to match the ATB and the outputted capacity in kW-AC from the PV performance model. Example usage of this cost model in the `tech_config.yaml` file is shown [in the first section below](#utility-scale-pv-cost-model). - The `"atb_comm_res_pv_cost"` model has costs input in `$/kW-DC` and the PV capacity is input in kW-DC from the **shared input parameter** of the PV performance model. Example usage of this cost model in the `tech_config.yaml` file is shown [in the second section below](#commercial-and-residential-pv-cost-model). +(utility-scale-pv-cost-model)= ## Utility-Scale PV Cost Model The inputs for `cost_parameters` are `capex_per_kWac` and `opex_per_kWac_per_year`. From the ATB workbook, a value for `capex_per_kWac` can be found on the `Solar - Utility PV` sheet under the "Overnight Capital Cost" section or the "CAPEX" section. The values in the "CAPEX" section include overnight capital costs, construction finance factor, and grid connection costs. A value for `opex_per_kWac_per_year` can be found on the `Solar - Utility PV` sheet under the "Fixed Operation and Maintenance Expenses" section. @@ -34,6 +35,7 @@ technologies: opex_per_kWac_per_year: 18 ``` +(commercial-and-residential-pv-cost-model)= ## Commercial and Residential PV Cost Model The inputs for `cost_parameters` are `capex_per_kWdc` and `opex_per_kWdc_per_year`. From the ATB workbook, a value for `capex_per_kWdc` can be found on the `Solar - PV Dist. Comm` or `Solar - PV Dist. Res` sheet under the "Overnight Capital Cost" section or the "CAPEX" section. The values in the "CAPEX" section include overnight capital costs, construction finance factor, and grid connection costs. A value for `opex_per_kWdc_per_year` can be found on the `Solar - PV Dist. Comm` or `Solar - PV Dist. Res` sheet under the "Fixed Operation and Maintenance Expenses" section. diff --git a/docs/technology_models/pvwattsv8_solar_pv.md b/docs/technology_models/pvwattsv8_solar_pv.md index 08987f545..76299bc79 100644 --- a/docs/technology_models/pvwattsv8_solar_pv.md +++ b/docs/technology_models/pvwattsv8_solar_pv.md @@ -28,6 +28,7 @@ technologies: ``` +(performance-parameters)= ## Performance Parameters - `pv_capacity_kWdc` (required): capacity of the PV system in kW-DC - `dc_ac_ratio`: the ratio of DC capacity to AC capacity, equal to `pv_capacity_kWdc/pv_capacity_kWac` is used to calculate the PV capacity in kW-AC and is equivalent as the inverter rated power. An inverter is used in PV systems to convert DC power (output from panels) to AC power (input to AC microgrid). The PV capacity in kW-AC is `pv_capacity_kWdc/dc_ac_ratio`. A general default `dc_ac_ratio` is between 1.2 and 1.3. **This is required if** `dc_ac_ratio` is not either loaded from a default Pvwattsv8 config OR not included in the `pysam_options` dictionary under the `SystemDesign` group. @@ -70,6 +71,7 @@ $$ - [Shading](https://nrel-pysam.readthedocs.io/en/main/modules/Pvwattsv8.html#shading-group) - [AdjustmentFactors](https://nrel-pysam.readthedocs.io/en/main/modules/Pvwattsv8.html#adjustmentfactors-group) +(systemdesign-group)= ### SystemDesign group ```{note} Do not include the `system_capacity` parameter of the `SystemDesign` group. The system capacity should be set in the performance parameters with the variable `pv_capacity_kWdc`. @@ -106,6 +108,7 @@ Some common design parameters that a user may want to specify within the [System - `tilt_angle_func` is set to "none" and `tilt` is specified under the performance parameters. ``` +(solarresource-group)= ### SolarResource group Solar resource data is downloaded from the [National Solar Resource Database](https://developer.nrel.gov/docs/solar/nsrdb/psm3-2-2-download/) and input as the `solar_resource_data` variable in the Pvwattsv8 SolarResource Group. Some other common resource parameters that a user may want to specify within the [SolarResource Group](https://nrel-pysam.readthedocs.io/en/main/modules/Pvwattsv8.html#solarresource-group) are: - `use_wf_albedo` (bool): if True, use albedo from weather file (if valid). If False, use value for `albedo_default`. Defaults to True. diff --git a/docs/technology_models/technology_overview.md b/docs/technology_models/technology_overview.md index 025c4dfb6..6d8f09641 100644 --- a/docs/technology_models/technology_overview.md +++ b/docs/technology_models/technology_overview.md @@ -8,6 +8,7 @@ Currently, H2I recognizes four types of models: - [Storage](#storage) - [Controllers](#controller) +(resource)= ## Resource `Resource` models process resource data that is usually passed to a technology model. @@ -19,6 +20,7 @@ Currently, H2I recognizes four types of models: The `Resource` models are under development. Many of the resources are currently integrated into the `Converter` model directly, notably this is true for the wind resource used in the `wind` converter and solar resource used in the `solar` converter. ``` +(converters)= ## Converters `Converter` models are technologies that: - converts energy available in the 'Primary Input' to another form of energy ('Primary Commodity') OR @@ -42,7 +44,7 @@ The inputs, outputs, and corresponding technology that are currently available i | `air_separator` | nitrogen | electricity | | `desal` | water | electricity | - +(transport)= ## Transport `Transport` models are used to either: - connect the 'Transport Commodity' from a technology that produces the 'Transport Commodity' to a technology that consumes or stores the 'Transport Commodity' OR @@ -60,6 +62,7 @@ The inputs, outputs, and corresponding technology that are currently available i Connection: `[source_tech, dest_tech, transport_commodity, transport_technology]` +(storage)= ## Storage `Storage` technologies input and output the 'Storage Commodity' at different times. These technologies can be filled or charged, then unfilled or discharged at some later time. These models are usually constrained by two key model parameters: storage capacity and charge/discharge rate. @@ -68,6 +71,7 @@ Connection: `[source_tech, dest_tech, transport_commodity, transport_technology] | `h2_storage` | hydrogen | | `battery` | electricity | +(controller)= ## Controller `Controller` models are used to control the `Storage` models and resource flows. @@ -84,13 +88,14 @@ Below summarizes the available performance, cost, and financial models for each - [Transport](#transport-models) - [Storage](#storage-models) - -### Resource models +(resource-models)= +## Resource models - `river`: - performance models: + `river_resource` -### Converter models +(converter-models)= +## Converter models - `wind`: wind turbine - performance models: + `'wind_plant_performance'` @@ -173,8 +178,8 @@ Below summarizes the available performance, cost, and financial models for each - cost models: + `'reverse_osmosis_desalination_cost'` - -### Transport Models +(transport-models)= +## Transport Models - `cable` - performance models: + `'cable'` @@ -185,8 +190,8 @@ Below summarizes the available performance, cost, and financial models for each - performance models: + `'combiner_performance'` - -### Storage Models +(storage-models)= +## Storage Models - `h2_storage`: hydrogen storage - combined performance and cost + `'h2_storage'` @@ -195,6 +200,6 @@ Below summarizes the available performance, cost, and financial models for each - cost models: + `'hydrogen_tank_cost'` -### Controller Models +## Controller Models - `pass_through_controller` - `demand_open_loop_controller` diff --git a/docs/user_guide/connecting_technologies.md b/docs/user_guide/connecting_technologies.md index dc8f5c6b5..da5b62e52 100644 --- a/docs/user_guide/connecting_technologies.md +++ b/docs/user_guide/connecting_technologies.md @@ -16,6 +16,7 @@ Technology interconnections are defined as an array of arrays in your `plant_con technology_interconnections: [ ["source_tech", "destination_tech", "variable_name", "transport_type"], ["tech_a", "tech_b", "shared_parameter"], + ["tech_a", "tech_b", ["tech_a_param_name", "tech_b_param_name"]], # ... more connections ] ``` @@ -33,6 +34,7 @@ There are two connection formats: - **transport_type**: The transport component to use (e.g., "cable", "pipeline") #### 3-element connections (direct connections) +##### Same shared parameter name ```yaml ["source_tech", "destination_tech", "shared_parameter"] ``` @@ -41,6 +43,17 @@ There are two connection formats: - **destination_tech**: Name of the technology receiving the input - **shared_parameter**: The exact parameter name to connect (e.g., "capacity_factor", "electrolyzer_degradation") +##### Different shared parameter names +```yaml +["source_tech", "destination_tech", ("source_parameter", "destination_parameter")] +``` + +- **source_tech**: Name of the technology providing the output +- **destination_tech**: Name of the technology receiving the input +- **source_parameter**: The name of the parameter within ``"source_tech"`` +- **destination_parameter**: The name of the parameter within ``"destination_tech"`` + + ### Internal connection logic H2Integrate processes these connections in the `connect_technologies()` method of `h2integrate_model.py`. Here's what happens internally: @@ -95,12 +108,12 @@ No additional configuration parameters are needed - the combiner simply adds the ### Inputs and outputs - **Inputs**: - - `electricity_input1`: Power from the first source (kW) - - `electricity_input2`: Power from the second source (kW) + - `electricity_in1`: Power from the first source (kW) + - `electricity_in2`: Power from the second source (kW) - **Output**: - `electricity_out`: Combined power output (kW) -The relationship is straightforward: `electricity_out = electricity_input1 + electricity_input2` +The relationship is straightforward: `electricity_out = electricity_in1 + electricity_in2` ### Usage example diff --git a/docs/user_guide/cost_years.md b/docs/user_guide/cost_years.md new file mode 100644 index 000000000..dba62d317 --- /dev/null +++ b/docs/user_guide/cost_years.md @@ -0,0 +1,63 @@ +(cost:cost_years)= +# Cost year of Cost Models +Some cost models are derived from literature and output costs (CapEx and OpEx) in a specific dollar-year. +Some cost models require users to input the key cost information and the output costs are in the same cost year as the user-provided costs. +For [cost models with a built-in cost year](#cost-models-with-inherent-cost-year), the cost year is not required as an input for the cost model. +For [cost models based on user-provided costs](#cost-models-with-user-input-cost-year), the `cost_year` should be included in the tech_config for that technology. + +(cost-models-with-inherent-cost-year)= +## Cost models with inherent cost year + +### Summary of cost models that are based around a cost year +| Cost Model | Cost Year | +| :---------------------- | :---------------: | +| `basic_electrolyzer_cost`| 2016 | +| `pem_electrolyzer_cost`| 2021 | +| `singlitico_electrolyzer_cost`| 2021 | +| `h2_storage` with `'mch'` storage type | 2024 | +| `h2_storage` for geologic storage or buried pipe | 2018 | +| `simple_ammonia_cost` | 2022 | +| `direct_ocean_capture_cost` | 2023 | +| `ocean_alkalinity_enhancement_cost` | 2024 | +| `ocean_alkalinity_enhancement_cost_financial` | 2024 | +| `steel_cost` | 2022 | +| `reverse_osmosis_desalination_cost` | 2013 | +| `synloop_ammonia_cost` | N/A (adjusts costs to `target_dollar_year` within cost model) | + +(cost-models-with-user-input-cost-year)= +## Cost models with user input cost year + +### Summary of cost models that have user-input cost year +| Cost Model | +| :---------------------- | +| `wind_plant_cost` | +| `atb_utility_pv_cost` | +| `atb_comm_res_pv_cost` | +| `simple_ASU_cost` | +| `hopp` | +| `run_of_river_hydro_cost` | +| `smr_methanol_plant_cost` | +| `stimulated_geoh2_cost` | +| `natural_geoh2_cost` | +| `wombat` | +| `hydrogen_tank_cost` | +| `custom_electrolyzer_cost` | + +### Example tech_config input for user-input cost year +```yaml +technologies: + solar: + performance_model: + model: "pysam_solar_plant_performance" + cost_model: + model: "atb_utility_pv_cost" + model_inputs: + performance_parameters: + pv_capacity_kWdc: 100000 + dc_ac_ratio: 1.34 + ... + cost_parameters: + capex_per_kWac: 1044 + opex_per_kWac_per_year: 18 + cost_year: 2022 +``` diff --git a/docs/user_guide/how_to_set_up_an_analysis.ipynb b/docs/user_guide/how_to_set_up_an_analysis.ipynb index af6024139..76abe3272 100644 --- a/docs/user_guide/how_to_set_up_an_analysis.ipynb +++ b/docs/user_guide/how_to_set_up_an_analysis.ipynb @@ -133,7 +133,6 @@ " latitude: 47.5233\n", " longitude: -92.5366\n", " elevation_m: 439.0\n", - " time_zone: -5\n", "\n", "# array of arrays containing left-to-right technology\n", "# interconnections; can support bidirectional connections\n", @@ -587,7 +586,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.11.13 ('h2i_env')", + "display_name": "hopp", "language": "python", "name": "python3" }, @@ -602,11 +601,6 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.13" - }, - "vscode": { - "interpreter": { - "hash": "e55566d5f9cb5003b92ad1d2254e8146f3d62519cfa868f35d73d51fb57327c6" - } } }, "nbformat": 4, diff --git a/docs/user_guide/specifying_finance_parameters.md b/docs/user_guide/specifying_finance_parameters.md index 07ac0e84b..8c041cf05 100644 --- a/docs/user_guide/specifying_finance_parameters.md +++ b/docs/user_guide/specifying_finance_parameters.md @@ -1,282 +1,159 @@ +(financeparameters:specifiyingfinanceparameters)= # Finance Parameters - -The finance model, finance model specific inputs, and cost adjustment information (regardless of the finance model) are required in the `finance_parameters` of the `plant_config`. - +## Overview +The `finance_parameters` section of the `plant_config` defines the financial subsystems of the plant. These parameters configure how costs, revenues, and investment metrics are calculated across all or parts of the modeled system. ```{note} The `plant_life` parameter from the `plant` section of the `plant_config` is also used in finance calculations as the operating life of the plant. ``` -The finance parameters section requires the following information: -- `finance_model`: name of the finance model. Current finance model options include: - - [`'ProFastComp'`](finance:profastcompmodel): calculates levelized cost of commodity using ProFAST -- `model_inputs`: inputs that are specific to the finance model +At minimum, `finance_parameters` must include: - `cost_adjustment_parameters`: - `target_dollar_year`: dollar-year to convert costs to. - - `cost_year_adjustment_inflation` is used to adjust costs for each technology from the cost year of the technology model (see [details on cost years and cost models here](#cost-year-of-cost-models)) to the `target_dollar_year` - -(finance:profastcompmodel) -# Finance Parameters: ProFastComp -The inputs for the `ProFastComp` model are outlined in this section: - -(finance:overview)= -## Finance parameters overview -The main inputs for `ProFastComp` model include: -- optional: information to export the ProFAST config to a .yaml file -- required: financial parameters (`params` section). These can be input in the `ProFastComp` format or the `ProFAST` format. These two formats are described in the following sections: - - [ProFastComp format](finance:direct_opt) - - [ProFAST format](finance:pf_params_opt) -- required: default capital item parameters (`capital_items` section). These parameters can be over-written for specific technologies if specified in the `tech_config`. Example usage of over-writing values in the `tech_config` is outlined [here](finance:tech_specific_finance) + - `cost_year_adjustment_inflation`: used to adjust costs for each technology from its native cost year to the `target_dollar_year` (see [details on cost years and cost models here](cost:cost_years)) + +Other variables in finance_parameters vary depending on the financial analysis structure. There are two major modes of operation: +- **Single-model mode (default)**: All technologies are grouped together into a single financial calculation. +- **Subgroup mode**: Technologies are split into one or more subgroups, each with its own commodity and one or more finance models. + +### Finance Groups vs. Finance Subgroups +Within this framework, there are two distinct layers, **finance groups** and **finance subgroups**: + +#### Finance groups + A finance group contains the attributes needed to run one finance model: + - `finance_model`: + The name of the financial model to use (e.g., `ProFastComp`). Must correspond to one of the available models in `self.supported_models`. + - `model_inputs`: + A dictionary of parameters passed into the chosen finance model. These provide customization of assumptions such as discount rate, debt fraction, or cost escalation. + - `commodity` (conditionally required): + The product or service whose financial performance is being analyzed (e.g., hydrogen, electricity). Required if `finance_subgroups` are not used, otherwise defined within `finance_subgroups`. + +#### Finance subgroups + Subgroups are flexible collections of technologies that map to one or more finance groups. They allow you to: + - Calculate financial metrics for only part of the system. + - Compare different metrics of the same system (e.g., delivered vs. produced cost of hydrogen). + - Run multiple models (e.g., LCOH, LCOE, LCOS, or NPV) on overlapping or distinct sets of technologies. + - Model distributed or multi-location systems finances within a single plant configuration. + + Subgroups contain information on how to construct the specific subgroup: + - `commodity`: + The product or service whose financial performance is being analyzed (e.g., hydrogen, electricity). Each finance subgroup is tied to a single commodity. + - `technologies`: + Technologies to include in the specific subgroup calculation (e.g., you might only want to include technologies that produce electricity in the levelized cost of energy calculation). + - `finance_groups`: + List of `finance_groups` that contain the `finance_model` and `model_inputs`. Required if multiple `finance_groups` are being used. Technology-specific `finance_groups` can be called by using the technology name listed in the `tech_config` (e.g., `steel` to use the steel specific finance model). + - `commodity_desc` (optional): + A text label to further distinguish outputs for a commodity. This is particularly useful when multiple finance models or subgroups reference the same commodity but need to produce separate outputs. + +```{important} +If no subgroups are defined, a **default subgroup** is created that contains *all technologies* and references the default finance model and commodity defined in `finance_groups`. +``` -```yaml -finance_parameters: - finance_model: "ProFastComp" - model_inputs: #inputs for the finance_model - save_profast_to_file: True #optional, will save ProFAST entries to .yaml file in the folder specified in the driver_config (`driver_config["general"]["folder_output"]`) - profast_output_description: "profast_config" #required if `save_profast_to_file` is True, used to name the output file. - params: #Financial parameters section - capital_items: #Required: section for default parameters for capital items - depr_type: "MACRS" #Required: depreciation method for capital items, can be "MACRS" or "Straight line" - depr_period: 5 #Required: depreciation period for capital items - refurb: [0.] #Optional: replacement schedule as a fraction of the capital cost. Defaults to [0.] - fixed_costs: #Optional section for default parameters for fixed cost items - escalation: #escalation rate for fixed costs, will default to `inflation_rate` specific in the params section - unit: "$/year" #optional unit of the cost. Defaults to $/year - usage: 1.0 #usage multiplier, most commonly is set to 1 and defaults to 1.0 +## Example finance configurations -``` +We'll now walk through three common configurations, highlighting the differences in the `plant_config` files and showcasing examples that use each approach. -(finance:direct_opt)= -## Providing Finance Parameters: ProFastComp Format -Below is an example inputting financial parameters directly in the `finance_parameters` section of `plant_config`: +(finparam:nosubgroups)= +### Single-model (no subgroups) +If no `finance_subgroups` are specified, all technologies are automatically grouped into a single default subgroup. In this case: + - `commodity` and `finance_model` must be defined directly in `finance_groups`. + - A default subgroup named `default` is created internally. +General format: ```yaml finance_parameters: - finance_model: "ProFastComp" #finance model - model_inputs: #inputs for finance_model - params: #Financing parameters - analysis_start_year: 2032 #year that financial analysis starts - installation_time: 36 #installation period in months - # Inflation parameters - inflation_rate: 0.0 # 0 for nominal analysis - # Finance parameters - discount_rate: 0.09 - debt_equity_ratio: 2.62 - property_tax_and_insurance: 0.03 - total_income_tax_rate: 0.257 - capital_gains_tax_rate: 0.15 - sales_tax_rate: 0.07375 - debt_interest_rate: 0.07 - debt_type: "Revolving debt" #"Revolving debt" or "One time loan" - loan_period_if_used: 0 #loan period if debt_type is 'One time loan' - cash_onhand_months: 1 - admin_expense: 0.00 #administrative expense as a fraction of sales - #default parameters for capital items unless specified in tech_config - capital_items: - depr_type: "MACRS" #depreciation method for capital items, can be "MACRS" or "Straight line" - depr_period: 5 #depreciation period for capital items in years. - refurb: [0.] #refurbishment schedule, values represent the replacement cost as a fraction of the CapEx - - # To adjust costs for technologies to target_dollar_year - cost_adjustment_parameters: - target_dollar_year: 2022 - cost_year_adjustment_inflation: 0.025 + finance_groups: + commodity: "hydrogen" + finance_model: "ProFastComp" + model_inputs: + discount_rate: 0.08 ``` -This approach also relies on data from `plant_config`: -- `plant_life`: used as the `operating life` ProFAST parameter - - -```{note} -`inflation_rate` is used to populate the escalation and inflation rates in ProFAST entries with a value of 0 corresponding to a *nominal analysis*. +Outputs are named: +``` +finance_subgroup_default. ``` -(finance:pf_params_opt)= -## Providing Finance Parameters: ProFAST format - -```{note} -To avoid errors, please check that `plant_config['plant']['plant_life']` is equal to `plant_config['finance_parameters']['model_inputs']['params']['operating life']`. Or remove `operating life` from the finance parameter inputs.` +Examples: +- [Example 7](https://github.com/NREL/H2Integrate/blob/develop/examples/07_run_of_river_plant/plant_config.yaml) -| plant config parameter | equivalent `params` parameter | -| -------- | ------- | -| `plant['plant']['plant_life']` | `operating life` | -``` +(finparams:singlemodelsubgroups)= +### Single finance model with subgroups +If `finance_groups` contains a single model definition, you may split technologies into multiple subgroups. Each subgroup defines its own `commodity` and list of `technologies` but uses the shared finance model. -Below is an example of the `finance_parameters` section of `plant_config` if using ProFAST input format to specify financial parameters: +In this case you see that the commodity is not defined within the `finance_groups` and is instead defined within the `finance_subgroups`. In this example there are two separate financial calculations one for `subgroup_a`, which is for the hydrogen commodity and one for `subgroup_b`, which is for the ammonia commodity and includes the "electrolyzer" and "asu". If you had additional technologies in your `tech_config` besides those, they would have to be included in the `finance_subgroups` to be included in the financial calculations. +General format: ```yaml finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: !include "profast_params.yaml" #Finance information - capital_items: #default parameters for capital items unless specified in tech_config - depr_type: "MACRS" ##depreciation method for capital items, can be "MACRS" or "Straight line" - depr_period: 5 #depreciation period for capital items - refurb: [0.] - cost_adjustment_parameters: - target_dollar_year: 2022 - cost_year_adjustment_inflation: 0.025 # used to adjust costs for technologies to target_dollar_year + finance_groups: + finance_model: "ProFastComp" + model_inputs: #dictionary of inputs for ProFastComp + finance_subgroups: + subgroup_a: + commodity: "hydrogen" #required + technologies: ["electrolyzer"] + subgroup_b: + commodity: "ammonia" #required + technologies: ["electrolyzer", "asu"] ``` -Below is an example of a valid ProFAST params config that may be specified in the `finance_parameters['model_inputs']['params]` section of `plant_config`: -```yaml -# Installation information -maintenance: - value: 0.0 - escalation: 0.0 -non depr assets: 250000 #such as land cost -end of proj sale non depr assets: 250000 #such as land cost -installation cost: - value: 0.0 - depr type: "Straight line" - depr period: 4 - depreciable: False -# Incentives information -incidental revenue: - value: 0.0 - escalation: 0.0 -annual operating incentive: - value: 0.0 - decay: 0.0 - sunset years: 0 - taxable: true -one time cap inct: - value: 0.0 - depr type: "MACRS" - depr period: 5 - depreciable: True -# Sales information -analysis start year: 2032 -operating life: 30 #if included, should equal plant_config['plant']['plant_life'] -installation months: 36 -demand rampup: 0 -# Take or pay specification -TOPC: - unit price: 0.0 - decay: 0.0 - support utilization: 0.0 - sunset years: 0 -# Other operating expenses -credit card fees: 0.0 -sales tax: 0.0 -road tax: - value: 0.0 - escalation: 0.0 -labor: - value: 0.0 - rate: 0.0 - escalation: 0.0 -rent: - value: 0.0 - escalation: 0.0 -license and permit: - value: 0.0 - escalation: 0.0 -admin expense: 0.0 -property tax and insurance: 0.015 -# Financing information -sell undepreciated cap: True -capital gains tax rate: 0.15 -total income tax rate: 0.2574 -leverage after tax nominal discount rate: 0.0948 -debt equity ratio of initial financing: 1.72 -debt interest rate: 0.046 -debt type: "Revolving debt" -general inflation rate: 0.0 -cash onhand: 1 # number of months with cash on-hand -tax loss carry forward years: 0 -tax losses monetized: True -loan period if used: 0 +Outputs are named: +``` +finance_subgroup_. ``` -(finance:tech_specific_finance)= -## Over-ride defaults for specific technologies - -Capital item entries can be over-written for individual technologies. - -#### **Over-write depreciation period:** +Examples: +- [Example 02](https://github.com/NREL/H2Integrate/tree/develop/examples/02_texas_ammonia/plant_config.yaml) +- [Example 03 - CO2H](https://github.com/NREL/H2Integrate/tree/develop/examples/03_methanol/co2_hydrogenation/plant_config_co2h.yaml) +- [Example 09 - DOC](https://github.com/NREL/H2Integrate/tree/develop/examples/09_co2/direct_ocean_capture/plant_config.yaml) + -Suppose the default depreciation period for capital items is 5 years (set in the `plant_config['finance_parameters']['model_inputs]['capital_items']['depr_period']`), but we want the depreciation period for the electrolyzer to be 7 years. This can be done in the `tech_config` as shown below: -```yaml -technologies: - electrolyzer: - model_inputs: - finance_parameters: - capital_items: - depr_period: 7 +```{note} +Within `finance_groups`, the `commodity`, `finance_model`, and `model_inputs` may be placed under a named key for the finance group and indented one level deeper. This structure is optional when only a single finance model is used, but it is supported for consistency with the format required when specifying multiple finance models (see [Specifying Multiple Finance Groups](finparams:multimodelsubgroups)). ``` +(finparams:multimodelsubgroups)= +### Multiple financial models with subgroups +When multiple finance models are needed (e.g., to calculate both NPV and LCOH, or to compare multiple finance cases), multiple finance groups can be defined and assigned to subgroups. -#### **Custom refurbishment period:** - -Suppose the default refurbishment schedule for capital items is `[0.]` (set in the `plant_config['finance_parameters']['model_inputs]['capital_items']['refurb']`), but we want our battery to be replaced in 15-years and the replacement cost is equal to the capital cost. This can be accomplished in the tech_config as shown below: +General format: ```yaml -technologies: - battery: - model_inputs: - finance_parameters: - capital_items: - refurbishment_period_years: 15 - replacement_cost_percent: 1.0 +finance_parameters: + finance_groups: + group_a: + finance_model: "ProFastComp" + model_inputs: {discount_rate: 0.08} + group_b: + finance_model: "NPVFinancial" + model_inputs: {discount_rate: 0.05} + finance_subgroups: + subgroup_a: + commodity: "hydrogen" + finance_groups: ["group_a"] + technologies: ["electrolyzer"] + subgroup_b: + commodity: "hydrogen" + commodity_desc: "delivered" + finance_groups: ["group_a", "group_b"] + technologies: ["pipeline", "storage"] +``` +Output naming: +- If multiple finance groups are in the same subgroup, output names include the subgroup, commodity, description (if provided), and finance group name to avoid collisions in the OpenMDAO framework: +``` +finance_subgroup_.__ +finance_subgroup_subgroup_a.LCOH_group_a +finance_subgroup_subgroup_b.LCOH_delivered_group_a +finance_subgroup_subgroup_b.NPV_hydrogen_delivered_group_b ``` +Examples: +- [Example 10](https://github.com/NREL/H2Integrate/blob/develop/examples/10_electrolyzer_om/plant_config.yaml) -# Cost year of Cost Models -Some cost models are derived from literature and output costs (CapEx and OpEx) in a specific dollar-year. Some cost models require users to input the key cost information, and the output costs are in the same cost year as the user-provided costs. For [cost models with a built-in cost year](#cost-models-with-inherent-cost-year), the cost year is not required as an input for the cost model. For [cost models based on user provided costs](#cost-models-with-user-input-cost-year), the `cost_year` should be included in the tech_config for that technology. - -## Cost models with inherent cost year - -### Summary of cost models that are based around a cost year -| Cost Model | Cost Year | -| :---------------------- | :---------------: | -| `basic_electrolyzer_cost`| 2016 | -| `pem_electrolyzer_cost`| 2021 | -| `singlitico_electrolyzer_cost`| 2021 | -| `h2_storage` with `'mch'` storage type | 2024 | -| `h2_storage` for geologic storage or buried pipe | 2018 | -| `simple_ammonia_cost` | 2022 | -| `direct_ocean_capture_cost` | 2023 | -| `ocean_alkalinity_enhancement_cost` | 2024 | -| `ocean_alkalinity_enhancement_cost_financial` | 2024 | -| `steel_cost` | 2022 | -| `reverse_osmosis_desalination_cost` | 2013 | -| `synloop_ammonia_cost` | N/A (adjusts costs to `target_dollar_year` within cost model) | - - -## Cost models with user input cost year - -### Summary of cost models that have user-input cost year -| Cost Model | -| :---------------------- | -| `wind_plant_cost` | -| `atb_utility_pv_cost` | -| `atb_comm_res_pv_cost` | -| `simple_ASU_cost` | -| `hopp` | -| `run_of_river_hydro_cost` | -| `smr_methanol_plant_cost` | -| `stimulated_geoh2_cost` | -| `natural_geoh2_cost` | -| `wombat` | -| `hydrogen_tank_cost` | -| `custom_electrolyzer_cost` | - -### Example tech_config input for user-input cost year -```yaml -technologies: - solar: - performance_model: - model: "pysam_solar_plant_performance" - cost_model: - model: "atb_utility_pv_cost" - model_inputs: - performance_parameters: - pv_capacity_kWdc: 100000 - dc_ac_ratio: 1.34 - ... - cost_parameters: - capex_per_kWac: 1044 - opex_per_kWac_per_year: 18 - cost_year: 2022 - -``` +#### Key Behaviors +- If `finance_parameters` is missing --> no finance model is created. +- If no `finance_subgroups` are defined → a default subgroup containing all technologies is created automatically. +- Finance groups must not include a key named "default", as this is reserved for internal use. +- Each subgroup must reference valid technology keys from technology_config['technologies']. Invalid keys raise errors. +- Finance models must be listed in `self.supported_models`. Unknown models raise errors. diff --git a/examples/01_onshore_steel_mn/plant_config.yaml b/examples/01_onshore_steel_mn/plant_config.yaml index 0f91c7225..e7fd38ea7 100644 --- a/examples/01_onshore_steel_mn/plant_config.yaml +++ b/examples/01_onshore_steel_mn/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -27,44 +25,52 @@ technology_interconnections: [ ["hopp", "electrolyzer", "electricity", "cable"], ["electrolyzer", "h2_storage", "efficiency"], ["electrolyzer", "h2_storage", "hydrogen", "pipe"], - ["financials_group_default", "steel", "LCOH"], + ["finance_subgroup_hydrogen", "steel", ["LCOH_delivered", "LCOH"]], ["hopp", "steel", "electricity", "cable"], # etc ] plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' - technologies_included_in_metrics: - LCOE: ["hopp"] - LCOH: ["hopp", "electrolyzer", "h2_storage"] + finance_groups: + profast_model: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] + finance_subgroups: + electricity: + commodity: "electricity" + finance_groups: ["profast_model"] + technologies: ["hopp"] + hydrogen: + commodity: "hydrogen" + commodity_desc: "delivered" + finance_groups: ["profast_model"] + technologies: ["hopp", "electrolyzer", "h2_storage"] + steel: + commodity: "steel" + finance_groups: ["steel"] + technologies: ["steel"] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 diff --git a/examples/01_onshore_steel_mn/tech_config.yaml b/examples/01_onshore_steel_mn/tech_config.yaml index c508fd9d8..fd4775e5e 100644 --- a/examples/01_onshore_steel_mn/tech_config.yaml +++ b/examples/01_onshore_steel_mn/tech_config.yaml @@ -8,8 +8,6 @@ technologies: config: !include tech_inputs/hopp_config.yaml cost_model: model: "hopp" - financial_model: - group: default electrolyzer_rating: 720. # MW model_inputs: cost_parameters: @@ -19,8 +17,6 @@ technologies: model: "eco_pem_electrolyzer_performance" cost_model: model: "singlitico_electrolyzer_cost" - financial_model: - group: default model_inputs: shared_parameters: location: "onshore" @@ -49,8 +45,6 @@ technologies: model: "pass_through_controller" cost_model: model: "h2_storage" - financial_model: - group: default model_inputs: performance_parameters: rating: 720. @@ -67,8 +61,8 @@ technologies: model: "steel_performance" cost_model: model: "steel_cost" - financial_model: - group: steel + finance_model: + model: "steel_cost" model_inputs: shared_parameters: capacity_factor: 0.9 diff --git a/examples/02_texas_ammonia/plant_config.yaml b/examples/02_texas_ammonia/plant_config.yaml index 252571afc..937b1e03d 100644 --- a/examples/02_texas_ammonia/plant_config.yaml +++ b/examples/02_texas_ammonia/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -28,42 +26,49 @@ technology_interconnections: [ ["electrolyzer", "h2_storage", "efficiency"], ["electrolyzer", "h2_storage", "hydrogen", "pipe"], ["h2_storage", "ammonia", "hydrogen", "pipe"], - ["financials_group_default", "ammonia", "LCOH"], + ["finance_subgroup_hydrogen", "ammonia", "LCOH"], # etc ] plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - finance_model: "ProFastComp" - model_inputs: - save_profast_to_file: True - profast_output_description: "profast_output" - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for real analysis - discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.025 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx and # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf - total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 7 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' + finance_groups: + finance_model: "ProFastComp" + model_inputs: + save_profast_config: True + save_profast_results: False + profast_output_description: "profast_output" + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for real analysis + discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.025 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx and # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf + total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 7 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + hydrogen: + commodity: "hydrogen" + technologies: ["hopp", "electrolyzer", "h2_storage"] + ammonia: + commodity: "ammonia" + technologies: ["hopp", "electrolyzer", "h2_storage", "ammonia"] diff --git a/examples/03_methanol/co2_hydrogenation/plant_config_co2h.yaml b/examples/03_methanol/co2_hydrogenation/plant_config_co2h.yaml index b2e46e057..35f4a928a 100644 --- a/examples/03_methanol/co2_hydrogenation/plant_config_co2h.yaml +++ b/examples/03_methanol/co2_hydrogenation/plant_config_co2h.yaml @@ -4,8 +4,6 @@ description: "This plant is located west of the Wolf Hollow II NGCC power plant site: latitude: 32.34 longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -26,41 +24,47 @@ site: technology_interconnections: [ ["hopp", "electrolyzer", "electricity", "cable"], ["electrolyzer", "methanol", "hydrogen", "pipe"], - ["financials_group_1", "methanol", "LCOE"], - ["financials_group_1", "methanol", "LCOH"], + ["finance_subgroup_electricity", "methanol", "LCOE"], + ["finance_subgroup_hydrogen", "methanol", "LCOH"], ] plant: plant_life: 30 - grid_connection: True # option, can be turned on or off - ppa_price: 0.027498168 # based off correlations of LBNL PPA data - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB basline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - options: - commodity_type: "methanol" + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB basline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + hydrogen: + commodity: "hydrogen" + technologies: ["hopp", "electrolyzer"] + methanol: + commodity: "methanol" + finance_groups: ["methanol"] + technologies: ["methanol"] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 diff --git a/examples/03_methanol/co2_hydrogenation/tech_config_co2h.yaml b/examples/03_methanol/co2_hydrogenation/tech_config_co2h.yaml index 046230af5..f90f58190 100644 --- a/examples/03_methanol/co2_hydrogenation/tech_config_co2h.yaml +++ b/examples/03_methanol/co2_hydrogenation/tech_config_co2h.yaml @@ -8,8 +8,6 @@ technologies: config: !include tech_inputs/hopp_config.yaml cost_model: model: "hopp" - financial_model: - group: "1" electrolyzer_rating: 156. # MW model_inputs: cost_parameters: @@ -19,8 +17,6 @@ technologies: model: "eco_pem_electrolyzer_performance" cost_model: model: "singlitico_electrolyzer_cost" - financial_model: - group: "1" model_inputs: shared_parameters: location: "onshore" @@ -46,9 +42,8 @@ technologies: model: "co2h_methanol_plant_performance" cost_model: model: "co2h_methanol_plant_cost" - financial_model: + finance_model: model: "co2h_methanol_plant_financial" - group: "2" model_inputs: shared_parameters: plant_capacity_kgpy: 127893196.8 diff --git a/examples/03_methanol/plant_config.yaml b/examples/03_methanol/plant_config.yaml deleted file mode 100644 index 861b4f7b8..000000000 --- a/examples/03_methanol/plant_config.yaml +++ /dev/null @@ -1,65 +0,0 @@ -name: "plant_config" -description: "This plant is located west of the Wolf Hollow II NGCC power plant in Texas" - -site: - latitude: 32.34 - longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 - - # array of polygons defining boundaries with x/y coords - boundaries: [ - { - x: [0.0, 1000.0, 1000.0, 0.0], - y: [0.0, 0.0, 100.0, 1000.0], - }, - { - x: [2000.0, 2500.0, 2000.0], - y: [2000.0, 2000.0, 2500.0], - } - ] - -# array of arrays containing left-to-right technology -# interconnections; can support bidirectional connections -# with the reverse definition. -# this will naturally grow as we mature the interconnected tech -technology_interconnections: [ -] - -plant: - plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.027498168 # based off correlations of LBNL PPA data - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True - -finance_parameters: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB basline workbook for land-based wind - debt_equity_split: False - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax: 0.02 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - property_insurance: 0.01 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf - total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - administrative_expense_percent_of_sales: 0.00 # percent of sales H2FAST default - depreciation_method: "MACRS" # can be "MACRS" or "Straight line" - MACRS may be better and can reduce LCOH by more than $1/kg and is spec'd in the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - depreciation_period: 5 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - depreciation_period_electrolyzer: 7 # based on PEM Electrolysis H2A Production Case Study Documentation estimate of 7 years. also see https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - options: - commodity_type: "methanol" - cost_adjustment_parameters: - cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year - target_dollar_year: 2022 - -policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $, then prevailing wage multiplier if applicable, then inflation - electricity_itc: 0 - electricity_ptc: 0 - h2_ptc: 0 - h2_storage_itc: 0 diff --git a/examples/03_methanol/smr/plant_config_smr.yaml b/examples/03_methanol/smr/plant_config_smr.yaml index 7b53ef179..ccf2666a1 100644 --- a/examples/03_methanol/smr/plant_config_smr.yaml +++ b/examples/03_methanol/smr/plant_config_smr.yaml @@ -4,8 +4,6 @@ description: "This plant is located west of the Wolf Hollow II NGCC power plant site: latitude: 32.34 longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -28,40 +26,4 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off ppa_price: 0.027498168 # based off correlations of LBNL PPA data - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True - -finance_parameters: - finance_model: "ProFastComp" - profast_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB basline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # https://www.house.mn.gov/hrd/issinfo/clsrates.aspx and https://www.nrel.gov/docs/fy25osti/91775.pdf - total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - options: - commodity_type: "methanol" - cost_adjustment_parameters: - cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year - target_dollar_year: 2022 - -policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $, then prevailing wage multiplier if applicable, then inflation - electricity_itc: 0 - electricity_ptc: 0 - h2_ptc: 0 - h2_storage_itc: 0 diff --git a/examples/03_methanol/smr/tech_config_smr.yaml b/examples/03_methanol/smr/tech_config_smr.yaml index 067652bcd..ff52dd360 100644 --- a/examples/03_methanol/smr/tech_config_smr.yaml +++ b/examples/03_methanol/smr/tech_config_smr.yaml @@ -7,7 +7,7 @@ technologies: model: "smr_methanol_plant_performance" cost_model: model: "smr_methanol_plant_cost" - financial_model: + finance_model: model: "smr_methanol_plant_financial" model_inputs: shared_parameters: diff --git a/examples/04_geo_h2/plant_config.yaml b/examples/04_geo_h2/plant_config.yaml index b2541761c..1c2dcc1c3 100644 --- a/examples/04_geo_h2/plant_config.yaml +++ b/examples/04_geo_h2/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located west of the Wolf Hollow II NGCC power plant site: latitude: 32.34 longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -28,32 +26,3 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True - -finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB basline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 #percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - cost_adjustment_parameters: - cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year - target_dollar_year: 2022 diff --git a/examples/04_geo_h2/tech_config_natural.yaml b/examples/04_geo_h2/tech_config_natural.yaml index 818a0d074..fc4467797 100644 --- a/examples/04_geo_h2/tech_config_natural.yaml +++ b/examples/04_geo_h2/tech_config_natural.yaml @@ -7,7 +7,7 @@ technologies: model: "natural_geoh2_performance" cost_model: model: "natural_geoh2_cost" - financial_model: + finance_model: model: "natural_geoh2" model_inputs: shared_parameters: diff --git a/examples/04_geo_h2/tech_config_stimulated.yaml b/examples/04_geo_h2/tech_config_stimulated.yaml index dda5a431e..505e3e6d7 100644 --- a/examples/04_geo_h2/tech_config_stimulated.yaml +++ b/examples/04_geo_h2/tech_config_stimulated.yaml @@ -7,7 +7,7 @@ technologies: model: "stimulated_geoh2_performance" cost_model: model: "stimulated_geoh2_cost" - financial_model: + finance_model: model: "stimulated_geoh2" model_inputs: shared_parameters: diff --git a/examples/05_wind_h2_opt/driver_config.yaml b/examples/05_wind_h2_opt/driver_config.yaml index f2ae451a4..d84bc9742 100644 --- a/examples/05_wind_h2_opt/driver_config.yaml +++ b/examples/05_wind_h2_opt/driver_config.yaml @@ -30,7 +30,7 @@ constraints: units: kg/year objective: - name: financials_group_default.LCOH + name: finance_subgroup_hydrogen.LCOH recorder: flag: True diff --git a/examples/05_wind_h2_opt/plant_config.yaml b/examples/05_wind_h2_opt/plant_config.yaml index 3b9a2c692..63d049174 100644 --- a/examples/05_wind_h2_opt/plant_config.yaml +++ b/examples/05_wind_h2_opt/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -35,27 +30,35 @@ technology_interconnections: [ ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["wind"] + hydrogen: + commodity: "hydrogen" + technologies: ["wind", "electrolyzer"] diff --git a/examples/06_custom_tech/plant_config.yaml b/examples/06_custom_tech/plant_config.yaml index c87250493..14c433690 100644 --- a/examples/06_custom_tech/plant_config.yaml +++ b/examples/06_custom_tech/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant models a wind plant with a custom paper mill model in M site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -33,29 +28,3 @@ technology_interconnections: [ ["wind", "paper_mill", "electricity", "cable"], # etc ] - -finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - cost_adjustment_parameters: - cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year - target_dollar_year: 2022 diff --git a/examples/06_custom_tech/tech_config.yaml b/examples/06_custom_tech/tech_config.yaml index a8a760673..ecb36885f 100644 --- a/examples/06_custom_tech/tech_config.yaml +++ b/examples/06_custom_tech/tech_config.yaml @@ -45,7 +45,7 @@ technologies: model: paper_mill_cost model_class_name: PaperMillCost model_location: user_defined_model/paper_mill.py - financial_model: + finance_model: model: paper_mill_finance model_class_name: PaperMillFinance model_location: user_defined_model/paper_mill.py diff --git a/examples/07_run_of_river_plant/plant_config.yaml b/examples/07_run_of_river_plant/plant_config.yaml index 08dc689fa..ae3de2f4a 100644 --- a/examples/07_run_of_river_plant/plant_config.yaml +++ b/examples/07_run_of_river_plant/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in Kansas" site: latitude: 32.34 longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -41,37 +39,31 @@ resource_to_tech_connections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.027498168 # based off correlations of LBNL PPA data - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + commodity: "electricity" + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.308 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 -policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $, then prevailing wage multiplier if applicable, then inflation - electricity_itc: 0 - electricity_ptc: 0 - h2_ptc: 0 - h2_storage_itc: 0 diff --git a/examples/08_wind_electrolyzer/plant_config.yaml b/examples/08_wind_electrolyzer/plant_config.yaml index 18c2b58ed..8360e5093 100644 --- a/examples/08_wind_electrolyzer/plant_config.yaml +++ b/examples/08_wind_electrolyzer/plant_config.yaml @@ -4,8 +4,7 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 + # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +20,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -33,31 +29,3 @@ technology_interconnections: [ ["wind", "electrolyzer", "electricity", "cable"], # etc ] - -finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' - cost_adjustment_parameters: - cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year - target_dollar_year: 2022 diff --git a/examples/09_co2/direct_ocean_capture/plant_config.yaml b/examples/09_co2/direct_ocean_capture/plant_config.yaml index 9d3777bb6..132897ae2 100644 --- a/examples/09_co2/direct_ocean_capture/plant_config.yaml +++ b/examples/09_co2/direct_ocean_capture/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in OR, USA" site: latitude: 43.807 longitude: -124.816 - elevation_m: 439.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -35,27 +30,35 @@ technology_interconnections: [ ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + co2: + commodity: "co2" + technologies: ["hopp", "doc"] diff --git a/examples/09_co2/ocean_alkalinity_enhancement/plant_config.yaml b/examples/09_co2/ocean_alkalinity_enhancement/plant_config.yaml index 1aaf7e3b5..cec912b9b 100644 --- a/examples/09_co2/ocean_alkalinity_enhancement/plant_config.yaml +++ b/examples/09_co2/ocean_alkalinity_enhancement/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in OR, USA" site: latitude: 43.807 longitude: -124.816 - elevation_m: 439.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -35,30 +30,35 @@ technology_interconnections: [ ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - discount_years: - hopp: 2022 - oae: 2023 + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # 2.5% inflation rate for cost adjustments target_dollar_year: 2022 + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + co2: + commodity: "co2" + technologies: ["hopp", "oae"] diff --git a/examples/09_co2/ocean_alkalinity_enhancement_financials/plant_config_financials.yaml b/examples/09_co2/ocean_alkalinity_enhancement_financials/plant_config_financials.yaml index db5822ae2..fb6d6caa6 100644 --- a/examples/09_co2/ocean_alkalinity_enhancement_financials/plant_config_financials.yaml +++ b/examples/09_co2/ocean_alkalinity_enhancement_financials/plant_config_financials.yaml @@ -4,8 +4,6 @@ description: "This plant is located in Puget Sound WA, USA" site: latitude: 48.153889 longitude: -122.774111 - elevation_m: 100 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 20 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -31,34 +26,41 @@ plant: # this will naturally grow as we mature the interconnected tech technology_interconnections: [ ["hopp", "oae", "electricity", "cable"], - ["financials_group_default", "oae", "LCOE"] + ["finance_subgroup_electricity", "oae", "LCOE"] # etc ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - technologies_included_in_metrics: - LCOE: ["hopp"] + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + # oae: + # commodity: "co2" + # finance_groups: ["oae"] + # technologies: ["oae"] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # 2.5% inflation rate for cost adjustments target_dollar_year: 2022 diff --git a/examples/09_co2/ocean_alkalinity_enhancement_financials/tech_config_financials.yaml b/examples/09_co2/ocean_alkalinity_enhancement_financials/tech_config_financials.yaml index 323efd999..5e1614cb3 100644 --- a/examples/09_co2/ocean_alkalinity_enhancement_financials/tech_config_financials.yaml +++ b/examples/09_co2/ocean_alkalinity_enhancement_financials/tech_config_financials.yaml @@ -8,17 +8,14 @@ technologies: config: !include tech_inputs/hopp_config.yaml cost_model: model: "hopp" - financial_model: - group: "default" model_inputs: cost_parameters: cost_year: 2022 oae: performance_model: model: "ocean_alkalinity_enhancement_performance" - financial_model: + finance_model: model: "ocean_alkalinity_enhancement_cost_financial" - group: "oae" model_inputs: performance_parameters: number_ed_min: 1 diff --git a/examples/10_electrolyzer_om/plant_config.yaml b/examples/10_electrolyzer_om/plant_config.yaml index b533534e7..5ce6b2a56 100644 --- a/examples/10_electrolyzer_om/plant_config.yaml +++ b/examples/10_electrolyzer_om/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,9 +19,6 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True # array of arrays containing left-to-right technology # interconnections; can support bidirectional connections @@ -35,27 +30,62 @@ technology_interconnections: [ ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + lcoe_financials: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.0615 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.015 + total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.0 + debt_interest_rate: 0.0439 + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] + lcoh_financials: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.1089 + debt_equity_ratio: 0.62 + property_tax_and_insurance: 0.03 + total_income_tax_rate: 0.2574 + capital_gains_tax_rate: 0.15 + sales_tax_rate: 0.0 + debt_interest_rate: 0.05 + debt_type: "Revolving debt" + loan_period_if_used: 0 + cash_onhand_months: 1 + admin_expense: 0.00 # percent of sales H2FAST default + non_depr_assets: 250000 + end_of_proj_sale_non_depr_assets: 250000 + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + electricity: + commodity: "electricity" + finance_groups: ["lcoe_financials"] + technologies: ["wind"] + hydrogen: + commodity: "hydrogen" + finance_groups: ["lcoe_financials", "lcoh_financials"] + technologies: ["wind", "electrolyzer"] diff --git a/examples/10_electrolyzer_om/run_elecrolyzer_om.py b/examples/10_electrolyzer_om/run_electrolyzer_om.py similarity index 100% rename from examples/10_electrolyzer_om/run_elecrolyzer_om.py rename to examples/10_electrolyzer_om/run_electrolyzer_om.py diff --git a/examples/11_hybrid_energy_plant/driver_config.yaml b/examples/11_hybrid_energy_plant/driver_config.yaml index f642f2a7e..23e7b1050 100644 --- a/examples/11_hybrid_energy_plant/driver_config.yaml +++ b/examples/11_hybrid_energy_plant/driver_config.yaml @@ -60,4 +60,4 @@ constraints: units: unitless objective: - name: financials_group_default.LCOE + name: finance_subgroup_default.LCOE diff --git a/examples/11_hybrid_energy_plant/plant_config.yaml b/examples/11_hybrid_energy_plant/plant_config.yaml index f9e4652fe..6112af41c 100644 --- a/examples/11_hybrid_energy_plant/plant_config.yaml +++ b/examples/11_hybrid_energy_plant/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in TX, USA near Sheffield" site: latitude: 30.6617 longitude: -101.7096 - elevation_m: 930.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -21,32 +19,31 @@ site: plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - installation_time: 12 # months finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 12 # months - inflation_rate: 0.025 # 0 for nominal analysis - discount_rate: 0.089 # nominal return - debt_equity_ratio: 2.1746031746031744 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.015 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.045 - debt_interest_rate: 0.06 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.01 - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + commodity: "electricity" + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 12 # months + inflation_rate: 0.025 # 0 for nominal analysis + discount_rate: 0.089 # nominal return + debt_equity_ratio: 2.1746031746031744 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.015 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.045 + debt_interest_rate: 0.06 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.01 + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2025 diff --git a/examples/12_ammonia_synloop/plant_config.yaml b/examples/12_ammonia_synloop/plant_config.yaml index 6a11d32fe..9a3c790b0 100644 --- a/examples/12_ammonia_synloop/plant_config.yaml +++ b/examples/12_ammonia_synloop/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -33,34 +31,37 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for real analysis - discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 7 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for real analysis + discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 7 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + h2: + commodity: "hydrogen" + technologies: ["hopp", "electrolyzer", "h2_storage"] + nh3: + commodity: "ammonia" + technologies: ["hopp", "electrolyzer", "h2_storage", "ammonia"] diff --git a/examples/13_air_separator/plant_config.yaml b/examples/13_air_separator/plant_config.yaml index e22d5d2e1..3f87e9cb8 100644 --- a/examples/13_air_separator/plant_config.yaml +++ b/examples/13_air_separator/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -30,40 +28,31 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for real analysis - discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 7 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' + finance_groups: + commodity: "nitrogen" + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for real analysis + discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 7 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2025 - -policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $, then prevailing wage multiplier if applicable, then inflation - electricity_itc: 0 - electricity_ptc: 0 - h2_ptc: 0 - h2_storage_itc: 0 diff --git a/examples/14_wind_hydrogen_dispatch/hydrogen_dispatch.ipynb b/examples/14_wind_hydrogen_dispatch/hydrogen_dispatch.ipynb index eb306d865..e4b3f13ca 100644 --- a/examples/14_wind_hydrogen_dispatch/hydrogen_dispatch.ipynb +++ b/examples/14_wind_hydrogen_dispatch/hydrogen_dispatch.ipynb @@ -44,15 +44,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "/Users/egrant/Documents/projects/GreenHEART/examples/14_wind_hydrogen_dispatch/log/hybrid_systems_2025-08-22T12.14.13.550319.log\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/egrant/opt/anaconda3/envs/h2i_env/lib/python3.11/site-packages/fastkml/__init__.py:28: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.\n", - " from pkg_resources import DistributionNotFound\n" + "/Users/kbrunik/github/H2Integrate/examples/14_wind_hydrogen_dispatch/log/hybrid_systems_2025-09-12T21.16.47.965370.log\n" ] } ], @@ -64,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "bcabc113", "metadata": {}, "outputs": [ @@ -80,128 +72,161 @@ "name": "stdout", "output_type": "stream", "text": [ - "38 Input(s) in 'model'\n", + "47 Input(s) in 'model'\n", "\n", - "varname val units prom_name \n", - "----------------------------------------- -------------------- --------- ------------------------------------------------------------\n", + "varname val units prom_name \n", + "----------------------------------------- -------------------- --------- ---------------------------------------------------------\n", "plant\n", " wind_to_electrolyzer_cable\n", - " electricity_in |40393548.72275606| kW wind_to_electrolyzer_cable.electricity_in \n", + " electricity_in |40393548.93300275| kW wind_to_electrolyzer_cable.electricity_in \n", " electrolyzer\n", " eco_pem_electrolyzer_performance\n", - " electricity_in |40393548.72275606| kW electrolyzer.electricity_in \n", - " n_clusters [18.] unitless electrolyzer.n_clusters \n", + " electricity_in |40393548.93300279| kW electrolyzer.electricity_in \n", + " n_clusters [18.] unitless electrolyzer.n_clusters \n", " singlitico_electrolyzer_cost\n", - " total_hydrogen_produced [58145418.05837836] kg/year electrolyzer.total_hydrogen_produced \n", - " electricity_in |40393548.72275606| kW electrolyzer.electricity_in \n", - " electrolyzer_size_mw [720.] MW electrolyzer.electrolyzer_size_mw \n", + " total_hydrogen_produced [58145418.38681877] kg/year electrolyzer.total_hydrogen_produced \n", + " electricity_in |40393548.93300275| kW electrolyzer.electricity_in \n", + " electrolyzer_size_mw [720.] MW electrolyzer.electrolyzer_size_mw \n", " electrolyzer_to_h2_storage_pipe\n", - " hydrogen_in |219.95801082| kg/s electrolyzer_to_h2_storage_pipe.hydrogen_in \n", + " hydrogen_in |219.95801192| kg/s electrolyzer_to_h2_storage_pipe.hydrogen_in \n", " h2_storage\n", " h2_storage\n", - " hydrogen_in |791848.83895374| kg/h h2_storage.hydrogen_in \n", - " rated_h2_production_kg_pr_hr [0.] kg/h h2_storage.rated_h2_production_kg_pr_hr \n", - " efficiency [0.77728804] None h2_storage.efficiency \n", + " hydrogen_in |791848.84291256| kg/h h2_storage.hydrogen_in \n", + " rated_h2_production_kg_pr_hr [0.] kg/h h2_storage.rated_h2_production_kg_pr_hr \n", + " efficiency [0.77728804] None h2_storage.efficiency \n", " demand_open_loop_controller\n", - " hydrogen_in |791848.83895374| kg/h h2_storage.hydrogen_in \n", - " hydrogen_demand_profile |467974.3582719| kg/h**2 h2_storage.hydrogen_demand_profile \n", - " financials_group_default\n", + " hydrogen_in |791848.84291256| kg/h h2_storage.hydrogen_in \n", + " hydrogen_demand_profile |467974.3582719| kg/h**2 h2_storage.hydrogen_demand_profile \n", + " finance_subgroup_h2\n", + " adjusted_capex_opex_comp\n", + " capex_wind [1.245e+09] USD finance_subgroup_h2.capex_wind \n", + " opex_wind [37350000.] USD/year finance_subgroup_h2.opex_wind \n", + " capex_electrolyzer [6.75464089e+08] USD finance_subgroup_h2.capex_electrolyzer \n", + " opex_electrolyzer [16541049.81608545] USD/year finance_subgroup_h2.opex_electrolyzer \n", + " capex_h2_storage [1.28437699e+08] USD finance_subgroup_h2.capex_h2_storage \n", + " opex_h2_storage [4330693.5188038] USD/year finance_subgroup_h2.opex_h2_storage \n", + " cost_year_wind 2019 n/a finance_subgroup_h2.cost_year_wind \n", + " cost_year_electrolyzer 2021 n/a finance_subgroup_h2.cost_year_electrolyzer \n", + " cost_year_h2_storage 2018 n/a finance_subgroup_h2.cost_year_h2_storage \n", + " default_hydrogen\n", + " total_hydrogen_produced [58145418.38681877] kg/year finance_subgroup_h2.total_hydrogen_produced \n", + " capex_adjusted_wind [1.34072883e+09] USD finance_subgroup_h2.capex_adjusted_wind \n", + " opex_adjusted_wind [40221864.84374999] USD/year finance_subgroup_h2.opex_adjusted_wind \n", + " capex_adjusted_electrolyzer [6.92350691e+08] USD finance_subgroup_h2.capex_adjusted_electrolyzer \n", + " opex_adjusted_electrolyzer [16954576.06148758] USD/year finance_subgroup_h2.opex_adjusted_electrolyzer \n", + " capex_adjusted_h2_storage [1.41771187e+08] USD finance_subgroup_h2.capex_adjusted_h2_storage \n", + " opex_adjusted_h2_storage [4780275.33140178] USD/year finance_subgroup_h2.opex_adjusted_h2_storage \n", + " electrolyzer_time_until_replacement [32414.89402766] h finance_subgroup_h2.electrolyzer_time_until_replacement \n", + " finance_subgroup_elec\n", " electricity_sum\n", - " electricity_wind |40393548.72275606| kW financials_group_default.electricity_sum.electricity_wind \n", + " electricity_wind |40393548.93300275| kW finance_subgroup_elec.electricity_sum.electricity_wind \n", " adjusted_capex_opex_comp\n", - " capex_wind [1.245e+09] USD financials_group_default.capex_wind \n", - " opex_wind [37350000.] USD/year financials_group_default.opex_wind \n", - " capex_electrolyzer [6.75464089e+08] USD financials_group_default.capex_electrolyzer \n", - " opex_electrolyzer [16541049.81608545] USD/year financials_group_default.opex_electrolyzer \n", - " capex_h2_storage [1.28437699e+08] USD financials_group_default.capex_h2_storage \n", - " opex_h2_storage [4330693.5188056] USD/year financials_group_default.opex_h2_storage \n", - " cost_year_wind 2019 n/a financials_group_default.cost_year_wind \n", - " cost_year_electrolyzer 2021 n/a financials_group_default.cost_year_electrolyzer \n", - " cost_year_h2_storage 2018 n/a financials_group_default.cost_year_h2_storage \n", - " ProFastComp_0\n", - " total_hydrogen_produced [58145418.05837836] kg/year financials_group_default.total_hydrogen_produced \n", - " capex_adjusted_wind [1.34072883e+09] USD financials_group_default.capex_adjusted_wind \n", - " opex_adjusted_wind [40221864.84374999] USD/year financials_group_default.opex_adjusted_wind \n", - " capex_adjusted_electrolyzer [6.92350691e+08] USD financials_group_default.capex_adjusted_electrolyzer \n", - " opex_adjusted_electrolyzer [16954576.06148758] USD/year financials_group_default.opex_adjusted_electrolyzer \n", - " capex_adjusted_h2_storage [1.41771187e+08] USD financials_group_default.capex_adjusted_h2_storage \n", - " opex_adjusted_h2_storage [4780275.33140376] USD/year financials_group_default.opex_adjusted_h2_storage \n", - " electrolyzer_time_until_replacement [32414.89403159] h financials_group_default.electrolyzer_time_until_replacement\n", - " ProFastComp_1\n", - " total_electricity_produced [3.11408814e+09] kW*h/year financials_group_default.total_electricity_produced \n", - " capex_adjusted_wind [1.34072883e+09] USD financials_group_default.capex_adjusted_wind \n", - " opex_adjusted_wind [40221864.84374999] USD/year financials_group_default.opex_adjusted_wind \n", - " capex_adjusted_electrolyzer [6.92350691e+08] USD financials_group_default.capex_adjusted_electrolyzer \n", - " opex_adjusted_electrolyzer [16954576.06148758] USD/year financials_group_default.opex_adjusted_electrolyzer \n", - " capex_adjusted_h2_storage [1.41771187e+08] USD financials_group_default.capex_adjusted_h2_storage \n", - " opex_adjusted_h2_storage [4780275.33140376] USD/year financials_group_default.opex_adjusted_h2_storage \n", - " electrolyzer_time_until_replacement [32414.89403159] h financials_group_default.electrolyzer_time_until_replacement\n", + " capex_wind [1.245e+09] USD finance_subgroup_elec.capex_wind \n", + " opex_wind [37350000.] USD/year finance_subgroup_elec.opex_wind \n", + " capex_electrolyzer [6.75464089e+08] USD finance_subgroup_elec.capex_electrolyzer \n", + " opex_electrolyzer [16541049.81608545] USD/year finance_subgroup_elec.opex_electrolyzer \n", + " capex_h2_storage [1.28437699e+08] USD finance_subgroup_elec.capex_h2_storage \n", + " opex_h2_storage [4330693.5188038] USD/year finance_subgroup_elec.opex_h2_storage \n", + " cost_year_wind 2019 n/a finance_subgroup_elec.cost_year_wind \n", + " cost_year_electrolyzer 2021 n/a finance_subgroup_elec.cost_year_electrolyzer \n", + " cost_year_h2_storage 2018 n/a finance_subgroup_elec.cost_year_h2_storage \n", + " default_electricity\n", + " total_electricity_produced [3.11408816e+09] kW*h/year finance_subgroup_elec.total_electricity_produced \n", + " capex_adjusted_wind [1.34072883e+09] USD finance_subgroup_elec.capex_adjusted_wind \n", + " opex_adjusted_wind [40221864.84374999] USD/year finance_subgroup_elec.opex_adjusted_wind \n", + " capex_adjusted_electrolyzer [6.92350691e+08] USD finance_subgroup_elec.capex_adjusted_electrolyzer \n", + " opex_adjusted_electrolyzer [16954576.06148758] USD/year finance_subgroup_elec.opex_adjusted_electrolyzer \n", + " capex_adjusted_h2_storage [1.41771187e+08] USD finance_subgroup_elec.capex_adjusted_h2_storage \n", + " opex_adjusted_h2_storage [4780275.33140178] USD/year finance_subgroup_elec.opex_adjusted_h2_storage \n", + " electrolyzer_time_until_replacement [32414.89402766] h finance_subgroup_elec.electrolyzer_time_until_replacement\n", "\n", "\n", - "41 Explicit Output(s) in 'model'\n", + "61 Explicit Output(s) in 'model'\n", "\n", - "varname val units prom_name \n", - "------------------------------------ -------------------- --------- -------------------------------------------------------------------\n", + "varname val units prom_name \n", + "----------------------------------------- -------------------- --------- ----------------------------------------------------------------\n", "site\n", " site_component\n", - " latitude [47.5233] None latitude \n", - " longitude [-92.5366] None longitude \n", - " elevation_m [439.] None elevation_m \n", - " time_zone [-5.] None time_zone \n", - " boundary_0_x |1414.21356237| None boundary_0_x \n", - " boundary_0_y |1004.98756211| None boundary_0_y \n", - " boundary_1_x |3774.91721764| None boundary_1_x \n", - " boundary_1_y |3774.91721764| None boundary_1_y \n", + " latitude [47.5233] None latitude \n", + " longitude [-92.5366] None longitude \n", + " elevation_m [0.] None elevation_m \n", + " time_zone [0.] None time_zone \n", + " boundary_0_x |1414.21356237| None boundary_0_x \n", + " boundary_0_y |1004.98756211| None boundary_0_y \n", + " boundary_1_x |3774.91721764| None boundary_1_x \n", + " boundary_1_y |3774.91721764| None boundary_1_y \n", "plant\n", " wind\n", " wind_plant_performance\n", - " electricity_out |40393548.72275606| kW wind.electricity_out \n", + " electricity_out |40393548.93300275| kW wind.electricity_out \n", " wind_plant_cost\n", - " CapEx [1.245e+09] USD wind.CapEx \n", - " OpEx [37350000.] USD/year wind.OpEx \n", - " cost_year 2019 n/a wind.cost_year \n", + " CapEx [1.245e+09] USD wind.CapEx \n", + " OpEx [37350000.] USD/year wind.OpEx \n", + " cost_year 2019 n/a wind.cost_year \n", " wind_to_electrolyzer_cable\n", - " electricity_out |40393548.72275606| kW wind_to_electrolyzer_cable.electricity_out \n", + " electricity_out |40393548.93300275| kW wind_to_electrolyzer_cable.electricity_out \n", " electrolyzer\n", " eco_pem_electrolyzer_performance\n", - " hydrogen_out |791848.83895374| kg/h electrolyzer.hydrogen_out \n", - " time_until_replacement [32414.89403159] h electrolyzer.time_until_replacement \n", - " total_hydrogen_produced [58145418.05837836] kg/year electrolyzer.total_hydrogen_produced \n", - " efficiency [0.77728804] None electrolyzer.efficiency \n", - " rated_h2_production_kg_pr_hr [14118.38052448] kg/h electrolyzer.rated_h2_production_kg_pr_hr \n", - " electrolyzer_size_mw [720.] MW electrolyzer.electrolyzer_size_mw \n", + " hydrogen_out |791848.84291256| kg/h electrolyzer.hydrogen_out \n", + " time_until_replacement [32414.89402766] h electrolyzer.time_until_replacement \n", + " total_hydrogen_produced [58145418.38681877] kg/year electrolyzer.total_hydrogen_produced \n", + " efficiency [0.77728804] None electrolyzer.efficiency \n", + " rated_h2_production_kg_pr_hr [14118.38052473] kg/h electrolyzer.rated_h2_production_kg_pr_hr \n", + " electrolyzer_size_mw [720.] MW electrolyzer.electrolyzer_size_mw \n", " singlitico_electrolyzer_cost\n", - " CapEx [6.75464089e+08] USD electrolyzer.CapEx \n", - " OpEx [16541049.81608545] USD/year electrolyzer.OpEx \n", - " cost_year 2021 n/a electrolyzer.cost_year \n", + " CapEx [6.75464089e+08] USD electrolyzer.CapEx \n", + " OpEx [16541049.81608545] USD/year electrolyzer.OpEx \n", + " cost_year 2021 n/a electrolyzer.cost_year \n", " electrolyzer_to_h2_storage_pipe\n", - " hydrogen_out |219.95801082| kg/s electrolyzer_to_h2_storage_pipe.hydrogen_out \n", + " hydrogen_out |219.95801192| kg/s electrolyzer_to_h2_storage_pipe.hydrogen_out \n", " h2_storage\n", " h2_storage\n", - " CapEx [1.28437699e+08] USD h2_storage.CapEx \n", - " OpEx [4330693.5188056] USD/year h2_storage.OpEx \n", - " cost_year 2018 n/a h2_storage.cost_year \n", + " CapEx [1.28437699e+08] USD h2_storage.CapEx \n", + " OpEx [4330693.5188038] USD/year h2_storage.OpEx \n", + " cost_year 2018 n/a h2_storage.cost_year \n", " demand_open_loop_controller\n", - " hydrogen_out |440928.0814644| kg/h h2_storage.hydrogen_out \n", - " hydrogen_soc |74.53109573| unitless h2_storage.hydrogen_soc \n", - " hydrogen_curtailed |376863.76618072| kg/h h2_storage.hydrogen_curtailed \n", - " hydrogen_missed_load |133351.12119996| kg/h h2_storage.hydrogen_missed_load \n", - " financials_group_default\n", + " hydrogen_out |440928.08133911| kg/h h2_storage.hydrogen_out \n", + " hydrogen_soc |74.53109581| unitless h2_storage.hydrogen_soc \n", + " hydrogen_curtailed |376863.77252| kg/h h2_storage.hydrogen_curtailed \n", + " hydrogen_missed_load |133351.12099949| kg/h h2_storage.hydrogen_missed_load \n", + " finance_subgroup_h2\n", + " adjusted_capex_opex_comp\n", + " capex_adjusted_wind [1.34072883e+09] USD finance_subgroup_h2.capex_adjusted_wind \n", + " opex_adjusted_wind [40221864.84374999] USD/year finance_subgroup_h2.opex_adjusted_wind \n", + " capex_adjusted_electrolyzer [6.92350691e+08] USD finance_subgroup_h2.capex_adjusted_electrolyzer \n", + " opex_adjusted_electrolyzer [16954576.06148758] USD/year finance_subgroup_h2.opex_adjusted_electrolyzer \n", + " capex_adjusted_h2_storage [1.41771187e+08] USD finance_subgroup_h2.capex_adjusted_h2_storage \n", + " opex_adjusted_h2_storage [4780275.33140178] USD/year finance_subgroup_h2.opex_adjusted_h2_storage \n", + " total_capex_adjusted [2.17485071e+09] USD finance_subgroup_h2.total_capex_adjusted \n", + " total_opex_adjusted [61956716.23663935] USD/year finance_subgroup_h2.total_opex_adjusted \n", + " default_hydrogen\n", + " LCOH [5.68452212] USD/kg finance_subgroup_h2.LCOH \n", + " wacc_hydrogen [0.06250448] percent finance_subgroup_h2.wacc_hydrogen \n", + " crf_hydrogen [0.07227903] percent finance_subgroup_h2.crf_hydrogen \n", + " irr_hydrogen [0.09] percent finance_subgroup_h2.irr_hydrogen \n", + " profit_index_hydrogen [1.80334107] unitless finance_subgroup_h2.profit_index_hydrogen \n", + " investor_payback_period_hydrogen [9.] year finance_subgroup_h2.investor_payback_period_hydrogen \n", + " price_hydrogen [5.68452212] USD/kg finance_subgroup_h2.price_hydrogen \n", + " finance_subgroup_elec\n", " electricity_sum\n", - " total_electricity_produced [3.11408814e+09] kW*h/year financials_group_default.electricity_sum.total_electricity_produced\n", + " total_electricity_produced [3.11408816e+09] kW*h/year finance_subgroup_elec.electricity_sum.total_electricity_produced\n", " adjusted_capex_opex_comp\n", - " capex_adjusted_wind [1.34072883e+09] USD financials_group_default.capex_adjusted_wind \n", - " opex_adjusted_wind [40221864.84374999] USD/year financials_group_default.opex_adjusted_wind \n", - " capex_adjusted_electrolyzer [6.92350691e+08] USD financials_group_default.capex_adjusted_electrolyzer \n", - " opex_adjusted_electrolyzer [16954576.06148758] USD/year financials_group_default.opex_adjusted_electrolyzer \n", - " capex_adjusted_h2_storage [1.41771187e+08] USD financials_group_default.capex_adjusted_h2_storage \n", - " opex_adjusted_h2_storage [4780275.33140376] USD/year financials_group_default.opex_adjusted_h2_storage \n", - " total_capex_adjusted [2.17485071e+09] USD financials_group_default.total_capex_adjusted \n", - " total_opex_adjusted [61956716.23664133] USD/year financials_group_default.total_opex_adjusted \n", - " ProFastComp_0\n", - " LCOH [5.68452215] USD/kg financials_group_default.LCOH \n", - " ProFastComp_1\n", - " LCOE [0.10613987] USD/kW/h financials_group_default.LCOE \n", + " capex_adjusted_wind [1.34072883e+09] USD finance_subgroup_elec.capex_adjusted_wind \n", + " opex_adjusted_wind [40221864.84374999] USD/year finance_subgroup_elec.opex_adjusted_wind \n", + " capex_adjusted_electrolyzer [6.92350691e+08] USD finance_subgroup_elec.capex_adjusted_electrolyzer \n", + " opex_adjusted_electrolyzer [16954576.06148758] USD/year finance_subgroup_elec.opex_adjusted_electrolyzer \n", + " capex_adjusted_h2_storage [1.41771187e+08] USD finance_subgroup_elec.capex_adjusted_h2_storage \n", + " opex_adjusted_h2_storage [4780275.33140178] USD/year finance_subgroup_elec.opex_adjusted_h2_storage \n", + " total_capex_adjusted [2.17485071e+09] USD finance_subgroup_elec.total_capex_adjusted \n", + " total_opex_adjusted [61956716.23663935] USD/year finance_subgroup_elec.total_opex_adjusted \n", + " default_electricity\n", + " LCOE [0.10613987] USD/kW/h finance_subgroup_elec.LCOE \n", + " wacc_electricity [0.06250448] percent finance_subgroup_elec.wacc_electricity \n", + " crf_electricity [0.07227903] percent finance_subgroup_elec.crf_electricity \n", + " irr_electricity [0.09] percent finance_subgroup_elec.irr_electricity \n", + " profit_index_electricity [1.80334107] unitless finance_subgroup_elec.profit_index_electricity \n", + " investor_payback_period_electricity [9.] year finance_subgroup_elec.investor_payback_period_electricity \n", + " price_electricity [0.10613987] USD/kW/h finance_subgroup_elec.price_electricity \n", "\n", "\n", "0 Implicit Output(s) in 'model'\n", @@ -315,7 +340,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.11.13 ('h2i_env')", + "display_name": "h2integrate-mcm", "language": "python", "name": "python3" }, @@ -329,12 +354,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.13" - }, - "vscode": { - "interpreter": { - "hash": "e55566d5f9cb5003b92ad1d2254e8146f3d62519cfa868f35d73d51fb57327c6" - } + "version": "3.11.12" } }, "nbformat": 4, diff --git a/examples/14_wind_hydrogen_dispatch/inputs/plant_config.yaml b/examples/14_wind_hydrogen_dispatch/inputs/plant_config.yaml index 796902871..6d3b6c212 100644 --- a/examples/14_wind_hydrogen_dispatch/inputs/plant_config.yaml +++ b/examples/14_wind_hydrogen_dispatch/inputs/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 47.5233 longitude: -92.5366 - elevation_m: 439.0 - time_zone: -5 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -31,35 +29,37 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.025 # $/kWh based on 2022 land based wind market report (ERCOT area ppa prices) https://www.energy.gov/sites/default/files/2022-08/land_based_wind_market_report_2202.pdf - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True - finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2030 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - wind: - expected_plant_cost: 'none' + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2030 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 + finance_subgroups: + elec: + commodity: "electricity" + technologies: ["wind", "electrolyzer", "h2_storage"] + h2: + commodity: "hydrogen" + technologies: ["wind", "electrolyzer", "h2_storage"] diff --git a/examples/15_wind_solar_electrolyzer/plant_config.yaml b/examples/15_wind_solar_electrolyzer/plant_config.yaml index d58c4b8b0..ddbef2829 100644 --- a/examples/15_wind_solar_electrolyzer/plant_config.yaml +++ b/examples/15_wind_solar_electrolyzer/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in MN, USA..." site: latitude: 30.6617 longitude: -101.7096 - elevation_m: 0.0 #unsure - time_zone: -5 #unsure year: 2013 # array of polygons defining boundaries with x/y coords @@ -30,40 +28,45 @@ technology_interconnections: [ # ["hopp", "electrolyzer", "electricity", "cable"], ["wind", "combiner", "electricity", "cable"], #source_tech, dest_tech, transport_item, transport_type = connection ["solar", "combiner", "electricity", "cable"], - ["combiner","electrolyzer","electricity","cable"], + ["combiner", "electrolyzer", "electricity", "cable"], ] plant: plant_life: 30 - grid_connection: False # option, can be turned on or off simulation: n_timesteps: 8760 dt: 3600 + finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for nominal analysis - discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] - technologies_included_in_metrics: - LCOE: ["wind", "solar"] - LCOH: ["wind", "solar", "electrolyzer"] + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for nominal analysis + discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["wind", "solar"] + hydrogen: + commodity: "hydrogen" + technologies: ["wind", "solar", "electrolyzer"] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 diff --git a/examples/15_wind_solar_electrolyzer/tech_config.yaml b/examples/15_wind_solar_electrolyzer/tech_config.yaml index e4f691d0d..8406a0ff8 100644 --- a/examples/15_wind_solar_electrolyzer/tech_config.yaml +++ b/examples/15_wind_solar_electrolyzer/tech_config.yaml @@ -73,8 +73,6 @@ technologies: model: "eco_pem_electrolyzer_performance" cost_model: model: "singlitico_electrolyzer_cost" - financial_model: - group: default model_inputs: shared_parameters: location: "onshore" diff --git a/examples/16_natural_gas/plant_config.yaml b/examples/16_natural_gas/plant_config.yaml index 025ad458a..0955376a2 100644 --- a/examples/16_natural_gas/plant_config.yaml +++ b/examples/16_natural_gas/plant_config.yaml @@ -4,8 +4,6 @@ description: "This plant is located in Texas" site: latitude: 32.34 longitude: -98.27 - elevation_m: 440.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -31,34 +29,33 @@ technology_interconnections: [ plant: plant_life: 30 - grid_connection: False # option, can be turned on or off - ppa_price: 0.027498168 # based off correlations of LBNL PPA data - hybrid_electricity_estimated_cf: 0.492 #should equal 1 if grid_connection = True simulation: n_timesteps: 8760 finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 - inflation_rate: 0.0 - discount_rate: 0.09 - debt_equity_ratio: 2.62 - property_tax_and_insurance: 0.03 - total_income_tax_rate: 0.308 - capital_gains_tax_rate: 0.15 - sales_tax_rate: 0.07375 - debt_interest_rate: 0.07 - debt_type: "Revolving debt" - loan_period_if_used: 0 - cash_onhand_months: 1 - admin_expense: 0.00 - capital_items: - depr_type: "MACRS" - depr_period: 5 - refurb: [0.] + finance_groups: + commodity: "electricity" + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 + inflation_rate: 0.0 + discount_rate: 0.09 + debt_equity_ratio: 2.62 + property_tax_and_insurance: 0.03 + total_income_tax_rate: 0.308 + capital_gains_tax_rate: 0.15 + sales_tax_rate: 0.07375 + debt_interest_rate: 0.07 + debt_type: "Revolving debt" + loan_period_if_used: 0 + cash_onhand_months: 1 + admin_expense: 0.00 + capital_items: + depr_type: "MACRS" + depr_period: 5 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 target_dollar_year: 2022 diff --git a/examples/17_splitter_wind_doc_h2/plant_config.yaml b/examples/17_splitter_wind_doc_h2/plant_config.yaml index 7266eb81c..c6d23776f 100644 --- a/examples/17_splitter_wind_doc_h2/plant_config.yaml +++ b/examples/17_splitter_wind_doc_h2/plant_config.yaml @@ -5,7 +5,6 @@ site: latitude: 43.807 longitude: -124.816 elevation_m: 439.0 - time_zone: -6 # array of polygons defining boundaries with x/y coords boundaries: [ @@ -39,31 +38,38 @@ technology_interconnections: [ ] finance_parameters: - finance_model: "ProFastComp" - model_inputs: - params: - analysis_start_year: 2032 - installation_time: 36 # months - inflation_rate: 0.0 # 0 for real analysis - discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind - debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind - property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx - total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) - capital_gains_tax_rate: 0.15 # H2FAST default - sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ - debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind - debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH - loan_period_if_used: 0 # H2FAST default, not used for revolving debt - cash_onhand_months: 1 # H2FAST default - admin_expense: 0.00 # percent of sales H2FAST default - capital_items: - depr_type: "MACRS" # can be "MACRS" or "Straight line" - depr_period: 7 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 - refurb: [0.] + finance_groups: + finance_model: "ProFastComp" + model_inputs: + params: + analysis_start_year: 2032 + installation_time: 36 # months + inflation_rate: 0.0 # 0 for real analysis + discount_rate: 0.06 # nominal return based on 2024 ATB baseline workbook for land-based wind + debt_equity_ratio: 0.724 # 2024 ATB uses 72.4% debt for land-based wind + property_tax_and_insurance: 0.025 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx + total_income_tax_rate: 0.2574 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8) + capital_gains_tax_rate: 0.15 # H2FAST default + sales_tax_rate: 0.0 # average combined state and local sales tax https://taxfoundation.org/location/texas/ + debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind + debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH + loan_period_if_used: 0 # H2FAST default, not used for revolving debt + cash_onhand_months: 1 # H2FAST default + admin_expense: 0.00 # percent of sales H2FAST default + capital_items: + depr_type: "MACRS" # can be "MACRS" or "Straight line" + depr_period: 7 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + refurb: [0.] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 - technologies_included_in_metrics: - LCOE: ["hopp"] - LCOH: ["hopp", "electrolyzer"] - LCOC: ["hopp", "doc"] + finance_subgroups: + electricity: + commodity: "electricity" + technologies: ["hopp"] + hydrogen: + commodity: "hydrogen" + technologies: ["hopp", "electrolyzer"] + co2: + commodity: "co2" + technologies: ["hopp", "doc"] diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index b619b1265..bdcffc1b9 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -5,8 +5,8 @@ import numpy as np import openmdao.api as om -from h2integrate.core.finances import AdjustedCapexOpexComp from h2integrate.core.utilities import create_xdsm_from_config +from h2integrate.finances.finances import AdjustedCapexOpexComp from h2integrate.core.resource_summer import ElectricitySumComp from h2integrate.core.supported_models import supported_models, electricity_producing_techs from h2integrate.core.inputs.validation import load_tech_yaml, load_plant_yaml, load_driver_yaml @@ -47,7 +47,7 @@ def __init__(self, config_file): # they will need tech_config but not driver or plant config self.create_technology_models() - self.create_financial_model() + self.create_finance_model() # connect technologies # technologies are connected within the `technology_interconnections` section of the @@ -81,7 +81,7 @@ def collect_custom_models(self): """ for tech_name, tech_config in self.technology_config["technologies"].items(): - for model_type in ["performance_model", "cost_model", "financial_model"]: + for model_type in ["performance_model", "cost_model", "finance_model"]: if model_type in tech_config: model_name = tech_config[model_type].get("model") if (model_name not in self.supported_models) and (model_name is not None): @@ -135,7 +135,6 @@ def create_site_model(self): site_component.add_output("latitude", val=site_config.get("latitude", 0.0)) site_component.add_output("longitude", val=site_config.get("longitude", 0.0)) site_component.add_output("elevation_m", val=site_config.get("elevation_m", 0.0)) - site_component.add_output("time_zone", val=site_config.get("time_zone", 0)) # Add boundaries if they exist site_config = self.plant_config.get("site", {}) @@ -182,7 +181,7 @@ def create_technology_models(self): self.performance_models = [] self.control_strategies = [] self.cost_models = [] - self.financial_models = [] + self.finance_models = [] combined_performance_and_cost_models = ["hopp", "h2_storage", "wombat"] @@ -201,11 +200,11 @@ def create_technology_models(self): tech_group = self.plant.add_subsystem(tech_name, om.Group()) self.tech_names.append(tech_name) - # Check if performance, cost, and financial models are the same + # Check if performance, cost, and finance models are the same # and in combined_performance_and_cost_models perf_model = individual_tech_config.get("performance_model", {}).get("model") cost_model = individual_tech_config.get("cost_model", {}).get("model") - individual_tech_config.get("financial_model", {}).get("model") + individual_tech_config.get("finance_model", {}).get("model") if ( perf_model and perf_model == cost_model @@ -219,7 +218,7 @@ def create_technology_models(self): tech_group.add_subsystem(tech_name, comp, promotes=["*"]) self.performance_models.append(comp) self.cost_models.append(comp) - self.financial_models.append(comp) + self.finance_models.append(comp) # Catch control models for systems that have the same performance & cost models if "control_strategy" in individual_tech_config: @@ -230,7 +229,7 @@ def create_technology_models(self): continue # Process the models - # TODO: integrate financial_model into the loop below + # TODO: integrate finance_model into the loop below model_types = ["performance_model", "control_strategy", "cost_model"] for model_type in model_types: if model_type in individual_tech_config: @@ -241,22 +240,25 @@ def create_technology_models(self): elif model_type == "performance_model": raise KeyError("Model definition requires 'performance_model'.") - # Process the financial models - if "financial_model" in individual_tech_config: - if "model" in individual_tech_config["financial_model"]: - financial_name = individual_tech_config["financial_model"]["model"] - - financial_object = self.supported_models[financial_name] - tech_group.add_subsystem( - f"{tech_name}_financial", - financial_object( - driver_config=self.driver_config, - plant_config=self.plant_config, - tech_config=individual_tech_config, - ), - promotes=["*"], - ) - self.financial_models.append(financial_object) + # Process the finance models + if "finance_model" in individual_tech_config: + if "model" in individual_tech_config["finance_model"]: + finance_name = individual_tech_config["finance_model"]["model"] + + if finance_name != individual_tech_config.get("cost_model", {}).get( + "model", "" + ): + finance_object = self.supported_models[finance_name] + tech_group.add_subsystem( + f"{tech_name}_finance", + finance_object( + driver_config=self.driver_config, + plant_config=self.plant_config, + tech_config=individual_tech_config, + ), + promotes=["*"], + ) + self.finance_models.append(finance_object) for tech_name, individual_tech_config in self.technology_config["technologies"].items(): cost_model = individual_tech_config.get("cost_model", {}).get("model") @@ -283,184 +285,290 @@ def _process_model(self, model_type, individual_tech_config, tech_group): ) return model_object - def create_financial_model(self): + def create_finance_model(self): """ - Creates and configures the financial model for the plant. + Create and configure the finance model(s) for the plant. + + This method initializes finance subsystems for the plant based on the + configuration provided in ``self.plant_config["finance_parameters"]``. It + supports both default (single-model) setups and multiple/distinct (subgroup-specific) + finance models. + + Within this framework, a finance subgroup serves as a flexible grouping mechanism for + calculating finance metrics across different subsets of technologies. + These groupings can draw on varying finance inputs or models within the same simulation. + To support a wide range of use cases, such as evaluating metrics for only part of a larger + system, finance subgroups may reference multiple finance_groups and may overlap + partially or fully with the technologies included in other finance subgroups. + + Behavior: + * If ``finance_parameters`` is not defined in the plant configuration, + no finance model is created. + * If no subgroups are defined, all technologies are grouped together + under a default finance group. ``commodity`` and ``finance_model`` are + required in this case. + * If subgroups are provided, each subgroup defines its own set of + technologies, associated commodity, and finance model(s). + Each subgroup is nested under a unique name of your choice under + ["finance_parameters"]["subgroups"] in the plant configuration. + * Subsystems such as ``ElectricitySumComp``, ``AdjustedCapexOpexComp``, + and the selected finance models are added to each subgroup's + finance group. + * Supports both global finance models and technology-specific finance + models. Technology-specific finance models are defined in the technology + configuration. + + Raises: + ValueError: + If ["finance_parameters"]["finance_group"] is incomplete (e.g., missing + ``commodity`` or ``finance_model``) when no subgroups are defined. + ValueError: + If a subgroup has an invalid technology. + ValueError: + If a specified finance model is not found in + ``self.supported_models``. + + Side Effects: + * Updates ``self.plant_config["finance_parameters"]["finance_group"] if only a single + finance model is provided (wraps it in a default finance subgroup). + * Constructs and attaches OpenMDAO finance subsystem groups to the + plant model under names ``finance_subgroup_``. + * Stores processed subgroup configurations in + ``self.finance_subgroups``. + + Example: + Suppose ``plant_config["finance_parameters"]["finance_group"]`` defines a single finance + model without subgroups: + + >>> self.plant_config["finance_parameters"]["finance_group"] = { + ... "commodity": "hydrogen", + ... "finance_model": "ProFastComp", + ... "model_inputs": {"discount_rate": 0.08}, + ... } + >>> self.create_finance_model() + # Creates a default subgroup containing all technologies and + # attaches a ProFAST finance model component to the plant. - Creates financial groups based on the technology configurations - and adds the appropriate financial components to each group. """ - + # if there aren't any finance parameters don't setup a finance model if "finance_parameters" not in self.plant_config: return - # Create a dictionary to hold financial groups - financial_groups = {} + subgroups = self.plant_config["finance_parameters"].get("finance_subgroups", None) + + if "finance_groups" not in self.plant_config["finance_parameters"]: + raise ValueError("plant_config['finance_parameters'] must define 'finance_groups'.") + + finance_subgroups = {} + + default_finance_group_name = "default" + # only one finance model is being used with subgroups + if ( + "finance_model" in self.plant_config["finance_parameters"]["finance_groups"] + and "model_inputs" in self.plant_config["finance_parameters"]["finance_groups"] + ): + if ( + default_finance_group_name + in self.plant_config["finance_parameters"]["finance_groups"] + ): + # throw an error if the user has an unused finance group named "default". + msg = ( + "Invalid key `default` in " + "plant_config['finance_parameters']['finance_groups']. " + "Please rename the `default` key to something else or remove it. " + "The name `default` will be used to reference the finance model group." + ) + raise ValueError(msg) + default_model_name = self.plant_config["finance_parameters"]["finance_groups"].pop( + "finance_model" + ) + default_model_inputs = self.plant_config["finance_parameters"]["finance_groups"].pop( + "model_inputs" + ) + default_model_dict = { + default_finance_group_name: { + "finance_model": default_model_name, + "model_inputs": default_model_inputs, + } + } + self.plant_config["finance_parameters"]["finance_groups"].update(default_model_dict) + + if subgroups is None: + # --- Default behavior --- + commodity = self.plant_config["finance_parameters"]["finance_groups"].get("commodity") + finance_model_name = ( + self.plant_config["finance_parameters"]["finance_groups"] + .get(default_finance_group_name, {}) + .get("finance_model") + ) - # Loop through each technology and add it to the appropriate financial group - for tech_name, individual_tech_config in self.technology_config["technologies"].items(): - financial_group_id = individual_tech_config.get("financial_model", {}).get("group") - if financial_group_id is not None: - if financial_group_id not in financial_groups: - financial_groups[financial_group_id] = {} - financial_groups[financial_group_id][tech_name] = individual_tech_config + if not commodity or not finance_model_name: + raise ValueError( + "plant_config['finance_parameters']['finance_groups'] " + "must define 'commodity' and 'finance_model' " + "if no finance_subgroups are provided." + ) - # Find technologies not assigned to any financial group and add them to group "default" - all_grouped_techs = set() - for group in financial_groups.values(): - all_grouped_techs.update(group.keys()) + # Collect all technologies into one subgroup + all_techs = list(self.technology_config["technologies"].keys()) + subgroup = { + "commodity": commodity, + "finance_groups": [default_finance_group_name], + "technologies": all_techs, + } + subgroups = {default_finance_group_name: subgroup} + + # --- Normal subgroup handling --- + for subgroup_name, subgroup_params in subgroups.items(): + commodity = subgroup_params.get("commodity", None) + commodity_desc = subgroup_params.get("commodity_desc", "") + finance_group_names = subgroup_params.get( + "finance_groups", [default_finance_group_name] + ) + tech_names = subgroup_params.get("technologies") - for tech_name, tech_config in self.technology_config["technologies"].items(): - if tech_name not in all_grouped_techs: - if "default" not in financial_groups: - financial_groups["default"] = {} - financial_groups["default"][tech_name] = tech_config - - # Add each financial group to the plant - for group_id, tech_configs in financial_groups.items(): - commodity_types = [] - if "steel" in tech_configs: - commodity_types.append("steel") - if "electrolyzer" in tech_configs: - commodity_types.append("hydrogen") - if "methanol" in tech_configs: - commodity_types.append("methanol") - if "ammonia" in tech_configs: - commodity_types.append("ammonia") - if "air_separator" in tech_configs: - commodity_types.append("nitrogen") - if "geoh2" in tech_configs: - commodity_types.append("hydrogen") - if "doc" in tech_configs: - commodity_types.append("co2") - if "oae" in tech_configs: - commodity_types.append("co2") - for tech in electricity_producing_techs: - if tech in tech_configs: - commodity_types.append("electricity") - break - - # Steel, methanol provides their own financials - if any(c in commodity_types for c in ("steel", "methanol")): - continue - - # GeoH2 provides own financials - if "geoh2" in tech_configs: - continue - - if commodity_types == []: - continue - - financial_group = om.Group() - - # Determine all technologies that should be included across all - # commodity types for this group - all_included_techs = set() - for commodity_type in commodity_types: - if commodity_type not in ["steel", "methanol"]: # These handle their own financials - included_techs = self.get_included_technologies( - tech_configs, commodity_type, self.plant_config - ) - all_included_techs.update(included_techs) + if isinstance(finance_group_names, str): + finance_group_names = [finance_group_names] - # Filter tech_configs to only include technologies that are in at least one stackup - filtered_tech_configs_for_capex = { - tech: config for tech, config in tech_configs.items() if tech in all_included_techs - } + # check commodity type + if commodity is None: + raise ValueError( + f"Required parameter ``commodity`` not provided in subgroup {subgroup_name}." + ) - # Add the ExecComp to the plant model - financial_group.add_subsystem( - "electricity_sum", ElectricitySumComp(tech_configs=filtered_tech_configs_for_capex) + tech_configs = {} + for tech in tech_names: + if tech in self.technology_config["technologies"]: + tech_configs[tech] = self.technology_config["technologies"][tech] + else: + raise KeyError( + f"Technology '{tech}' not found in the technology configuration, " + f"but is listed in subgroup '{subgroup_name}', " + "Available " + f"technologies: {list(self.technology_config['technologies'].keys())}" + ) + + finance_subgroups.update( + { + subgroup_name: { + "tech_configs": tech_configs, + "commodity": commodity, + } + } ) + finance_subgroup = om.Group() + + if commodity == "electricity": + finance_subgroup.add_subsystem( + "electricity_sum", ElectricitySumComp(tech_configs=tech_configs) + ) - # Add adjusted capex component + # Add adjusted capex/opex adjusted_capex_opex_comp = AdjustedCapexOpexComp( driver_config=self.driver_config, - tech_config=filtered_tech_configs_for_capex, + tech_configs=tech_configs, plant_config=self.plant_config, ) - financial_group.add_subsystem( + + finance_subgroup.add_subsystem( "adjusted_capex_opex_comp", adjusted_capex_opex_comp, promotes=["*"] ) - # Add profast components - for idx, commodity_type in enumerate(commodity_types): - # Get included technologies for this commodity type - included_techs = self.get_included_technologies( - tech_configs, commodity_type, self.plant_config - ) + for finance_group_name in finance_group_names: + # check if using tech-specific finance model + if any( + tech_name == finance_group_name + for tech_name, tech_params in tech_configs.items() + ): + tech_finance_group_name = ( + tech_configs.get(finance_group_name).get("finance_model", {}).get("model") + ) - # Filter tech_configs to only include the technologies in the stackup - filtered_tech_configs = { - tech: config for tech, config in tech_configs.items() if tech in included_techs - } + # this is created in create_technologies() + if tech_finance_group_name is not None: + # tech specific finance models are created in create_technologies() + # and do not need to be included in the general finance models + continue - fin_model_name = self.plant_config["finance_parameters"].get("finance_model") - if isinstance(fin_model_name, list): - for model_name in fin_model_name: - fin_model = self.supported_models.get(model_name) - fin_comp = fin_model( - driver_config=self.driver_config, - tech_config=filtered_tech_configs, - plant_config=self.plant_config, - commodity_type=commodity_type, - ) - financial_group.add_subsystem( - f"{model_name}_{idx}", fin_comp, promotes=["*"] - ) - else: - fin_model = self.supported_models.get(fin_model_name) - fin_comp = fin_model( - driver_config=self.driver_config, - tech_config=filtered_tech_configs, - plant_config=self.plant_config, - commodity_type=commodity_type, - ) - financial_group.add_subsystem( - f"{fin_model_name}_{idx}", fin_comp, promotes=["*"] - ) + # if not using a tech-specific finance group, get the finance model and inputs for + # the finance model group specified by finance_group_name + finance_group_config = self.plant_config["finance_parameters"][ + "finance_groups" + ].get(finance_group_name) + model_name = finance_group_config.get("finance_model") # finance model + fin_model_inputs = finance_group_config.get( + "model_inputs" + ) # inputs to finance model - self.plant.add_subsystem(f"financials_group_{group_id}", financial_group) + # get finance model component definition + fin_model = self.supported_models.get(model_name) - self.financial_groups = financial_groups + if fin_model is None: + raise ValueError(f"finance model '{model_name}' not found.") - def get_included_technologies(self, tech_config, commodity_type, plant_config): - """ - Determine which technologies should be included in the financial metrics. + # filter the plant_config so the finance_parameters only includes data for + # this finance model group - Args: - tech_config: Dictionary of technology configurations - commodity_type: Type of commodity (e.g., 'hydrogen', 'electricity', 'ammonia') - plant_config: Plant configuration dictionary + # first, grab information from the plant config, except the finance parameters + filtered_plant_config = { + k: v for k, v in self.plant_config.items() if k != "finance_parameters" + } - Returns: - List of technology names to include in the financial stackup - """ - # Check if the user defined specific technologies to include in the metrics. - # If provided, only include those technologies in the stackup. - # If not provided, include all technologies in the financial group in the stackup. - metric_key = f"LCO{commodity_type[0].upper()}" - - included_techs = ( - plant_config["finance_parameters"] - .get("technologies_included_in_metrics", {}) - .get(metric_key, None) - ) + # then, reformat the finance_parameters to only include inputs for the + # finance group specified by finance_group_name + filtered_plant_config.update( + { + "finance_parameters": { + "finance_model": model_name, # unused by the finance model + "model_inputs": fin_model_inputs, # inputs for finance model + } + } + ) - # Check if the included technologies are valid - if included_techs is not None: - missing_techs = [tech for tech in included_techs if tech not in tech_config] - if missing_techs: - raise ValueError( - f"Included technology(ies) {missing_techs} not found in tech_config. " - f"Available techs: {list(tech_config.keys())}" + commodity_desc = subgroup_params.get("commodity_desc", "") + commodity_output_desc = subgroup_params.get("commodity_desc", "") + + # check if multiple finance models are specified for the subgroup + if len(finance_group_names) > 1: + # check that the finance model groups do not include tech-specific finances + non_tech_finances = [ + k + for k in finance_group_names + if k in self.plant_config["finance_parameters"]["finance_groups"] + ] + + # if multiple non-tech specific finance model groups are specified for the + # subgroup, the outputs of the finance model must have unique names to + # avoid errors. + if len(non_tech_finances) > 1: + # finance models name their outputs based on the description and commodity + # update the description to include the finance model name to ensure + # uniquely named outputs + commodity_output_desc = commodity_output_desc + f"_{finance_group_name}" + + # create the finance component + fin_comp = fin_model( + driver_config=self.driver_config, + tech_config=tech_configs, + plant_config=filtered_plant_config, + commodity_type=commodity, + description=commodity_output_desc, + ) + + # name the finance component based on the commodity and description + finance_subsystem_name = ( + f"{commodity}_finance_{finance_group_name}" + if commodity_desc == "" + else f"{commodity}_{commodity_desc}_finance_{finance_group_name}" ) - # If no specific technologies are included, default to all technologies in tech_config - if included_techs is None: - included_techs = list(tech_config.keys()) + # add the finance component to the finance group + finance_subgroup.add_subsystem(finance_subsystem_name, fin_comp, promotes=["*"]) - return included_techs + # add the finance group to the subgroup + self.plant.add_subsystem(f"finance_subgroup_{subgroup_name}", finance_subgroup) + + self.finance_subgroups = finance_subgroups def connect_technologies(self): technology_interconnections = self.plant_config.get("technology_interconnections", []) @@ -587,129 +695,97 @@ def connect_technologies(self): # Connect the resource output to the technology input self.model.connect(f"{resource_name}.{variable}", f"{tech_name}.{variable}") - # TODO: connect outputs of the technology models to the cost and financial models of the - # same name if the cost and financial models are not None + # TODO: connect outputs of the technology models to the cost and finance models of the + # same name if the cost and finance models are not None if "finance_parameters" in self.plant_config: - # Connect the outputs of the technology models to the appropriate financial groups - for group_id, tech_configs in self.financial_groups.items(): - # Skip steel financials; it provides its own financials + # Connect the outputs of the technology models to the appropriate finance groups + for group_id, group_configs in self.finance_subgroups.items(): + tech_configs = group_configs.get("tech_configs") + primary_commodity_type = group_configs.get("commodity") + # Skip steel finances; it provides its own finances if any(c in tech_configs for c in ("steel", "methanol", "geoh2")): continue plant_producing_electricity = False - # Determine which commodity types this financial group handles - commodity_types = [] - if "steel" in tech_configs: - commodity_types.append("steel") - if "electrolyzer" in tech_configs: - commodity_types.append("hydrogen") - if "methanol" in tech_configs: - commodity_types.append("methanol") - if "ammonia" in tech_configs: - commodity_types.append("ammonia") - if "geoh2" in tech_configs: - commodity_types.append("hydrogen") - if "doc" in tech_configs: - commodity_types.append("co2") - if "air_separator" in tech_configs: - commodity_types.append("nitrogen") - if "oae" in tech_configs: - commodity_types.append("co2") - for tech in electricity_producing_techs: - if tech in tech_configs: - commodity_types.append("electricity") - break - - # Get all included technologies for all commodity types in this group - all_included_techs = set() - for commodity_type in commodity_types: - if commodity_type not in [ - "steel", - "methanol", - ]: # These handle their own financials - included_techs = self.get_included_technologies( - tech_configs, commodity_type, self.plant_config - ) - all_included_techs.update(included_techs) - # Loop through technologies and connect electricity outputs to the ExecComp # Only connect if the technology is included in at least one commodity's stackup - # and in this financial group + # and in this finance group for tech_name in tech_configs.keys(): - if tech_name in electricity_producing_techs and tech_name in all_included_techs: + if ( + tech_name in electricity_producing_techs + # and tech_name in all_included_techs + and primary_commodity_type == "electricity" + ): self.plant.connect( f"{tech_name}.electricity_out", - f"financials_group_{group_id}.electricity_sum.electricity_{tech_name}", + f"finance_subgroup_{group_id}.electricity_sum.electricity_{tech_name}", ) plant_producing_electricity = True - if plant_producing_electricity: - # Connect total electricity produced to the financial group + if plant_producing_electricity and primary_commodity_type == "electricity": + # Connect total electricity produced to the finance group self.plant.connect( - f"financials_group_{group_id}.electricity_sum.total_electricity_produced", - f"financials_group_{group_id}.total_electricity_produced", + f"finance_subgroup_{group_id}.electricity_sum.total_electricity_produced", + f"finance_subgroup_{group_id}.total_electricity_produced", ) - # Only connect technologies that are included in the financial stackup + # Only connect technologies that are included in the finance stackup for tech_name in tech_configs.keys(): # For now, assume splitters and combiners do not add any costs if "splitter" in tech_name or "combiner" in tech_name: continue - if tech_name in all_included_techs: - self.plant.connect( - f"{tech_name}.CapEx", f"financials_group_{group_id}.capex_{tech_name}" - ) - self.plant.connect( - f"{tech_name}.OpEx", f"financials_group_{group_id}.opex_{tech_name}" - ) + self.plant.connect( + f"{tech_name}.CapEx", + f"finance_subgroup_{group_id}.capex_{tech_name}", + ) + self.plant.connect( + f"{tech_name}.OpEx", f"finance_subgroup_{group_id}.opex_{tech_name}" + ) + self.plant.connect( + f"{tech_name}.cost_year", + f"finance_subgroup_{group_id}.cost_year_{tech_name}", + ) + + if "electrolyzer" in tech_name: self.plant.connect( - f"{tech_name}.cost_year", - f"financials_group_{group_id}.cost_year_{tech_name}", + f"{tech_name}.time_until_replacement", + f"finance_subgroup_{group_id}.{tech_name}_time_until_replacement", ) - - if "electrolyzer" in tech_name: + if primary_commodity_type == "hydrogen": self.plant.connect( f"{tech_name}.total_hydrogen_produced", - f"financials_group_{group_id}.total_hydrogen_produced", - ) - self.plant.connect( - f"{tech_name}.time_until_replacement", - f"financials_group_{group_id}.{tech_name}_time_until_replacement", + f"finance_subgroup_{group_id}.total_hydrogen_produced", ) - if "ammonia" in tech_name: - self.plant.connect( - f"{tech_name}.total_ammonia_produced", - f"financials_group_{group_id}.total_ammonia_produced", - ) - - if "doc" in tech_name: - self.plant.connect( - f"{tech_name}.co2_capture_mtpy", - f"financials_group_{group_id}.co2_capture_kgpy", - ) + if "ammonia" in tech_name and primary_commodity_type == "ammonia": + self.plant.connect( + f"{tech_name}.total_ammonia_produced", + f"finance_subgroup_{group_id}.total_ammonia_produced", + ) - if "oae" in tech_name: - self.plant.connect( - f"{tech_name}.co2_capture_mtpy", - f"financials_group_{group_id}.co2_capture_kgpy", - ) + if ( + "doc" in tech_name or "oae" in tech_name + ) and primary_commodity_type == "co2": + self.plant.connect( + f"{tech_name}.co2_capture_mtpy", + f"finance_subgroup_{group_id}.co2_capture_kgpy", + ) - if "air_separator" in tech_name: - self.plant.connect( - f"{tech_name}.total_nitrogen_produced", - f"financials_group_{group_id}.total_nitrogen_produced", - ) + if "air_separator" in tech_name and primary_commodity_type == "nitrogen": + self.plant.connect( + f"{tech_name}.total_nitrogen_produced", + f"finance_subgroup_{group_id}.total_nitrogen_produced", + ) self.plant.options["auto_order"] = True - # Check if there are any connections FROM a financial group to ammonia - # This handles the case where LCOH is computed in the financial group and passed to ammonia + # Check if there are any connections FROM a finance group to ammonia + # This handles the case where LCOH is computed in the finance group and passed to ammonia for connection in technology_interconnections: - if connection[0].startswith("financials_group_") and connection[1] == "ammonia": - # If the connection is from a financial group, set solvers for the + if connection[0].startswith("finance_subgroup_") and connection[1] == "ammonia": + # If the connection is from a finance group, set solvers for the # plant to resolve the coupling self.plant.nonlinear_solver = om.NonlinearBlockGS() self.plant.linear_solver = om.DirectSolver() diff --git a/h2integrate/core/inputs/plant_schema.yaml b/h2integrate/core/inputs/plant_schema.yaml index 818a6f1fa..b5616e235 100644 --- a/h2integrate/core/inputs/plant_schema.yaml +++ b/h2integrate/core/inputs/plant_schema.yaml @@ -27,11 +27,6 @@ properties: type: number description: Elevation of the site in meters minimum: 0 - time_zone: - type: number - description: Time zone offset from UTC in hours - minimum: -12 - maximum: 14 boundaries: type: array description: Array of polygons defining boundaries with x/y coordinates @@ -80,8 +75,8 @@ properties: description: timezone as UTC offset corresponding to start_time minimum: -12 maximum: 14 - required: ["dt","n_timesteps"] - required: ["plant_life","simulation"] + required: ["dt", "n_timesteps"] + required: ["plant_life", "simulation"] technology_interconnections: type: array description: Array of arrays representing technology interconnections diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index fd4a4cd70..ed38dfddb 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -3,8 +3,8 @@ from h2integrate.transporters.pipe import PipePerformanceModel from h2integrate.transporters.cable import CablePerformanceModel from h2integrate.converters.steel.steel import SteelPerformanceModel, SteelCostAndFinancialModel -from h2integrate.core.profast_financial import ProFastComp from h2integrate.converters.wind.wind_plant import WindPlantCostModel, WindPlantPerformanceModel +from h2integrate.finances.profast_financial import ProFastComp from h2integrate.converters.hopp.hopp_wrapper import HOPPComponent from h2integrate.converters.solar.solar_pysam import PYSAMSolarPlantPerformanceModel from h2integrate.storage.hydrogen.eco_storage import H2Storage diff --git a/h2integrate/core/test/test_finances.py b/h2integrate/core/test/test_finances.py index cd773341d..9e4944295 100644 --- a/h2integrate/core/test/test_finances.py +++ b/h2integrate/core/test/test_finances.py @@ -6,7 +6,7 @@ from pytest import approx from h2integrate.core.inputs.validation import load_tech_yaml, load_plant_yaml, load_driver_yaml -from h2integrate.core.profast_financial import ProFastComp +from h2integrate.finances.profast_financial import ProFastComp examples_dir = Path(__file__).resolve().parent.parent.parent.parent / "examples/." @@ -101,10 +101,13 @@ def test_modified_lcoe_calc(self): tech_config = load_tech_yaml(example_case_dir / "tech_config.yaml") plant_config = load_plant_yaml(example_case_dir / "plant_config.yaml") driver_config = load_driver_yaml(example_case_dir / "driver_config.yaml") + finance_inputs = plant_config["finance_parameters"]["finance_groups"].pop("profast_model") + plant_config_filtered = {k: v for k, v in plant_config.items() if k != "finance_parameters"} + plant_config_filtered.update({"finance_parameters": finance_inputs}) # Run ProFastComp with loaded configs prob = om.Problem() comp = ProFastComp( - plant_config=plant_config, + plant_config=plant_config_filtered, tech_config=tech_config["technologies"], driver_config=driver_config, commodity_type="electricity", @@ -137,14 +140,17 @@ def test_lcoe_with_selected_technologies(self): driver_config = load_driver_yaml(example_case_dir / "driver_config.yaml") # Only include HOPP and electrolyzer in metrics - plant_config["finance_parameters"]["technologies_included_in_metrics"]["LCOE"] = [ + plant_config["finance_parameters"]["finance_subgroups"]["electricity"]["technologies"] = [ "hopp", "steel", ] + finance_inputs = plant_config["finance_parameters"]["finance_groups"].pop("profast_model") + plant_config_filtered = {k: v for k, v in plant_config.items() if k != "finance_parameters"} + plant_config_filtered.update({"finance_parameters": finance_inputs}) prob = om.Problem() comp = ProFastComp( - plant_config=plant_config, + plant_config=plant_config_filtered, tech_config=tech_config["technologies"], driver_config=driver_config, commodity_type="electricity", diff --git a/h2integrate/core/test/test_framework.py b/h2integrate/core/test/test_framework.py index 6fa8c05dc..ac6b6387f 100644 --- a/h2integrate/core/test/test_framework.py +++ b/h2integrate/core/test/test_framework.py @@ -83,7 +83,7 @@ def test_custom_financial_model_grouping(subtests): tech_config_data = load_tech_yaml(temp_tech_config) # Modify the financial_model entry for one of the technologies - tech_config_data["technologies"]["steel"]["financial_model"]["group"] = "test_financial_group" + tech_config_data["technologies"]["steel"]["finance_model"]["group"] = "test_financial_group" tech_config_data["technologies"]["electrolyzer"].pop("financial_model", None) # Save the modified tech_config YAML back @@ -110,60 +110,6 @@ def test_custom_financial_model_grouping(subtests): temp_highlevel_yaml.unlink(missing_ok=True) -def test_get_included_technologies(): - # Create a mock model instance - model = H2IntegrateModel.__new__(H2IntegrateModel) - - # Test case 1: No specific technologies defined (should include all) - tech_config = { - "wind": {"performance_model": {"model": "test"}}, - "electrolyzer": {"performance_model": {"model": "test"}}, - "storage": {"performance_model": {"model": "test"}}, - } - plant_config = {"finance_parameters": {}} - - included_techs = model.get_included_technologies(tech_config, "hydrogen", plant_config) - expected = ["wind", "electrolyzer", "storage"] - assert set(included_techs) == set(expected), f"Expected {expected}, got {included_techs}" - - # Test case 2: Specific technologies defined for LCOH - plant_config_with_specific = { - "finance_parameters": { - "technologies_included_in_metrics": {"LCOH": ["electrolyzer", "wind"]} - } - } - - included_techs = model.get_included_technologies( - tech_config, "hydrogen", plant_config_with_specific - ) - expected = ["electrolyzer", "wind"] - assert set(included_techs) == set(expected), f"Expected {expected}, got {included_techs}" - - # Test case 3: Test different commodity type (electricity) - plant_config_with_lcoe = { - "finance_parameters": {"technologies_included_in_metrics": {"LCOE": ["wind"]}} - } - - included_techs = model.get_included_technologies( - tech_config, "electricity", plant_config_with_lcoe - ) - expected = ["wind"] - assert set(included_techs) == set(expected), f"Expected {expected}, got {included_techs}" - - # Test case 4: Invalid technology should raise error - plant_config_invalid = { - "finance_parameters": { - "technologies_included_in_metrics": {"LCOH": ["electrolyzer", "invalid_tech"]} - } - } - - try: - model.get_included_technologies(tech_config, "hydrogen", plant_config_invalid) - raise AssertionError("Should have raised ValueError for invalid technology") - except ValueError as e: - assert "invalid_tech" in str(e), f"Error message should mention invalid_tech: {e}" - - def test_unsupported_simulation_parameters(): orig_plant_config = EXAMPLE_DIR / "01_onshore_steel_mn" / "plant_config.yaml" temp_plant_config_ntimesteps = Path.cwd() / "temp_plant_config_ntimesteps.yaml" @@ -215,7 +161,7 @@ def test_technology_connections(): # Load the plant_config YAML content plant_config_data = load_plant_yaml(temp_plant_config) - new_connection = (["financials_group_default", "steel", ("LCOE", "electricity_cost")],) + new_connection = (["finance_subgroup_electricity", "steel", ("LCOE", "electricity_cost")],) new_tech_interconnections = ( plant_config_data["technology_interconnections"][0:4] + list(new_connection) diff --git a/h2integrate/finances/__init__.py b/h2integrate/finances/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/h2integrate/core/finances.py b/h2integrate/finances/finances.py similarity index 56% rename from h2integrate/core/finances.py rename to h2integrate/finances/finances.py index c64cf811f..0deef1ec4 100644 --- a/h2integrate/core/finances.py +++ b/h2integrate/finances/finances.py @@ -3,13 +3,40 @@ class AdjustedCapexOpexComp(om.ExplicitComponent): + """ + OpenMDAO component to adjust CapEx and OpEx values for multiple technologies to a target + dollar year using inflation. + + This component takes in capital expenditures (CapEx), operational expenditures (OpEx), + and their associated cost years for each technology, and adjusts them to a specified target + dollar year using a given inflation rate. The adjusted values are output for each technology, + along with the total adjusted CapEx and OpEx across all technologies. + + Attributes: + inflation_rate (float): The annual inflation rate used for cost adjustment. + target_dollar_year (int): The year to which all costs are adjusted. + + Inputs: + capex_{tech} (float, USD): Capital expenditure for each technology. + opex_{tech} (float, USD/year): Operational expenditure for each technology. + cost_year_{tech} (int): Dollar year for the costs of each technology. + + Outputs: + capex_adjusted_{tech} (float, USD): CapEx for each technology adjusted to the + target dollar year. + opex_adjusted_{tech} (float, USD/year): OpEx for each technology adjusted to the + target dollar year. + total_capex_adjusted (float, USD): Total adjusted CapEx across all technologies. + total_opex_adjusted (float, USD/year): Total adjusted OpEx across all technologies. + """ + def initialize(self): self.options.declare("driver_config", types=dict) - self.options.declare("tech_config", types=dict) + self.options.declare("tech_configs", types=dict) self.options.declare("plant_config", types=dict) def setup(self): - tech_config = self.options["tech_config"] + tech_configs = self.options["tech_configs"] plant_config = self.options["plant_config"] self.inflation_rate = plant_config["finance_parameters"]["cost_adjustment_parameters"][ "cost_year_adjustment_inflation" @@ -18,7 +45,7 @@ def setup(self): "target_dollar_year" ] - for tech in tech_config: + for tech in tech_configs: self.add_input(f"capex_{tech}", val=0.0, units="USD") self.add_input(f"opex_{tech}", val=0.0, units="USD/year") self.add_discrete_input(f"cost_year_{tech}", val=0, desc="Dollar year for costs") @@ -32,7 +59,7 @@ def setup(self): def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): total_capex_adjusted = 0.0 total_opex_adjusted = 0.0 - for tech in self.options["tech_config"]: + for tech in self.options["tech_configs"]: capex = float(inputs[f"capex_{tech}"][0]) opex = float(inputs[f"opex_{tech}"][0]) cost_year = int(discrete_inputs[f"cost_year_{tech}"]) diff --git a/h2integrate/core/profast_financial.py b/h2integrate/finances/profast_financial.py similarity index 87% rename from h2integrate/core/profast_financial.py rename to h2integrate/finances/profast_financial.py index 59c73b2ad..7608206e6 100644 --- a/h2integrate/core/profast_financial.py +++ b/h2integrate/finances/profast_financial.py @@ -14,7 +14,12 @@ ) from h2integrate.core.dict_utils import update_defaults from h2integrate.core.validators import gt_zero, contains, gte_zero, range_val -from h2integrate.tools.profast_tools import run_profast, create_and_populate_profast +from h2integrate.tools.profast_tools import ( + run_profast, + make_price_breakdown, + create_and_populate_profast, + format_profast_price_breakdown_per_year, +) from h2integrate.core.inputs.validation import write_yaml from h2integrate.tools.profast_reverse_tools import convert_pf_to_dict @@ -143,7 +148,7 @@ class BasicProFASTParameterConfig(BaseConfig): debt_interest_rate (float): interest rate on debt inflation_rate (float): escalation rate. Set to zero for a nominal analysis. cash_onhand_months (int): number of months with cash onhand. - admin_expense (float): adminstrative expense as a fraction of sales + admin_expense (float): administrative expense as a fraction of sales non_depr_assets (float, optional): cost (in `$`) of nondepreciable assets, such as land. Defaults to 0. end_of_proj_sale_non_depr_assets (float, optional): cost (in `$`) of nondepreciable assets @@ -212,7 +217,7 @@ class BasicProFASTParameterConfig(BaseConfig): default={ "name": None, "unit": None, - "inital price": 100, + "initial price": 100, "escalation": 0.0, } ) @@ -388,6 +393,13 @@ class ProFastComp(om.ExplicitComponent): of the commodity). For example, LCOH if commodity_type is "hydrogen". If commodity_type is "hydrogen", "ammonia", "nitrogen", or "co2", the units are USD/kg. If the commodity type is "electricity", the units are USD/kWh. + wacc_ (float): weighted average cost of capital as a fraction. + crf_ (float): capital recovery factor as a fraction. + irr_ (float): internal rate of return as a fraction. + profit_index_ (float): + investor_payback_period_ (float): time until initial investment costs are + recovered in years. + price_ (float): first year price of commodity in same units as `LCOx` Methods: initialize(): Declares component options. @@ -409,6 +421,7 @@ def initialize(self): self.options.declare("plant_config", types=dict) self.options.declare("tech_config", types=dict) self.options.declare("commodity_type", types=str) + self.options.declare("description", types=str, default="") def setup(self): if self.options["commodity_type"] == "electricity": @@ -418,8 +431,29 @@ def setup(self): commodity_units = "kg/year" lco_units = "USD/kg" - self.LCO_str = f"LCO{self.options['commodity_type'][0].upper()}" + LCO_base_str = f"LCO{self.options['commodity_type'][0].upper()}" + self.output_txt = self.options["commodity_type"].lower() + if self.options["description"] == "": + self.LCO_str = LCO_base_str + else: + desc_str = self.options["description"].strip().strip("_()-") + if desc_str == "": + self.LCO_str = LCO_base_str + else: + self.output_txt = f"{self.options['commodity_type'].lower()}_{desc_str}" + self.LCO_str = f"{LCO_base_str}_{desc_str}" + self.add_output(self.LCO_str, val=0.0, units=lco_units) + self.outputs_to_units = { + "wacc": "percent", + "crf": "percent", + "irr": "percent", + "profit_index": "unitless", + "investor_payback_period": "yr", + "price": lco_units, + } + for output_var, units in self.outputs_to_units.items(): + self.add_output(f"{output_var}_{self.output_txt}", val=0.0, units=units) if self.options["commodity_type"] == "co2": self.add_input("co2_capture_kgpy", val=0.0, units="kg/year") @@ -481,6 +515,9 @@ def compute(self, inputs, outputs): capacity = float(inputs[f"total_{self.options['commodity_type']}_produced"][0]) / 365.0 else: capacity = float(inputs["co2_capture_kgpy"]) / 365.0 + if capacity == 0.0: + raise ValueError("Capacity cannot be zero") + profast_params["capacity"] = capacity # TODO: update to actual daily capacity profast_params["long term utilization"] = 1 # TODO: update to capacity factor @@ -549,24 +586,46 @@ def compute(self, inputs, outputs): pf_dict["capital_items"] = capital_items pf_dict["fixed_costs"] = fixed_costs # create ProFAST object + pf = create_and_populate_profast(pf_dict) # simulate ProFAST sol, summary, price_breakdown = run_profast(pf) # Check whether to export profast object to .yaml file - if self.options["plant_config"]["finance_parameters"]["model_inputs"].get( - "save_profast_to_file", False - ): + save_results = self.options["plant_config"]["finance_parameters"]["model_inputs"].get( + "save_profast_results", False + ) + save_config = self.options["plant_config"]["finance_parameters"]["model_inputs"].get( + "save_profast_config", False + ) + if save_results or save_config: + pf_config_dict = convert_pf_to_dict(pf) + output_dir = self.options["driver_config"]["general"]["folder_output"] - fdesc = self.options["plant_config"]["finance_parameters"]["model_inputs"][ - "profast_output_description" - ] - fname = f"{fdesc}_{self.options['commodity_type']}.yaml" - fpath = Path(output_dir) / fname + fdesc = self.options["plant_config"]["finance_parameters"]["model_inputs"].get( + "profast_output_description", "ProFastComp" + ) + + fbasename = f"{fdesc}_{self.output_txt}" + output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) - d = convert_pf_to_dict(pf) - d = dict_to_yaml_formatting(d) - write_yaml(d, fpath) - - outputs[self.LCO_str] = sol["price"] # TODO: replace with sol['lco'] + if save_config: + pf_config_dict = dict_to_yaml_formatting(pf_config_dict) + config_fpath = Path(output_dir) / f"{fbasename}_config.yaml" + write_yaml(pf_config_dict, config_fpath) + if save_results: + lco_breakdown, lco_check = make_price_breakdown(price_breakdown, pf_config_dict) + price_breakdown_formatted = format_profast_price_breakdown_per_year(price_breakdown) + pf_breakdown_fpath = Path(output_dir) / f"{fbasename}_profast_price_breakdown.csv" + lco_breakdown_fpath = Path(output_dir) / f"{fbasename}_LCO_breakdown.yaml" + price_breakdown_formatted.to_csv(pf_breakdown_fpath) + lco_breakdown = dict_to_yaml_formatting(lco_breakdown) + write_yaml(lco_breakdown, lco_breakdown_fpath) + + outputs[self.LCO_str] = sol["lco"] + for output_var in self.outputs_to_units.keys(): + val = sol[output_var.replace("_", " ")] + if isinstance(val, (np.ndarray, list, tuple)): # only for IRR + val = val[-1] + outputs[f"{output_var}_{self.output_txt}"] = val diff --git a/h2integrate/simulation/technologies/iron/rosner_override/finance_model.py b/h2integrate/simulation/technologies/iron/rosner_override/finance_model.py index 1f46c44b2..1fb03b8d3 100644 --- a/h2integrate/simulation/technologies/iron/rosner_override/finance_model.py +++ b/h2integrate/simulation/technologies/iron/rosner_override/finance_model.py @@ -18,7 +18,7 @@ def main(config): Args: config (object): Configuration object containing: product_selection (str): The selected technology - (e.g., "ng_dri", "h2_dri","ng_eaf", "h2_eaf"). + (e.g., "ng_dri", "h2_dri", "ng_eaf", "h2_eaf"). performance (object): Contains plant performance data as a dataframe. cost (object): Contains cost data as a dataframe. params (dict): Key financial and operational parameters, including: diff --git a/h2integrate/tools/profast_tools.py b/h2integrate/tools/profast_tools.py index b462200f4..b62481a8d 100644 --- a/h2integrate/tools/profast_tools.py +++ b/h2integrate/tools/profast_tools.py @@ -1,4 +1,5 @@ import numpy as np +import pandas as pd import ProFAST @@ -115,7 +116,7 @@ def make_price_breakdown(price_breakdown, pf_config): price_breakdown_capex = {} price_breakdown_fixed_cost = {} full_price_breakdown = {} - lco_str = "LCO{}".format(pf_config["params"]["commodity"]["name"][0]) + lco_str = "LCO{}".format(pf_config["params"]["commodity"]["name"][0].upper()) lco_units = "$/{}".format(pf_config["params"]["commodity"]["unit"]) config_keys = list(pf_config.keys()) if "capital_items" in config_keys: @@ -219,3 +220,29 @@ def create_years_of_operation( ) year_keys = [f"{y}" for y in years_of_operation] return year_keys + + +def format_profast_price_breakdown_per_year(price_breakdown): + """ + Formats a price breakdown DataFrame to expand yearly amounts into separate columns. + + Args: + price_breakdown (pd.DataFrame): A DataFrame containing "Type", "Name", "Amount", and "NPV" + - "Amount" should be an array-like object per row, representing values for each year. + Returns: + pd.DataFrame: A formatted DataFrame with columns: + - "Type" + - "Name" + - "Year {i} Amount" for each year (e.g., "Year 0 Amount", "Year 1 Amount", ...) + - "NPV" + Each row corresponds to an entry in the input DataFrame, + with yearly amounts expanded into separate columns. + """ + n_years = len(price_breakdown.iloc[0]["Amount"]) + year_cols = [f"Year {i} Amount" for i in range(n_years)] + + amount_df = pd.DataFrame(np.array(price_breakdown["Amount"].to_list()), columns=year_cols) + formatted_df = pd.concat( + [price_breakdown[["Type", "Name"]], amount_df, price_breakdown["NPV"]], axis=1 + ) + return formatted_df diff --git a/tests/h2integrate/test_all_examples.py b/tests/h2integrate/test_all_examples.py index 07defb67a..a24256b29 100644 --- a/tests/h2integrate/test_all_examples.py +++ b/tests/h2integrate/test_all_examples.py @@ -24,7 +24,9 @@ def test_steel_example(subtests): # Subtests for checking specific values with subtests.test("Check LCOH"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOH")[0], rel=1e-3) + pytest.approx( + model.prob.get_val("finance_subgroup_hydrogen.LCOH_delivered")[0], rel=1e-3 + ) == 7.47944016 ) @@ -34,7 +36,7 @@ def test_steel_example(subtests): with subtests.test("Check total adjusted CapEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_capex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_capex_adjusted")[0], rel=1e-3 ) == 5.10869916e09 ) @@ -42,7 +44,7 @@ def test_steel_example(subtests): with subtests.test("Check total adjusted OpEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_opex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_opex_adjusted")[0], rel=1e-3 ) == 96349901.77625626 ) @@ -100,42 +102,42 @@ def test_simple_ammonia_example(subtests): with subtests.test("Check total adjusted CapEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_capex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_capex_adjusted")[0], rel=1e-3 ) - == 2678403968.6 + == 2577162708.3 ) with subtests.test("Check total adjusted OpEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_opex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_opex_adjusted")[0], rel=1e-3 ) - == 64338137.8 + == 53161706.5 ) # Currently underestimated compared to the Reference Design Doc with subtests.test("Check LCOH"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOH")[0], rel=1e-3) - == 4.233055 + pytest.approx(model.prob.get_val("finance_subgroup_hydrogen.LCOH")[0], rel=1e-3) + == 3.970 ) # Currently underestimated compared to the Reference Design Doc with subtests.test("Check LCOA"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOA")[0], rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_ammonia.LCOA")[0], rel=1e-3) == 1.02470046 ) # Check that the expected output files exist outputs_dir = Path.cwd() / "outputs" assert ( - outputs_dir / "profast_output_ammonia.yaml" + outputs_dir / "profast_output_ammonia_config.yaml" ).is_file(), "profast_output_ammonia.yaml not found" assert ( - outputs_dir / "profast_output_electricity.yaml" + outputs_dir / "profast_output_electricity_config.yaml" ).is_file(), "profast_output_electricity.yaml not found" assert ( - outputs_dir / "profast_output_hydrogen.yaml" + outputs_dir / "profast_output_hydrogen_config.yaml" ).is_file(), "profast_output_hydrogen.yaml not found" @@ -185,7 +187,7 @@ def test_ammonia_synloop_example(subtests): with subtests.test("Check total adjusted CapEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_capex_adjusted")[0], rel=1e-6 + model.prob.get_val("finance_subgroup_nh3.total_capex_adjusted")[0], rel=1e-6 ) == 3.7289e09 ) @@ -193,20 +195,20 @@ def test_ammonia_synloop_example(subtests): with subtests.test("Check total adjusted OpEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_opex_adjusted")[0], rel=1e-6 + model.prob.get_val("finance_subgroup_nh3.total_opex_adjusted")[0], rel=1e-6 ) == 78480154.4 ) with subtests.test("Check LCOH"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOH")[0], rel=1e-6) - == 5.659321302703965 + pytest.approx(model.prob.get_val("finance_subgroup_h2.LCOH")[0], rel=1e-6) + == 3.9705799098258776 ) with subtests.test("Check LCOA"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOA")[0], rel=1e-6) + pytest.approx(model.prob.get_val("finance_subgroup_nh3.LCOA")[0], rel=1e-6) == 1.067030996544544 ) @@ -242,7 +244,7 @@ def test_co2h_methanol_example(subtests): # Check levelized cost of methanol (LCOM) with subtests.test("Check CO2 Hydrogenation LCOM"): - assert pytest.approx(model.prob.get_val("methanol.LCOM"), rel=1e-6) == 1.38341179 + assert pytest.approx(model.prob.get_val("methanol.LCOM")[0], rel=1e-6) == 1.381162 def test_wind_h2_opt_example(subtests): @@ -272,8 +274,8 @@ def test_wind_h2_opt_example(subtests): with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE")[0], rel=1e-3) - == 0.151189 + pytest.approx(model.prob.get_val("finance_subgroup_electricity.LCOE")[0], rel=1e-3) + == 0.059311 ) with subtests.test("Check electrolyzer size"): @@ -300,8 +302,8 @@ def test_wind_h2_opt_example(subtests): assert len(cases) > 1, "Not enough cases recorded in SQL file." # Get initial and final LCOH values - initial_lcoh = cases[0].outputs["financials_group_default.LCOH"][0] - final_lcoh = cases[-1].outputs["financials_group_default.LCOH"][0] + initial_lcoh = cases[0].outputs["finance_subgroup_hydrogen.LCOH"][0] + final_lcoh = cases[-1].outputs["finance_subgroup_hydrogen.LCOH"][0] with subtests.test("Check LCOH changed"): assert final_lcoh != initial_lcoh @@ -309,14 +311,14 @@ def test_wind_h2_opt_example(subtests): with subtests.test("Check total adjusted CapEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_capex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_capex_adjusted")[0], rel=1e-3 ) == 2783126102 ) with subtests.test("Check total adjusted OpEx"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.total_opex_adjusted")[0], rel=1e-3 + model.prob.get_val("finance_subgroup_hydrogen.total_opex_adjusted")[0], rel=1e-3 ) == 75543899 ) @@ -345,12 +347,7 @@ def test_paper_example(subtests): # Subtests for checking specific values with subtests.test("Check LCOP"): - assert ( - pytest.approx( - model.prob.get_val("plant.paper_mill.paper_mill_financial.LCOP"), rel=1e-3 - ) - == 51.91476681 - ) + assert pytest.approx(model.prob.get_val("paper_mill.LCOP"), rel=1e-3) == 51.91476681 @unittest.skipUnless(importlib.util.find_spec("mcm") is not None, "mcm is not installed") @@ -369,14 +366,14 @@ def test_wind_wave_doc_example(subtests): # Subtests for checking specific values with subtests.test("Check LCOC"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOC")[0], rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_co2.LCOC")[0], rel=1e-3) == 2.26955589 ) with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE")[0], rel=1e-3) - == 1.05281478 + pytest.approx(model.prob.get_val("finance_subgroup_electricity.LCOE")[0], rel=1e-3) + == 0.330057 ) @@ -396,19 +393,19 @@ def test_splitter_wind_doc_h2_example(subtests): # Subtests for checking specific values with subtests.test("Check LCOH"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOH")[0], rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_hydrogen.LCOH")[0], rel=1e-3) == 10.25515911 ) with subtests.test("Check LCOC"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOC")[0], rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_co2.LCOC")[0], rel=1e-3) == 14.19802243 ) with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE")[0], rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_electricity.LCOE")[0], rel=1e-3) == 0.1385128 ) @@ -425,12 +422,12 @@ def test_hydro_example(subtests): model.post_process() - print(model.prob.get_val("financials_group_default.LCOE")) + print(model.prob.get_val("finance_subgroup_default.LCOE")) # Subtests for checking specific values with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE"), rel=1e-3) + pytest.approx(model.prob.get_val("finance_subgroup_default.LCOE"), rel=1e-3) == 0.17653979 ) @@ -449,7 +446,7 @@ def test_hybrid_energy_plant_example(subtests): # Subtests for checking specific values with subtests.test("Check LCOE"): - assert model.prob.get_val("financials_group_default.LCOE", units="USD/MW/h")[0] < 83.2123 + assert model.prob.get_val("finance_subgroup_default.LCOE", units="USD/MW/h")[0] < 83.2123 def test_asu_example(subtests): @@ -468,7 +465,7 @@ def test_asu_example(subtests): with subtests.test("Check LCON"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.LCON", units="USD/kg")[0], + model.prob.get_val("finance_subgroup_default.LCON", units="USD/kg")[0], abs=1e-4, ) == 0.309041977334972 @@ -489,7 +486,7 @@ def test_hydrogen_dispatch_example(subtests): with subtests.test("Check LCOE"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.LCOE", units="USD/MW/h")[0], + model.prob.get_val("finance_subgroup_elec.LCOE", units="USD/MW/h")[0], rel=1e-5, ) == 106.13987 @@ -498,7 +495,7 @@ def test_hydrogen_dispatch_example(subtests): with subtests.test("Check LCOH"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.LCOH", units="USD/kg")[0], + model.prob.get_val("finance_subgroup_h2.LCOH", units="USD/kg")[0], rel=1e-5, ) == 5.68452215 @@ -522,16 +519,17 @@ def test_wind_wave_oae_example(subtests): # Note: These are placeholder values. Update with actual values after running the test # when MCM package is properly installed and configured with subtests.test("Check LCOC"): - assert pytest.approx(model.prob.get_val("financials_group_default.LCOC"), rel=1e-3) == 37.82 + assert pytest.approx(model.prob.get_val("finance_subgroup_co2.LCOC"), rel=1e-3) == 37.82 with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE"), rel=1e-3) == 0.36956 + pytest.approx(model.prob.get_val("finance_subgroup_electricity.LCOE"), rel=1e-3) + == 0.367 ) @unittest.skipUnless(importlib.util.find_spec("mcm") is not None, "mcm is not installed") -def test_wind_wave_oae_example_with_financials(subtests): +def test_wind_wave_oae_example_with_finance(subtests): # Change the current working directory to the example's directory os.chdir(EXAMPLE_DIR / "09_co2/ocean_alkalinity_enhancement_financials") @@ -548,7 +546,8 @@ def test_wind_wave_oae_example_with_financials(subtests): # when MCM package is properly installed and configured with subtests.test("Check LCOE"): assert ( - pytest.approx(model.prob.get_val("financials_group_default.LCOE"), rel=1e-3) == 0.09180 + pytest.approx(model.prob.get_val("finance_subgroup_electricity.LCOE"), rel=1e-3) + == 0.09180 ) with subtests.test("Check Carbon Credit"): @@ -580,38 +579,38 @@ def test_natural_gas_example(subtests): with subtests.test("Check total electricity produced"): total_electricity = model.prob.get_val( - "financials_group_default.electricity_sum.total_electricity_produced" + "finance_subgroup_default.electricity_sum.total_electricity_produced" )[0] assert pytest.approx(total_electricity, rel=1e-6) == 1.168e8 with subtests.test("Check opex adjusted ng_feedstock"): opex_ng_feedstock = model.prob.get_val( - "financials_group_default.opex_adjusted_ng_feedstock" + "finance_subgroup_default.opex_adjusted_ng_feedstock" )[0] assert pytest.approx(opex_ng_feedstock, rel=1e-6) == 3589463.41463415 with subtests.test("Check capex adjusted natural_gas_plant"): capex_ng_plant = model.prob.get_val( - "financials_group_default.capex_adjusted_natural_gas_plant" + "finance_subgroup_default.capex_adjusted_natural_gas_plant" )[0] assert pytest.approx(capex_ng_plant, rel=1e-6) == 97560975.60975611 with subtests.test("Check opex adjusted natural_gas_plant"): opex_ng_plant = model.prob.get_val( - "financials_group_default.opex_adjusted_natural_gas_plant" + "finance_subgroup_default.opex_adjusted_natural_gas_plant" )[0] assert pytest.approx(opex_ng_plant, rel=1e-6) == 1260487.80487805 with subtests.test("Check total adjusted CapEx"): - total_capex = model.prob.get_val("financials_group_default.total_capex_adjusted")[0] + total_capex = model.prob.get_val("finance_subgroup_default.total_capex_adjusted")[0] assert pytest.approx(total_capex, rel=1e-6) == 97658536.58536586 with subtests.test("Check total adjusted OpEx"): - total_opex = model.prob.get_val("financials_group_default.total_opex_adjusted")[0] + total_opex = model.prob.get_val("finance_subgroup_default.total_opex_adjusted")[0] assert pytest.approx(total_opex, rel=1e-6) == 4849951.2195122 with subtests.test("Check LCOE"): - lcoe = model.prob.get_val("financials_group_default.LCOE")[0] + lcoe = model.prob.get_val("finance_subgroup_default.LCOE")[0] assert pytest.approx(lcoe, rel=1e-6) == 0.12959097 # Test feedstock-specific values @@ -652,7 +651,7 @@ def test_wind_solar_electrolyzer_example(subtests): with subtests.test("Check LCOE"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.LCOE", units="USD/MW/h")[0], + model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/MW/h")[0], rel=1e-5, ) == 54.12889 @@ -661,7 +660,7 @@ def test_wind_solar_electrolyzer_example(subtests): with subtests.test("Check LCOH"): assert ( pytest.approx( - model.prob.get_val("financials_group_default.LCOH", units="USD/kg")[0], + model.prob.get_val("finance_subgroup_hydrogen.LCOH", units="USD/kg")[0], rel=1e-5, ) == 5.33209234 @@ -678,3 +677,27 @@ def test_wind_solar_electrolyzer_example(subtests): ) with subtests.test("Check electrolyzer input power"): assert pytest.approx(total_generation.sum(), rel=1e-5) == total_energy_to_electrolyzer.sum() + + +def test_electrolyzer_om_example(subtests): + # Change the current working directory to the example's directory + os.chdir(EXAMPLE_DIR / "10_electrolyzer_om") + + # Create a H2Integrate model + model = H2IntegrateModel(Path.cwd() / "electrolyzer_om.yaml") + + model.run() + + lcoe = model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/MW/h")[0] + lcoh_with_lcoh_finance = model.prob.get_val( + "finance_subgroup_hydrogen.LCOH_lcoh_financials", units="USD/kg" + )[0] + lcoh_with_lcoe_finance = model.prob.get_val( + "finance_subgroup_hydrogen.LCOH_lcoe_financials", units="USD/kg" + )[0] + with subtests.test("Check LCOE"): + assert pytest.approx(lcoe, rel=1e-5) == 40.12819 + with subtests.test("Check LCOH with lcoh_financials"): + assert pytest.approx(lcoh_with_lcoh_finance, rel=1e-5) == 13.18328175 + with subtests.test("Check LCOH with lcoe_financials"): + assert pytest.approx(lcoh_with_lcoe_finance, rel=1e-5) == 8.05688467 diff --git a/tests/h2integrate/test_hydrogen/test_geologic_h2.py b/tests/h2integrate/test_hydrogen/test_geologic_h2.py index 6889423e3..3a06ed2db 100644 --- a/tests/h2integrate/test_hydrogen/test_geologic_h2.py +++ b/tests/h2integrate/test_hydrogen/test_geologic_h2.py @@ -17,7 +17,7 @@ def test_natural_geoh2(subtests): h2_prod = h2i_nat.plant.geoh2.natural_geoh2_performance.get_val("hydrogen_out") assert np.mean(h2_prod) == approx(48.94393478, 1e-6) with subtests.test("LCOH"): - lcoh = h2i_nat.plant.geoh2.geoh2_financial.get_val("LCOH") + lcoh = h2i_nat.plant.geoh2.geoh2_finance.get_val("LCOH") assert lcoh == approx(3.14353262, 1e-6) @@ -29,5 +29,5 @@ def test_stimulated_geoh2(subtests): h2_prod = h2i_stim.plant.geoh2.stimulated_geoh2_performance.get_val("hydrogen_out") assert np.mean(h2_prod) == approx(108.49331847, 1e-6) with subtests.test("LCOH"): - lcoh = h2i_stim.plant.geoh2.geoh2_financial.get_val("LCOH") + lcoh = h2i_stim.plant.geoh2.geoh2_finance.get_val("LCOH") assert lcoh == approx(1.8666849, 1e-6)