Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
26a6ec6
Reading in Stinn input tables
jmartin4u Nov 6, 2025
3a803fd
Sucessfully testing Stinn model
jmartin4u Nov 7, 2025
6fa32fd
Merge remote-tracking branch 'upstream/develop' into ewin-dev
jmartin4u Nov 7, 2025
9d4ff83
Making humbert perf model
jmartin4u Nov 7, 2025
84aad1c
Adding humbert/stinn cost model inputs only
jmartin4u Nov 11, 2025
674cd47
Progress on humbert cost
jmartin4u Nov 11, 2025
0728b2d
Humbert Stinn complete, not debugged
jmartin4u Nov 11, 2025
9601cce
Debugging electrowinning
jmartin4u Nov 12, 2025
3351d51
Merge remote-tracking branch 'upstream/develop' into ewin-dev
jmartin4u Nov 12, 2025
6310a12
Debugging ewinning
jmartin4u Nov 12, 2025
6455234
Merge remote-tracking branch 'upstream/develop' into ewin-dev
jmartin4u Nov 12, 2025
4f978b8
Electrowinning cases running, need to add DRI case
jmartin4u Nov 12, 2025
bd5cdb4
Merge remote-tracking branch 'upstream/develop' into ewin-dev
jmartin4u Dec 4, 2025
9388822
Cleanup of old trailing underscores
jmartin4u Dec 5, 2025
db6864b
Fix input csv names
jmartin4u Jan 2, 2026
c130111
Merge remote-tracking branch 'upstream/develop' into ewin-merge
jmartin4u Jan 2, 2026
0b41cbf
Integrate ewin example with feedstocks
jmartin4u Jan 2, 2026
ab63af7
Moving functions out of h2i module and renumbering example
jmartin4u Jan 2, 2026
47b6535
Merge branch 'develop' into ewin-merge
johnjasa Jan 5, 2026
149ee57
Small fixes to PR
jmartin4u Jan 12, 2026
efa47cc
start of unit test
kbrunik Jan 12, 2026
5b44977
Merge branch 'ewin-merge' of https://github.com/jmartin4nrel/H2Integr…
kbrunik Jan 12, 2026
502aa8c
Testing example
jmartin4u Jan 13, 2026
8c79a30
Expanding unit tests
jmartin4u Jan 13, 2026
95c5e70
Merge branch 'develop' into ewin-merge
kbrunik Jan 13, 2026
d30a44a
fix import
kbrunik Jan 13, 2026
3992372
Docstrings begun
jmartin4u Jan 13, 2026
6845b13
Docstrings plus a little reorg
jmartin4u Jan 14, 2026
9229ed7
Everything but the docs page
jmartin4u Jan 14, 2026
bde4c2d
Finished documentation
jmartin4u Jan 14, 2026
d3af390
Split off humbert cost_model
jmartin4u Jan 14, 2026
4e51c3b
Config docstrings
jmartin4u Jan 14, 2026
504785a
Merge remote-tracking branch 'upstream/develop' into ewin-merge
jmartin4u Jan 14, 2026
821ba8b
Merge branch 'develop' into ewin-merge
johnjasa Jan 16, 2026
674dac1
Refactoring iron ewinning calcs for clarity
johnjasa Jan 16, 2026
c34f4e5
Addressing reviews
jmartin4u Jan 22, 2026
71ea58a
Merge branch 'develop' into ewin-merge
johnjasa Jan 24, 2026
a7e62c7
site -> sites
jmartin4u Jan 24, 2026
f4b24f5
Updating test values
jmartin4u Jan 26, 2026
c4cc271
Merge remote-tracking branch 'upstream/develop' into ewin-merge
jmartin4u Jan 27, 2026
09fa9a2
Merge branch 'develop' into ewin-merge
johnjasa Jan 27, 2026
98bb8c5
Added autodoc to the electrowinning docs
johnjasa Jan 27, 2026
fe7d704
Merge branch 'develop' into ewin-merge
johnjasa Jan 27, 2026
2a0d6d5
Merge remote-tracking branch 'upstream/develop' into ewin-merge
jmartin4u Jan 27, 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 @@ -5,6 +5,7 @@
- Updates models for NumPy version 2.4.0
- Update test values for WOMBAT update to 0.13.0
- Added standalone iron DRI and steel EAF performance and cost models
- Added iron electrowinning model
- Added capability to have transport models that require user input parameters
- Add geologic hydrogen surface processing converter
- Add baseclass for caching functionality
Expand Down
1 change: 1 addition & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ parts:
- file: technology_models/geologic_hydrogen.md
- file: technology_models/grid
- file: technology_models/hydrogen_storage.md
- file: technology_models/iron_ewin.md

- caption: Resource Models
chapters:
Expand Down
58 changes: 58 additions & 0 deletions docs/technology_models/iron_ewin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Iron electrowinning models

H2I contains iron electrowinning models to simulate the reduction of iron oxide to pure iron and removal of impurities.
The main input feedstock is iron ore, while the output commodity is "sponge iron", i.e. iron that is typically brittle ("spongey") and contains less carbon than most steel alloys.
This sponge iron can then be used in an electric arc furnace (EAF) to produce steel.

There are currently three iron electrowinning processes modeled in H2I:
- Aqueous Hydroxide Electrolysis (AHE)
- Molten Salt Electrolysis (MSE)
- Molten Oxide Electrolysis (MOE)

In reality, the exact composition and structure of the resulting sponge iron will differ depending on the process and the conditions.
Currently, H2I models do not make these distinctions, as the technology is new and we are still building out the capability.
Instead, the models in their current form are based on two recent studies of electrowinning technology as a whole.

The first study is by [Humbert et al.](doi.org/10.1007/s40831-024-00878-3), who focus specifically on iron and the three technologies above.
These authors gather information on the specific energy required for electrolysis and associated pretreatments needed, which is applied in the `humbert_electrowinning_performance` performance model.
In their supporting information, they also model the full operational expenditures for each process, which is applied in the `humbert_stinn_electrowinning_cost` cost model.

The second study is by [Stinn & Allanore](doi.org/10.1149.2/2.F06202IF), who present a generalized capital cost model for electrowinning of many different metals.
These authors use both cost data and physical parameters from existing studies to fit the model to be applicable to any metal, including iron.
This model is applied in the `humbert_stinn_electrowinning_cost` cost model.

To use this model, specify `"humbert_electrowinning_performance"` as the performance model and `"humbert_stinn_electrowinning_cost"` as the cost model.
The performance model will Humbert et al.'s energy consumption data to consume electricity as a feedstock and feed this information to the cost model.
The cost model will calculate capex costs based on the Stinn correlations and opex costs based on the Humbert SI.

## Performance Model

```{eval-rst}
.. autoclass:: h2integrate.converters.iron.humbert_ewin_perf.HumbertEwinConfig
:members:
:undoc-members:
:show-inheritance:
```

```{eval-rst}
.. autoclass:: h2integrate.converters.iron.humbert_ewin_perf.HumbertEwinPerformanceComponent
:members:
:undoc-members:
:show-inheritance:
```

## Cost Model

```{eval-rst}
.. autoclass:: h2integrate.converters.iron.humbert_stinn_ewin_cost.HumbertStinnEwinCostConfig
:members:
:undoc-members:
:show-inheritance:
```

```{eval-rst}
.. autoclass:: h2integrate.converters.iron.humbert_stinn_ewin_cost.HumbertStinnEwinCostComponent
:members:
:undoc-members:
:show-inheritance:
```
9 changes: 7 additions & 2 deletions docs/user_guide/model_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The inputs, outputs, and corresponding technology that are currently available i
| `hopp` | electricity | N/A |
| `electrolyzer` | hydrogen | electricity |
| `geoh2` | hydrogen | rock type |
| `steel` | steel | hydrogen |
| `steel` | steel | iron ore |
| `ammonia` | ammonia | nitrogen, hydrogen |
| `doc` | co2 | electricity |
| `oae` | co2 | electricity |
Expand Down Expand Up @@ -225,13 +225,18 @@ Below summarizes the available performance, cost, and financial models for each
+ `'iron_mine_performance_martin'`
- cost models:
+ `'iron_mine_cost_martin'`
- `iron_dri`: iron ore direct reduction
- `iron_dri`: direct reduced iron
- performance models:
+ `'ng_dri_performance_rosner'`
+ `'h2_dri_performance_rosner'`
- cost models:
+ `'ng_dri_cost_rosner'`
+ `'h2_dri_cost_rosner'`
- `iron_ewin`: iron electrowinning
- performance models:
+ `'humbert_electrowinning_performance'`
- cost models:
+ `'humbert_stinn_electrowinning_cost'`

(transport-models)=
## Transport Models
Expand Down
7 changes: 7 additions & 0 deletions examples/27_iron_electrowinning/27_iron_electrowinning.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "H2Integrate_config"

system_summary: "An iron plant using processed ore pellets for electrowinning."

driver_config: "driver_config.yaml"
technology_config: "tech_config.yaml"
plant_config: "plant_config.yaml"
5 changes: 5 additions & 0 deletions examples/27_iron_electrowinning/driver_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: "driver_config"
description: "Simply setting up an outputs folder, nothing fancy"

general:
folder_output: outputs
65 changes: 65 additions & 0 deletions examples/27_iron_electrowinning/plant_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: "plant_config"
description: "Configures an iron electrowinning system."

sites:
ewin_site:
latitude: 41.717
longitude: -88.398

technology_interconnections: [
# Connect feedstocks to iron mine.
# Requires `electricity` and `crude ore`.
# Both are set up as generic feedstock components - see tech_config.
["grid_feedstock","iron_mine","electricity","cable"],
["mine_feedstock","iron_mine","crude_ore","pipe"],
# Connect feedstocks to iron electrowinning plant.
# Requires `electricity` and `iron_ore`.
# Electricity is set up as generic feedstock component,
# but iron_ore is set up as an output of an iron_mine.
["iron_mine","iron_plant","iron_ore","iron_transport"],
["ewin_grid_feedstock","iron_plant","electricity","cable"],
]

plant:
plant_life: 30
finance_parameters:
finance_groups:
finance_model: "ProFastComp"
model_inputs:
params:
analysis_start_year: 2032
installation_time: 36 # months
inflation_rate: 0.0 # 0 for nominal analysis
discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind
debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind
property_tax_and_insurance: 0.03 # percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf https://www.house.mn.gov/hrd/issinfo/clsrates.aspx
total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8)
capital_gains_tax_rate: 0.15 # H2FAST default
sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/
debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind
debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH
loan_period_if_used: 0 # H2FAST default, not used for revolving debt
cash_onhand_months: 1 # H2FAST default
admin_expense: 0.00 # percent of sales H2FAST default
capital_items:
depr_type: "MACRS" # can be "MACRS" or "Straight line"
depr_period: 5 # 5 years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507
refurb: [0.]
cost_adjustment_parameters:
cost_year_adjustment_inflation: 0.025
target_dollar_year: 2022
finance_subgroups:
iron_ore:
commodity: "iron_ore"
commodity_stream: "iron_mine"
technologies: ["iron_mine", "grid_feedstock", "mine_feedstock"]
sponge_iron:
commodity: "sponge_iron"
commodity_stream: "iron_plant"
technologies:
- "iron_mine"
- "grid_feedstock"
- "mine_feedstock"
- "iron_transport"
- "iron_plant"
- "ewin_grid_feedstock"
43 changes: 43 additions & 0 deletions examples/27_iron_electrowinning/run_iron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Comparing three different iron electrowinning technologies

This script runs an end-to-end iron production system (including the mine) and compares the
levelized cost of sponge_iron across three different iron electrowinning technologies to see
how their costs compare:
- Aqueous Hydroxide Electrolysis (AHE)
- Molten Salt Electrolysis (MSE)
- Molten Oxide Electrolysis (MOE)

New users may find it helpful to look at the tech_config.yaml (particularly the iron_plant) to see
how the technologies were set up, as well as the plant_config.yaml (particularly the
technology_interconnections) to see how the technologies were connected.

"""

from h2integrate.core.h2integrate_model import H2IntegrateModel


# Create H2Integrate model
model = H2IntegrateModel("27_iron_electrowinning.yaml")

# Define the electrowinning types as a list
electrolysis_types = ["ahe", "mse", "moe"]
lcois = []

for electrolysis_type in electrolysis_types:
# Set the technology config value directly
model.technology_config["technologies"]["iron_plant"]["model_inputs"]["shared_parameters"][
"electrolysis_type"
] = electrolysis_type
model.setup() # re-setup the model after changing config
model.run()
model.post_process()
lcois.append(
float(
model.model.get_val("finance_subgroup_sponge_iron.price_sponge_iron", units="USD/kg")[0]
)
)

# Compare the LCOIs from each electrowinning type
print("Levelized Cost of Iron (LCOI) by Electrowinning Type:")
for electrolysis_type, lcoi in zip(electrolysis_types, lcois):
print(f" {electrolysis_type.upper()}: ${lcoi:,.2f} per kg of sponge iron")
90 changes: 90 additions & 0 deletions examples/27_iron_electrowinning/tech_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: "technology_config"
description: "Set up technology for an iron mine/iron electrowinning system"

technologies:
grid_feedstock: #electricity feedstock for iron ore - comes from grid
performance_model:
model: "feedstock_performance"
cost_model:
model: "feedstock_cost"
model_inputs:
shared_parameters:
feedstock_type: "electricity"
units: "MW"
performance_parameters:
rated_capacity: 30.
cost_parameters:
cost_year: 2022
price: 58.02 #USD/MW
annual_cost: 0.
start_up_cost: 0.

mine_feedstock: #crude iron ore feedstock - comes from the ground
performance_model:
model: "feedstock_performance"
cost_model:
model: "feedstock_cost"
model_inputs:
shared_parameters:
feedstock_type: "crude_ore"
units: "t/h"
performance_parameters:
rated_capacity: 2000.
cost_parameters:
cost_year: 2022
price: 0.0
annual_cost: 0.
start_up_cost: 0.

iron_mine: # iron mine - turns crude_iron into iron_ore
performance_model:
model: "iron_mine_performance_martin"
cost_model:
model: "iron_mine_cost_martin"
model_inputs:
shared_parameters:
mine: "Northshore"
taconite_pellet_type: "drg"
max_ore_production_rate_tonnes_per_hr: 250

iron_transport: # ship iron_ore from iron_mine to iron_plant
performance_model:
model: "iron_transport_performance"
cost_model:
model: "iron_transport_cost"
model_inputs:
performance_parameters:
find_closest_ship_site: False
shipment_site: "Chicago"
cost_parameters:
transport_year: 2022
cost_year: 2022

ewin_grid_feedstock: #electricity feedstock for iron electrowinning
performance_model:
model: "feedstock_performance"
cost_model:
model: "feedstock_cost"
model_inputs:
shared_parameters:
feedstock_type: "electricity"
units: "kW"
performance_parameters:
rated_capacity: 600000.
cost_parameters:
cost_year: 2022
price: 0.05802 #USD/kW
annual_cost: 0.
start_up_cost: 0.

iron_plant: # iron plant - turns iron_ore into sponge_iron
performance_model:
model: "humbert_electrowinning_performance"
cost_model:
model: "humbert_stinn_electrowinning_cost"
model_inputs:
shared_parameters:
electrolysis_type: "ahe"
performance_parameters:
ore_fe_wt_pct: 65
capacity_mw: 600
33 changes: 33 additions & 0 deletions examples/test/test_all_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -1795,6 +1795,39 @@ def test_21_iron_dri_eaf_example(subtests):
assert pytest.approx(lcos, rel=1e-4) == 524.8228189073025


def test_27_iron_electrowinning_example(subtests):
os.chdir(EXAMPLE_DIR / "27_iron_electrowinning")

model = H2IntegrateModel("27_iron_electrowinning.yaml")

with subtests.test("Value check on AHE"):
model.technology_config["technologies"]["iron_plant"]["model_inputs"]["shared_parameters"][
"electrolysis_type"
] = "ahe"
model.setup()
model.run()
lcoi = model.model.get_val("finance_subgroup_sponge_iron.LCOS", units="USD/kg")[0]
assert pytest.approx(lcoi, rel=1e-4) == 2.187928233525775

with subtests.test("Value check on MSE"):
model.technology_config["technologies"]["iron_plant"]["model_inputs"]["shared_parameters"][
"electrolysis_type"
] = "mse"
model.setup()
model.run()
lcoi = model.model.get_val("finance_subgroup_sponge_iron.LCOS", units="USD/kg")[0]
assert pytest.approx(lcoi, rel=1e-4) == 3.3410182461323226

with subtests.test("Value check on MOE"):
model.technology_config["technologies"]["iron_plant"]["model_inputs"]["shared_parameters"][
"electrolysis_type"
] = "moe"
model.setup()
model.run()
lcoi = model.model.get_val("finance_subgroup_sponge_iron.LCOS", units="USD/kg")[0]
assert pytest.approx(lcoi, rel=1e-4) == 2.2832248695268893


def test_sweeping_different_resource_sites_doe(subtests):
os.chdir(EXAMPLE_DIR / "27_site_doe_diff")
import pandas as pd
Expand Down
Loading