Repository navigation
Nonannual framework - #934
Open
jaredthomas68 wants to merge 13 commits into
Open
jaredthomas68 wants to merge 13 commits into
jaredthomas68 wants to merge 13 commits into
Conversation
jaredthomas68
added this pull request to stack #935
October 14, 2026 15:48
jaredthomas68
marked this pull request as ready for review
October 14, 2026 18:17
jaredthomas68
requested review from
elenya-grant,
genevievestarke and
johnjasa
October 14, 2026 18:17
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add core framework support for non-annual simulation durations
Allow plant configurations to specify a positive simulation duration up to the configured plant
life, rather than requiring exactly one year. Duration is determined by
n_timesteps * dt;framework duration checks and annualization express that duration in nominal 8760-hour years
(31,536,000 seconds). This convention does not define resource calendar-year length or change
the
include_leap_daysetting, which controls leap-day handling in resource data.Models declare supported simulation durations through
_simulation_duration_bounds, a(minimum_years, maximum_years)class attribute. The default remains(1.0, 1.0), so existingmodels remain annual-only unless explicitly validated and opted in. A model that supports
arbitrary positive durations can declare:
Model assembly checks duration compatibility alongside timestep compatibility and reports an
error identifying a model whose bounds exclude the requested horizon. Performance, cost, and
control base classes declare annual-only defaults.
Add shared annualization helpers for capacity factors, degradation-aware replacement schedules,
and variable operating costs. The helpers account for partial simulated years and predict results
across plant life using explicit extrapolation strategies. ProFAST converts rated production from
its actual rate units into daily capacity and annual commodity production, avoiding hard-coded
hourly conversion assumptions and duplicate conversion in the NPV model.
This is PR #934, the second PR in the
nonannual-resource->nonannual-framework->nonannualstack. It depends onPR #933 and is reviewed relative to
nonannual-resource. Resource resampling is implemented in #933; concrete model opt-ins andthe non-annual solar/battery/grid example belong to the subsequent
nonannualPR.Section 1: Type of Contribution
Section 2: Draft PR Checklist
TODO:
Type of Reviewer Feedback Requested (on Draft PR)
Structural feedback: Annual-only defaults with explicit model opt-in, duration checks during
model assembly, and separation of framework support from individual model adaptations.
Implementation feedback: Partial-year annualization, lifetime extrapolation, SOH cycle and
replacement handling, variable operating costs, and unit-aware ProFAST capacity/production inputs.
Other feedback: Clarity of model-author guidance and unsupported-duration errors.
Section 3: General PR Checklist
docs/files are up-to-date, or added when necessaryCHANGELOG.md"A complete thought. [PR XYZ]((https://github.com/NatLabRockies/H2Integrate/pull/XYZ)", where
XYZshould be replaced with the actual number.New-model checklist: N/A. The checked test item refers to the focused framework and finance
tests reported in Section 7, not the full repository suite. Documentation verification is
reported complete by the author; the earlier assistant-launched fresh build has no recorded
final result. Remote checks have not been verified.
Section 4: Related Issues
Related to #890. This PR provides
simulation duration validation.
Related to #636. This PR provides
simulation duration validation.
Related to #204. This PR provides
framework changes to pave the way for variable simulation duration.
Related to #733. This PR provides unit
conversions for financial modeling using rate and amount units provided by the input config.
Section 5: Impacted Areas of the Software
Section 5.1: New Files
h2integrate/core/test/test_model_baseclasses.py: Test annual capacity factors, extrapolationmodes, degradation/replacement cycles, helper behavior, and invalid inputs.
Section 5.2: Modified Files
h2integrate/core/inputs/validation.py: Accept positive non-annual horizons up to plant lifeand reject non-positive or over-life horizons.
h2integrate/core/model_checks.py: Addcheck_model_simulation_durationwith annual-onlyfallback bounds and model-specific compatibility errors.
h2integrate/core/h2integrate_model.py: Check duration compatibility when assembling models,including feedstock sources, combined models, controllers, and transporters.
h2integrate/core/model_baseclass.py: Add duration bounds and shared helpers to annualizecapacity factors, degradation/replacements, and variable operating costs across plant life.
h2integrate/control/control_strategies/openloop_control_baseclass.py: Declare annual-onlyduration bounds for open-loop control models.
h2integrate/control/control_strategies/pyomo_storage_controller_baseclass.py: Declareannual-only duration bounds for Pyomo storage controllers.
h2integrate/control/control_rules/pyomo_rule_baseclass.py: Declare annual-only durationbounds for Pyomo control rules.
h2integrate/finances/profast_baseclass.py: Retain simulation timestep/count and convertproduction rates to ProFAST daily capacity and annual commodity amounts using their units.
h2integrate/finances/profast_npv.py: Use the shared production conversion instead ofseparately adjusting rated-production units in the NPV calculation.
h2integrate/core/test/test_framework.py: Test accepted horizons, invalid horizons,annual-only defaults, and explicitly declared model duration bounds.
h2integrate/finances/test/test_finances.py: Add finance coverage for sub-annual horizons.h2integrate/finances/test/test_profast_lco.py: Add ProFAST levelized-cost duration coverage.h2integrate/finances/test/test_profast_npv.py: Add NPV coverage for non-annual horizons andproduction-rate unit conversion.
Section 6: Additional Supporting Information
that duration. All models used in the simulation must satisfy their own duration bounds;
models without declared bounds default to annual-only.
calculate_annual_cf_and_replacement_schedulesupportstile,final_sim_value, andaverage_sim_valueextrapolation without degradation. With SOH data,it detects end-of-life/reset cycles, extrapolates an incomplete trailing cycle, and supports
repeating all cycles or the final cycle across plant life.
calculate_annual_varopexseparately annualizes variable operating costs, includingpartial-year segments, using the same named extrapolation strategies.
annualization, not as a claim that every resource calendar year has 8760 hours. Resource
calendar-year lengths and leap-day inclusion are handled separately by the resource layer.
adapted before declaring wider bounds. Those model updates are deferred to the next PR.
Section 7: Test Results, if applicable
Focused framework and finance tests on
nonannual-framework: 84 passed, 108 subtests passed.Ruff, import-order checks, and
git diff --checkpassed for the framework PR changes.The documentation-consistency test returned 2 passed, 1 failed: the local example-directory
scan found
09_wind_farm_layout_hybridand98_battery_degradationoutside its expecteddocumentation-reference allowlist. This result is separate from the passing framework/finance
tests; a clean-checkout comparison has not yet been run.
Documentation verification is reported complete by the author. A fresh assistant-launched build
was also started, but its final result was not captured, so no independent passing result is
claimed for that run. Full repository CI and remote documentation checks remain unverified.
Section 8 (Optional): New Model Checklist
N/A; no new model is introduced. The checklist is retained as required by the template.
docs/developer_guide/coding_guidelines.md{ModelName}Config, where{ModelName}is the complete model class name registered with@registerattrsclass to define theConfigto load in attributes for the modelBaseConfigorCostModelBaseConfiginitialize()method,setup()method,compute()methodPerformanceModelBaseClassandCostModelBaseClass__init__.pyfile so it can be imported from its subpackage@registerfromh2integrate/core/supported_models.pytest_all_examples.pydocs/section_toc.ymldocs/_static/class_hierarchy.htmlby doing one of the below options:docsfolder and runsh build_book.shgenerate_class_hierarchy.pyto update the class hierarchy diagram indocs/developer_guide/class_structure.md. You may need to delete the_autosummaryfolder before doing this.