Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion h2integrate/core/supported_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from h2integrate.converters.hydrogen.wombat_model import WOMBATElectrolyzerModel
from h2integrate.converters.wind.wind_plant_pysam import PYSAMWindPlantPerformanceModel
from h2integrate.storage.battery.atb_battery_cost import ATBBatteryCostModel
from h2integrate.transporters.electricity_combiner import CombinerPerformanceModel
from h2integrate.transporters.electricity_splitter import SplitterPerformanceModel
from h2integrate.converters.ammonia.ammonia_synloop import (
Expand All @@ -34,6 +35,7 @@
from h2integrate.converters.solar.atb_res_com_pv_cost import ATBResComPVCostModel
from h2integrate.converters.solar.atb_utility_pv_cost import ATBUtilityPVCostModel
from h2integrate.control.control_rules.converters.wind import PyomoDispatchWind
from h2integrate.control.control_rules.storage.battery import PyomoDispatchBattery
from h2integrate.converters.methanol.smr_methanol_plant import (
SMRMethanolPlantCostModel,
SMRMethanolPlantFinanceModel,
Expand All @@ -49,7 +51,6 @@
CO2HMethanolPlantPerformanceModel,
)
from h2integrate.control.control_rules.storage.h2_storage import PyomoDispatchH2Storage
from h2integrate.control.control_rules.storage.battery import PyomoDispatchBattery
from h2integrate.converters.natural_gas.natural_gas_cc_ct import (
NaturalGasCostModel,
NaturalGasPerformanceModel,
Expand Down Expand Up @@ -151,6 +152,7 @@
"h2_storage": H2Storage,
"hydrogen_tank_performance": HydrogenTankPerformanceModel,
"hydrogen_tank_cost": HydrogenTankCostModel,
"atb_battery_cost": ATBBatteryCostModel,
# Control
"pass_through_controller": PassThroughOpenLoopController,
"demand_open_loop_controller": DemandOpenLoopController,
Expand Down
68 changes: 68 additions & 0 deletions h2integrate/storage/battery/atb_battery_cost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from attrs import field, define

from h2integrate.core.utilities import CostModelBaseConfig, merge_shared_inputs
from h2integrate.core.validators import gt_zero, range_val
from h2integrate.core.model_baseclasses import CostModelBaseClass


@define
class ATBBatteryCostConfig(CostModelBaseConfig):
"""Configuration class for the ATBBatteryCostModel with costs based on storage
capacity and charge rate. More information on ATB methodology and representative
battery technologies can be found
`here <https://atb.nrel.gov/electricity/2024/utility-scale_battery_storage>`_
Reference cost values can be found on the `Utility-Scale Battery Storage`,
`Commercial Battery Storage`, and `Residential Battery Storage` sheets of the
`NREL ATB workbook <https://atb.nrel.gov/electricity/2024/data>`_.

Attributes:
energy_capex (float|int): battery energy capital cost in $/kWh
power_capex (float|int): battery power capital cost in $/kW
opex_fraction (float): annual operating cost as a fraction of the total system cost.
cost_year (int): dollar year corresponding to input costs
"""

energy_capex: float | int = field(validator=gt_zero)
power_capex: float | int = field(validator=gt_zero)
opex_fraction: float = field(validator=range_val(0, 1))


class ATBBatteryCostModel(CostModelBaseClass):
"""This cost model is based on the equations in the "Utility-Scale Battery Storage"
sheet in the ATB 2024 workbook.

- Cell E29 has the equation for CapEx. Also found in the cells for the CapEx section.
- Cell G121 (all the cells in the Fixed Operation and Maintenance Expenses
section) include the equation to calculate fixed o&m costs.

Total_CapEx = Energy_CapEx * Storage_Hours + Power_CapEx

- Total_CapEx: Total System Cost (USD/kW)
- Storage_Hours: Storage Duration (hr)
- Energy_CapEx: Battery Energy Cost (USD/kWh)
- Power_CapEx: Battery Power Cost (USD/kW)

"""

def setup(self):
self.config = ATBBatteryCostConfig.from_dict(
merge_shared_inputs(self.options["tech_config"]["model_inputs"], "cost")
)

super().setup()

self.add_input("charge_rate", val=0.0, units="kW", desc="Battery charge/discharge rate")
self.add_input("storage_capacity", val=0.0, units="kW*h", desc="Battery storage capacity")

def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
storage_duration_hrs = inputs["storage_capacity"][0] / inputs["charge_rate"][0]

# CapEx equation from Cell E29
total_system_cost = (
storage_duration_hrs * self.config.energy_capex
) + self.config.power_capex
capex = total_system_cost * inputs["charge_rate"][0]
# OpEx equation from cells in the Fixed Operation and Maintenance Expenses section
opex = self.config.opex_fraction * capex
outputs["CapEx"] = capex
outputs["OpEx"] = opex

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not confident on the math here for lines 44-50. I also think total_system_cost is confusing when we use that to calculate capex. Can you include the reference in the ATB for the cell where the equation(s) is(are) you are using?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Loading