Skip to content

Commit

Permalink
add steel sizing
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrunik committed Feb 28, 2024
1 parent 78170b1 commit c091428
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 29 deletions.
44 changes: 22 additions & 22 deletions greenheart/simulation/technologies/ammonia/ammonia.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,61 +163,61 @@ class AmmoniaSizeModelConfig:
feedstock details.
Attributes:
hydrogen_amount_kg Optional (float): The amount of hydrogen available in kilograms to
make ammonia.
ammonia_plant_size_kg Optional (float): The amount of desired ammonia production in
kilograms.
hydrogen_amount_kg Optional (float): The amount of hydrogen available in kilograms
per year to make ammonia.
ammonia_plant_size_kgpy Optional (float): The amount of desired ammonia production in
kilograms per year.
plant_capcity_factor (float): The ammonia plant capacity factor.
feedstocks (Feedstocks): An instance of the `Feedstocks` class detailing the
costs and consumption rates of resources used in production.
"""
plant_capacity_factor: float
feedstock: Feedstocks
feedstocks: Feedstocks
hydrogen_amount_kg: Optional[float] = field(default=None)
ammonia_plant_size_kg: Optional[float] = field(default=None)
ammonia_plant_size_kgpy: Optional[float] = field(default=None)


def __attrs_post_init__(self):
if self.hydrogen_amount_kg is None and self.ammonia_plant_size_kg is None:
raise ValueError("`hydrogen_amount_kg` or `ammonia_plant_size_kg` is a required input.")
if self.hydrogen_amount_kg is None and self.ammonia_plant_size_kgpy is None:
raise ValueError("`hydrogen_amount_kg` or `ammonia_plant_size_kgpy` is a required input.")

if self.hydrogen_amount_kg and self.ammonia_plant_size_kg:
raise ValueError("can only select one input: `hydrogen_amount_kg` or `ammonia_plant_size_kg`.")
if self.hydrogen_amount_kg and self.ammonia_plant_size_kgpy:
raise ValueError("can only select one input: `hydrogen_amount_kg` or `ammonia_plant_size_kgpy`.")

@define
class AmmoniaSizeModelOutputs:
"""
Outputs from the ammonia size model.
Attributes:
ammonia_plant_size_kg (float): If amount of hydrogen in kilograms is input,
the size of the ammonia plant in kilograms is output.
hydrogen_amount_kg (float): If amount of ammonia production in kilograms is input,
the amount of necessary hydrogen feedstock in kilograms is output.
ammonia_plant_size_kgpy (float): If amount of hydrogen in kilograms per year is input,
the size of the ammonia plant in kilograms per year is output.
hydrogen_amount_kg (float): If amount of ammonia production in kilograms per year is input,
the amount of necessary hydrogen feedstock in kilograms per year is output.
"""
ammonia_plant_size_kg: float
ammonia_plant_size_kgpy: float
hydrogen_amount_kg: float

def run_size_ammonia_plant(config: AmmoniaSizeModelConfig) -> AmmoniaSizeModelOutputs:

if config.hydrogen_amount_kg:
ammonia_plant_size_kg = (config.hydrogen_amount_kg
/ config.feedstock.hydrogen_consumption
ammonia_plant_size_kgpy = (config.hydrogen_amount_kg
/ config.feedstocks.hydrogen_consumption
* config.plant_capacity_factor
)
hydrogen_amount_kg = config.hydrogen_amount_kg

if config.ammonia_plant_size_kg:
hydrogen_amount_kg = (config.ammonia_plant_size_kg
* config.feedstock.hydrogen_consumption
if config.ammonia_plant_size_kgpy:
hydrogen_amount_kg = (config.ammonia_plant_size_kgpy
* config.feedstocks.hydrogen_consumption
/ config.plant_capacity_factor
)
ammonia_plant_size_kg = (config.ammonia_plant_size_kg
ammonia_plant_size_kgpy = (config.ammonia_plant_size_kgpy
/ config.plant_capacity_factor
)

return AmmoniaSizeModelOutputs(
ammonia_plant_size_kg=ammonia_plant_size_kg,
ammonia_plant_size_kgpy=ammonia_plant_size_kgpy,
hydrogen_amount_kg=hydrogen_amount_kg
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Dict, Union
from typing import Dict, Union, Optional

import ProFAST
import pandas as pd
from attrs import define, Factory
from attrs import define, Factory, field


@define
Expand Down Expand Up @@ -191,6 +191,72 @@ class SteelCostModelOutputs(SteelCosts):
spare_parts_cost: float
misc_owners_costs: float

@define
class SteelSizeModelConfig:
"""
Configuration inputs for the steel sizing model, including plant capacity and
feedstock details.
Attributes:
hydrogen_amount_kg Optional (float): The amount of hydrogen available in kilograms
per year to make steel.
steel_plant_size_mtpy Optional (float): The amount of desired steel production in
metric tonnes per year.
plant_capcity_factor (float): The steel plant capacity factor.
feedstocks (Feedstocks): An instance of the `Feedstocks` class detailing the
costs and consumption rates of resources used in production.
"""
plant_capacity_factor: float
feedstocks: Feedstocks
hydrogen_amount_kg: Optional[float] = field(default=None)
steel_plant_size_mtpy: Optional[float] = field(default=None)


def __attrs_post_init__(self):
if self.hydrogen_amount_kg is None and self.steel_plant_size_mtpy is None:
raise ValueError("`hydrogen_amount_kg` or `steel_plant_size_mtpy` is a required input.")

if self.hydrogen_amount_kg and self.steel_plant_size_mtpy:
raise ValueError("can only select one input: `hydrogen_amount_kg` or `steel_plant_size_mtpy`.")

@define
class SteelSizeModelOutputs:
"""
Outputs from the steel size model.
Attributes:
steel_plant_size_mtpy (float): If amount of hydrogen in kilograms per year is input,
the size of the steel plant in metric tonnes per year is output.
hydrogen_amount_kg (float): If amount of steel production in metric tonnes per year is input,
the amount of necessary hydrogen feedstock in kilograms per year is output.
"""
steel_plant_size_mtpy: float
hydrogen_amount_kg: float

def run_size_steel_plant(config: SteelSizeModelConfig) -> SteelSizeModelOutputs:

if config.hydrogen_amount_kg:
steel_plant_size_mtpy = (config.hydrogen_amount_kg
/ 1000
/ config.feedstocks.hydrogen_consumption
* config.plant_capacity_factor
)
hydrogen_amount_kg = config.hydrogen_amount_kg

if config.steel_plant_size_mtpy:
hydrogen_amount_kg = (config.steel_plant_size_mtpy
* 1000
* config.feedstocks.hydrogen_consumption
/ config.plant_capacity_factor
)
steel_plant_size_mtpy = (config.steel_plant_size_mtpy
/ config.plant_capacity_factor
)

return SteelSizeModelOutputs(
steel_plant_size_mtpy=steel_plant_size_mtpy,
hydrogen_amount_kg=hydrogen_amount_kg
)

def run_steel_model(plant_capacity_mtpy: float, plant_capacity_factor: float) -> float:
"""
Expand Down
10 changes: 5 additions & 5 deletions tests/greenheart/test_ammonia.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def test_ammonia_size_h2_input(subtests):
config = ammonia.AmmoniaSizeModelConfig(
hydrogen_amount_kg=73288888.8888889,
plant_capacity_factor=0.9,
feedstock=ammonia.Feedstocks(
feedstocks=ammonia.Feedstocks(
electricity_cost=89.42320514456621,
hydrogen_cost=4.2986685034417045,
cooling_water_cost=0.00291,
Expand All @@ -127,15 +127,15 @@ def test_ammonia_size_h2_input(subtests):
res: ammonia.AmmoniaSizeModelOutputs = ammonia.run_size_ammonia_plant(config)

with subtests.test("Ammonia plant size"):
assert res.ammonia_plant_size_kg == approx(334339658.8730839)
assert res.ammonia_plant_size_kgpy == approx(334339658.8730839)
with subtests.test("hydrogen input"):
assert res.hydrogen_amount_kg == approx(73288888.8888889)

def test_ammonia_size_NH3_input(subtests):
config = ammonia.AmmoniaSizeModelConfig(
ammonia_plant_size_kg=334339658.8730839,
ammonia_plant_size_kgpy=334339658.8730839,
plant_capacity_factor=0.9,
feedstock=ammonia.Feedstocks(
feedstocks=ammonia.Feedstocks(
electricity_cost=89.42320514456621,
hydrogen_cost=4.2986685034417045,
cooling_water_cost=0.00291,
Expand All @@ -147,6 +147,6 @@ def test_ammonia_size_NH3_input(subtests):
res: ammonia.AmmoniaSizeModelOutputs = ammonia.run_size_ammonia_plant(config)

with subtests.test("Ammonia plant size"):
assert res.ammonia_plant_size_kg == approx(371488509.8589821)
assert res.ammonia_plant_size_kgpy == approx(371488509.8589821)
with subtests.test("hydrogen input"):
assert res.hydrogen_amount_kg == approx(73288888.8888889)
32 changes: 32 additions & 0 deletions tests/greenheart/test_steel.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,35 @@ def test_steel_finance_model(cost_config):
res: steel.SteelFinanceModelOutputs = steel.run_steel_finance_model(config)

assert res.sol.get("price") == lcos_expected

def test_steel_size_h2_input(subtests):
config = steel.SteelSizeModelConfig(
hydrogen_amount_kg=73288888.8888889,
plant_capacity_factor=0.9,
feedstocks=steel.Feedstocks(
natural_gas_prices=ng_prices_dict, oxygen_market_price=0
),
)

res: steel.SteelSizeModelOutputs = steel.run_size_steel_plant(config)

with subtests.test("steel plant size"):
assert res.steel_plant_size_mtpy == approx(1000000)
with subtests.test("hydrogen input"):
assert res.hydrogen_amount_kg == approx(73288888.8888889)

def test_steel_size_NH3_input(subtests):
config = steel.SteelSizeModelConfig(
steel_plant_size_mtpy=1000000,
plant_capacity_factor=0.9,
feedstocks=steel.Feedstocks(
natural_gas_prices=ng_prices_dict, oxygen_market_price=0
),
)

res: steel.SteelSizeModelOutputs = steel.run_size_steel_plant(config)

with subtests.test("steel plant size"):
assert res.steel_plant_size_mtpy == approx(1111111.111111111)
with subtests.test("hydrogen input"):
assert res.hydrogen_amount_kg == approx(73288888.8888889)

0 comments on commit c091428

Please sign in to comment.