Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
a862e69
added draft of performance model baseclass to set outputs
elenya-grant Jan 20, 2026
bc6a798
updated wind models for standardized outputs
elenya-grant Jan 20, 2026
73edcd0
minor cleanup to wind pysam
elenya-grant Jan 20, 2026
d3d5616
minor cleanup to floris outputs
elenya-grant Jan 20, 2026
3a8ad35
updated outputs of hydroplant
elenya-grant Jan 20, 2026
682959e
updated solar pv models for standardized outputs
elenya-grant Jan 20, 2026
0aef02a
updated solar resource integration tests with updated solar model out…
elenya-grant Jan 20, 2026
8f993d4
added fraction_of_year_simulated attribute to performance baseclass
elenya-grant Jan 20, 2026
a660e21
updated tests for turbine preprocessing tools
elenya-grant Jan 21, 2026
1f9788a
fixed variable naming in test_all_examples for wind and solar
elenya-grant Jan 21, 2026
d1f2387
started updating electrolyzer model outputs
elenya-grant Jan 21, 2026
5db62ae
Merge branch 'develop' into converter_baseclass
johnjasa Jan 21, 2026
f515f5a
Merge branch 'converter_baseclass' of github.com:elenya-grant/GreenHE…
elenya-grant Jan 21, 2026
4227c13
minor bugfix to test_sql_timeseries_to_csv for example 2
elenya-grant Jan 21, 2026
ff3de30
fixed save_case_timeseries_as_csv
elenya-grant Jan 21, 2026
d84c10a
update to sql_to_csv function just in case
elenya-grant Jan 21, 2026
1169376
merged in develop
elenya-grant Jan 21, 2026
40ae090
added attribute check in PerformanceModelBaseClass
elenya-grant Jan 26, 2026
82116bc
typo bugfix in refurb period calc in electrolyzer model
elenya-grant Jan 26, 2026
08f94ef
added test for solar performance baseclass
elenya-grant Jan 27, 2026
7da471c
merged in develop
elenya-grant Jan 27, 2026
8df11d0
added solar test to check that all outputs are set in parent class
elenya-grant Jan 27, 2026
5a38e8f
commented out unused variables in new solar test
elenya-grant Jan 27, 2026
1a51e7b
generalized solar unit test so it can be easily used for other compon…
elenya-grant Jan 27, 2026
3ea3568
updated natural gas plant
elenya-grant Jan 27, 2026
d02ec1b
started updating co2 models
elenya-grant Jan 27, 2026
e868d82
updated grid model
elenya-grant Jan 27, 2026
16a44c5
updated asu model
elenya-grant Jan 27, 2026
d8fda02
updated grid tests
elenya-grant Jan 27, 2026
c32e752
updated desal model
elenya-grant Jan 27, 2026
910a374
updated co2 models and tests
elenya-grant Jan 27, 2026
cca9e4b
updated newest steel models
elenya-grant Jan 27, 2026
b899fae
started updating methanol models but not tested
elenya-grant Jan 27, 2026
e570263
made it so ResizablePerformanceModelBaseClass inherits PerformanceMod…
elenya-grant Jan 27, 2026
ee220e5
updated electrolyzer model and ammonia synloop model
elenya-grant Jan 27, 2026
1b64406
updated simple ammonia model
elenya-grant Jan 27, 2026
496fba0
updated hopp wrapper
elenya-grant Jan 27, 2026
8117034
updated steel.py
elenya-grant Jan 27, 2026
6c7790c
updated iron mine and dri models
elenya-grant Jan 27, 2026
1d0b1ea
updated geoh2 models
elenya-grant Jan 28, 2026
f582c4c
updated battery
elenya-grant Jan 28, 2026
71a1b85
added todo comments to storage models
elenya-grant Jan 28, 2026
be535a3
added unit tests to check that outputs are populated
elenya-grant Jan 28, 2026
b54f32f
working on updating combiners and h2imodel
elenya-grant Jan 28, 2026
8349163
updated electrolyzer so test values dont change and other bugfixes so…
elenya-grant Jan 28, 2026
199c6fd
updated how_to_set_up_an_analysis.md
elenya-grant Jan 28, 2026
d0ac7d8
removed init file from new hydro power test folder
elenya-grant Jan 29, 2026
95fe559
updated remaining failing tests
elenya-grant Jan 29, 2026
9503a1b
updated example 28 and iron_wrapper
elenya-grant Jan 29, 2026
d98ed88
updated capacity factor strings in run_size_modes files
elenya-grant Jan 29, 2026
022f6ca
Merge remote-tracking branch 'h2i_upstream/develop' into converter_ba…
elenya-grant Jan 29, 2026
11d45b2
removed commented out outputs
elenya-grant Jan 29, 2026
01f4124
updated changelog
elenya-grant Jan 29, 2026
9c8dd0e
removed duplicate inheritance of PerformanceModelBaseClass in electro…
elenya-grant Jan 29, 2026
1011686
updated pysam battery outputs
elenya-grant Jan 29, 2026
36c0772
updated annual outputs to properly account for fraction of year simul…
elenya-grant Jan 30, 2026
6c9e6ba
updates based on reviewer feedback
elenya-grant Jan 30, 2026
7f0a2ab
updated finance model to use electrolyzer replacement_schedule instea…
elenya-grant Jan 30, 2026
e49ff98
updated logic and test values for using electrolyzer lifetime perform…
elenya-grant Jan 30, 2026
e1780a8
fixed tests in test_finances
elenya-grant Jan 30, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- Remove unused dependencies.
- Fixes typos for skipped folders.
- Fixes missing dependencies for `gis` modifier used in new iron mapping tests.
- Added `PerformanceModelBaseClass` and standardized outputs of converter performance models

## 0.5.1 [December 18, 2025]

Expand Down
12 changes: 6 additions & 6 deletions docs/user_guide/how_to_set_up_an_analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ h2i_model.run()

# h2i_model.post_process()

# Print the total hydrogen produced by the electrolyzer in kg/year
total_hydrogen = h2i_model.model.get_val("electrolyzer.total_hydrogen_produced", units="kg/year")[0]
print(f"Total hydrogen produced by the electrolyzer: {total_hydrogen:.2f} kg/year")
# Print the average annual hydrogen produced by the electrolyzer in kg/year
annual_hydrogen = h2i_model.model.get_val("electrolyzer.annual_hydrogen_produced", units="kg/year").mean()
print(f"Total hydrogen produced by the electrolyzer: {annual_hydrogen:.2f} kg/year")
```

This will run the analysis defined in the config files and generate the output files in the through the `post_process` method.
Expand All @@ -169,9 +169,9 @@ h2i_model.run()
# Post-process the results
# h2i_model.post_process()

# Print the total hydrogen produced by the electrolyzer in kg/year
total_hydrogen = h2i_model.model.get_val("electrolyzer.total_hydrogen_produced", units="kg/year")[0]
print(f"Total hydrogen produced by the electrolyzer: {total_hydrogen:.2f} kg/year")
# Print the average annual hydrogen produced by the electrolyzer in kg/year
annual_hydrogen = h2i_model.model.get_val("electrolyzer.annual_hydrogen_produced", units="kg/year").mean()
print(f"Total hydrogen produced by the electrolyzer: {annual_hydrogen:.2f} kg/year")
```

This is especially useful when you want to run an H2I model as a script and modify parameters dynamically without changing the original YAML configuration file.
Expand Down
16 changes: 8 additions & 8 deletions docs/user_guide/run_size_modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ model.run()
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down Expand Up @@ -225,10 +225,10 @@ model.run()
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down Expand Up @@ -270,10 +270,10 @@ model.run()
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down Expand Up @@ -323,10 +323,10 @@ model.run()
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down
3 changes: 3 additions & 0 deletions examples/08_wind_electrolyzer/plant_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ finance_parameters:
finance_subgroups:
electricity_profast:
commodity: "electricity"
# commodity_stream: "wind"
finance_groups: ["profast_model"]
technologies: ["wind"]
electricity_custom:
commodity: "electricity"
# commodity_stream: "wind"
finance_groups: ["custom_model"]
technologies: ["wind"]
hydrogen:
commodity: "hydrogen"
# commodity_stream: "electrolyzer"
commodity_desc: "produced"
finance_groups: ["custom_model","profast_model"]
technologies: ["wind", "electrolyzer"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def initialize(self):
self.options.declare("tech_config", types=dict)
self.options.declare("commodity_type", types=str)
self.options.declare("description", types=str, default="")
self.options.declare("commodity_stream", types=str, default="") # unused in this model

def setup(self):
if self.options["commodity_type"] == "electricity":
Expand All @@ -41,10 +42,13 @@ def setup(self):
else f"{LCO_base_str}_{self.options['description']}"
)

plant_life = int(self.options["plant_config"]["plant"]["plant_life"])

# add inputs for commodity production and costs
self.add_input(
f"total_{self.options['commodity_type']}_produced",
val=0.0,
shape=plant_life,
units=commodity_units,
)
tech_config = self.tech_config = self.options["tech_config"]
Expand Down
16 changes: 8 additions & 8 deletions examples/25_sizing_modes/run_size_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand All @@ -112,10 +112,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down Expand Up @@ -153,10 +153,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down Expand Up @@ -198,10 +198,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.hydrogen_capacity_factor",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.ammonia_capacity_factor",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
Expand Down
2 changes: 1 addition & 1 deletion examples/28_iron_map/driver_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ general:
driver:
design_of_experiments:
flag: true
debug_print: true
debug_print: false
generator: "csvgen"
filename: "ned_reduced_sitelist.csv"
run_parallel: False
Expand Down
19 changes: 4 additions & 15 deletions examples/28_iron_map/plant_config.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
name: "plant_config"
description: "This plant is located in MN, USA..."

site:
latitude: 41.717
longitude: -88.398

# array of polygons defining boundaries with x/y coords
boundaries: [
{
x: [0.0, 1000.0, 1000.0, 0.0],
y: [0.0, 0.0, 100.0, 1000.0],
},
{
x: [2000.0, 2500.0, 2000.0],
y: [2000.0, 2000.0, 2500.0],
}
]
sites:
site:
latitude: 41.717
longitude: -88.398

# array of arrays containing left-to-right technology
# interconnections; can support bidirectional connections
Expand Down
46 changes: 25 additions & 21 deletions examples/test/test_all_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def test_steel_example(subtests):
pytest.approx(
model.prob.get_val("finance_subgroup_hydrogen.LCOH_delivered")[0], rel=1e-3
)
== 8.270362492342693
== 8.235313509720276
)

with subtests.test("Check LCOS"):
assert pytest.approx(model.prob.get_val("steel.LCOS")[0], rel=1e-3) == 1266.6193378846617
assert pytest.approx(model.prob.get_val("steel.LCOS")[0], rel=1e-3) == 1264.2821232584045

with subtests.test("Check total adjusted CapEx"):
assert (
Expand Down Expand Up @@ -175,15 +175,15 @@ def test_simple_ammonia_example(subtests):
with subtests.test("Check LCOH"):
assert (
pytest.approx(model.prob.get_val("finance_subgroup_hydrogen.LCOH")[0], rel=1e-3)
== 4.025446
== 4.01554337
)

with subtests.test("Check price of hydrogen"):
assert (
pytest.approx(
model.prob.get_val("finance_subgroup_hydrogen.price_hydrogen")[0], rel=1e-3
)
== 4.025446
== 4.01554337
)

# Currently underestimated compared to the Reference Design Doc
Expand Down Expand Up @@ -279,7 +279,7 @@ def test_ammonia_synloop_example(subtests):
with subtests.test("Check LCOH"):
assert (
pytest.approx(model.prob.get_val("finance_subgroup_h2.LCOH")[0], rel=1e-6)
== 4.025385101169759
== 4.015543377027795
)

with subtests.test("Check LCOA"):
Expand Down Expand Up @@ -320,7 +320,7 @@ def test_co2h_methanol_example(subtests):

# Check levelized cost of methanol (LCOM)
with subtests.test("Check CO2 Hydrogenation LCOM"):
assert pytest.approx(model.prob.get_val("methanol.LCOM")[0], rel=1e-6) == 1.7555607442
assert pytest.approx(model.prob.get_val("methanol.LCOM")[0], rel=1e-6) == 1.751617212520347


@pytest.mark.skipif(importlib.util.find_spec("mcm") is None, reason="mcm is not installed")
Expand Down Expand Up @@ -356,7 +356,9 @@ def test_wind_h2_opt_example(subtests):

model_init.post_process()

annual_h20 = model_init.prob.get_val("electrolyzer.total_hydrogen_produced", units="kg/year")[0]
annual_h20 = model_init.prob.get_val("electrolyzer.annual_hydrogen_produced", units="kg/year")[
0
]

# Create a H2Integrate model
model = H2IntegrateModel(Path.cwd() / "wind_plant_electrolyzer.yaml")
Expand Down Expand Up @@ -422,7 +424,7 @@ def test_wind_h2_opt_example(subtests):
with subtests.test("Check minimum total hydrogen produced"):
assert (
pytest.approx(
model.prob.get_val("electrolyzer.total_hydrogen_produced", units="kg/year")[0],
model.prob.get_val("electrolyzer.annual_hydrogen_produced", units="kg/year")[0],
abs=15000,
)
== 29028700
Expand Down Expand Up @@ -504,7 +506,7 @@ def test_splitter_wind_doc_h2_example(subtests):
with subtests.test("Check LCOH"):
assert (
pytest.approx(model.prob.get_val("finance_subgroup_hydrogen.LCOH")[0], rel=1e-3)
== 9.82319908
== 9.80590834551064
)

with subtests.test("Check LCOC"):
Expand Down Expand Up @@ -587,7 +589,7 @@ def test_hydrogen_dispatch_example(subtests):
model.prob.get_val("finance_subgroup_all_hydrogen.LCOH", units="USD/kg")[0],
rel=1e-5,
)
== 5.380013537850591
== 5.6545296034469
)

with subtests.test("Check dispatched h2 LCOH"):
Expand Down Expand Up @@ -851,7 +853,7 @@ def test_wind_solar_electrolyzer_example(subtests):
model.prob.get_val("finance_subgroup_hydrogen.LCOH", units="USD/kg")[0],
rel=1e-5,
)
== 5.3277923
== 5.3063358
)

wind_generation = model.prob.get_val("wind.electricity_out", units="kW")
Expand Down Expand Up @@ -886,9 +888,9 @@ def test_electrolyzer_om_example(subtests):
with subtests.test("Check LCOE"):
assert pytest.approx(lcoe, rel=1e-4) == 39.98869
with subtests.test("Check LCOH with lcoh_financials"):
assert pytest.approx(lcoh_with_lcoh_finance, rel=1e-4) == 13.0858012
assert pytest.approx(lcoh_with_lcoh_finance, rel=1e-4) == 16.9204156301
with subtests.test("Check LCOH with lcoe_financials"):
assert pytest.approx(lcoh_with_lcoe_finance, rel=1e-4) == 7.9935907
assert pytest.approx(lcoh_with_lcoe_finance, rel=1e-4) == 10.3360027653


def test_wombat_electrolyzer_example(subtests):
Expand Down Expand Up @@ -917,7 +919,7 @@ def test_wombat_electrolyzer_example(subtests):
with subtests.test("Check LCOH from custom model"):
assert pytest.approx(lcoh_with_custom_model, rel=1e-5) == 4.19232346
with subtests.test("Check LCOH from ProFAST model"):
assert pytest.approx(lcoh_with_profast_model, rel=1e-5) == 5.32632237
assert pytest.approx(lcoh_with_profast_model, rel=1e-5) == 5.308630730506
with subtests.test("Check LCOE from custom model"):
assert pytest.approx(lcoe_with_custom_model, rel=1e-5) == 51.17615298
with subtests.test("Check LCOE from ProFAST model"):
Expand Down Expand Up @@ -1243,7 +1245,7 @@ def test_csvgen_design_of_experiments(subtests):
min_lcoh_case_num = i

with subtests.test("Min LCOH value"):
assert pytest.approx(min_lcoh_val, rel=1e-6) == 4.468258
assert pytest.approx(min_lcoh_val, rel=1e-6) == 4.6630144

with subtests.test("Min LCOH case number"):
assert min_lcoh_case_num == 6
Expand Down Expand Up @@ -1310,9 +1312,9 @@ def test_sweeping_solar_sites_doe(subtests):
for ci, case in enumerate(cases):
solar_resource_data = case.get_val("site.solar_resource.solar_resource_data")
lat_lon = f"{case.get_val('site.latitude')[0]} {case.get_val('site.longitude')[0]}"
solar_capacity = case.get_design_vars()["solar.system_capacity_DC"]
aep = case.get_val("solar.annual_energy", units="MW*h/yr")
lcoe = case.get_val("finance_subgroup_electricity.LCOE_optimistic", units="USD/(MW*h)")
solar_capacity = case.get_design_vars()["solar.system_capacity_DC"][0]
aep = case.get_val("solar.annual_electricity_produced", units="MW*h/yr")[0]
lcoe = case.get_val("finance_subgroup_electricity.LCOE_optimistic", units="USD/(MW*h)")[0]

site_res = pd.DataFrame(
[aep, lcoe, solar_capacity], index=["AEP", "LCOE", "solar_capacity"], columns=[lat_lon]
Expand Down Expand Up @@ -1395,7 +1397,8 @@ def test_floris_example(subtests):
with subtests.test("Distributed wind plant capacity"):
assert (
pytest.approx(
h2i.prob.get_val("distributed_wind_plant.total_capacity", units="MW"), rel=1e-6
h2i.prob.get_val("distributed_wind_plant.rated_electricity_production", units="MW"),
rel=1e-6,
)
== 66.0
)
Expand All @@ -1405,7 +1408,7 @@ def test_floris_example(subtests):
pytest.approx(
np.sum(
h2i.prob.get_val(
"distributed_wind_plant.total_electricity_produced", units="MW*h/yr"
"distributed_wind_plant.total_electricity_produced", units="MW*h"
)
),
rel=1e-6,
Expand Down Expand Up @@ -1433,7 +1436,8 @@ def test_floris_example(subtests):
with subtests.test("Utility wind plant capacity"):
assert (
pytest.approx(
h2i.prob.get_val("utility_wind_plant.total_capacity", units="MW"), rel=1e-6
h2i.prob.get_val("utility_wind_plant.rated_electricity_production", units="MW"),
rel=1e-6,
)
== 120.0
)
Expand Down
Loading