-
Notifications
You must be signed in to change notification settings - Fork 27
Description
some cost models won't be accurate in capacity optimizations to minimize some cost or financial value (I think)
Many of the cost models in H2I calculate CapEx and OpEx for a component based on its capacity and some input or calculated costs in $/capacity unit. I'll use the electrolyzer as an example:
- performance model:
ECOElectrolyzerPerformanceModelinh2integrate/converters/hydrogen/eco_tools_pem_electrolyzer.py - cost model:
SingliticoCostModelinh2integrate/converters/hydrogen/singlitico_cost_model.py
Suppose we want to optimize the electrolyzer capacity to meet some annual hydrogen demand and minimize LCOH.
ECOElectrolyzerPerformanceModel has the electrolyzer_size_mw as an input, initialized to the rating value provided in the config. SingliticoCostModel does not have electrolyzer_size_mw as an input and only uses the value provided in the config. My understanding is that if we are trying to optimize the electrolyzer capacity, then the performance model will see that capacity change (because the electrolyzer capacity is an input) but the cost model won't (because it'll always be using the same value that's in the config). This means the following situation is possible:
- in the config, the electrolyzer rating is 100 MW
- the optimizer runs an electrolyzer with a rating of 50 MW
- the performance model runs an electrolyzer rated at 50 MW
- the cost model outputs the same cost as the 100 MW system, even though the optimizer is running a 50 MW system.
- The capital cost and fixed maintenance cost of the electrolyzer never changes as the electrolyzer capacity is varied in the optimizer. The only thing that changes is the electrolyzer hydrogen production.
Proposed solution
Access the component capacity needed for capex and opex calculations within cost models from inputs rather than the config. Or - begin to include component capacity as as input in cost model base classes (if that ever makes sense). Here's an example of what I propose all cost models look like:
class myExampleCostModel(ExampleCostBaseClass):
def setup(self):
super().setup()
self.config = ExampleCostModelConfig.from_dict(
merge_shared_inputs(self.options["tech_config"]["model_inputs"], "cost")
)
self.add_input(
"example_capacity",
val=self.config.example_capacity_kW,
units="kW",
desc="example component rated capacity in kW",
)
def compute(self, inputs, outputs):
capacity = inputs['example_capacity'][0]
capex = self.config.capex_per_kW*capacity
opex = self.config.opex_per_kW_per_year*capacity
outputs["CapEx"] = capex
outputs["OpEx"] = opex