Skip to content
Open
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 @@ -13,6 +13,7 @@
- Fixed error message that is thrown in `check_inputs` and updated testing of `check_inputs` to actually test the error messages [PR #846](https://github.com/NatLabRockies/H2Integrate/pull/846)
- Fixed several tests where the assert statements paired with `pytest.raises` were indented inside the context manager block and never ran, and corrected the now-active expected error strings. [PR #846](https://github.com/NatLabRockies/H2Integrate/pull/846)
- Replaces all custom attrs validators in `h2integrate.core.validators` with built in attrs validators. [PR 835](https://github.com/NatLabRockies/H2Integrate/pull/835)
- Add `NRRIIronMinePerformanceModel` and `NRRIIronMineCostModel`. [PR 840](https://github.com/NatLabRockies/H2Integrate/pull/840)
- Exempted demand components from the tech interconnections checking, added unit test. [PR 850](https://github.com/NatLabRockies/H2Integrate/pull/850)

## 0.9 [August 10, 2026]
Expand Down
4 changes: 2 additions & 2 deletions docs/_static/class_hierarchy.html

Large diffs are not rendered by default.

52 changes: 49 additions & 3 deletions docs/technology_models/iron_mine.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Iron mine model

H2I contains an iron mine model that simulates the extraction of crude ore and its processing into iron ore pellets.
H2I contains 2 iron mine models that simulate the extraction of crude ore and its processing into iron ore pellets:
- `SimpleIronMine`: Models only the flow of `crude_ore` in and `iron_ore` out, with costs all lumped together
- `NRRIIronMine`: Models mass flows and electricity/fuel consumption at intermediate steps, with costs broken out

## SimpleIronMine
The main input feedstock is `crude_ore`, i.e. the unprocessed ore in the earth containing iron oxide.
The output commodity is `iron_ore` in the form of pellets that can be shipped to other plants (e.g. `iron_plant`) for further processing.

Expand All @@ -14,7 +18,7 @@ There are two potential grades of ore produced from an iron mine in this model:

It was determined that 3 of these mines (Northshore, United, and Hibbing) had crude reserves sufficient to produce DR-grade pellets, although only one (Northshore) reported production data on DR-grade pellets, with the rest reporting their data strictly on standard ore pellets.
The increases in cost and energy usage reported at the Northshore mine were used to project the potential performance and cost of DR-grade production at United and Hibbing.
The results of this analysis are compiled in the directory `h2integrate/converters/iron/martin_ore/`.
The results of this analysis are compiled in the directory `h2integrate/converters/iron/simple_ore/`.
Performance data are included in `perf_inputs.csv` with cost data in `cost_inputs.csv`.

These data were compiled from two sources:
Expand All @@ -27,8 +31,50 @@ These data were compiled from two sources:
- [Minorca Mine](https://minedocs.com/22/Minorca-TR-12312021.pdf)
- [Tilden Mine](https://minedocs.com/22/Tilden-TR-12312021.pdf)

To use this model, specify `"MartinIronMinePerformanceComponent"` as the performance model and `"MartinIronMineCostComponent"` as the cost model.
To use this model, specify `"SimpleIronMinePerformanceComponent"` as the performance model and `"SimpleIronMineCostComponent"` as the cost model.
Currently, no complex calculations occur beyond importing performance and costs.
In the performance model, the "wet long tons" (wlt) that ore production is typically reported in are converted to dry metric tons for use in H2I.
In the cost model, the total capex costs for a plant are scaled by the amount of are produced annually.
Besides these calculations, previously-calculated performance and cost metrics are simply loaded from the input spreadsheets.

## NRRIIronMine
The main inputs are `electricity` and `fuel`.
The output commodity is `iron_ore` in the form of pellets that can be shipped to other plants (e.g. `iron_plant`) for further processing.

This model was developed in conjunction with the [University of Minnesota's Natural Resource Research Institute (NRRI)](https://www.nrri.umn.edu/), led by Kimberly Anderson <kimander@d.umn.edu>

This model splits out the separate processes to produce iron ore pellets at a mine (mining, comminution, beneficiation, pelletization) and tracks the material flows.

Sources (2021 costs):
- [SEC S-K 1300 Tilden Mining Company](https://www.sec.gov/Archives/edgar/data/764065/000076406522000037/clf-2021123110xkex965.htm)
- [SEC S-K 1300 Hibbing Taconite](https://www.sec.gov/Archives/edgar/data/764065/000076406522000033/a20220211-8xkxex961.htm)
- [SEC S-K 1300 United Taconite](https://www.sec.gov/Archives/edgar/data/764065/000076406522000033/a20220211-8xkxex964.htm)
- [SEC S-K 1300 Minorca Mine](https://www.sec.gov/Archives/edgar/data/764065/000076406522000033/a20220211-8xkxex962.htm)
- [SEC S-K 1300 Northshore Mining Company](https://www.sec.gov/Archives/edgar/data/764065/000076406522000033/a20220211-8xkxex963.htm)

Local electricity costs (2012):
- [Tilden Estimated Electrical Costs](https://www.electricitylocal.com/states/michigan/marquette/)
- [Hibtac Estimate Electrical Costs](https://www.electricitylocal.com/states/minnesota/hibbing/)
- [Utac Estimated Electrical Costs](https://www.electricitylocal.com/states/minnesota/virginia/)
- [Minora Estimated Electrical Costs](https://www.electricitylocal.com/states/minnesota/virginia/)
- [Northshore - Babbitt Electrical Costs](https://www.electricitylocal.com/states/minnesota/babbitt/)
- [Northshore - Silver Bay Electrical Costs](https://www.electricitylocal.com/states/minnesota/silver-bay/)
- All inflated to 2021 costs using electricity [CPI](https://fred.stlouisfed.org/series/CUUR0000SEHF01):
- 2012 average electricity CPI: 196.6298
- 2021 average electricity CPI: 223.8915833

Estimated electrical breakdown data synthesized using Gemini and ChatGPT and verified using:
- Prediction of fuel consumption of mining dump trucks: A neural networks approach Elnaz Siami-Irdemoosa, Saeid Dindarloo, Applied Energy 151, 2015, pp. 77-84
- US DOE - Critical Minerals & Energy Innovation under Lawrence Berkeley National Laboratory under Contract DE-AC02-05CH11231 (January 2026)
- The Effects of Increasing Costs of the Future Relation Between Open Pit and Underground Mining, Dan Nilsson, 1982. US Dept of Interior - Office of Surface Mining - Bureau of Mines under Grand No. OSM G5105032

Fuel Costs (2021):
- Natural Gas:
- MN industrial NG $5.47/tcf [EIA](https://www.eia.gov/dnav/ng/ng_pri_sum_dcu_smn_a.htm)
- 1.037 MMBtu/tcf
- Final NG price: $5.275/MMBtu
- Diesel:
- MN pump diesel $3.208/gal [MN Dept. of Revenue](https://www.revenue.state.mn.us/petroleum-tax-eia-average-retail-fuel-price)
- minus est. $0.285/gal MN excise tax [MN Dept. of Revenue](https://www.revenue.state.mn.us/petroleum-tax-fuel-excise-tax-rates-and-fees)
- minus $0.244/gal federal tax [EIA](https://www.eia.gov/tools/faqs/faq.php?id=10&t=5)
- Final off road diesel price: $2.679/gal
8 changes: 6 additions & 2 deletions docs/user_guide/model_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ auto-generated API page.
+ {py:class}`~h2integrate.converters.water.desal.desalination.ReverseOsmosisCostModel` - An OpenMDAO component that computes the cost of a reverse osmosis desalination system.

- `generic`: generic converter components
- performance models:
+ {py:class}`~h2integrate.converters.combustion_machines.turbine_simple_cycle.SimpleCycleTurbinePerformanceModel` - Performance model for simple Brayton-cycle turbines.
- cost models:
+ {py:class}`~h2integrate.converters.generic_converter_cost.GenericConverterCostModel`

Expand Down Expand Up @@ -168,14 +170,16 @@ auto-generated API page.
- performance models:
+ {py:class}`~h2integrate.converters.iron.humbert_ewin_perf.HumbertEwinPerformanceComponent` - OpenMDAO component for the Humbert iron electrowinning performance model.
+ {py:class}`~h2integrate.converters.iron.iron_dri_plant.HydrogenIronReductionPlantPerformanceComponent` - Performance component for hydrogen-based direct reduced iron (DRI) plant using the Rosner performance model.
+ {py:class}`~h2integrate.converters.iron.martin_mine_perf_model.MartinIronMinePerformanceComponent`
+ {py:class}`~h2integrate.converters.iron.nrri_iron_mine.NRRIIronMinePerformanceComponent`
+ {py:class}`~h2integrate.converters.iron.iron_dri_plant.NaturalGasIronReductionPlantPerformanceComponent` - Performance component for natural gas-based direct reduced iron (DRI) plant using the Rosner performance model.
+ {py:class}`~h2integrate.converters.iron.simple_mine_perf_model.SimpleIronMinePerformanceComponent`
- cost models:
+ {py:class}`~h2integrate.converters.iron.humbert_stinn_ewin_cost.HumbertStinnEwinCostComponent` - OpenMDAO component for the Humbert/Stinn iron electrowinning cost model.
+ {py:class}`~h2integrate.converters.iron.iron_dri_plant.HydrogenIronReductionPlantCostComponent` - Cost component for hydrogen-based direct reduced iron (DRI) plant using the Rosner cost model.
+ {py:class}`~h2integrate.converters.iron.iron_transport.IronTransportCostComponent`
+ {py:class}`~h2integrate.converters.iron.martin_mine_cost_model.MartinIronMineCostComponent`
+ {py:class}`~h2integrate.converters.iron.nrri_iron_mine.NRRIIronMineCostComponent`
+ {py:class}`~h2integrate.converters.iron.iron_dri_plant.NaturalGasIronReductionPlantCostComponent` - Cost component for natural gas-based direct reduced iron (DRI) plant using the Rosner cost model.
+ {py:class}`~h2integrate.converters.iron.simple_mine_cost_model.SimpleIronMineCostComponent`
- other components:
+ {py:class}`~h2integrate.converters.iron.iron_transport.IronTransportPerformanceComponent`

Expand Down
4 changes: 2 additions & 2 deletions examples/21_iron_examples/iron_dri/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ technologies:
commodity_rate_units: t/h
iron_mine:
performance_model:
model: MartinIronMinePerformanceComponent
model: SimpleIronMinePerformanceComponent
cost_model:
model: MartinIronMineCostComponent
model: SimpleIronMineCostComponent
model_inputs:
shared_parameters:
mine: Northshore
Expand Down
4 changes: 4 additions & 0 deletions examples/21_iron_examples/iron_dri_nrri/driver_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: driver_config
description: Simply setting up an outputs folder, nothing fancy
general:
folder_output: outputs
92 changes: 92 additions & 0 deletions examples/21_iron_examples/iron_dri_nrri/plant_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: plant_config
description: This plant is located in MN, USA...
sites:
site:
latitude: 41.717
longitude: -88.398
technology_interconnections:
# Connect feedstocks to iron mine.
- [mine_electricity_feedstock, iron_mine, electricity, cable]
- [mine_natural_gas_feedstock, iron_mine, natural_gas, pipe]
- [mine_diesel_feedstock, iron_mine, diesel, pipe]
# Connect iron_ore price and processed_ore_feedstock to iron_transport
# Connect the LCOI of iron ore to the price of a feedstock component representing the ore to be used in DRI
- [finance_subgroup_iron_ore, processed_ore_feedstock, [price_iron_ore, price]]
# Connect the ore feedstock available to the iron plant
- [processed_ore_feedstock, iron_plant, iron_ore, iron_ore_transport]
- [dri_grid_feedstock, iron_plant, electricity, cable]
- [catalyst_feedstock, iron_plant, reformer_catalyst, catalyst_transport]
- [water_feedstock, iron_plant, water, pipe]
- [natural_gas_feedstock, iron_plant, natural_gas, pipe]
# Use the iron ore consumed by the iron plant to calculate transport costs
- [iron_plant, iron_transport, [iron_ore_consumed, iron_ore_in]]
# Connect feedstocks to steel plant
- [eaf_grid_feedstock, steel_plant, electricity, cable]
- [eaf_water_feedstock, steel_plant, water, pipe]
- [eaf_natural_gas_feedstock, steel_plant, natural_gas, pipe]
- [iron_plant, steel_plant, sponge_iron, sponge_iron_transport]
plant:
plant_life: 30
simulation:
n_timesteps: 8760
dt: 3600
timezone: 0
finance_parameters:
finance_groups:
finance_model: ProFastLCO
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.nlr.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
- mine_electricity_feedstock
sponge_iron:
commodity: sponge_iron
commodity_stream: iron_plant
technologies:
- processed_ore_feedstock
- iron_transport
- iron_plant
- dri_grid_feedstock
- catalyst_feedstock
- water_feedstock
- natural_gas_feedstock
steel:
commodity: steel
commodity_stream: steel_plant
technologies:
- processed_ore_feedstock
- iron_transport
- iron_plant
- dri_grid_feedstock
- catalyst_feedstock
- water_feedstock
- natural_gas_feedstock
- eaf_water_feedstock
- eaf_natural_gas_feedstock
- eaf_grid_feedstock
- steel_plant
156 changes: 156 additions & 0 deletions examples/21_iron_examples/iron_dri_nrri/run_iron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
"""Example of an iron mine sending processed ore pellets to a separate DRI iron plant and EAF

In this example, iron ore pellets are produced at different iron mine locations in NE Minnesota.
These mines send processed ore pellets to a separate iron DRI plant located outside Chicago.
Four different cases are generated for four different iron mine setups in the `test_inputs.csv`.
The first two cases generate standard blast furnace grade pellets at two different mine locations.
The second two cases generate DR grade pellets at the same location, with the output capacity
varied to show how the capacity of the mine does not affect the levelized cost of iron_ore pellets
(LCOI), nor does it affect the final cost of the sponge_iron produced by DRI (LCOS) or the cost
of the steel produced by the EAF (LCOS).

"""

from pathlib import Path

import numpy as np
import pandas as pd

from h2integrate import H2IntegrateModel
from h2integrate.tools.run_cases import modify_tech_config, load_tech_config_cases


# Create H2Integrate model
model = H2IntegrateModel("single_site_iron.yaml")

# Load cases
case_file = Path("test_inputs.csv")
cases = load_tech_config_cases(case_file)

# Modify and run the model for different cases
casenames = [
"Standard Iron - Hibbing",
"Standard Iron - Northshore",
"DR Grade Iron - Northshore",
"DR Grade Iron - Northshore (adjusted)",
]

# Create empty lists to store the costs
lcois_ore = []
capexes_ore = []
fopexes_ore = []
vopexes_ore = []
production_ore = []
lcois_iron = []
capexes_iron = []
fopexes_iron = []
vopexes_iron = []
production_ore = []
lcois_steel = []
capexes_steel = []
fopexes_steel = []
vopexes_steel = []

model.run()
model.post_process()

for casename in casenames:
model = modify_tech_config(model, cases[casename])
model.run()
lcois_ore.append(
float(model.model.get_val("finance_subgroup_iron_ore.price_iron_ore", units="USD/kg")[0])
)
capexes_ore.append(
float(model.model.get_val("finance_subgroup_iron_ore.total_capex_adjusted", units="USD")[0])
)
fopexes_ore.append(
float(
model.model.get_val("finance_subgroup_iron_ore.total_opex_adjusted", units="USD/year")[
0
]
)
)
vopexes_ore.append(
float(
model.model.get_val(
"finance_subgroup_iron_ore.total_varopex_adjusted", units="USD/year"
)[0]
)
)
lcois_iron.append(
float(
model.model.get_val("finance_subgroup_sponge_iron.price_sponge_iron", units="USD/kg")[0]
)
)
capexes_iron.append(
float(
model.model.get_val("finance_subgroup_sponge_iron.total_capex_adjusted", units="USD")[0]
)
)
fopexes_iron.append(
float(
model.model.get_val(
"finance_subgroup_sponge_iron.total_opex_adjusted", units="USD/year"
)[0]
)
)
vopexes_iron.append(
float(
model.model.get_val(
"finance_subgroup_sponge_iron.total_varopex_adjusted", units="USD/year"
)[0]
)
)
lcois_steel.append(
float(model.model.get_val("finance_subgroup_steel.price_steel", units="USD/kg")[0])
)
capexes_steel.append(
float(model.model.get_val("finance_subgroup_steel.total_capex_adjusted", units="USD")[0])
)
fopexes_steel.append(
float(
model.model.get_val("finance_subgroup_steel.total_opex_adjusted", units="USD/year")[0]
)
)
vopexes_steel.append(
float(
model.model.get_val("finance_subgroup_steel.total_varopex_adjusted", units="USD/year")[
0
]
)
)

# Compare the Capex, Fixed Opex, and Variable Opex across the 4 cases
columns = pd.MultiIndex.from_tuples(
[
("Levelized Cost", "[USD/kg]"),
("Capex", "[USD]"),
("Fixed Opex", "[USD/year]"),
("Variable Opex", "[USD/year]"),
]
)
print()

df_ore = pd.DataFrame(
np.transpose(np.vstack([lcois_ore, capexes_ore, fopexes_ore, vopexes_ore])),
index=casenames,
columns=columns,
)
print(df_ore)

print()
df_iron = pd.DataFrame(
np.transpose(np.vstack([lcois_iron, capexes_iron, fopexes_iron, vopexes_iron])),
index=casenames,
columns=columns,
)
print(df_iron)

print()
df_steel = pd.DataFrame(
np.transpose(np.vstack([lcois_steel, capexes_steel, fopexes_steel, vopexes_steel])),
index=casenames,
columns=columns,
)
df_steel = df_steel.iloc[2:]
print(df_steel)
5 changes: 5 additions & 0 deletions examples/21_iron_examples/iron_dri_nrri/single_site_iron.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: H2Integrate_config
system_summary: An iron mine producing ore pellets and a separately-located iron plant performing direct reduction.
driver_config: driver_config.yaml
technology_config: tech_config.yaml
plant_config: plant_config.yaml
Loading
Loading