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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
- Added a storage performance baseclass model `StoragePerformanceBase` and updated the other storage performance models to inherit it [PR 624](https://github.com/NatLabRockies/H2Integrate/pull/624)
- Modified the calc tilt angle function for pysam solar to support latitudes in the southern hemisphere [PR 646](https://github.com/NatLabRockies/H2Integrate/pull/646)
- Added oxygen production metrics and as outputs to `ECOElectrolyzerPerformanceModel` [PR 642](https://github.com/NatLabRockies/H2Integrate/pull/642)
- Removed the last of the logic that was based on technology names rather than model classes [PR 654](https://github.com/NatLabRockies/H2Integrate/pull/654)

## 0.7.1 [March 13, 2026]

Expand Down
1 change: 0 additions & 1 deletion docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ parts:
chapters:
- file: user_guide/model_overview
- file: user_guide/how_to_set_up_an_analysis
- file: user_guide/expected_naming_convention
- file: user_guide/connecting_technologies
- file: user_guide/defining_sites_and_resources
- file: user_guide/design_optimization_in_h2i
Expand Down
39 changes: 0 additions & 39 deletions docs/user_guide/expected_naming_convention.md

This file was deleted.

15 changes: 9 additions & 6 deletions h2integrate/core/h2integrate_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from h2integrate.core.utilities import create_xdsm_from_config
from h2integrate.core.file_utils import get_path, find_file, load_yaml
from h2integrate.finances.finances import AdjustedCapexOpexComp
from h2integrate.core.supported_models import supported_models
from h2integrate.core.supported_models import (
no_cost_models,
supported_models,
no_replacement_schedule_models,
)
from h2integrate.core.inputs.validation import load_tech_yaml, load_plant_yaml, load_driver_yaml
from h2integrate.core.pose_optimization import PoseOptimization
from h2integrate.postprocess.sql_to_csv import convert_sql_to_csv_summary
Expand Down Expand Up @@ -1234,10 +1238,9 @@ def connect_technologies(self):

# Only connect technologies that are included in the finance stackup
for tech_name in tech_configs.keys():
# For now, assume splitters and combiners do not add any costs
if "splitter" in tech_name or "combiner" in tech_name:
continue
if tech_name == "cable" or tech_name == "pipe":
# Skip technologies whose models doesn't add costs
perf_model = tech_configs[tech_name].get("performance_model").get("model")
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.

would using dictionary defaults prevent issues in case a technology (maybe not one that exists now) has a cost model but not a performance model?

perf_model = tech_configs[tech_name].get("performance_model", {}).get("model", None)

Copy link
Copy Markdown
Collaborator Author

@johnjasa johnjasa Apr 7, 2026

Choose a reason for hiding this comment

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

Good consideration. This would avoid issues in the future for models that don't necessarily exist now, but it may also obfuscate the issue. Or at least I'd want to catch it sooner than this (connection time). So based on this comment, I've added required: [performance_model] to the tech_schema.yaml to require models there and do the checking.

Copy link
Copy Markdown
Collaborator

@elenya-grant elenya-grant Apr 7, 2026

Choose a reason for hiding this comment

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

Okay - I think requiring the performance model makes sense for now (I was spooked when you said performance and cost model since splitters and combiners can be defined in the tech config but don't have an associated cost model). Thanks for explaining!

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.

Yeah, I underthought it at first and thought we could require both but you're exactly right!

if perf_model in no_cost_models:
continue

self.plant.connect(
Expand All @@ -1255,7 +1258,7 @@ def connect_technologies(self):
f"finance_subgroup_{group_id}.cost_year_{tech_name}",
)

if is_system_finance_model and "transport" not in tech_name:
if is_system_finance_model and perf_model not in no_replacement_schedule_models:
# connect replacement schedule to system-level finance models
self.plant.connect(
f"{tech_name}.replacement_schedule",
Expand Down
2 changes: 1 addition & 1 deletion h2integrate/core/inputs/tech_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ properties:
type: object
description: Financial model details (optional)
additionalProperties: true
required: []
required: [performance_model]
required: [name, description, technologies]
22 changes: 22 additions & 0 deletions h2integrate/core/supported_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,25 @@
"SimpleGasConsumerCost": SimpleGasConsumerCost,
"GasStreamCombinerPerformanceModel": GasStreamCombinerPerformanceModel,
}


# This next section is to demarcate specific models that belong to certain categories that are
# relevant for processing in the model stackup. Right now, these designations are
# used in `h2integrate_model.py`.


# Model classes that do not contribute costs to the finance stackup because they are essentially
# internal-only models that aren't categorized as a specific technology (e.g. a generic combiner
# or splitter, or a model that is only used for performance modeling within another model and
# doesn't have an independent cost model).
no_cost_models = {
"GenericSplitterPerformanceModel",
"GenericCombinerPerformanceModel",
"GasStreamCombinerPerformanceModel",
"CablePerformanceModel",
"PipePerformanceModel",
}

no_replacement_schedule_models = {
"IronTransportPerformanceComponent",
}
Loading