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
10 changes: 6 additions & 4 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ parts:
- file: technology_models/iron_mine.md
- file: technology_models/iron_dri.md
- file: technology_models/steel_eaf.md
- file: technology_models/storage_models_index.md
- caption: Storage Models
chapters:
- file: storage/storage_models_index.md
sections:
- file: technology_models/simple_generic_storage.md
- file: technology_models/pysam_battery.md
- file: technology_models/hydrogen_storage.md
- file: storage/simple_generic_storage.md
- file: storage/pysam_battery.md
- file: storage/hydrogen_storage.md
- caption: Resource Models
chapters:
- file: resource/resource_index
Expand Down
2 changes: 1 addition & 1 deletion docs/control/control_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ The second systematic control approach, [pyomo control](#pyomo-control), allows
In the pyomo control framework in H2Integrate, each technology can have control rules associated with them that are in turn passed to the pyomo control component, which is owned by the storage technology. The pyomo control component combines the technology rules into a single pyomo model, which is then passed to the storage technology performance model inside a callable dispatch function. The dispatch function also accepts a simulation method from the performance model and iterates between the pyomo model for dispatch commands and the performance simulation function to simulated performance with the specified commands. The dispatch function runs in specified time windows for dispatch and performance until the whole simulation time has been run.

Supported controllers:
- [`HeuristicLoadFollowingController`](#heuristic-load-following-controller)
- [`HeuristicLoadFollowingStorageController`](#heuristic-load-following-controller)
8 changes: 4 additions & 4 deletions docs/control/pyomo_controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ The Pyomo control framework currently supports both a simple heuristic method an
(heuristic-load-following-controller)=
## Heuristic Load Following Controller

The simple heuristic method is specified by setting the storage control to `HeuristicLoadFollowingController`. When using the Pyomo framework, a `dispatch_rule_set` for each technology connected to the storage technology must also be specified. These will typically be `PyomoDispatchGenericConverter` for generating technologies, and `PyomoRuleStorageBaseclass` for storage technologies. More complex rule sets may be developed as needed.
The simple heuristic method is specified by setting the storage control to `HeuristicLoadFollowingStorageController`. When using the Pyomo framework, a `dispatch_rule_set` for each technology connected to the storage technology must also be specified. These will typically be `PyomoDispatchGenericConverter` for generating technologies, and `PyomoRuleStorageBaseclass` for storage technologies. More complex rule sets may be developed as needed.

For an example of how to use the heuristic Pyomo control framework with the `HeuristicLoadFollowingController`, see
For an example of how to use the heuristic Pyomo control framework with the `HeuristicLoadFollowingStorageController`, see
- `examples/18_pyomo_heuristic_wind_battery_dispatch`


(optimized-load-following-controller)=
## Optimized Load Following Controller
The optimized dispatch method is specified by setting the storage control to `OptimizedDispatchController`. Unlike the heuristic method, the optimized dispatch method does not use `dispatch_rule_set` as an input in the `tech_config`. The `OptimizedDispatchController` method maximizes the load met while minimizing the cost of the system (operating cost) over each specified time window.
The optimized dispatch method is specified by setting the storage control to `OptimizedDispatchStorageController`. Unlike the heuristic method, the optimized dispatch method does not use `dispatch_rule_set` as an input in the `tech_config`. The `OptimizedDispatchStorageController` method maximizes the load met while minimizing the cost of the system (operating cost) over each specified time window.

The optimized dispatch using Pyomo is implemented differently than the heuristic dispatch in order to be able to properly aggregate the individual Pyomo technology models into a cohesive Pyomo plant model for the optimization solver. Practically, this means that the Pyomo elements of the dispatch (including the individual technology models and the plant model) are not exposed to the main H2I code flow, and do not appear in the N2 diagram. The figure below shows a flow diagram of how the dispatch is implemented. The green blocks below represent what is represented in the N2 diagram of the system. The dispatch routine is currently self-contained within the storage technology of the system, though it includes solving an aggregated plant model in the optimization

Expand All @@ -40,7 +40,7 @@ We have exposed the optimization cost (weighting) values to the user in this imp
- The cost values are defined in units of "$/kW".
```

For an example of how to use the optimized Pyomo control framework with the `OptimizedDispatchController`, see
For an example of how to use the optimized Pyomo control framework with the `OptimizedDispatchStorageController`, see
- `examples/27_pyomo_optimized_dispatch`


Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ The results that are output per-year of the `plant_life` are:
- `annual_commodity_produced`: each value is the `total_commodity_produced` scaled to a 1-year (8760 hours) simulation. This value may be negative if the storage charges more than discharges.
- `capacity_factor`: the storage capacity factor calculated as capacity factors are calculated in converter technologies, a ratio of the sum of *`total_commodity_produced`* to the discharge rate (or `rated_commodity_production`). This value may be negative if the storage charges more than discharges.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
- `capacity_factor`: the storage capacity factor calculated as capacity factors are calculated in converter technologies, a ratio of the sum of *`total_commodity_produced`* to the discharge rate (or `rated_commodity_production`). This value may be negative if the storage charges more than discharges.
- `capacity_factor`: the storage capacity factor which is calculated in the same way that capacity factors are calculated in converter technologies, which is a ratio of the sum of *`total_commodity_produced`* to the discharge rate (or `rated_commodity_production`). This value may be negative if the storage charges more than discharges.

$
CF = \frac{\sum_{t=0}^{n_{\text{timesteps}}}(\text{commodity\_out}_t*dt)}{\text{discharge\_rate}*n_{\text{timesteps}}*dt}
CF = \frac{\sum_{t=0}^{n_{\text{timesteps}}}(\text{commodity_out}_t*dt)}{\text{\text{discharge}\_\text{rate}*n_{\text{timesteps}}*dt}
$
- `standard_capacity_factor`: the storage capacity factor as defined by the [NLR ATB](https://atb.nrel.gov/electricity/2024b/utility-scale_battery_storage). The ratio of the total *commodity discharged* to the discharge rate (or `rated_commodity_production`). This value will always be greater than or equal to zero.
$
CF_{\text{standard}} = \frac{\sum_{t=0}^{n_{\text{timesteps}}}(\text{storage\_commodity\_discharge}_t*dt)}{\text{discharge\_rate}*n_{\text{timesteps}}*dt}
CF_{\text{standard}} = \frac{\sum_{t=0}^{n_{\text{timesteps}}}(\text{storage_commodity_discharge}_t*dt)}{\text{discharge_rate}*n_{\text{timesteps}}*dt}
$


Expand Down
4 changes: 2 additions & 2 deletions docs/user_guide/model_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,9 @@ Below summarizes the available performance, cost, and financial models for each
- Storage Controllers:
- `'SimpleStorageOpenLoopController'`: open-loop control; manages resource flow based on demand and input commodity
- `'DemandOpenLoopStorageController'`: open-loop control; manages resource flow based on demand and storage constraints
- `'HeuristicLoadFollowingController'`: open-loop control that works on a time window basis to set dispatch commands; uses Pyomo
- `'HeuristicLoadFollowingStorageController'`: open-loop control that works on a time window basis to set dispatch commands; uses Pyomo
- Optimized Dispatch:
- `'OptimizedDispatchController'`: optimization-based dispatch using Pyomo
- `'OptimizedDispatchStorageController'`: optimization-based dispatch using Pyomo

(demand-models)=
## Demand Models
Expand Down
2 changes: 1 addition & 1 deletion examples/01_onshore_steel_mn/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
2 changes: 1 addition & 1 deletion examples/02_texas_ammonia/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
2 changes: 1 addition & 1 deletion examples/09_co2/direct_ocean_capture/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
2 changes: 1 addition & 1 deletion examples/12_ammonia_synloop/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
2 changes: 1 addition & 1 deletion examples/18_pyomo_heuristic_dispatch/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ technologies:
dispatch_rule_set:
model: PyomoRuleStorageBaseclass
control_strategy:
model: HeuristicLoadFollowingController
model: HeuristicLoadFollowingStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
2 changes: 1 addition & 1 deletion examples/30_pyomo_optimized_dispatch/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ technologies:
commodity_rate_units: kW
battery:
control_strategy:
model: OptimizedDispatchController
model: OptimizedDispatchStorageController
performance_model:
model: PySAMBatteryPerformanceModel
cost_model:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def dispatch_block_rule_function(self, pyomo_model: pyo.ConcreteModel):
This method sets up all model elements (parameters, variables, constraints,
and ports) associated with a technology block within the dispatch model.
It is typically called in the setup_pyomo() method of the PyomoControllerBaseClass.
It is typically called in the setup_pyomo() method of the PyomoStorageControllerBaseClass.
Args:
pyomo_model (pyo.ConcreteModel): The Pyomo model to which the technology
Expand Down
2 changes: 1 addition & 1 deletion h2integrate/control/control_rules/pyomo_rule_baseclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def dispatch_block_rule_function(self, pyomo_model: pyo.ConcreteModel, tech_name
This method sets up all model elements (parameters, variables, constraints,
and ports) associated with a technology block within the dispatch model.
It is typically called in the setup_pyomo() method of the PyomoControllerBaseClass.
It is typically called in the setup_pyomo() method of the PyomoStorageControllerBaseClass.
Args:
pyomo_model (pyo.ConcreteModel): The Pyomo model to which the technology
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


@define(kw_only=True)
class PyomoControllerBaseConfig(BaseConfig):
class PyomoStorageControllerBaseConfig(BaseConfig):
"""
Configuration data container for Pyomo-based storage / dispatch controllers.

Expand Down Expand Up @@ -74,7 +74,7 @@ def __attrs_post_init__(self):
] * self.n_control_window


class PyomoControllerBaseClass(om.ExplicitComponent):
class PyomoStorageControllerBaseClass(om.ExplicitComponent):
_time_step_bounds = (
3600,
3600,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

from h2integrate.core.utilities import merge_shared_inputs
from h2integrate.core.validators import range_val_or_none
from h2integrate.control.control_strategies.pyomo_controller_baseclass import (
PyomoControllerBaseClass,
PyomoControllerBaseConfig,
from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import (
PyomoStorageControllerBaseClass,
PyomoStorageControllerBaseConfig,
)


Expand All @@ -17,8 +17,8 @@


@define(kw_only=True)
class HeuristicLoadFollowingControllerConfig(PyomoControllerBaseConfig):
"""Configuration class for the HeuristicLoadFollowingController.
class HeuristicLoadFollowingStorageControllerConfig(PyomoStorageControllerBaseConfig):
"""Configuration class for the HeuristicLoadFollowingStorageController.

Attributes:
charge_efficiency (float | None, optional): Efficiency of charging the storage, represented
Expand Down Expand Up @@ -61,7 +61,7 @@ def __attrs_post_init__(self):
self.discharge_efficiency = np.sqrt(self.round_trip_efficiency)


class HeuristicLoadFollowingController(PyomoControllerBaseClass):
class HeuristicLoadFollowingStorageController(PyomoStorageControllerBaseClass):
"""Operates storage based on heuristic rules to meet the demand profile based on
available commodity from generation profiles and demand profile.

Expand All @@ -77,7 +77,7 @@ class HeuristicLoadFollowingController(PyomoControllerBaseClass):

def setup(self):
"""Initialize the heuristic load-following controller."""
self.config = HeuristicLoadFollowingControllerConfig.from_dict(
self.config = HeuristicLoadFollowingStorageControllerConfig.from_dict(
merge_shared_inputs(self.options["tech_config"]["model_inputs"], "control"),
additional_cls_name=self.__class__.__name__,
strict=False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
from h2integrate.core.utilities import merge_shared_inputs
from h2integrate.core.validators import range_val
from h2integrate.control.control_rules.plant_dispatch_model import PyomoDispatchPlantModel
from h2integrate.control.control_strategies.pyomo_controller_baseclass import (
from h2integrate.control.control_strategies.controller_opt_problem_state import DispatchProblemState
from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import (
SolverOptions,
PyomoControllerBaseClass,
PyomoControllerBaseConfig,
PyomoStorageControllerBaseClass,
PyomoStorageControllerBaseConfig,
)
from h2integrate.control.control_strategies.controller_opt_problem_state import DispatchProblemState
from h2integrate.control.control_rules.storage.pyomo_storage_rule_min_operating_cost import (
PyomoRuleStorageMinOperatingCosts,
)
Expand All @@ -27,7 +27,7 @@


@define
class OptimizedDispatchControllerConfig(PyomoControllerBaseConfig):
class OptimizedDispatchStorageControllerConfig(PyomoStorageControllerBaseConfig):
"""
Configuration data container for Pyomo-based optimal dispatch.

Expand Down Expand Up @@ -92,7 +92,7 @@ def make_dispatch_inputs(self):
return dispatch_inputs


class OptimizedDispatchController(PyomoControllerBaseClass):
class OptimizedDispatchStorageController(PyomoStorageControllerBaseClass):
"""Operates storage based on optimization to meet the demand profile based on
available commodity from generation profiles and demand profile while minimizing costs.

Expand All @@ -107,7 +107,7 @@ class OptimizedDispatchController(PyomoControllerBaseClass):

def setup(self):
"""Initialize the optimized dispatch controller."""
self.config = OptimizedDispatchControllerConfig.from_dict(
self.config = OptimizedDispatchStorageControllerConfig.from_dict(
merge_shared_inputs(self.options["tech_config"]["model_inputs"], "control")
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from h2integrate.storage.battery.pysam_battery import PySAMBatteryPerformanceModel
from h2integrate.storage.storage_performance_model import StoragePerformanceModel
from h2integrate.storage.simple_storage_auto_sizing import StorageAutoSizingModel
from h2integrate.control.control_strategies.heuristic_pyomo_controller import (
HeuristicLoadFollowingController,
)
from h2integrate.control.control_rules.storage.pyomo_storage_rule_baseclass import (
PyomoRuleStorageBaseclass,
)
from h2integrate.control.control_strategies.storage.heuristic_pyomo_controller import (
HeuristicLoadFollowingStorageController,
)


@fixture
Expand Down Expand Up @@ -39,7 +39,7 @@ def tech_config_battery():
"technologies": {
"battery": {
"dispatch_rule_set": {"model": "PyomoRuleStorageBaseclass"},
"control_strategy": {"model": "HeuristicLoadFollowingController"},
"control_strategy": {"model": "HeuristicLoadFollowingStorageController"},
"performance_model": {"model": "PySAMBatteryPerformanceModel"},
"model_inputs": {
"shared_parameters": {
Expand Down Expand Up @@ -97,7 +97,7 @@ def tech_config_generic():
"technologies": {
"h2_storage": {
"dispatch_rule_set": {"model": "PyomoRuleStorageBaseclass"},
"control_strategy": {"model": "HeuristicLoadFollowingController"},
"control_strategy": {"model": "HeuristicLoadFollowingStorageController"},
"performance_model": {"model": "StoragePerformanceModel"},
"model_inputs": {
"shared_parameters": {
Expand Down Expand Up @@ -134,7 +134,7 @@ def tech_config_autosizing():
"technologies": {
"h2_storage": {
"dispatch_rule_set": {"model": "PyomoRuleStorageBaseclass"},
"control_strategy": {"model": "HeuristicLoadFollowingController"},
"control_strategy": {"model": "HeuristicLoadFollowingStorageController"},
"performance_model": {"model": "StorageAutoSizingModel"},
"model_inputs": {
"shared_parameters": {
Expand Down Expand Up @@ -204,7 +204,7 @@ def test_heuristic_load_following_battery_dispatch(

prob.model.add_subsystem(
"battery_heuristic_load_following_controller",
HeuristicLoadFollowingController(
HeuristicLoadFollowingStorageController(
plant_config=plant_config_battery,
tech_config=tech_config_battery["technologies"]["battery"],
),
Expand Down Expand Up @@ -563,7 +563,7 @@ def test_heuristic_load_following_battery_dispatch_change_capacities(

prob.model.add_subsystem(
"battery_heuristic_load_following_controller",
HeuristicLoadFollowingController(
HeuristicLoadFollowingStorageController(
plant_config=plant_config_battery,
tech_config=tech_config_battery["technologies"]["battery"],
),
Expand Down Expand Up @@ -787,7 +787,7 @@ def test_heuristic_load_following_dispatch_with_generic_storage(

prob.model.add_subsystem(
"h2_storage_heuristic_load_following_controller",
HeuristicLoadFollowingController(
HeuristicLoadFollowingStorageController(
plant_config=plant_config_h2_storage,
tech_config=tech_config_generic["technologies"]["h2_storage"],
),
Expand Down Expand Up @@ -935,7 +935,7 @@ def test_heuristic_dispatch_with_autosizing_storage_demand_less_than_avg_in(

prob.model.add_subsystem(
"h2_storage_controller",
HeuristicLoadFollowingController(
HeuristicLoadFollowingStorageController(
plant_config=plant_config_h2_storage,
tech_config=tech_config_autosizing["technologies"]["h2_storage"],
),
Expand Down Expand Up @@ -1021,7 +1021,7 @@ def test_heuristic_dispatch_with_autosizing_storage_demand_is_avg_in(

prob.model.add_subsystem(
"h2_storage_controller",
HeuristicLoadFollowingController(
HeuristicLoadFollowingStorageController(
plant_config=plant_config_h2_storage,
tech_config=tech_config_autosizing["technologies"]["h2_storage"],
),
Expand Down
Loading
Loading