Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7d61a1c
add draft for variable timestep framework
jaredthomas68 Apr 3, 2026
3d44da6
Merge branch 'develop' into variabledt
jaredthomas68 Apr 7, 2026
c36dfb8
Changed error wording
johnjasa Apr 9, 2026
852bc7f
Merge branch 'develop' into variabledt
johnjasa Apr 9, 2026
f4b1fc8
Merge branch 'develop' into variabledt
jaredthomas68 Apr 10, 2026
352ed79
Merge remote-tracking branch 'myfork/variabledt' into variabledt
jaredthomas68 Apr 10, 2026
0774f31
switch bounds to tuple
jaredthomas68 Apr 10, 2026
1adab8c
minor test correction
jaredthomas68 Apr 10, 2026
c74968e
include time-series generation functions
jaredthomas68 Apr 10, 2026
935ef26
add tests for variable dt and update simulation length check for non-…
jaredthomas68 Apr 10, 2026
58ebc70
Merge branch 'develop' into variabledt
jaredthomas68 Apr 10, 2026
82e8bff
update docs
jaredthomas68 Apr 10, 2026
ee2a46f
update changelog
jaredthomas68 Apr 10, 2026
b9dc167
update docs and doc strings
jaredthomas68 Apr 10, 2026
e866dd6
restore develop version of utilities.py
jaredthomas68 Apr 10, 2026
9eeec64
update dt bounds error
jaredthomas68 Apr 11, 2026
f4e8701
Merge branch 'develop' into variabledt
johnjasa Apr 11, 2026
d358b92
Merge branch 'develop' into variabledt
kbrunik Apr 11, 2026
edd178b
Apply suggestions from code review
johnjasa Apr 11, 2026
ac3ddcc
Fixing tests
johnjasa Apr 11, 2026
7334507
Adding time step bounds to all models
johnjasa Apr 11, 2026
22b6cf7
Adding time step bounds to the combiner/splitter/transporters
johnjasa Apr 11, 2026
4b50db0
Updates for tests
johnjasa Apr 11, 2026
467caea
Adding time step bounds to the custom paper mill performance model
johnjasa Apr 11, 2026
5bc9b5e
Added time step bounds to paper mill cost
johnjasa Apr 11, 2026
13332ac
update transporters and feedstocks with time step bounds
jaredthomas68 Apr 13, 2026
7939a15
resolve merge conglicts
jaredthomas68 Apr 13, 2026
1697178
update changelog
jaredthomas68 Apr 13, 2026
fd3de3c
restrict summer and feedstocks to hourly
jaredthomas68 Apr 13, 2026
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
- The `FlexibleDemandOpenLoopConverterController` has been renamed to `FlexibleDemandComponent`
- The `DemandOpenLoopConverterController` has been renamed to `GenericDemandComponent`
- Modified CI setup so Windows is temporarily disabled and also so unit, regression, and integration tests are run in separate jobs to speed up testing and provide more information on test failures. [PR 668](https://github.com/NatLabRockies/H2Integrate/pull/668)
- Added infrastructure for running models with non-hourly time steps via a class attribute `_time_step_bounds` and sets new time step bounds of 5-minutes to 1-hour for the grid components. [PR 653](https://github.com/NatLabRockies/H2Integrate/pull/653)
- Added infrastructure for running models with non-hourly time steps via a class attribute `_time_step_bounds` and sets new time step bounds of 5-minutes to 1-hour for the grid components. [PR 653](https://github.com/NatLabRockies/H2Integrate/pull/653) and [PR 671](https://github.com/NatLabRockies/H2Integrate/pull/671)

## 0.7.2 [April 9, 2026]

Expand Down
10 changes: 8 additions & 2 deletions examples/06_custom_tech/user_defined_model/paper_mill.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ class PaperMillConfig(BaseConfig):


class PaperMillPerformance(om.ExplicitComponent):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
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.

why is there a comma after the second 3600? I think this is what caused the linting change and resulted in 82 file changes. Can you revert these changes?

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.

The extended comment length (adding (in seconds)) led to the line being longer than our max, so then the tuple instantiation gets split up, and the comma actually gets added as part of the linting so each line is the same regardless of the length of the tuple (i.e. if you added on here and there wasn't a comma, you'd need to add a comma to add another item).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That's exactly right

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Though many of the files changed was adding the bounds to transporters and feedstocks

) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
self.options.declare("driver_config", types=dict)
Expand Down Expand Up @@ -55,7 +58,10 @@ class PaperMillCostConfig(CostModelBaseConfig):


class PaperMillCost(CostModelBaseClass):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = PaperMillCostConfig.from_dict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@


class PyomoDispatchGenericConverter(PyomoRuleBaseClass):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = PyomoRuleBaseConfig.from_dict(
Expand Down
5 changes: 4 additions & 1 deletion h2integrate/control/control_rules/pyomo_rule_baseclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ class PyomoRuleBaseConfig(BaseConfig):


class PyomoRuleBaseClass(om.ExplicitComponent):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
self.options.declare("driver_config", types=dict)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ class PyomoStorageRuleBaseConfig(PyomoRuleBaseConfig):
class PyomoRuleStorageBaseclass(PyomoRuleBaseClass):
"""Base class defining Pyomo rules for generic commodity storage components."""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = PyomoStorageRuleBaseConfig.from_dict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ class HeuristicLoadFollowingController(PyomoControllerBaseClass):

"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
"""Initialize the heuristic load-following controller."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ class OptimizedDispatchController(PyomoControllerBaseClass):

"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
"""Initialize the optimized dispatch controller."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ def __attrs_post_init__(self):


class PyomoControllerBaseClass(om.ExplicitComponent):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ class DemandOpenLoopStorageController(StorageOpenLoopControlBase):
commodity to charge, discharge, or curtail at each time step.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = DemandOpenLoopStorageControllerConfig.from_dict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ class StorageOpenLoopControlBase(om.ExplicitComponent):
dispatch command profile.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
self.options.declare("driver_config", types=dict)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ class SimpleStorageOpenLoopController(StorageOpenLoopControlBase):
uncontrolled frameworks.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = SimpleStorageOpenLoopControllerConfig.from_dict(
Expand Down
10 changes: 8 additions & 2 deletions h2integrate/converters/ammonia/ammonia_synloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ class AmmoniaSynLoopPerformanceModel(ResizeablePerformanceModelBaseClass):
conversion efficiency up to the limiting reagent or energy input.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -425,7 +428,10 @@ class AmmoniaSynLoopCostModel(CostModelBaseClass):
Annual maintenance cost
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
target_cost_year = self.options["plant_config"]["finance_parameters"][
Expand Down
10 changes: 8 additions & 2 deletions h2integrate/converters/ammonia/simple_ammonia_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ class SimpleAmmoniaPerformanceModel(PerformanceModelBaseClass):
Computes annual ammonia production based on plant capacity and capacity factor.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -110,7 +113,10 @@ class SimpleAmmoniaCostModel(CostModelBaseClass):
Includes CapEx, OpEx, and byproduct credits, and exposes all detailed cost outputs.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = AmmoniaCostModelConfig.from_dict(
Expand Down
10 changes: 8 additions & 2 deletions h2integrate/converters/co2/marine/direct_ocean_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ class DOCPerformanceModel(PerformanceModelBaseClass):
An OpenMDAO component for modeling the performance of a Direct Ocean Capture (DOC) plant.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -155,7 +158,10 @@ class DOCCostModel(CostModelBaseClass):
direct ocean capture (DOC) system.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down
15 changes: 12 additions & 3 deletions h2integrate/converters/co2/marine/ocean_alkalinity_enhancement.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ class OAEPerformanceConfig(BaseConfig):
class OAEPerformanceModel(PerformanceModelBaseClass):
"""OpenMDAO component for modeling Ocean Alkalinity Enhancement (OAE) performance."""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -257,7 +260,10 @@ class OAECostModel(CostModelBaseClass):
ocean alkalinity enhancement (OAE) system.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -351,7 +357,10 @@ class OAECostAndFinancialModel(CostModelBaseClass):
- Carbon Credit Value
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down
5 changes: 4 additions & 1 deletion h2integrate/converters/generic_converter_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def __attrs_post_init__(self):


class GenericConverterCostModel(CostModelBaseClass):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = GenericConverterCostConfig.from_dict(
Expand Down
10 changes: 8 additions & 2 deletions h2integrate/converters/grid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ class GridPerformanceModel(PerformanceModelBaseClass):
electricity_out (array): Power flowing out of the grid (buying) (kW).
"""

_time_step_bounds = (300, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
300,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -182,7 +185,10 @@ class GridCostModel(CostModelBaseClass):

"""

_time_step_bounds = (300, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
300,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = GridCostModelConfig.from_dict(
Expand Down
5 changes: 4 additions & 1 deletion h2integrate/converters/hopp/hopp_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ class HOPPComponent(PerformanceModelBaseClass, CacheBaseClass):
computed results when the same configuration is encountered.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down
5 changes: 4 additions & 1 deletion h2integrate/converters/hydrogen/basic_cost_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class BasicElectrolyzerCostModel(ElectrolyzerCostBaseClass):
An OpenMDAO component that computes the cost of a PEM electrolyzer.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = BasicElectrolyzerCostModelConfig.from_dict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ class CustomElectrolyzerCostModel(ElectrolyzerCostBaseClass):
An OpenMDAO component that computes the cost of a PEM electrolyzer.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = CustomElectrolyzerCostModelConfig.from_dict(
Expand Down
10 changes: 8 additions & 2 deletions h2integrate/converters/hydrogen/electrolyzer_baseclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@


class ElectrolyzerPerformanceBaseClass(ResizeablePerformanceModelBaseClass):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand All @@ -30,7 +33,10 @@ def compute(self, inputs, outputs):


class ElectrolyzerCostBaseClass(CostModelBaseClass):
_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
n_timesteps = self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ class AspenGeoH2SurfacePerformanceModel(GeoH2SurfacePerformanceBaseClass):
Hourly steam production profile (8760 hours), in kW thermal.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = AspenGeoH2SurfacePerformanceConfig.from_dict(
Expand Down Expand Up @@ -246,7 +249,10 @@ class AspenGeoH2SurfaceCostModel(GeoH2SurfaceCostBaseClass):
All inherited from GeoH2SurfaceCostBaseClass
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
self.config = AspenGeoH2SurfaceCostConfig.from_dict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ class GeoH2SubsurfacePerformanceBaseClass(PerformanceModelBaseClass):
The total hydrogen produced over the plant lifetime, in kilograms per year.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def initialize(self):
super().initialize()
Expand Down Expand Up @@ -171,7 +174,10 @@ class GeoH2SubsurfaceCostBaseClass(CostModelBaseClass):
Variable OPEX per kilogram of wellhead gas produced, in USD/kg.
"""

_time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model
_time_step_bounds = (
3600,
3600,
) # (min, max) time step lengths (in seconds) compatible with this model

def setup(self):
super().setup()
Expand Down
Loading
Loading