Sizing Modes with Resizeable Converters#
When the size of one converter is changed, it may be desirable to have other converters in the plant resized to match.
This can be done manually by setting the sizes of each converter in the tech_config, but it can also be done automatically with resizeable converters.
Resizeable converters can execute their own built-in sizing methods based on how much of a feedstock can be produced upstream, or how much of a commodity can be offtaken downstream by other converters.
By connecting the capacities of converters to other converters, one can build a logical re-sizing scheme for a multi-technology plant that will resize all converters by changing just one config parameter.
Setting up a resizeable converter#
To set up a resizeable converter, use ResizeablePerformanceModelBaseConfig and ResizeablePerformanceModelBaseClass.
The ResizeablePerformanceModelBaseConfig will declare sizing performance parameters (size_mode, flow_used_for_sizing, max_feedstock_ratio, max_commodity_ratio) within the tech_config.
The ResizeablePerformanceModelBaseClass will automatically parse these parameters into the inputs and discrete_inputs that the performance model will need for resizing.
Here is the start of an example tech_config for such a converter:
tech_config = {
"model_inputs": {
"shared_parameters": {
"production_capacity": 1000.0,
},
"performance_parameters": {
"size_mode": "normal", # Always required
"flow_used_for_sizing": "electricity", # Not required in "normal" mode
"max_feedstock_ratio": 1.6, # Only used in "resize_by_max_feedstock"
"max_commodity_ratio": 0.7, # Only used in "resize_by_max_commodity"
},
}
}
Currently, there are three different modes defined for size_mode:
normal: In this mode, converters function as they always have previously:The size of the asset is fixed within
compute().
resize_by_max_feedstock: In this mode, the size of the converter is adjusted to be able to utilize all of the available feedstock:The size of the asset should be calculated within
compute()as a function of the maximum value of<feedstock>_in- with the<feedstock>specified by theflow_used_for_sizingparameter.This function will utilizes the
max_feedstock_ratioparameter - e.g., ifmax_feedstock_ratiois 1.6, the converter will be resized so that its input capacity is 1.6 times the max of<feedstock>_in.The
set_valmethod will over-write any previous sizing variables to reflect the adjusted size of the converter.
resize_by_max_commodity: In this mode, the size of the asset is adjusted to be able to supply its product to the full capacity of another downstream converter:The size of the asset should be calculated within
compute()as a function of themax_<commodity>_capacityinput - with the<feedstock>specified by theresize by flowparameter.This function will utilizes the
max_commodity_ratioparameter - e.g., ifmax_commodity_ratiois 0.7, the converter will be resized so that its output capacity is 0.7 times a connectedmax_<commodity>_capacityinput.The
set_valmethod will over-write any previous sizing variables to reflect the adjusted size of the converter.
To construct a resizeable converter from an existing converter, very few changes must be made, and only to the performance model.
ResizeablePerformanceModelBaseConfig can replace BaseConfig and ResizeablePerformanceModelBaseClass can replace om.ExplicitComponent.
The setup function must be modified to include any max_<feedstock>_capacity outputs or max_<commodity>_capacity inputs that can be connected to do the resizing.
Then, any feedstock_sizing_function or feedstock_sizing_function that the converter needs to resize itself should be defined, if not already.
from pathlib import Path
import numpy as np
from h2integrate.core.utilities import merge_shared_inputs
from h2integrate.core.model_baseclasses import ResizeablePerformanceModelBaseClass, ResizeablePerformanceModelBaseConfig
from h2integrate.core.h2integrate_model import H2IntegrateModel
from h2integrate.core.inputs.validation import load_tech_yaml, load_driver_yaml, load_plant_yaml
# Set a root directory for file loading
EXAMPLE_DIR = Path("../../examples/25_sizing_modes").resolve()
class TechPerformanceModelConfig(ResizeablePerformanceModelBaseConfig):
# Declare tech-specific config parameters
size: float = 1.0
class TechPerformanceModel(ResizeablePerformanceModelBaseClass):
def setup(self):
self.config = TechPerformanceModelConfig.from_dict(
merge_shared_inputs(self.options["tech_config"]["model_inputs"], "performance"),
strict=False,
)
super().setup()
# Declare tech-specific inputs and outputs
self.add_input("size", val=self.config.size, units="unitless")
# Declare any commodities produced that need to be connected to downstream converters
# if this converter is in `resize_by_max_commodity` mode
self.add_input("max_<commodity>_capacity", val=1000.0, units="kg/h")
# Any feedstocks consumed that need to be connected to upstream converters
# if those converters are in `resize_by_max_commodity` mode
self.add_output("max_<feedstock>_capacity", val=1000.0, units="kg/h")
def feedstock_sizing_function(max_feedstock):
max_feedstock * 0.1231289 # random number for example
def commodity_sizing_function(max_commodity):
max_commodity * 0.4651 # random number for example
def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
size_mode = discrete_inputs["size_mode"]
# Make changes to computation based on sizing_mode:
if size_mode != "normal":
size = inputs["size"]
if size_mode == "resize_by_max_feedstock":
if inputs["flow_used_for_sizing"] == "<feedstock>":
feed_ratio = inputs["max_feedstock_ratio"]
size_for_max_feed = self.feedstock_sizing_function(
np.max(inputs["<feedstock>_in"])
)
size = size_for_max_feed * feed_ratio
elif size_mode == "resize_by_max_commodity":
if inputs["flow_used_for_sizing"] == "<commodity>":
comm_ratio = inputs["max_commodity_ratio"]
size_for_max_comm = self.commodity_sizing_function(
np.max(inputs["max_<commodity>_capacity"])
)
size = size_for_max_comm * comm_ratio
self.set_val("size", size)
Example plant setup#
Here, there are three technologies in the the tech_config.yaml:
A
hoppplant producing electricity,An
electrolyzerproducing hydrogen from that electricity, andAn
ammoniaplant producing ammonia from that hydrogen.
The electrolyzer and ammonia technologies are resizeable. For starters, we will set them up in "normal" mode
# Create a H2Integrate model
driver_config = load_driver_yaml(EXAMPLE_DIR / "driver_config.yaml")
plant_config = load_plant_yaml(EXAMPLE_DIR / "plant_config.yaml")
tech_config = load_tech_yaml(EXAMPLE_DIR / "tech_config.yaml")
# Replace a relative file in the example with a hard-coded reference for the docs version
fn = tech_config["technologies"]["hopp"]["model_inputs"]["performance_parameters"]["hopp_config"]["site"]["solar_resource_file"][3:]
tech_config["technologies"]["hopp"]["model_inputs"]["performance_parameters"]["hopp_config"]["site"]["solar_resource_file"] = EXAMPLE_DIR.parent / fn
fn = tech_config["technologies"]["hopp"]["model_inputs"]["performance_parameters"]["hopp_config"]["site"]["wind_resource_file"][3:]
tech_config["technologies"]["hopp"]["model_inputs"]["performance_parameters"]["hopp_config"]["site"]["wind_resource_file"] = EXAMPLE_DIR.parent / fn
input_config = {
"name": "H2Integrate_config",
"system_summary": "hybrid plant containing ammonia plant and electrolyzer",
"driver_config": driver_config,
"plant_config": plant_config,
"technology_config": tech_config,
}
model = H2IntegrateModel(input_config)
# Print the value of the size_mode tech_config parameters
for tech in ["electrolyzer", "ammonia"]:
print(
tech
+ ": "
+ str(
model.technology_config["technologies"][tech]["model_inputs"]["performance_parameters"][
"size_mode"
]
)
)
electrolyzer: normal
ammonia: normal
UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/h2integrate/core/pose_optimization.py:367
Design variables are set to be optimized or studied, but no driver is selected. If you want to run an optimization, please enable a driver.
The technology_interconnections in the plant_config is set up to send electricity from the wind plant to the electrolyzer, then hydrogen from the electrolyzer to the ammonia plant. When set up to run in resize_by_max_commodity mode, there will also be an entry to send the max_hydrogen_capacity from the ammonia plant to the electrolyzer. Note: this will create a feedback loop within the OpenMDAO problem, which requires an iterative solver.
for connection in model.plant_config["technology_interconnections"]:
print(connection)
['hopp', 'electrolyzer', 'electricity', 'cable']
['electrolyzer', 'ammonia', 'hydrogen', 'pipe']
When we run this example the electrolyzer is sized to 640 MW (as set by the config), although the electricity profile going in has a max of over 1000 MW. The LCOH is $4.49/kg H2 and the LCOA is $1.35/kg NH3.
# Run the model
model.run()
# Print selected output
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
print(value + ": " + str(np.max(model.prob.get_val(value))))
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1997
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1997
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1996
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1996
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1998
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
Warning: Storage dispatch was initialized with a state-of-charge less than minimum value!
Initial SOC = 0.1999
Initial SOC was set to minimum value.
HOPP Results
Hybrid Annual Energy: {"pv": 853774920.3077677, "wind": 1713131802.4014313, "battery": -1299.3288329240827, "hybrid": 2566905423.3803596}
Capacity factors: {"pv": 31.67543939497997, "wind": 22.022859362805846, "battery": 0, "hybrid": 24.504816728647782}
Real LCOE from HOPP: {"pv": 4.743076625535104, "wind": 6.139760797224929, "battery": 26.46110199177945, "hybrid": 5.713621765595212}
electrolyzer.electricity_in: 1048680.996768964
electrolyzer.electrolyzer_size_mw: 640.0
electrolyzer.capacity_factor: 0.4448455934100944
ammonia.hydrogen_in: 12548.415602484365
ammonia.max_hydrogen_capacity: 10589.360138101109
ammonia.capacity_factor: 0.5065573551797645
finance_subgroup_h2.LCOH: 6.801431052239145
finance_subgroup_nh3.LCOA: 1.940394189590241
/home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/openmdao/core/group.py:1267: DerivativesWarning:Constraints or objectives [plant.finance_subgroup_nh3.ammonia_finance_default.LCOA] cannot be impacted by the design variables of the problem because no partials were defined for them in their parent component(s).
UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/hopp/simulation/hopp.py:150
'om_capacity[0]' in the wind 'fin_model' was 29, but 'wind_om_per_kw' in 'cost_info' was 29. The 'om_capacity' value in the wind 'fin_model' is being overwritten with the value from the 'cost_info'UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/hopp/simulation/hopp.py:200
'om_capacity[0]' in the pv 'fin_model' was 18, but 'pv_om_per_kw' in 'cost_info' was 18. The 'om_capacity' value in the pv 'fin_model' is being overwritten with the value from the 'cost_info'UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/hopp/simulation/hopp.py:249
'om_capacity' in the battery 'fin_model' was 15.525, but 'battery_om_per_kw' in 'cost_info' was 15.525. The 'om_capacity' value in the battery 'fin_model' is being overwritten with the value from the 'cost_info'
resize_by_max_feedstock mode#
In this case, the electrolyzer will be sized to match the maximum electricity_in coming from HOPP.
This increases the electrolyzer size to 1080 MW, the smallest multiple of 40 MW (the cluster size) matching the max HOPP power output of 1048 MW.
This increases the LCOH to $4.80/kg H2, and increases the LCOA to $1.54/kg NH3, since electrolyzer is now oversized to utilize all of the HOPP electricity at peak output but thus has a lower hydrogen production capacity factor.
# Create a H2Integrate model, modifying tech_config as necessary
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"size_mode"
] = "resize_by_max_feedstock"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"flow_used_for_sizing"
] = "electricity"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"max_feedstock_ratio"
] = 1.0
input_config["technology_config"] = tech_config
model = H2IntegrateModel(input_config)
# Run the model
model.run()
# Print selected output
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
print(value + ": " + str(np.max(model.prob.get_val(value))))
electrolyzer.electricity_in: 1048680.996768964
electrolyzer.electrolyzer_size_mw: 1080.0
electrolyzer.capacity_factor: 0.28736786938132675
ammonia.hydrogen_in: 20488.419654025012
ammonia.max_hydrogen_capacity: 10589.360138101109
ammonia.capacity_factor: 0.5146952834406818
finance_subgroup_h2.LCOH: 7.850901414106746
finance_subgroup_nh3.LCOA: 2.2183335046017616
UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/h2integrate/core/pose_optimization.py:367
Design variables are set to be optimized or studied, but no driver is selected. If you want to run an optimization, please enable a driver./home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/openmdao/core/group.py:1267: DerivativesWarning:Constraints or objectives [plant.finance_subgroup_nh3.ammonia_finance_default.LCOA] cannot be impacted by the design variables of the problem because no partials were defined for them in their parent component(s).
resize_by_max_product mode#
In this case, the electrolyzer will be sized to match the maximum hydrogen capacity of the ammonia plant.
This requires the technology_interconnections entry to send the max_hydrogen_capacity from the ammonia plant to the electrolyzer.
This decreases the electrolyzer size to 560 MW, the closest multiple of 40 MW (the cluster size) that will ensure an h2 production capacity that matches the ammonia plant’s h2 intake at its max ammonia production capacity.
This increases the LCOH to $4.64/kg H2, but reduces the LCOA to $1.30/kg NH3, since electrolyzer size was matched to ammonia production but not HOPP.
# Create a H2Integrate model, modifying tech_config and plant_config as necessary
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"size_mode"
] = "resize_by_max_commodity"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"flow_used_for_sizing"
] = "hydrogen"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"max_commodity_ratio"
] = 1.0
input_config["technology_config"] = tech_config
plant_config["technology_interconnections"] = [
["hopp", "electrolyzer", "electricity", "cable"],
["electrolyzer", "ammonia", "hydrogen", "pipe"],
["ammonia", "electrolyzer", "max_hydrogen_capacity"],
]
input_config["plant_config"] = plant_config
model = H2IntegrateModel(input_config)
# Run the model
model.run()
# Print selected output
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
print(value + ": " + str(np.max(model.prob.get_val(value))))
=====
plant
=====
NL: NLBGS Converged in 4 iterations
electrolyzer.electricity_in: 1048680.996768964
electrolyzer.electrolyzer_size_mw: 560.0
electrolyzer.capacity_factor: 0.49725420470273646
ammonia.hydrogen_in: 10705.252862710096
ammonia.max_hydrogen_capacity: 10589.360138101109
ammonia.capacity_factor: 0.5025756908304677
finance_subgroup_h2.LCOH: 6.8380609094149
finance_subgroup_nh3.LCOA: 1.8983395275228419
UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/h2integrate/core/pose_optimization.py:367
Design variables are set to be optimized or studied, but no driver is selected. If you want to run an optimization, please enable a driver./home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/openmdao/core/group.py:1267: DerivativesWarning:Constraints or objectives [plant.finance_subgroup_nh3.ammonia_finance_default.LCOA] cannot be impacted by the design variables of the problem because no partials were defined for them in their parent component(s).
Using optimizer with multiple connections#
With both electrolyzer and ammonia in size_by_max_feedstock mode, the COBYLA optimizer can co-optimize the max_feedstock_ratio variables to minimize LCOA to $1.20/kg. This is achieved at a capacity factor of approximately 55% in both the electrolyzer and the ammonia plant.
# Create a H2Integrate model, modifying tech_config and driver_config as necessary
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"size_mode"
] = "resize_by_max_feedstock"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"flow_used_for_sizing"
] = "electricity"
tech_config["technologies"]["electrolyzer"]["model_inputs"]["performance_parameters"][
"max_feedstock_ratio"
] = 1.0
tech_config["technologies"]["ammonia"]["model_inputs"]["performance_parameters"]["size_mode"] = (
"resize_by_max_feedstock"
)
tech_config["technologies"]["ammonia"]["model_inputs"]["performance_parameters"][
"flow_used_for_sizing"
] = "hydrogen"
tech_config["technologies"]["ammonia"]["model_inputs"]["performance_parameters"][
"max_feedstock_ratio"
] = 1.0
input_config["technology_config"] = tech_config
plant_config["technology_interconnections"] = [
["hopp", "electrolyzer", "electricity", "cable"],
["electrolyzer", "ammonia", "hydrogen", "pipe"],
]
input_config["plant_config"] = plant_config
driver_config["driver"]["optimization"]["flag"] = True
driver_config["design_variables"]["electrolyzer"]["max_feedstock_ratio"]["flag"] = True
driver_config["design_variables"]["ammonia"]["max_feedstock_ratio"]["flag"] = True
input_config["driver_config"] = driver_config
model = H2IntegrateModel(input_config)
# Run the model
model.run()
# Print selected outputs
for value in [
"electrolyzer.electricity_in",
"electrolyzer.electrolyzer_size_mw",
"electrolyzer.capacity_factor",
"ammonia.hydrogen_in",
"ammonia.max_hydrogen_capacity",
"ammonia.capacity_factor",
"finance_subgroup_h2.LCOH",
"finance_subgroup_nh3.LCOA",
]:
print(value + ": " + str(np.max(model.prob.get_val(value))))
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|0
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.]),
'electrolyzer.max_feedstock_ratio': array([1.])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.29250307])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|1
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.]),
'electrolyzer.max_feedstock_ratio': array([1.])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.29250307])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|2
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.]),
'electrolyzer.max_feedstock_ratio': array([1.1])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.33682732])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|3
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.1]),
'electrolyzer.max_feedstock_ratio': array([1.])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.33851963])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|4
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.92797737]),
'electrolyzer.max_feedstock_ratio': array([0.93062608])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.18761591])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|5
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.74428337]),
'electrolyzer.max_feedstock_ratio': array([0.85152795])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.07824969])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|6
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.67920523]),
'electrolyzer.max_feedstock_ratio': array([0.66241202])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.03416033])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|7
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.4795303]),
'electrolyzer.max_feedstock_ratio': array([0.65101364])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.30719503])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|8
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.76830131]),
'electrolyzer.max_feedstock_ratio': array([0.617004])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.99401156])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|9
---------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.83327449]),
'electrolyzer.max_feedstock_ratio': array([0.54098764])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.95926094])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|10
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.90374357]),
'electrolyzer.max_feedstock_ratio': array([0.35381364])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([2.03062468])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|11
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.91925175]),
'electrolyzer.max_feedstock_ratio': array([0.59205535])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.92987297])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|12
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.01581879]),
'electrolyzer.max_feedstock_ratio': array([0.56607833])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.91223969])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|13
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.09411812]),
'electrolyzer.max_feedstock_ratio': array([0.62828134])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.98247945])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|14
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.01137891]),
'electrolyzer.max_feedstock_ratio': array([0.51627585])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.90552514])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|15
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([1.04616285]),
'electrolyzer.max_feedstock_ratio': array([0.4803582])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.91290006])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|16
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.99892829]),
'electrolyzer.max_feedstock_ratio': array([0.51738582])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.90113081])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|17
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.97487432]),
'electrolyzer.max_feedstock_ratio': array([0.51057358])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.90716512])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|18
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.99937227]),
'electrolyzer.max_feedstock_ratio': array([0.52236606])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.90128753])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|19
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.98892829]),
'electrolyzer.max_feedstock_ratio': array([0.51738571])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.89829665])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|20
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.96893307]),
'electrolyzer.max_feedstock_ratio': array([0.51694816])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.89990568])}
Driver debug print for iter coord: rank0:ScipyOptimize_COBYLA|21
----------------------------------------------------------------
Design Vars
{'ammonia.max_feedstock_ratio': array([0.99013625]),
'electrolyzer.max_feedstock_ratio': array([0.50745894])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'finance_subgroup_nh3.LCOA': array([1.90667881])}
Return from COBYLA because the trust region radius reaches its lower bound.
Number of function values = 21 Least value of F = 1.8982966469984954 Constraint violation = 0.0
The corresponding X is: [0.51738571 0.98892829]
The constraint value is:
[-0.41738571 -0.88892829 -9.48261429 -9.01107171]
Optimization Complete
-----------------------------------
electrolyzer.electricity_in: 1048680.996768964
electrolyzer.electrolyzer_size_mw: 560.0
electrolyzer.capacity_factor: 0.5057539828876682
ammonia.hydrogen_in: 10430.772135000178
ammonia.max_hydrogen_capacity: 10327.885587246077
ammonia.capacity_factor: 0.510706583441214
finance_subgroup_h2.LCOH: 6.900384304904491
finance_subgroup_nh3.LCOA: 1.906678810927961