From 0abe06fa083a9ebc6fd96ea0ec57aa2f07a7baa6 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 9 Apr 2026 12:50:50 -0600 Subject: [PATCH 001/132] added test to highlight error --- .../test/test_storage_performance_model.py | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 159ee36cf..6edcbd235 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -957,3 +957,136 @@ def test_generic_storage_with_simple_control_with_losses_round_trip(plant_config expected_charge, rtol=1e-6, ) + + +@pytest.mark.regression +@pytest.mark.parametrize("n_timesteps", [24]) +def test_generic_storage_charge_more_than_available(plant_config, subtests): + # this tests a case where the demand < charge rate and charge_rate=discharge_rate + model_inputs = { + "shared_parameters": { + "commodity": "hydrogen", + "commodity_rate_units": "kg/h", + }, + "performance_parameters": { + "max_capacity": 40, + "max_charge_rate": 10, + "min_soc_fraction": 0.1, + "max_soc_fraction": 1.0, + "init_soc_fraction": 0.1, + "commodity_amount_units": "kg", + "charge_equals_discharge": True, + "charge_efficiency": 1.0, + "discharge_efficiency": 1.0, + "demand_profile": 0.0, + }, + "control_parameters": {"set_demand_as_avg_commodity_in": False}, + } + + prob = om.Problem() + + commodity_demand = np.full(24, 5.0) + commodity_in = np.concat([np.zeros(3), np.cumsum(np.ones(15)), np.full(6, 4.0)]) + nominal_set_point = commodity_demand - commodity_in + nominal_charge_profile = np.where(nominal_set_point < 0, nominal_set_point, 0) + indx_charge = np.argwhere(nominal_charge_profile < 0).flatten() + excess_commodity_avail = np.abs( + np.abs(nominal_charge_profile)[indx_charge] - commodity_in[indx_charge] + ) + more_than_avail_charge_cmd = nominal_charge_profile[indx_charge] - excess_commodity_avail * 2 + # nominal_charge_profile[indx_charge] = more_than_avail_charge_cmd + nominal_set_point[indx_charge] = more_than_avail_charge_cmd + + prob.model.add_subsystem( + name="IVC1", + subsys=om.IndepVarComp(name="hydrogen_in", val=commodity_in, units="kg/h"), + promotes=["*"], + ) + + prob.model.add_subsystem( + name="IVC2", + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + promotes=["*"], + ) + + prob.model.add_subsystem( + name="IVC3", + subsys=om.IndepVarComp(name="hydrogen_set_point", val=nominal_set_point, units="kg/h"), + promotes=["*"], + ) + + prob.model.add_subsystem( + "storage", + StoragePerformanceModel( + plant_config=plant_config, + tech_config={"model_inputs": model_inputs}, + ), + promotes=["*"], + ) + + prob.setup() + + prob.run_model() + + performance_model_config = model_inputs["performance_parameters"] + + charge_rate = prob.get_val("storage.max_charge_rate", units="kg/h")[0] + discharge_rate = prob.get_val("storage.max_charge_rate", units="kg/h")[0] + prob.get_val("storage.storage_capacity", units="kg")[0] + + # Test that discharge is always positive + with subtests.test("Discharge is always positive"): + assert np.all(prob.get_val("storage.storage_hydrogen_discharge", units="kg/h") >= 0) + + with subtests.test("Charge is always negative"): + assert np.all(prob.get_val("storage.storage_hydrogen_charge", units="kg/h") <= 0) + + with subtests.test("Charge + Discharge == storage_hydrogen_out"): + charge_plus_discharge = prob.get_val( + "storage.storage_hydrogen_charge", units="kg/h" + ) + prob.get_val("storage.storage_hydrogen_discharge", units="kg/h") + np.testing.assert_allclose( + charge_plus_discharge, prob.get_val("storage_hydrogen_out", units="kg/h"), rtol=1e-6 + ) + with subtests.test("Initial SOC is correct"): + assert ( + pytest.approx(prob.model.get_val("storage.SOC", units="unitless")[0], rel=1e-6) + == performance_model_config["init_soc_fraction"] + ) + + with subtests.test("Charge never exceeds charge rate"): + assert ( + prob.get_val("storage.storage_hydrogen_charge", units="kg/h").min() >= -1 * charge_rate + ) + + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + + with subtests.test("Discharge never exceeds discharge rate"): + assert ( + prob.get_val("storage.storage_hydrogen_discharge", units="kg/h").max() <= discharge_rate + ) + + with subtests.test("Discharge never exceeds demand"): + assert np.all( + prob.get_val("storage.storage_hydrogen_discharge", units="kg/h").max() + <= commodity_demand + ) + + with subtests.test("Expected discharge"): + expected_discharge = np.concat([np.zeros(18), np.ones(6)]) + np.testing.assert_allclose( + prob.get_val("storage.storage_hydrogen_discharge", units="kg/h"), + expected_discharge, + rtol=1e-6, + ) + + with subtests.test("Expected charge"): + expected_charge = np.concat([np.zeros(8), np.arange(-1, -9, -1), np.zeros(8)]) + np.testing.assert_allclose( + prob.get_val("storage.storage_hydrogen_charge", units="kg/h"), + expected_charge, + rtol=1e-6, + ) From f65d00f4a90c3bb49ae689652d60f5fdb5305cc1 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:33:19 -0600 Subject: [PATCH 002/132] fixed bug of charging with unavailable commodity --- h2integrate/storage/battery/pysam_battery.py | 6 +++++- h2integrate/storage/storage_baseclass.py | 14 +++++++++++++- .../storage/test/test_storage_performance_model.py | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/h2integrate/storage/battery/pysam_battery.py b/h2integrate/storage/battery/pysam_battery.py index c20bc7b32..7848a1e54 100644 --- a/h2integrate/storage/battery/pysam_battery.py +++ b/h2integrate/storage/battery/pysam_battery.py @@ -180,6 +180,7 @@ def simulate( charge_rate: float, discharge_rate: float, storage_capacity: float, + commodity_available=list | np.ndarray, sim_start_index: int = 0, ): """Run the PySAM BatteryStateful model over a control window. @@ -236,13 +237,16 @@ def simulate( # expressed as a rate (commodity_rate_units). headroom = (soc_max - soc) * storage_capacity / self.dt_hr + # charge available based on the available input commodity + charge_available = commodity_available[sim_start_index + t] + # Calculate the max charge according to the charge rate and the simulation max_charge_input = min([charge_rate, -self.system_model.value("P_chargeable")]) # Clip to the most restrictive limit, # max(0, ...) guards against negative headroom when SOC # slightly exceeds soc_max. - actual_charge = max(0.0, min(headroom, max_charge_input, -cmd)) + actual_charge = max(0.0, min(headroom, max_charge_input, -cmd, charge_available)) # Update the charge command for the PySAM batttery cmd = -actual_charge diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index 65fa00f3e..7299b7bc4 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -269,6 +269,7 @@ def run_storage( "charge_rate": charge_rate, "discharge_rate": discharge_rate, "storage_capacity": storage_capacity, + "commodity_available": inputs[f"{self.commodity}_in"], } storage_commodity_out, soc = dispatch(self.simulate, kwargs, inputs) @@ -278,6 +279,7 @@ def run_storage( charge_rate=charge_rate, discharge_rate=discharge_rate, storage_capacity=storage_capacity, + commodity_available=inputs[f"{self.commodity}_in"], ) # determine storage charge and discharge @@ -342,6 +344,7 @@ def simulate( charge_rate: float, discharge_rate: float, storage_capacity: float, + commodity_available: list | np.ndarray, sim_start_index: int = 0, ): """Run the storage model over a control window of ``n_control_window`` timesteps. @@ -380,6 +383,8 @@ def simulate( ``commodity_rate_units`` (before discharge efficiency is applied). storage_capacity (float): Rated storage capacity in ``commodity_amount_units``. + commodity_available (list | np.ndarray): the input commodity available + to charge storage. sim_start_index (int, optional): Starting index for writing into persistent output arrays. Defaults to 0. @@ -422,11 +427,18 @@ def simulate( # expressed as a rate (commodity_rate_units). headroom = (soc_max - soc) * storage_capacity / self.dt_hr + # charge available based on the available input commodity + charge_available = commodity_available[sim_start_index + t] + # Clip to the most restrictive limit, then apply efficiency. # max(0, ...) guards against negative headroom when SOC # slightly exceeds soc_max. # correct headroom to not include charge_eff. - actual_charge = max(0.0, min(headroom / charge_eff, charge_rate, -cmd)) * charge_eff + + actual_charge = ( + max(0.0, min(headroom / charge_eff, charge_rate, -cmd, charge_available)) + * charge_eff + ) # Update SOC (actual_charge is in post-efficiency units) soc += actual_charge / storage_capacity diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 6edcbd235..386e1d515 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -1084,7 +1084,9 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): ) with subtests.test("Expected charge"): - expected_charge = np.concat([np.zeros(8), np.arange(-1, -9, -1), np.zeros(8)]) + expected_charge = np.concat( + [np.zeros(8), np.arange(-6, -10, -1), np.array([-6]), np.zeros(11)] + ) np.testing.assert_allclose( prob.get_val("storage.storage_hydrogen_charge", units="kg/h"), expected_charge, From 255b7c319ba97276bb41b23c72d35accc6672b70 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:43:52 -0600 Subject: [PATCH 003/132] added subtests for charging less than available --- .../control/test/test_optimal_controllers.py | 20 +++++++++++++++ .../battery/test/test_pysam_battery.py | 14 +++++++++++ .../storage/test/test_storage_auto_sizing.py | 17 +++++++++++++ .../test/test_storage_performance_model.py | 25 +++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/h2integrate/control/test/test_optimal_controllers.py b/h2integrate/control/test/test_optimal_controllers.py index f1f1d5496..84528b11a 100644 --- a/h2integrate/control/test/test_optimal_controllers.py +++ b/h2integrate/control/test/test_optimal_controllers.py @@ -328,6 +328,11 @@ def test_min_operating_cost_load_following_battery_dispatch( rtol=1e-2, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("battery.storage_electricity_charge", units="kW") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= electricity_in[indx_charging]) + @pytest.mark.regression def test_optimal_control_with_generic_storage( @@ -477,6 +482,11 @@ def test_optimal_control_with_generic_storage( rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("h2_storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression def test_optimal_dispatch_with_autosizing_storage_demand_less_than_avg_in( @@ -547,6 +557,11 @@ def test_optimal_dispatch_with_autosizing_storage_demand_less_than_avg_in( rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("h2_storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression def test_optimal_dispatch_with_autosizing_storage_demand_is_avg_in( @@ -624,3 +639,8 @@ def test_optimal_dispatch_with_autosizing_storage_demand_is_avg_in( expected_charge, rtol=1e-6, ) + + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("h2_storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) diff --git a/h2integrate/storage/battery/test/test_pysam_battery.py b/h2integrate/storage/battery/test/test_pysam_battery.py index 1f47e22c5..9089e7c9b 100644 --- a/h2integrate/storage/battery/test/test_pysam_battery.py +++ b/h2integrate/storage/battery/test/test_pysam_battery.py @@ -190,6 +190,10 @@ def test_pysam_battery_performance_model_without_controller(plant_config, subtes expected_unused_electricity, rtol=1e-2, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage_electricity_charge", units="kW") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= electricity_in[indx_charging]) @pytest.mark.regression @@ -382,6 +386,11 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): == init_charge_rate ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob_init.get_val("pysam_battery.storage_electricity_charge", units="kW") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= electricity_in[indx_charging]) + # Re-run and set the charge rate as half of what it was before prob = om.Problem() prob.model.add_subsystem( @@ -458,3 +467,8 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): ) == 2.5 ) + + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("pysam_battery.storage_electricity_charge", units="kW") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= electricity_in[indx_charging]) diff --git a/h2integrate/storage/test/test_storage_auto_sizing.py b/h2integrate/storage/test/test_storage_auto_sizing.py index e7918ff5f..3aa247a78 100644 --- a/h2integrate/storage/test/test_storage_auto_sizing.py +++ b/h2integrate/storage/test/test_storage_auto_sizing.py @@ -188,6 +188,10 @@ def test_storage_autosizing_basic_performance_no_losses(plant_config, subtests): assert ( pytest.approx(prob.get_val("unused_hydrogen_out", units="kg/h").sum(), rel=1e-6) == 5.0 ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) @pytest.mark.regression @@ -285,6 +289,10 @@ def test_storage_autosizing_soc_bounds(plant_config, subtests): np.testing.assert_allclose( prob.get_val("hydrogen_out", units="kg/h"), commodity_demand, rtol=1e-6, atol=1e-10 ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) @pytest.mark.regression @@ -416,6 +424,11 @@ def test_storage_autosizing_losses(plant_config, subtests): atol=1e-10, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) @@ -507,3 +520,7 @@ def test_storage_autosizing_with_passthrough_controller(plant_config, subtests): rtol=1e-6, atol=1e-10, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 386e1d515..f07c40e08 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -184,6 +184,11 @@ def test_generic_storage_with_simple_control_dmd_lessthan_charge_rate(plant_conf rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) @@ -376,6 +381,11 @@ def test_generic_storage_with_simple_control_charge_rate_lessthan_demand(plant_c rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) @@ -537,6 +547,11 @@ def test_generic_storage_with_simple_control_zero_size(plant_config, subtests): == performance_model_config["init_soc_fraction"] ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) @@ -764,6 +779,11 @@ def test_generic_storage_with_simple_control_with_losses(plant_config, subtests) rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) @@ -958,6 +978,11 @@ def test_generic_storage_with_simple_control_with_losses_round_trip(plant_config rtol=1e-6, ) + with subtests.test("Charge never exceeds available commodity"): + charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") + indx_charging = np.argwhere(charge_profile).flatten() + assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) + @pytest.mark.regression @pytest.mark.parametrize("n_timesteps", [24]) From ade5a20ebf2a99c248c2d40b2ae46533c16600d1 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:56:49 -0600 Subject: [PATCH 004/132] added test for technology naming and updated logic for using_feedback_control in storage baseclass setup() --- ...est_multistorage_pyomo_openloop_control.py | 98 +++++++++++++++++++ h2integrate/storage/storage_baseclass.py | 2 +- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/h2integrate/control/test/test_multistorage_pyomo_openloop_control.py b/h2integrate/control/test/test_multistorage_pyomo_openloop_control.py index dc41da0fe..33841e0ae 100644 --- a/h2integrate/control/test/test_multistorage_pyomo_openloop_control.py +++ b/h2integrate/control/test/test_multistorage_pyomo_openloop_control.py @@ -788,3 +788,101 @@ def test_battery_pyomo_h2s_openloop(subtests, plant_config): h2s_expected_discharge, rtol=1e-6, ) + + +@pytest.mark.regression +@pytest.mark.parametrize("pyo_controllers", ["bat"]) +def test_battery_pyomo_battery_openloop(subtests, plant_config): + bat2_expected_discharge = np.concat([np.zeros(18), np.ones(6)]) + bat2_expected_charge = np.concat([np.zeros(8), np.arange(-1, -9, -1), np.zeros(8)]) + bat_expected_charge = np.concat( + [ + np.zeros(12), + np.array( + [ + -3988.62235554, + -3989.2357847, + -3989.76832626, + -3990.26170521, + -3990.71676106, + -3991.13573086, + -3991.52143699, + -3991.87684905, + -3992.20485715, + -3992.50815603, + -3992.78920148, + -3993.05020268, + ] + ), + ] + ) + bat_expected_discharge = np.concat( + [ + np.array( + [ + 5999.99995059, + 5990.56676743, + 5990.138959, + 5989.64831176, + 5989.08548217, + 5988.44193888, + 5987.70577962, + 5986.86071125, + 5985.88493352, + 5984.7496388, + 5983.41717191, + 5981.839478, + ] + ), + np.zeros(12), + ] + ) + + prob = om.Problem() + + # make h2 storage group + h2s_group = prob.model.add_subsystem("battery_2", om.Group()) + h2s_ivc_comp, h2s_perf_comp, h2s_control_comp = make_h2_storage_openloop_group(plant_config) + h2s_group.add_subsystem("IVC1", h2s_ivc_comp, promotes=["*"]) + h2s_group.add_subsystem("control", h2s_control_comp, promotes=["*"]) + h2s_group.add_subsystem("perf", h2s_perf_comp, promotes=["*"]) + + # make battery group + bat_rule_comp, bat_perf_comp, bat_control_comp, electricity_in = make_battery_pyo_group( + plant_config + ) + bat_group = prob.model.add_subsystem("battery", om.Group()) + bat_group.add_subsystem("IVC2", electricity_in, promotes=["*"]) + bat_group.add_subsystem("rule", bat_rule_comp, promotes=["*"]) + bat_group.add_subsystem("control", bat_control_comp, promotes=["*"]) + bat_group.add_subsystem("perf", bat_perf_comp, promotes=["*"]) + + prob.setup() + prob.run_model() + + with subtests.test("Battery #1: Expected charge"): + np.testing.assert_allclose( + prob.get_val("battery.storage_electricity_charge", units="kW")[:24], + bat_expected_charge, + rtol=1e-6, + ) + with subtests.test("Battery #1: Expected discharge"): + np.testing.assert_allclose( + prob.get_val("battery.storage_electricity_discharge", units="kW")[:24], + bat_expected_discharge, + rtol=1e-6, + ) + + # battery_2 is a "hydrogen battery" + with subtests.test("Battery #2: Expected charge"): + np.testing.assert_allclose( + prob.get_val("battery_2.storage_hydrogen_charge", units="kg/h")[:24], + bat2_expected_charge, + rtol=1e-6, + ) + with subtests.test("Battery #2: Expected discharge"): + np.testing.assert_allclose( + prob.get_val("battery_2.storage_hydrogen_discharge", units="kg/h")[:24], + bat2_expected_discharge, + rtol=1e-6, + ) diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index 7299b7bc4..28d96f822 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -181,7 +181,7 @@ def setup(self): for _source_tech, intended_dispatch_tech in self.options["plant_config"][ "tech_to_dispatch_connections" ]: - if any(intended_dispatch_tech in name for name in self.tech_group_name): + if any(intended_dispatch_tech == name for name in self.tech_group_name): self.add_discrete_input("pyomo_dispatch_solver", val=lambda: None) # set the using feedback control variable to True using_feedback_control = True From a2fe7822ffb391af16b1bd194e3b2686acdf6af8 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:22:09 -0600 Subject: [PATCH 005/132] other fixes from merge --- h2integrate/storage/test/test_storage_auto_sizing.py | 10 ++++------ .../storage/test/test_storage_performance_model.py | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/h2integrate/storage/test/test_storage_auto_sizing.py b/h2integrate/storage/test/test_storage_auto_sizing.py index 3912ff214..3fa782f2c 100644 --- a/h2integrate/storage/test/test_storage_auto_sizing.py +++ b/h2integrate/storage/test/test_storage_auto_sizing.py @@ -188,16 +188,14 @@ def test_storage_autosizing_basic_performance_no_losses(plant_config, subtests): ) with subtests.test("Total unused commodity"): - assert ( - pytest.approx(prob.get_val("unused_hydrogen_out", units="kg/h").sum(), rel=1e-6) == 5.0 - ) + combined_out = prob.get_val("hydrogen_out", units="kg/h") + commodity_in + unused_commodity_out = combined_out - commodity_demand + assert pytest.approx(unused_commodity_out.sum(), rel=1e-6) == 5.0 + with subtests.test("Charge never exceeds available commodity"): charge_profile = prob.get_val("storage.storage_hydrogen_charge", units="kg/h") indx_charging = np.argwhere(charge_profile).flatten() assert np.all(np.abs(charge_profile)[indx_charging] <= commodity_in[indx_charging]) - combined_out = prob.get_val("hydrogen_out", units="kg/h") + commodity_in - unused_commodity_out = combined_out - commodity_demand - assert pytest.approx(unused_commodity_out.sum(), rel=1e-6) == 5.0 @pytest.mark.regression diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 39c44b54a..542c03463 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -1121,7 +1121,7 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): "storage.storage_hydrogen_charge", units="kg/h" ) + prob.get_val("storage.storage_hydrogen_discharge", units="kg/h") np.testing.assert_allclose( - charge_plus_discharge, prob.get_val("storage_hydrogen_out", units="kg/h"), rtol=1e-6 + charge_plus_discharge, prob.get_val("hydrogen_out", units="kg/h"), rtol=1e-6 ) with subtests.test("Initial SOC is correct"): assert ( @@ -1169,7 +1169,7 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): ) with subtests.test("Expected capacity factor"): assert ( - pytest.approx(-17.5, rel=1e-6) + pytest.approx(-12.5, rel=1e-6) == prob.get_val("storage.capacity_factor", units="percent")[0] ) From 3d0e272fcf75ba619019a0cc6cc9c86ef7adb6c8 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 28 Apr 2026 10:57:11 -0600 Subject: [PATCH 006/132] Add system_level_control to the CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b362c792..f9f154f59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: branches: - main - develop + - system_level_control pull_request: branches: - main From d13d25a4425808a6a853d2b56cbb2723cb251d81 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:22:14 -0600 Subject: [PATCH 007/132] added control classifiers to key technology models --- h2integrate/converters/ammonia/ammonia_synloop.py | 1 + h2integrate/converters/grid/grid.py | 1 + h2integrate/converters/hydrogen/pem_electrolyzer.py | 1 + h2integrate/converters/natural_gas/natural_gas_cc_ct.py | 1 + h2integrate/converters/solar/solar_baseclass.py | 1 + h2integrate/converters/wind/wind_plant_baseclass.py | 1 + h2integrate/storage/storage_baseclass.py | 1 + 7 files changed, 7 insertions(+) diff --git a/h2integrate/converters/ammonia/ammonia_synloop.py b/h2integrate/converters/ammonia/ammonia_synloop.py index ac1308c29..972de7207 100644 --- a/h2integrate/converters/ammonia/ammonia_synloop.py +++ b/h2integrate/converters/ammonia/ammonia_synloop.py @@ -143,6 +143,7 @@ class AmmoniaSynLoopPerformanceModel(ResizeablePerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/grid/grid.py b/h2integrate/converters/grid/grid.py index cb0760c47..dfe61b572 100644 --- a/h2integrate/converters/grid/grid.py +++ b/h2integrate/converters/grid/grid.py @@ -51,6 +51,7 @@ class GridPerformanceModel(PerformanceModelBaseClass): 300, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 57bd10908..0e18eb985 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -63,6 +63,7 @@ class ECOElectrolyzerPerformanceModel(ElectrolyzerPerformanceBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def setup(self): self.config = ECOElectrolyzerPerformanceModelConfig.from_dict( diff --git a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py index 41771ebae..21bb091ff 100644 --- a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py +++ b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py @@ -60,6 +60,7 @@ class NaturalGasPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/solar/solar_baseclass.py b/h2integrate/converters/solar/solar_baseclass.py index 0bfa4019c..cdb125a8d 100644 --- a/h2integrate/converters/solar/solar_baseclass.py +++ b/h2integrate/converters/solar/solar_baseclass.py @@ -6,6 +6,7 @@ class SolarPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/wind/wind_plant_baseclass.py b/h2integrate/converters/wind/wind_plant_baseclass.py index 6e4de0bd2..b8a90ed6e 100644 --- a/h2integrate/converters/wind/wind_plant_baseclass.py +++ b/h2integrate/converters/wind/wind_plant_baseclass.py @@ -6,6 +6,7 @@ class WindPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index 803966d70..9de0fc0ad 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -49,6 +49,7 @@ class StoragePerformanceBase(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "storage" def setup(self): """Set up the storage performance model in OpenMDAO. From c51d33d0cc6315622a6315769f8deaeb346c221c Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:38:18 -0600 Subject: [PATCH 008/132] added curtailable component --- .../converters/curtailable_component.py | 48 ++++++++++++++++ .../test/test_curtailable_component.py | 56 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 h2integrate/control/control_strategies/converters/curtailable_component.py create mode 100644 h2integrate/control/control_strategies/converters/test/test_curtailable_component.py diff --git a/h2integrate/control/control_strategies/converters/curtailable_component.py b/h2integrate/control/control_strategies/converters/curtailable_component.py new file mode 100644 index 000000000..54578a5cb --- /dev/null +++ b/h2integrate/control/control_strategies/converters/curtailable_component.py @@ -0,0 +1,48 @@ +import numpy as np +import openmdao.api as om + + +class CurtailableComponentModel(om.ExplicitComponent): + _time_step_bounds = ( + 1, + 1e9, + ) # (min, max) time step lengths (in seconds) compatible with this model + + def initialize(self): + self.options.declare("commodity", types=str) + self.options.declare("plant_config", types=dict) + + def setup(self): + self.commodity = self.options["commodity"] + n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) + self.add_input(f"{self.commodity}_out", shape=n_timesteps, units=None, units_by_conn=True) + self.add_input( + f"{self.commodity}_set_point", + shape=n_timesteps, + units=None, + copy_units=f"{self.commodity}_out", + ) + + self.add_output( + f"modulated_{self.commodity}_out", + shape=n_timesteps, + units=None, + copy_units=f"{self.commodity}_out", + ) + self.add_output( + f"curtailed_{self.commodity}_out", + shape=n_timesteps, + units=None, + copy_units=f"{self.commodity}_out", + ) + + def compute(self, inputs, outputs): + set_point_difference = ( + inputs[f"{self.commodity}_out"] - inputs[f"{self.commodity}_set_point"] + ) + # commodity_out exceeds setpoint + excess_commodity = np.where(set_point_difference > 0, set_point_difference, 0) + commodity_to_setpoint = inputs[f"{self.commodity}_out"] - excess_commodity + + outputs[f"modulated_{self.commodity}_out"] = commodity_to_setpoint + outputs[f"curtailed_{self.commodity}_out"] = excess_commodity diff --git a/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py new file mode 100644 index 000000000..a08b37774 --- /dev/null +++ b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py @@ -0,0 +1,56 @@ +import numpy as np +import openmdao.api as om +from pytest import fixture + +from h2integrate.control.control_strategies.converters.curtailable_component import ( + CurtailableComponentModel, +) + + +@fixture +def plant_config_base(): + plant_config = { + "plant": { + "plant_life": 30, + "simulation": { + "n_timesteps": 8760, + "dt": 3600, + "timezone": 0, + "start_time": "01/01/2000 00:00:00", + }, + } + } + + return plant_config + + +def test_curtailable_component(plant_config_base, subtests): + prob = om.Problem() + + prob.model.add_subsystem( + name="IVC1", + subsys=om.IndepVarComp(name="hydrogen_out", val=20, shape=8760, units="kg/h"), + promotes=["*"], + ) + + prob.model.add_subsystem( + name="IVC2", + subsys=om.IndepVarComp(name="hydrogen_set_point", val=10, shape=8760, units="kg/h"), + promotes=["*"], + ) + + prob.model.add_subsystem( + "comp", + CurtailableComponentModel( + plant_config=plant_config_base, + commodity="hydrogen", + ), + promotes=["*"], + ) + + prob.setup() + + prob.run_model() + + with subtests.test("modulated output"): + assert np.all(prob.get_val("comp.modulated_hydrogen_out", units="kg/h") == 10) From 0e9dd0b66be169222a7c4816255de27806001ae7 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:56:00 -0600 Subject: [PATCH 009/132] added logic in h2imodel to add curtailment component to curtailment control_classifiers models --- .../control_strategies/converters/__init__.py | 0 h2integrate/core/h2integrate_model.py | 63 +++++++++++++++++++ h2integrate/core/supported_models.py | 5 ++ h2integrate/transporters/generic_combiner.py | 2 + h2integrate/transporters/generic_splitter.py | 2 + 5 files changed, 72 insertions(+) create mode 100644 h2integrate/control/control_strategies/converters/__init__.py diff --git a/h2integrate/control/control_strategies/converters/__init__.py b/h2integrate/control/control_strategies/converters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 652640a07..466fa80b4 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -46,6 +46,11 @@ def __init__(self, config_input): # read in config file; it's a yaml dict that looks like this: self.load_config(config_input) + # add bool for whether using system-level control + self.slc = False + if "system_level_control" in self.plant_config: + self.slc = True + # load in supported models self.supported_models = supported_models.copy() @@ -463,6 +468,7 @@ def create_technology_models(self): self.dispatch_rule_sets = [] self.cost_models = [] self.finance_models = [] + self.tech_control_classifiers = {} # for system-level control combined_performance_and_cost_models = [ "HOPPComponent", @@ -520,6 +526,7 @@ def create_technology_models(self): tech_config=individual_tech_config, ) self._check_time_step(perf_model, comp) + self.tech_control_classifiers.update({tech_name: "feedback"}) self.plant.add_subsystem(f"{tech_name}_source", comp) else: tech_group = self.plant.add_subsystem(tech_name, om.Group()) @@ -555,6 +562,9 @@ def create_technology_models(self): plant_config=self.plant_config, tech_config=individual_tech_config, ) + + self._check_control_classifier(perf_model, comp) + self.tech_control_classifiers.update({tech_name: comp._control_classifier}) self._check_time_step(perf_model, comp) om_model_object = tech_group.add_subsystem(perf_model, comp, promotes=["*"]) self.performance_models.append(om_model_object) @@ -583,6 +593,52 @@ def create_technology_models(self): plural_model_type_name = model_type + "s" getattr(self, plural_model_type_name).append(om_model_object) + # below logic is only used if using system-level control + if self.slc and model_type == "performance_model": + self._check_control_classifier(perf_model, om_model_object) + control_classifier = comp._control_classifier + self.tech_control_classifiers.update( + {tech_name: getattr(comp, control_classifier)} + ) + + # add curtail component to curtailable technology performance models + if control_classifier == "curtailable": + # get the commodity output from this component with length + # 4 connections + # TODO: update to handle length 3 connections + tech_is_source_connections = [ + k + for k in self.plant_config["technology_interconnections"] + if k[0] == tech_name and len(k) == 4 + ] + if len(tech_is_source_connections) == 0: + msg = ( + f"{tech_name} is not a source technology " + f"for another component" + ) + + raise ValueError(msg) + # Get unique commodity outputs + tech_commodity_output = list( + {k[3] for k in tech_is_source_connections} + ) + if len(tech_commodity_output) > 1: + msg = ( + f"{tech_name} has multiple commodity outputs " + f"({tech_commodity_output}) which is not yet supported" + ) + raise ValueError(msg) + # get the commodity of the component + model_object = self.supported_models["CurtailableComponentModel"] + om_model_object = tech_group.add_subsystem( + "CurtailableComponentModel", + model_object( + commodity=tech_commodity_output[0], + plant_config=self.plant_config, + ), + promotes=["*"], + ) + # Process the finance models if "finance_model" in individual_tech_config: if "model" in individual_tech_config["finance_model"]: @@ -648,6 +704,13 @@ def _check_time_step(self, model_name, model_object): ) raise ValueError(msg) + def _check_control_classifier(self, model_name, model_object): + if not self.slc: + return + if not hasattr(model_object, "_control_classifier"): + msg = f"Model {model_name} is missing a control classifier" + raise ValueError(msg) + def create_finance_model(self): """ Create and configure the finance model(s) for the plant. diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 62e197de9..98249fb09 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -158,6 +158,9 @@ from h2integrate.control.control_rules.storage.pyomo_storage_rule_baseclass import ( PyomoRuleStorageBaseclass, ) +from h2integrate.control.control_strategies.converters.curtailable_component import ( + CurtailableComponentModel, +) from h2integrate.resource.solar.nlr_developer_meteosat_prime_meridian_models import ( MeteosatPrimeMeridianSolarAPI, MeteosatPrimeMeridianTMYSolarAPI, @@ -281,6 +284,8 @@ "IronTransportCostComponent": IronTransportCostComponent, # Simple Summers "GenericSummerPerformanceModel": GenericSummerPerformanceModel, + # Curtailable component + "CurtailableComponentModel": CurtailableComponentModel, # Storage "PySAMBatteryPerformanceModel": PySAMBatteryPerformanceModel, "StoragePerformanceModel": StoragePerformanceModel, diff --git a/h2integrate/transporters/generic_combiner.py b/h2integrate/transporters/generic_combiner.py index d9d11a2ef..c02ef56f4 100644 --- a/h2integrate/transporters/generic_combiner.py +++ b/h2integrate/transporters/generic_combiner.py @@ -43,6 +43,8 @@ class GenericCombinerPerformanceModel(om.ExplicitComponent): 1e9, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "connector" + def initialize(self): self.options.declare("driver_config", types=dict) self.options.declare("plant_config", types=dict) diff --git a/h2integrate/transporters/generic_splitter.py b/h2integrate/transporters/generic_splitter.py index 3f07a3df8..1573a83f5 100644 --- a/h2integrate/transporters/generic_splitter.py +++ b/h2integrate/transporters/generic_splitter.py @@ -68,6 +68,8 @@ class GenericSplitterPerformanceModel(om.ExplicitComponent): 1e9, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "connector" + def initialize(self): self.options.declare("driver_config", types=dict, default={}) self.options.declare("plant_config", types=dict, default={}) From 0cedd828f5ce30577e23d2ed27cebb15e00632c2 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 28 Apr 2026 15:48:51 -0600 Subject: [PATCH 010/132] Working through start of system level controller --- .../23_solar_wind_ng_demand/plant_config.yaml | 10 +- .../system_level/system_level_control.py | 156 ++++++++++++++++++ 2 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 h2integrate/control/control_strategies/system_level/system_level_control.py diff --git a/examples/23_solar_wind_ng_demand/plant_config.yaml b/examples/23_solar_wind_ng_demand/plant_config.yaml index cdb2b956b..5bf31591d 100644 --- a/examples/23_solar_wind_ng_demand/plant_config.yaml +++ b/examples/23_solar_wind_ng_demand/plant_config.yaml @@ -21,14 +21,14 @@ sites: # this will naturally grow as we mature the interconnected tech technology_interconnections: - [wind, combiner, electricity, cable] - # source_tech, dest_tech, transport_item, transport_type = connection + # source_tech, dest_tech, transport_item, transport_type = connection - [solar, combiner, electricity, cable] - [ng_feedstock, natural_gas_plant, natural_gas, pipe] - # connect NG feedstock to NG plant - - [combiner, electrical_load_demand, [electricity_out, electricity_in]] - # subtract wind and solar from demand + # connect NG feedstock to NG plant + - [combiner, electrical_load_demand, electricity, cable] + # subtract wind and solar from demand - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] - # give remaining load demand to natural gas plant + # give remaining load demand to natural gas plant - [combiner, fin_combiner, electricity, cable] - [natural_gas_plant, fin_combiner, electricity, cable] resource_to_tech_connections: diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py new file mode 100644 index 000000000..f67222736 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -0,0 +1,156 @@ +import numpy as np +import openmdao.api as om + + +class SystemLevelControl(om.ExplicitComponent): + """System-level control that satisfies demand evenly across all technologies. + + Parses ``technology_interconnections`` and ``tech_config`` to identify: + + - **Demand technology**: the single component with a ``demand_profile`` + - **Dispatchable technologies**: all producing technologies found in + 4-element connections (excluding demand techs, combiners, splitters, + and feedstocks) + + Only one commodity demand stream is supported. At each timestep the + demand is distributed equally as set-points to the dispatchable + technologies. + """ + + def initialize(self): + self.options.declare("driver_config", types=dict) + self.options.declare("plant_config", types=dict) + self.options.declare("tech_config", types=dict) + + def setup(self): + plant_config = self.options["plant_config"] + tech_config = self.options["tech_config"] + + self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] + interconnections = plant_config.get("technology_interconnections", []) + technologies = tech_config.get("technologies", {}) + + # ---- 1. Identify the (single) demand technology from tech_config ---- + # A demand tech has ``demand_profile`` in its performance or shared params. + self.commodity = None + self.demand_profile = None + self.commodity_units = None + for tech_name, tech_def in technologies.items(): + model_inputs = tech_def.get("model_inputs", {}) + perf_params = model_inputs.get("performance_parameters", {}) + shared_params = model_inputs.get("shared_parameters", {}) + all_params = {**shared_params, **perf_params} + + if "demand_profile" in all_params: + if self.commodity is not None: + raise ValueError( + "SystemLevelControl currently supports only one demand " + f"stream, but found demands for both '{self.commodity}' " + f"and '{all_params['commodity']}'." + ) + self.commodity = all_params["commodity"] + self.commodity_units = all_params.get("commodity_rate_units", None) + self.demand_profile = all_params["demand_profile"] + self.demand_tech = tech_name + + # ---- 2. Identify all dispatchable (producing) technologies ---- + # Every source tech in a 4-element connection is dispatchable, + # excluding demand techs, infrastructure (combiners, splitters), + # and feedstocks. + demand_tech_names = {self.demand_tech} if self.commodity else set() + + infrastructure_techs = set() + feedstock_techs = set() + for tech_name, tech_def in technologies.items(): + model_name = tech_def.get("performance_model", {}).get("model", "") + if "Combiner" in model_name or "Splitter" in model_name: + infrastructure_techs.add(tech_name) + if "Feedstock" in model_name: + feedstock_techs.add(tech_name) + + excluded = demand_tech_names | infrastructure_techs | feedstock_techs + + self.dispatchable_techs = [] # [tech_name, ...] + seen = set() + for connection in interconnections: + if len(connection) == 4: + source_tech, _dest, commodity, _transport = connection + if ( + commodity == self.commodity + and source_tech not in excluded + and source_tech not in seen + ): + self.dispatchable_techs.append(source_tech) + seen.add(source_tech) + + # Also pick up destination techs from 3-element set-point connections + # that weren't already found via 4-element connections. + for connection in interconnections: + if len(connection) == 3: + _source, dest_tech, var_mapping = connection + if isinstance(var_mapping, list | tuple) and len(var_mapping) == 2: + _src_var, dst_var = var_mapping + if "_set_point" in dst_var: + commodity = dst_var.replace("_set_point", "") + if ( + commodity == self.commodity + and dest_tech not in excluded + and dest_tech not in seen + ): + self.dispatchable_techs.append(dest_tech) + seen.add(dest_tech) + + # ---- 3. Add OpenMDAO inputs / outputs ---- + # Input: demand profile + self.demand_input_name = f"{self.commodity}_demand" + self.add_input( + self.demand_input_name, + val=self.demand_profile, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Demand profile of {self.commodity}", + ) + + # Inputs: commodity output from each dispatchable tech + self.commodity_input_names = [] + for tech_name in self.dispatchable_techs: + var_name = f"{tech_name}_{self.commodity}_out" + self.add_input( + var_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) + self.commodity_input_names.append(var_name) + + # Outputs: set-points for all dispatchable techs + self.set_point_output_names = [] + for tech_name in self.dispatchable_techs: + var_name = f"{tech_name}_{self.commodity}_set_point" + self.add_output( + var_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} production", + ) + self.set_point_output_names.append(var_name) + + def compute(self, inputs, outputs): + demand = np.maximum(inputs[self.demand_input_name], 0.0) + + # Sum actual commodity output from all dispatchable techs + total_supply = np.zeros(self.n_timesteps) + for var_name in self.commodity_input_names: + total_supply += inputs[var_name] + + # Gap between demand and current total supply + gap = demand - total_supply + + # Adjust each tech's set_point: current output + its share of the gap + n_dispatchable = len(self.set_point_output_names) + if n_dispatchable > 0: + correction = gap / n_dispatchable + for var_name, in_name in zip(self.set_point_output_names, self.commodity_input_names): + outputs[var_name] = inputs[in_name] + correction From 0aff1348a9ab3d92ac72fd16005b3afee0e39c33 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 28 Apr 2026 22:42:51 -0600 Subject: [PATCH 011/132] Added initial system level control example --- .../driver_config.yaml | 4 + .../35_system_level_control/plant_config.yaml | 101 +++++++++ .../run_wind_ng_demand.py | 102 +++++++++ .../35_system_level_control/tech_config.yaml | 114 ++++++++++ .../wind_ng_demand.yaml | 5 + .../system_level/system_level_control.py | 208 ++++++++++-------- 6 files changed, 440 insertions(+), 94 deletions(-) create mode 100644 examples/35_system_level_control/driver_config.yaml create mode 100644 examples/35_system_level_control/plant_config.yaml create mode 100644 examples/35_system_level_control/run_wind_ng_demand.py create mode 100644 examples/35_system_level_control/tech_config.yaml create mode 100644 examples/35_system_level_control/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/driver_config.yaml b/examples/35_system_level_control/driver_config.yaml new file mode 100644 index 000000000..5b6b7e05a --- /dev/null +++ b/examples/35_system_level_control/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: This analysis runs a natural gas power plant +general: + folder_output: outputs diff --git a/examples/35_system_level_control/plant_config.yaml b/examples/35_system_level_control/plant_config.yaml new file mode 100644 index 000000000..80dff18d7 --- /dev/null +++ b/examples/35_system_level_control/plant_config.yaml @@ -0,0 +1,101 @@ +name: plant_config +description: This plant is located in Texas, USA. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 +# array of arrays containing left-to-right technology +# interconnections; can support bidirectional connections +# with the reverse definition. +# this will naturally grow as we mature the interconnected tech +technology_interconnections: + - [wind, combiner, electricity, cable] + # source_tech, dest_tech, transport_item, transport_type = connection + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + # connect NG feedstock to NG plant + - [combiner, electrical_load_demand, electricity, cable] + # subtract wind and solar from demand + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] + # give remaining load demand to natural gas plant + - [combiner, fin_combiner, electricity, cable] + - [natural_gas_plant, fin_combiner, electricity, cable] +resource_to_tech_connections: + # connect the wind resource to the wind technology + - [site.wind_resource, wind, wind_resource_data] + - [site.solar_resource, solar, solar_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +finance_parameters: + finance_groups: + profast_lco: + 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.] + profast_npv: + finance_model: ProFastNPV + model_inputs: + commodity_sell_price: 0.05167052 + 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.] + finance_subgroups: + renewables: + commodity: electricity + commodity_stream: combiner + finance_groups: [profast_lco, profast_npv] + technologies: [solar, wind] + natural_gas: + commodity: electricity + commodity_stream: natural_gas_plant + finance_groups: [profast_lco] + technologies: [natural_gas_plant, ng_feedstock] + electricity: + commodity: electricity + commodity_stream: fin_combiner + finance_groups: [profast_lco] + technologies: [solar, wind, natural_gas_plant, ng_feedstock] + cost_adjustment_parameters: + cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year + target_dollar_year: 2022 diff --git a/examples/35_system_level_control/run_wind_ng_demand.py b/examples/35_system_level_control/run_wind_ng_demand.py new file mode 100644 index 000000000..4abe424ff --- /dev/null +++ b/examples/35_system_level_control/run_wind_ng_demand.py @@ -0,0 +1,102 @@ +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +################################## +# Create an H2I model with a fixed electricity load demand +h2i = H2IntegrateModel("solar_wind_ng_demand.yaml") + +# Run the model +h2i.run() + +# Post-process the results +h2i.post_process() + + +################################## +# Create H2I model but replace electrical load demand to be flexible +h2i_flexible = H2IntegrateModel("solar_wind_ng_flexible_demand.yaml") + +# Run the model +h2i_flexible.run() + +# Post-process the results +h2i_flexible.post_process() + +import matplotlib.pyplot as plt + + +# Battery dispatch plotting +model = h2i_flexible +fig, ax = plt.subplots(2, 1, sharex=True, figsize=(11, 9)) + +start_hour = 0 +end_hour = 200 +total_time_steps = model.prob.get_val("wind.electricity_out", units="MW").size +demand_profile = [ + model.technology_config["technologies"]["electrical_load_demand"]["model_inputs"][ + "control_parameters" + ]["demand_profile"] + * 1e-3 +] * total_time_steps + +# First subplot for wind and solar production and baseline demand profile +ax[0].plot( + range(start_hour, end_hour), + model.prob.get_val("wind.electricity_out", units="MW")[start_hour:end_hour], + linestyle="-", + label="Wind Electricity (MW)", + linewidth=2, + color="blue", +) +ax[0].plot( + range(start_hour, end_hour), + model.prob.get_val("solar.electricity_out", units="MW")[start_hour:end_hour], + linestyle="-", + label="Solar Electricity (MW)", + linewidth=2, + color="gold", +) + +ax[0].plot( + range(start_hour, end_hour), + demand_profile[start_hour:end_hour], + linestyle="--", + label="Baseline Electricity Demand (MW)", + linewidth=2, +) +ax[0].set_ylabel("Generation (MW)") +ax[0].legend(loc="upper right") + +# Second subplot for renewables electricity, NG electricity, and flexible demand profile +ax[1].plot( + range(start_hour, end_hour), + model.prob.get_val("combiner.electricity_out", units="MW")[start_hour:end_hour], + linestyle="-", + label="Combined Wind+Solar Electricity (MW)", + linewidth=2, + color="green", +) +ax[1].plot( + range(start_hour, end_hour), + model.prob.get_val("natural_gas_plant.electricity_out", units="MW")[start_hour:end_hour], + linestyle="-", + label="NG Plant Electricity (MW)", + linewidth=2, + color="orange", +) +ax[1].plot( + range(start_hour, end_hour), + model.prob.get_val("electrical_load_demand.electricity_flexible_demand_profile", units="MW")[ + start_hour:end_hour + ], + linestyle="--", + label="Flexible Demand Profile (MW)", + linewidth=2, + color="purple", +) +ax[1].set_ylabel("Generation & Demand (MW)") +ax[1].set_xlabel("Timestep (hr)") +ax[1].legend(loc="upper right") + +plt.tight_layout() +plt.show() diff --git a/examples/35_system_level_control/tech_config.yaml b/examples/35_system_level_control/tech_config.yaml new file mode 100644 index 000000000..e044c1788 --- /dev/null +++ b/examples/35_system_level_control/tech_config.yaml @@ -0,0 +1,114 @@ +name: technology_config +description: This plant produces electricity with wind, solar, and a natural gas power plant to meet a fixed electrical load + demand. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + solar: + performance_model: + model: PYSAMSolarPlantPerformanceModel + cost_model: + model: ATBUtilityPVCostModel + model_inputs: + performance_parameters: + pv_capacity_kWdc: 100000 # 100 MWdc + dc_ac_ratio: 1.34 + create_model_from: new + tilt_angle_func: none + tilt: 0 + pysam_options: + SystemDesign: + gcr: 0.3 + array_type: 2 + bifaciality: 0.65 + inv_eff: 96.0 + losses: 14.6 + module_type: 1 + azimuth: 180 + rotlim: 45 + SolarResource: + albedo_default: 0.2 + cost_parameters: + capex_per_kWac: 1193 + opex_per_kWac_per_year: 18 + cost_year: 2024 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. # MMBtu + cost_parameters: + cost_year: 2023 + price: 4.2 # USD/MMBtu + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 # MMBtu/MWh - typical for NGCC + system_capacity_mw: 100. # MW + cost_parameters: + capex_per_kw: 1000 # $/kW - typical for NGCC + fixed_opex_per_kw_per_year: 10.0 # $/kW/year + variable_opex_per_mwh: 0.0 # $/MWh + cost_year: 2023 + electrical_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 100000 # 100 MW + combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + fin_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW diff --git a/examples/35_system_level_control/wind_ng_demand.yaml b/examples/35_system_level_control/wind_ng_demand.yaml new file mode 100644 index 000000000..f2b5599a0 --- /dev/null +++ b/examples/35_system_level_control/wind_ng_demand.yaml @@ -0,0 +1,5 @@ +name: H2Integrate_config +system_summary: This example uses wind, solar and a natural gas power plant to meet a fixed electrical load demand. +driver_config: driver_config.yaml +technology_config: tech_config.yaml +plant_config: plant_config.yaml diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index f67222736..537ca503c 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -1,20 +1,18 @@ import numpy as np import openmdao.api as om +from h2integrate.core.supported_models import supported_models -class SystemLevelControl(om.ExplicitComponent): - """System-level control that satisfies demand evenly across all technologies. - Parses ``technology_interconnections`` and ``tech_config`` to identify: +class SystemLevelControl(om.ExplicitComponent): + """System-level control that satisfies demand across all technologies. - - **Demand technology**: the single component with a ``demand_profile`` - - **Dispatchable technologies**: all producing technologies found in - 4-element connections (excluding demand techs, combiners, splitters, - and feedstocks) + Parses ``tech_config`` to classify each technology by its + ``_control_classifier`` attribute (curtailable, dispatchable, or storage). - Only one commodity demand stream is supported. At each timestep the - demand is distributed equally as set-points to the dispatchable - technologies. + Only one commodity demand stream is supported. At each timestep, + curtailable production is applied first, then the remaining demand + is distributed equally across dispatchable technologies. """ def initialize(self): @@ -27,80 +25,35 @@ def setup(self): tech_config = self.options["tech_config"] self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] - interconnections = plant_config.get("technology_interconnections", []) + plant_config.get("technology_interconnections", []) technologies = tech_config.get("technologies", {}) # ---- 1. Identify the (single) demand technology from tech_config ---- - # A demand tech has ``demand_profile`` in its performance or shared params. + # A demand tech has "Demand" in its performance model name. self.commodity = None self.demand_profile = None self.commodity_units = None for tech_name, tech_def in technologies.items(): + model_name = tech_def.get("performance_model", {}).get("model", "") + if "Demand" not in model_name: + continue + model_inputs = tech_def.get("model_inputs", {}) perf_params = model_inputs.get("performance_parameters", {}) shared_params = model_inputs.get("shared_parameters", {}) all_params = {**shared_params, **perf_params} - if "demand_profile" in all_params: - if self.commodity is not None: - raise ValueError( - "SystemLevelControl currently supports only one demand " - f"stream, but found demands for both '{self.commodity}' " - f"and '{all_params['commodity']}'." - ) - self.commodity = all_params["commodity"] - self.commodity_units = all_params.get("commodity_rate_units", None) - self.demand_profile = all_params["demand_profile"] - self.demand_tech = tech_name - - # ---- 2. Identify all dispatchable (producing) technologies ---- - # Every source tech in a 4-element connection is dispatchable, - # excluding demand techs, infrastructure (combiners, splitters), - # and feedstocks. - demand_tech_names = {self.demand_tech} if self.commodity else set() - - infrastructure_techs = set() - feedstock_techs = set() - for tech_name, tech_def in technologies.items(): - model_name = tech_def.get("performance_model", {}).get("model", "") - if "Combiner" in model_name or "Splitter" in model_name: - infrastructure_techs.add(tech_name) - if "Feedstock" in model_name: - feedstock_techs.add(tech_name) - - excluded = demand_tech_names | infrastructure_techs | feedstock_techs - - self.dispatchable_techs = [] # [tech_name, ...] - seen = set() - for connection in interconnections: - if len(connection) == 4: - source_tech, _dest, commodity, _transport = connection - if ( - commodity == self.commodity - and source_tech not in excluded - and source_tech not in seen - ): - self.dispatchable_techs.append(source_tech) - seen.add(source_tech) - - # Also pick up destination techs from 3-element set-point connections - # that weren't already found via 4-element connections. - for connection in interconnections: - if len(connection) == 3: - _source, dest_tech, var_mapping = connection - if isinstance(var_mapping, list | tuple) and len(var_mapping) == 2: - _src_var, dst_var = var_mapping - if "_set_point" in dst_var: - commodity = dst_var.replace("_set_point", "") - if ( - commodity == self.commodity - and dest_tech not in excluded - and dest_tech not in seen - ): - self.dispatchable_techs.append(dest_tech) - seen.add(dest_tech) + if self.commodity is not None: + raise ValueError( + "SystemLevelControl currently supports only one demand " + f"stream, but found demands for both '{self.commodity}' " + f"and '{all_params.get('commodity', tech_name)}'." + ) + self.commodity = all_params["commodity"] + self.commodity_units = all_params.get("commodity_rate_units", None) + self.demand_profile = all_params.get("demand_profile", 0.0) + self.demand_tech = tech_name - # ---- 3. Add OpenMDAO inputs / outputs ---- # Input: demand profile self.demand_input_name = f"{self.commodity}_demand" self.add_input( @@ -111,46 +64,113 @@ def setup(self): desc=f"Demand profile of {self.commodity}", ) - # Inputs: commodity output from each dispatchable tech - self.commodity_input_names = [] - for tech_name in self.dispatchable_techs: - var_name = f"{tech_name}_{self.commodity}_out" + # ---- 2. Classify technologies by _control_classifier ---- + self.curtailable_techs = [] + self.dispatchable_techs = [] + self.storage_techs = [] + + for tech_name, tech_def in technologies.items(): + perf_model_name = tech_def.get("performance_model", {}).get("model", "") + if perf_model_name not in supported_models: + continue + model_cls = supported_models[perf_model_name] + classifier = getattr(model_cls, "_control_classifier", None) + if classifier == "curtailable": + self.curtailable_techs.append(tech_name) + elif classifier == "dispatchable": + self.dispatchable_techs.append(tech_name) + elif classifier == "storage": + self.storage_techs.append(tech_name) + + # ---- 3. Add OpenMDAO inputs / outputs ---- + # Inputs & outputs for curtailable techs + self.curtailable_input_names = [] + self.curtailable_output_names = [] + for tech_name in self.curtailable_techs: + in_name = f"{tech_name}_{self.commodity}_out" + out_name = f"{tech_name}_{self.commodity}_set_point" self.add_input( - var_name, + in_name, val=0.0, shape=self.n_timesteps, units=self.commodity_units, desc=f"{self.commodity} output from {tech_name}", ) - self.commodity_input_names.append(var_name) + self.add_output( + out_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} production", + ) + self.curtailable_input_names.append(in_name) + self.curtailable_output_names.append(out_name) - # Outputs: set-points for all dispatchable techs - self.set_point_output_names = [] + # Inputs & outputs for dispatchable techs + self.dispatchable_input_names = [] + self.dispatchable_output_names = [] for tech_name in self.dispatchable_techs: - var_name = f"{tech_name}_{self.commodity}_set_point" + in_name = f"{tech_name}_{self.commodity}_out" + out_name = f"{tech_name}_{self.commodity}_set_point" + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) + self.add_output( + out_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} production", + ) + self.dispatchable_input_names.append(in_name) + self.dispatchable_output_names.append(out_name) + + # Inputs & outputs for storage techs + self.storage_input_names = [] + self.storage_output_names = [] + for tech_name in self.storage_techs: + in_name = f"{tech_name}_{self.commodity}_out" + out_name = f"{tech_name}_{self.commodity}_set_point" + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) self.add_output( - var_name, + out_name, val=0.0, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} production", ) - self.set_point_output_names.append(var_name) + self.storage_input_names.append(in_name) + self.storage_output_names.append(out_name) def compute(self, inputs, outputs): - demand = np.maximum(inputs[self.demand_input_name], 0.0) + demand = inputs[self.demand_input_name].copy() - # Sum actual commodity output from all dispatchable techs - total_supply = np.zeros(self.n_timesteps) - for var_name in self.commodity_input_names: - total_supply += inputs[var_name] + # 1. Apply curtailable production first (pass through actual output) + for in_name, out_name in zip(self.curtailable_input_names, self.curtailable_output_names): + curtailable_output = inputs[in_name] + outputs[out_name] = curtailable_output + demand -= curtailable_output - # Gap between demand and current total supply - gap = demand - total_supply + # Remaining demand after curtailable production + remaining = np.maximum(demand, 0.0) - # Adjust each tech's set_point: current output + its share of the gap - n_dispatchable = len(self.set_point_output_names) + # 2. Distribute remaining demand equally across dispatchable techs + n_dispatchable = len(self.dispatchable_output_names) if n_dispatchable > 0: - correction = gap / n_dispatchable - for var_name, in_name in zip(self.set_point_output_names, self.commodity_input_names): - outputs[var_name] = inputs[in_name] + correction + share = remaining / n_dispatchable + for out_name in self.dispatchable_output_names: + outputs[out_name] = share + + # 3. Storage techs get zero set_point for now + for out_name in self.storage_output_names: + outputs[out_name] = np.zeros(self.n_timesteps) From 9ff6faed9bbca51c062d846eb4371e642d39775c Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 28 Apr 2026 22:58:50 -0600 Subject: [PATCH 012/132] Fixed SLC example --- .../35_system_level_control/plant_config.yaml | 7 +- .../run_wind_ng_demand.py | 92 +------------------ .../35_system_level_control/tech_config.yaml | 28 ------ 3 files changed, 4 insertions(+), 123 deletions(-) diff --git a/examples/35_system_level_control/plant_config.yaml b/examples/35_system_level_control/plant_config.yaml index 80dff18d7..095f33c27 100644 --- a/examples/35_system_level_control/plant_config.yaml +++ b/examples/35_system_level_control/plant_config.yaml @@ -19,7 +19,7 @@ technology_interconnections: - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect NG feedstock to NG plant - [combiner, electrical_load_demand, electricity, cable] - # subtract wind and solar from demand + # subtract wind from demand - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] # give remaining load demand to natural gas plant - [combiner, fin_combiner, electricity, cable] @@ -27,7 +27,6 @@ technology_interconnections: resource_to_tech_connections: # connect the wind resource to the wind technology - [site.wind_resource, wind, wind_resource_data] - - [site.solar_resource, solar, solar_resource_data] plant: plant_life: 30 simulation: @@ -85,7 +84,7 @@ finance_parameters: commodity: electricity commodity_stream: combiner finance_groups: [profast_lco, profast_npv] - technologies: [solar, wind] + technologies: [wind] natural_gas: commodity: electricity commodity_stream: natural_gas_plant @@ -95,7 +94,7 @@ finance_parameters: commodity: electricity commodity_stream: fin_combiner finance_groups: [profast_lco] - technologies: [solar, wind, natural_gas_plant, ng_feedstock] + technologies: [wind, natural_gas_plant, ng_feedstock] cost_adjustment_parameters: cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year target_dollar_year: 2022 diff --git a/examples/35_system_level_control/run_wind_ng_demand.py b/examples/35_system_level_control/run_wind_ng_demand.py index 4abe424ff..9e85c88ca 100644 --- a/examples/35_system_level_control/run_wind_ng_demand.py +++ b/examples/35_system_level_control/run_wind_ng_demand.py @@ -3,100 +3,10 @@ ################################## # Create an H2I model with a fixed electricity load demand -h2i = H2IntegrateModel("solar_wind_ng_demand.yaml") +h2i = H2IntegrateModel("wind_ng_demand.yaml") # Run the model h2i.run() # Post-process the results h2i.post_process() - - -################################## -# Create H2I model but replace electrical load demand to be flexible -h2i_flexible = H2IntegrateModel("solar_wind_ng_flexible_demand.yaml") - -# Run the model -h2i_flexible.run() - -# Post-process the results -h2i_flexible.post_process() - -import matplotlib.pyplot as plt - - -# Battery dispatch plotting -model = h2i_flexible -fig, ax = plt.subplots(2, 1, sharex=True, figsize=(11, 9)) - -start_hour = 0 -end_hour = 200 -total_time_steps = model.prob.get_val("wind.electricity_out", units="MW").size -demand_profile = [ - model.technology_config["technologies"]["electrical_load_demand"]["model_inputs"][ - "control_parameters" - ]["demand_profile"] - * 1e-3 -] * total_time_steps - -# First subplot for wind and solar production and baseline demand profile -ax[0].plot( - range(start_hour, end_hour), - model.prob.get_val("wind.electricity_out", units="MW")[start_hour:end_hour], - linestyle="-", - label="Wind Electricity (MW)", - linewidth=2, - color="blue", -) -ax[0].plot( - range(start_hour, end_hour), - model.prob.get_val("solar.electricity_out", units="MW")[start_hour:end_hour], - linestyle="-", - label="Solar Electricity (MW)", - linewidth=2, - color="gold", -) - -ax[0].plot( - range(start_hour, end_hour), - demand_profile[start_hour:end_hour], - linestyle="--", - label="Baseline Electricity Demand (MW)", - linewidth=2, -) -ax[0].set_ylabel("Generation (MW)") -ax[0].legend(loc="upper right") - -# Second subplot for renewables electricity, NG electricity, and flexible demand profile -ax[1].plot( - range(start_hour, end_hour), - model.prob.get_val("combiner.electricity_out", units="MW")[start_hour:end_hour], - linestyle="-", - label="Combined Wind+Solar Electricity (MW)", - linewidth=2, - color="green", -) -ax[1].plot( - range(start_hour, end_hour), - model.prob.get_val("natural_gas_plant.electricity_out", units="MW")[start_hour:end_hour], - linestyle="-", - label="NG Plant Electricity (MW)", - linewidth=2, - color="orange", -) -ax[1].plot( - range(start_hour, end_hour), - model.prob.get_val("electrical_load_demand.electricity_flexible_demand_profile", units="MW")[ - start_hour:end_hour - ], - linestyle="--", - label="Flexible Demand Profile (MW)", - linewidth=2, - color="purple", -) -ax[1].set_ylabel("Generation & Demand (MW)") -ax[1].set_xlabel("Timestep (hr)") -ax[1].legend(loc="upper right") - -plt.tight_layout() -plt.show() diff --git a/examples/35_system_level_control/tech_config.yaml b/examples/35_system_level_control/tech_config.yaml index e044c1788..e1a6c2cf3 100644 --- a/examples/35_system_level_control/tech_config.yaml +++ b/examples/35_system_level_control/tech_config.yaml @@ -32,34 +32,6 @@ technologies: capex_per_kW: 1300 opex_per_kW_per_year: 39 cost_year: 2022 - solar: - performance_model: - model: PYSAMSolarPlantPerformanceModel - cost_model: - model: ATBUtilityPVCostModel - model_inputs: - performance_parameters: - pv_capacity_kWdc: 100000 # 100 MWdc - dc_ac_ratio: 1.34 - create_model_from: new - tilt_angle_func: none - tilt: 0 - pysam_options: - SystemDesign: - gcr: 0.3 - array_type: 2 - bifaciality: 0.65 - inv_eff: 96.0 - losses: 14.6 - module_type: 1 - azimuth: 180 - rotlim: 45 - SolarResource: - albedo_default: 0.2 - cost_parameters: - capex_per_kWac: 1193 - opex_per_kWac_per_year: 18 - cost_year: 2024 ng_feedstock: performance_model: model: FeedstockPerformanceModel From 08f87900230f6032093c99d33f57e4b6ec44b915 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 00:36:13 -0600 Subject: [PATCH 013/132] Reordering SLC settings --- .../35_system_level_control/plant_config.yaml | 7 +- .../system_level/system_level_control.py | 113 ++++------- h2integrate/core/h2integrate_model.py | 184 +++++++++++++----- 3 files changed, 183 insertions(+), 121 deletions(-) diff --git a/examples/35_system_level_control/plant_config.yaml b/examples/35_system_level_control/plant_config.yaml index 095f33c27..217d57a9b 100644 --- a/examples/35_system_level_control/plant_config.yaml +++ b/examples/35_system_level_control/plant_config.yaml @@ -20,8 +20,6 @@ technology_interconnections: # connect NG feedstock to NG plant - [combiner, electrical_load_demand, electricity, cable] # subtract wind from demand - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] - # give remaining load demand to natural gas plant - [combiner, fin_combiner, electricity, cable] - [natural_gas_plant, fin_combiner, electricity, cable] resource_to_tech_connections: @@ -32,6 +30,11 @@ plant: simulation: n_timesteps: 8760 dt: 3600 +system_level_control: + control_strategy: load_meeting + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 finance_parameters: finance_groups: profast_lco: diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index 537ca503c..3c566b731 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -1,14 +1,19 @@ import numpy as np import openmdao.api as om -from h2integrate.core.supported_models import supported_models - class SystemLevelControl(om.ExplicitComponent): """System-level control that satisfies demand across all technologies. - Parses ``tech_config`` to classify each technology by its - ``_control_classifier`` attribute (curtailable, dispatchable, or storage). + Reads pre-computed technology classification from + ``plant_config["system_level_control"]``, which must contain: + + - ``commodity``: the commodity being controlled (e.g. "electricity") + - ``commodity_units``: units string (or None) + - ``demand_tech``: name of the demand technology + - ``curtailable_techs``: list of curtailable technology names + - ``dispatchable_techs``: list of dispatchable technology names + - ``storage_techs``: list of storage technology names Only one commodity demand stream is supported. At each timestep, curtailable production is applied first, then the remaining demand @@ -22,73 +27,35 @@ def initialize(self): def setup(self): plant_config = self.options["plant_config"] - tech_config = self.options["tech_config"] + slc_config = plant_config["system_level_control"] self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] - plant_config.get("technology_interconnections", []) - technologies = tech_config.get("technologies", {}) - - # ---- 1. Identify the (single) demand technology from tech_config ---- - # A demand tech has "Demand" in its performance model name. - self.commodity = None - self.demand_profile = None - self.commodity_units = None - for tech_name, tech_def in technologies.items(): - model_name = tech_def.get("performance_model", {}).get("model", "") - if "Demand" not in model_name: - continue - - model_inputs = tech_def.get("model_inputs", {}) - perf_params = model_inputs.get("performance_parameters", {}) - shared_params = model_inputs.get("shared_parameters", {}) - all_params = {**shared_params, **perf_params} - - if self.commodity is not None: - raise ValueError( - "SystemLevelControl currently supports only one demand " - f"stream, but found demands for both '{self.commodity}' " - f"and '{all_params.get('commodity', tech_name)}'." - ) - self.commodity = all_params["commodity"] - self.commodity_units = all_params.get("commodity_rate_units", None) - self.demand_profile = all_params.get("demand_profile", 0.0) - self.demand_tech = tech_name - - # Input: demand profile + + # Read pre-computed classification from plant_config + self.commodity = slc_config["commodity"] + self.commodity_units = slc_config.get("commodity_units", None) + self.demand_tech = slc_config["demand_tech"] + self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) + self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) + self.storage_techs = list(slc_config.get("storage_techs", [])) + + # Input: demand profile (default value from config) + demand_profile = slc_config.get("demand_profile", 0.0) self.demand_input_name = f"{self.commodity}_demand" self.add_input( self.demand_input_name, - val=self.demand_profile, + val=demand_profile, shape=self.n_timesteps, units=self.commodity_units, desc=f"Demand profile of {self.commodity}", ) - # ---- 2. Classify technologies by _control_classifier ---- - self.curtailable_techs = [] - self.dispatchable_techs = [] - self.storage_techs = [] - - for tech_name, tech_def in technologies.items(): - perf_model_name = tech_def.get("performance_model", {}).get("model", "") - if perf_model_name not in supported_models: - continue - model_cls = supported_models[perf_model_name] - classifier = getattr(model_cls, "_control_classifier", None) - if classifier == "curtailable": - self.curtailable_techs.append(tech_name) - elif classifier == "dispatchable": - self.dispatchable_techs.append(tech_name) - elif classifier == "storage": - self.storage_techs.append(tech_name) - - # ---- 3. Add OpenMDAO inputs / outputs ---- - # Inputs & outputs for curtailable techs + # ---- Add OpenMDAO inputs / outputs per tech category ---- + # Curtailable techs: read-only (no set_point output, since these + # produce based on resource availability, not a set_point) self.curtailable_input_names = [] - self.curtailable_output_names = [] for tech_name in self.curtailable_techs: in_name = f"{tech_name}_{self.commodity}_out" - out_name = f"{tech_name}_{self.commodity}_set_point" self.add_input( in_name, val=0.0, @@ -96,17 +63,18 @@ def setup(self): units=self.commodity_units, desc=f"{self.commodity} output from {tech_name}", ) - self.add_output( - out_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} production", - ) self.curtailable_input_names.append(in_name) - self.curtailable_output_names.append(out_name) - # Inputs & outputs for dispatchable techs + # Compute a reasonable initial set_point for dispatchable techs + n_dispatchable = len(self.dispatchable_techs) + if n_dispatchable > 0: + if np.isscalar(demand_profile): + initial_sp = demand_profile / n_dispatchable + else: + initial_sp = np.array(demand_profile) / n_dispatchable + else: + initial_sp = 0.0 + self.dispatchable_input_names = [] self.dispatchable_output_names = [] for tech_name in self.dispatchable_techs: @@ -121,7 +89,7 @@ def setup(self): ) self.add_output( out_name, - val=0.0, + val=initial_sp, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} production", @@ -129,7 +97,6 @@ def setup(self): self.dispatchable_input_names.append(in_name) self.dispatchable_output_names.append(out_name) - # Inputs & outputs for storage techs self.storage_input_names = [] self.storage_output_names = [] for tech_name in self.storage_techs: @@ -155,11 +122,9 @@ def setup(self): def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() - # 1. Apply curtailable production first (pass through actual output) - for in_name, out_name in zip(self.curtailable_input_names, self.curtailable_output_names): - curtailable_output = inputs[in_name] - outputs[out_name] = curtailable_output - demand -= curtailable_output + # 1. Subtract curtailable production from demand + for in_name in self.curtailable_input_names: + demand -= inputs[in_name] # Remaining demand after curtailable production remaining = np.maximum(demand, 0.0) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 466fa80b4..6ad4fb22f 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -23,6 +23,9 @@ multivariable_streams, is_electricity_producer, ) +from h2integrate.control.control_strategies.system_level.system_level_control import ( + SystemLevelControl, +) from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import ( PyomoStorageControllerBaseClass, ) @@ -81,6 +84,11 @@ def __init__(self, config_input): self.create_finance_model() + # add system-level controller if configured + if self.slc: + self._classify_slc_technologies() + self.add_system_level_controller() + # connect technologies # technologies are connected within the `technology_interconnections` section of the # plant config @@ -458,6 +466,130 @@ def create_plant_model(self): # Create the plant model group and add components self.plant = self.model.add_subsystem("plant", plant_group, promotes=["*"]) + def _classify_slc_technologies(self): + """Classify technologies for system-level control and store in plant_config. + + Uses ``self.tech_control_classifiers`` (populated by ``create_technology_models()``) + to partition technologies into curtailable, dispatchable, and storage lists. + Also identifies the single demand technology and its commodity. + + Results are written into ``self.plant_config["system_level_control"]`` so + they are available to the ``SystemLevelControl`` component at setup time. + """ + slc_config = self.plant_config["system_level_control"] + technologies = self.technology_config.get("technologies", {}) + + # Identify the (single) demand technology + commodity = None + demand_tech = None + commodity_units = None + for tech_name, tech_def in technologies.items(): + model_name = tech_def.get("performance_model", {}).get("model", "") + if "Demand" not in model_name: + continue + + model_inputs = tech_def.get("model_inputs", {}) + perf_params = model_inputs.get("performance_parameters", {}) + shared_params = model_inputs.get("shared_parameters", {}) + all_params = {**shared_params, **perf_params} + + if commodity is not None: + raise ValueError( + "SystemLevelControl currently supports only one demand " + f"stream, but found demands for both '{commodity}' " + f"and '{all_params.get('commodity', tech_name)}'." + ) + commodity = all_params["commodity"] + commodity_units = all_params.get("commodity_rate_units", None) + demand_profile = all_params.get("demand_profile", 0.0) + demand_tech = tech_name + + # Classify technologies using pre-computed classifiers + curtailable_techs = [] + dispatchable_techs = [] + storage_techs = [] + for tech_name, classifier in self.tech_control_classifiers.items(): + if classifier == "curtailable": + curtailable_techs.append(tech_name) + elif classifier == "dispatchable": + dispatchable_techs.append(tech_name) + elif classifier == "storage": + storage_techs.append(tech_name) + + # Store classification results in plant_config for SLC component + slc_config["commodity"] = commodity + slc_config["commodity_units"] = commodity_units + slc_config["demand_tech"] = demand_tech + slc_config["demand_profile"] = demand_profile + slc_config["curtailable_techs"] = curtailable_techs + slc_config["dispatchable_techs"] = dispatchable_techs + slc_config["storage_techs"] = storage_techs + + def add_system_level_controller(self): + """Add the SystemLevelControl component and configure the plant solver. + + This method: + 1. Adds a ``SystemLevelControl`` subsystem to the plant group + 2. Configures the nonlinear solver on the plant group based on + ``plant_config["system_level_control"]`` parameters + 3. Creates connections between the controller and each technology + """ + slc_config = self.plant_config["system_level_control"] + + # Map user-facing solver names to OpenMDAO solver classes + solver_map = { + "gauss_seidel": om.NonlinearBlockGS, + "newton": om.NewtonSolver, + "block_jacobi": om.NonlinearBlockJac, + } + + # 1. Add the controller as the first subsystem in the plant group + slc_comp = SystemLevelControl( + driver_config=self.driver_config, + plant_config=self.plant_config, + tech_config=self.technology_config, + ) + self.plant.add_subsystem("system_level_controller", slc_comp) + + # 2. Configure the nonlinear solver + solver_name = slc_config.get("solver_name", "gauss_seidel") + solver_cls = solver_map.get(solver_name) + if solver_cls is None: + raise ValueError( + f"Unknown solver_name '{solver_name}' in system_level_control. " + f"Supported: {list(solver_map.keys())}" + ) + solver = solver_cls() + solver.options["maxiter"] = slc_config.get("max_iter", 20) + solver.options["atol"] = slc_config.get("convergence_tolerance", 1e-6) + solver.options["rtol"] = slc_config.get("convergence_tolerance", 1e-6) + solver.options["iprint"] = 2 # print convergence at each iteration + self.plant.nonlinear_solver = solver + self.plant.linear_solver = om.DirectSolver() + + # 3. Connect the controller's inputs/outputs to technology models + commodity = slc_config["commodity"] + + # Curtailable techs: read their output but don't write a set_point + # (curtailable sources like wind produce based on resource, not a set_point) + for tech_name in slc_config["curtailable_techs"]: + self.plant.connect( + f"{tech_name}.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) + + # Dispatchable and storage techs: read output and write set_point + for tech_list in ["dispatchable_techs", "storage_techs"]: + for tech_name in slc_config[tech_list]: + self.plant.connect( + f"{tech_name}.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) + def create_technology_models(self): # Loop through each technology and instantiate an OpenMDAO object (assume it exists) # for each technology @@ -593,51 +725,13 @@ def create_technology_models(self): plural_model_type_name = model_type + "s" getattr(self, plural_model_type_name).append(om_model_object) - # below logic is only used if using system-level control - if self.slc and model_type == "performance_model": - self._check_control_classifier(perf_model, om_model_object) - control_classifier = comp._control_classifier - self.tech_control_classifiers.update( - {tech_name: getattr(comp, control_classifier)} - ) - - # add curtail component to curtailable technology performance models - if control_classifier == "curtailable": - # get the commodity output from this component with length - # 4 connections - # TODO: update to handle length 3 connections - tech_is_source_connections = [ - k - for k in self.plant_config["technology_interconnections"] - if k[0] == tech_name and len(k) == 4 - ] - if len(tech_is_source_connections) == 0: - msg = ( - f"{tech_name} is not a source technology " - f"for another component" - ) - - raise ValueError(msg) - # Get unique commodity outputs - tech_commodity_output = list( - {k[3] for k in tech_is_source_connections} - ) - if len(tech_commodity_output) > 1: - msg = ( - f"{tech_name} has multiple commodity outputs " - f"({tech_commodity_output}) which is not yet supported" - ) - raise ValueError(msg) - # get the commodity of the component - model_object = self.supported_models["CurtailableComponentModel"] - om_model_object = tech_group.add_subsystem( - "CurtailableComponentModel", - model_object( - commodity=tech_commodity_output[0], - plant_config=self.plant_config, - ), - promotes=["*"], - ) + # Collect control classifier for system-level control + if model_type == "performance_model" and self.slc: + perf_cls = self.supported_models.get(perf_model) + if perf_cls is not None: + classifier = getattr(perf_cls, "_control_classifier", None) + if classifier is not None: + self.tech_control_classifiers[tech_name] = classifier # Process the finance models if "finance_model" in individual_tech_config: From 733c636ceaa3f3c0e888c049330cddaa6f2ac074 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 00:56:42 -0600 Subject: [PATCH 014/132] Updating the SLC example --- .../run_wind_ng_demand.py | 35 +++++++++++++++++++ .../35_system_level_control/tech_config.yaml | 2 +- h2integrate/core/h2integrate_model.py | 9 +++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/examples/35_system_level_control/run_wind_ng_demand.py b/examples/35_system_level_control/run_wind_ng_demand.py index 9e85c88ca..f4be3e869 100644 --- a/examples/35_system_level_control/run_wind_ng_demand.py +++ b/examples/35_system_level_control/run_wind_ng_demand.py @@ -1,3 +1,6 @@ +import numpy as np +import matplotlib.pyplot as plt + from h2integrate.core.h2integrate_model import H2IntegrateModel @@ -10,3 +13,35 @@ # Post-process the results h2i.post_process() + +# Plot the first 100 hours +n_hours = 100 +hours = np.arange(n_hours) + +demand = h2i.prob.get_val("plant.electrical_load_demand.electricity_demand")[:n_hours] +wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] +ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] +curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] + +fig, axes = plt.subplots(4, 1, figsize=(12, 10), sharex=True) + +axes[0].plot(hours, demand, color="black") +axes[0].set_ylabel("Demand (kW)") +axes[0].set_title("System-Level Control: First 100 Hours") + +axes[1].plot(hours, wind_out, color="tab:blue") +axes[1].set_ylabel("Wind (kW)") + +axes[2].plot(hours, ng_out, color="tab:orange") +axes[2].set_ylabel("Natural Gas (kW)") + +axes[3].plot(hours, curtailed, color="tab:red") +axes[3].set_ylabel("Curtailed (kW)") +axes[3].set_xlabel("Hour") + +for ax in axes: + ax.grid(True, alpha=0.3) + +plt.tight_layout() +plt.savefig("slc_results.png", dpi=150) +plt.show() diff --git a/examples/35_system_level_control/tech_config.yaml b/examples/35_system_level_control/tech_config.yaml index e1a6c2cf3..10c0959c6 100644 --- a/examples/35_system_level_control/tech_config.yaml +++ b/examples/35_system_level_control/tech_config.yaml @@ -69,7 +69,7 @@ technologies: performance_parameters: commodity: electricity commodity_rate_units: kW - demand_profile: 100000 # 100 MW + demand_profile: 50000 combiner: performance_model: model: GenericCombinerPerformanceModel diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 6ad4fb22f..ef7c47742 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -590,6 +590,15 @@ def add_system_level_controller(self): f"{tech_name}.{commodity}_set_point", ) + ### Commented out for now; we'll need to determine how to treat demand + ### components in the new SLC paradigm. + # # Connect demand profile to the controller + # demand_tech = slc_config["demand_tech"] + # self.plant.connect( + # f"{demand_tech}.{commodity}_demand", + # f"system_level_controller.{commodity}_demand", + # ) + def create_technology_models(self): # Loop through each technology and instantiate an OpenMDAO object (assume it exists) # for each technology From d91e8aec3fab3379e180399a577745d21b37a14b Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 01:23:41 -0600 Subject: [PATCH 015/132] Added curtailment --- .../system_level/system_level_control.py | 51 +++++++++++++++---- .../converters/hydrogen/pem_electrolyzer.py | 3 ++ h2integrate/converters/solar/solar_pysam.py | 3 ++ h2integrate/converters/wind/floris.py | 3 ++ h2integrate/converters/wind/wind_pysam.py | 3 ++ h2integrate/core/h2integrate_model.py | 18 ++++++- h2integrate/core/model_baseclasses.py | 41 +++++++++++++++ 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index 3c566b731..0184ae35a 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -51,11 +51,14 @@ def setup(self): ) # ---- Add OpenMDAO inputs / outputs per tech category ---- - # Curtailable techs: read-only (no set_point output, since these - # produce based on resource availability, not a set_point) + # Curtailable techs: read output + rated production, write set_point self.curtailable_input_names = [] + self.curtailable_output_names = [] + self.curtailable_rated_names = [] for tech_name in self.curtailable_techs: in_name = f"{tech_name}_{self.commodity}_out" + out_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, val=0.0, @@ -63,23 +66,40 @@ def setup(self): units=self.commodity_units, desc=f"{self.commodity} output from {tech_name}", ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) + self.add_output( + out_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} curtailment", + ) self.curtailable_input_names.append(in_name) + self.curtailable_output_names.append(out_name) + self.curtailable_rated_names.append(rated_name) # Compute a reasonable initial set_point for dispatchable techs n_dispatchable = len(self.dispatchable_techs) if n_dispatchable > 0: if np.isscalar(demand_profile): - initial_sp = demand_profile / n_dispatchable + initial_set_point = demand_profile / n_dispatchable else: - initial_sp = np.array(demand_profile) / n_dispatchable + initial_set_point = np.array(demand_profile) / n_dispatchable else: - initial_sp = 0.0 + initial_set_point = 0.0 self.dispatchable_input_names = [] self.dispatchable_output_names = [] + self.dispatchable_rated_names = [] for tech_name in self.dispatchable_techs: in_name = f"{tech_name}_{self.commodity}_out" out_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, val=0.0, @@ -87,15 +107,22 @@ def setup(self): units=self.commodity_units, desc=f"{self.commodity} output from {tech_name}", ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) self.add_output( out_name, - val=initial_sp, + val=initial_set_point, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} production", ) self.dispatchable_input_names.append(in_name) self.dispatchable_output_names.append(out_name) + self.dispatchable_rated_names.append(rated_name) self.storage_input_names = [] self.storage_output_names = [] @@ -122,9 +149,15 @@ def setup(self): def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() - # 1. Subtract curtailable production from demand - for in_name in self.curtailable_input_names: - demand -= inputs[in_name] + # 1. Curtailable techs: set_point = rated production (no curtailment) + for in_name, out_name, rated_name in zip( + self.curtailable_input_names, + self.curtailable_output_names, + self.curtailable_rated_names, + ): + curtailable_output = inputs[in_name] + outputs[out_name] = inputs[rated_name] * np.ones(self.n_timesteps) + demand -= curtailable_output # Remaining demand after curtailable production remaining = np.maximum(demand, 0.0) diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 0e18eb985..d09d6d65c 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -215,3 +215,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): outputs["annual_oxygen_produced"] = H2_Results["Performance Schedules"][ "Annual O2 Production [kg/year]" ] + + # Apply curtailment based on set_point + self.apply_curtailment(outputs) diff --git a/h2integrate/converters/solar/solar_pysam.py b/h2integrate/converters/solar/solar_pysam.py index 2fefd5986..1a400485d 100644 --- a/h2integrate/converters/solar/solar_pysam.py +++ b/h2integrate/converters/solar/solar_pysam.py @@ -311,3 +311,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): outputs["capacity_factor"] = outputs["total_electricity_produced"] / max_production outputs["annual_electricity_produced"] = self.system_model.value("ac_annual") + + # Apply curtailment based on set_point + self.apply_curtailment(outputs) diff --git a/h2integrate/converters/wind/floris.py b/h2integrate/converters/wind/floris.py index 02c26ef1e..90d66b2d0 100644 --- a/h2integrate/converters/wind/floris.py +++ b/h2integrate/converters/wind/floris.py @@ -287,6 +287,9 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): 1 / self.fraction_of_year_simulated ) + # Apply curtailment based on set_point + self.apply_curtailment(outputs) + # 3. Cache the results for future use if enabled self.cache_outputs( inputs, outputs, discrete_inputs, discrete_outputs={}, config_dict=config_dict diff --git a/h2integrate/converters/wind/wind_pysam.py b/h2integrate/converters/wind/wind_pysam.py index 46dd84a2e..310657a1a 100644 --- a/h2integrate/converters/wind/wind_pysam.py +++ b/h2integrate/converters/wind/wind_pysam.py @@ -478,6 +478,9 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): ) outputs["capacity_factor"] = outputs["total_electricity_produced"] / max_production + # Apply curtailment based on set_point + self.apply_curtailment(outputs) + def post_process(self, show_plots=False): def plot_turbine_points( ax: plt.Axes = None, diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index ef7c47742..0ed6d0577 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -570,13 +570,20 @@ def add_system_level_controller(self): # 3. Connect the controller's inputs/outputs to technology models commodity = slc_config["commodity"] - # Curtailable techs: read their output but don't write a set_point - # (curtailable sources like wind produce based on resource, not a set_point) + # Curtailable techs: read their output and write set_point for tech_name in slc_config["curtailable_techs"]: self.plant.connect( f"{tech_name}.{commodity}_out", f"system_level_controller.{tech_name}_{commodity}_out", ) + self.plant.connect( + f"{tech_name}.rated_{commodity}_production", + f"system_level_controller.{tech_name}_rated_{commodity}_production", + ) + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) # Dispatchable and storage techs: read output and write set_point for tech_list in ["dispatchable_techs", "storage_techs"]: @@ -590,6 +597,13 @@ def add_system_level_controller(self): f"{tech_name}.{commodity}_set_point", ) + # Dispatchable techs: also connect rated production + for tech_name in slc_config["dispatchable_techs"]: + self.plant.connect( + f"{tech_name}.rated_{commodity}_production", + f"system_level_controller.{tech_name}_rated_{commodity}_production", + ) + ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. # # Connect demand profile to the controller diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index c6adf5cd6..45d8b98da 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -3,6 +3,7 @@ from pathlib import Path import dill +import numpy as np import openmdao.api as om from attrs import field, define @@ -98,6 +99,46 @@ def setup(self): # operational life of the technology if the technology cannot be replaced self.add_output("operational_life", val=self.plant_life, units="yr") + # Curtailable models get additional I/O for set_point-based curtailment + if getattr(self, "_control_classifier", None) == "curtailable": + self.add_input( + f"{self.commodity}_set_point", + val=0.0, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Set point for {self.commodity} production (curtailment limit)", + ) + self.add_output( + f"uncurtailed_{self.commodity}_out", + val=0.0, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Full (uncurtailed) {self.commodity} output", + ) + + def apply_curtailment(self, outputs): + """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_set_point``. + + Copies the current ``{commodity}_out`` into ``uncurtailed_{commodity}_out``, + then clips ``{commodity}_out`` to ``min(uncurtailed, set_point)`` element-wise. + + Only operates when the model has ``_control_classifier == "curtailable"``. + Should be called at the end of each curtailable model's ``compute()`` method + after the raw production has been written to ``outputs[f"{commodity}_out"]``. + """ + if getattr(self, "_control_classifier", None) != "curtailable": + return + + commodity_out_key = f"{self.commodity}_out" + uncurtailed_key = f"uncurtailed_{self.commodity}_out" + set_point_key = f"{self.commodity}_set_point" + + uncurtailed = np.array(outputs[commodity_out_key]) + outputs[uncurtailed_key] = uncurtailed + + set_point = self._inputs[set_point_key] + outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) + def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """ Computation for the OM component. From fc6bd5fe6599558078a714153d89267ba21f9edd Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 12:04:59 -0600 Subject: [PATCH 016/132] WIP: adding battery example for SLC --- .../{ => no_battery}/driver_config.yaml | 0 .../{ => no_battery}/plant_config.yaml | 0 .../{ => no_battery}/run_wind_ng_demand.py | 0 .../{ => no_battery}/tech_config.yaml | 0 .../{ => no_battery}/wind_ng_demand.yaml | 0 .../yes_battery/driver_config.yaml | 4 + .../yes_battery/plant_config.yaml | 106 +++++++++++++++++ .../yes_battery/run_wind_ng_demand.py | 55 +++++++++ .../yes_battery/tech_config.yaml | 109 ++++++++++++++++++ .../yes_battery/wind_ng_demand.yaml | 5 + .../system_level/system_level_control.py | 32 +++-- h2integrate/core/h2integrate_model.py | 13 ++- 12 files changed, 311 insertions(+), 13 deletions(-) rename examples/35_system_level_control/{ => no_battery}/driver_config.yaml (100%) rename examples/35_system_level_control/{ => no_battery}/plant_config.yaml (100%) rename examples/35_system_level_control/{ => no_battery}/run_wind_ng_demand.py (100%) rename examples/35_system_level_control/{ => no_battery}/tech_config.yaml (100%) rename examples/35_system_level_control/{ => no_battery}/wind_ng_demand.yaml (100%) create mode 100644 examples/35_system_level_control/yes_battery/driver_config.yaml create mode 100644 examples/35_system_level_control/yes_battery/plant_config.yaml create mode 100644 examples/35_system_level_control/yes_battery/run_wind_ng_demand.py create mode 100644 examples/35_system_level_control/yes_battery/tech_config.yaml create mode 100644 examples/35_system_level_control/yes_battery/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/driver_config.yaml b/examples/35_system_level_control/no_battery/driver_config.yaml similarity index 100% rename from examples/35_system_level_control/driver_config.yaml rename to examples/35_system_level_control/no_battery/driver_config.yaml diff --git a/examples/35_system_level_control/plant_config.yaml b/examples/35_system_level_control/no_battery/plant_config.yaml similarity index 100% rename from examples/35_system_level_control/plant_config.yaml rename to examples/35_system_level_control/no_battery/plant_config.yaml diff --git a/examples/35_system_level_control/run_wind_ng_demand.py b/examples/35_system_level_control/no_battery/run_wind_ng_demand.py similarity index 100% rename from examples/35_system_level_control/run_wind_ng_demand.py rename to examples/35_system_level_control/no_battery/run_wind_ng_demand.py diff --git a/examples/35_system_level_control/tech_config.yaml b/examples/35_system_level_control/no_battery/tech_config.yaml similarity index 100% rename from examples/35_system_level_control/tech_config.yaml rename to examples/35_system_level_control/no_battery/tech_config.yaml diff --git a/examples/35_system_level_control/wind_ng_demand.yaml b/examples/35_system_level_control/no_battery/wind_ng_demand.yaml similarity index 100% rename from examples/35_system_level_control/wind_ng_demand.yaml rename to examples/35_system_level_control/no_battery/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/yes_battery/driver_config.yaml b/examples/35_system_level_control/yes_battery/driver_config.yaml new file mode 100644 index 000000000..5b6b7e05a --- /dev/null +++ b/examples/35_system_level_control/yes_battery/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: This analysis runs a natural gas power plant +general: + folder_output: outputs diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml new file mode 100644 index 000000000..821d07237 --- /dev/null +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -0,0 +1,106 @@ +name: plant_config +description: This plant is located in Texas, USA. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 +# array of arrays containing left-to-right technology +# interconnections; can support bidirectional connections +# with the reverse definition. +# this will naturally grow as we mature the interconnected tech +technology_interconnections: + - [wind, combiner, electricity, cable] + # source_tech, dest_tech, transport_item, transport_type = connection + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + # connect NG feedstock to NG plant + - [combiner, battery, electricity, cable] + # wind available for battery charging + - [combiner, electrical_load_demand, electricity, cable] + # subtract wind from demand + - [combiner, fin_combiner, electricity, cable] + - [battery, fin_combiner, electricity, cable] + - [natural_gas_plant, fin_combiner, electricity, cable] +resource_to_tech_connections: + # connect the wind resource to the wind technology + - [site.wind_resource, wind, wind_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +system_level_control: + control_strategy: load_meeting + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 +finance_parameters: + finance_groups: + profast_lco: + 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.] + profast_npv: + finance_model: ProFastNPV + model_inputs: + commodity_sell_price: 0.05167052 + 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.] + finance_subgroups: + renewables: + commodity: electricity + commodity_stream: combiner + finance_groups: [profast_lco, profast_npv] + technologies: [wind] + natural_gas: + commodity: electricity + commodity_stream: natural_gas_plant + finance_groups: [profast_lco] + technologies: [natural_gas_plant, ng_feedstock] + electricity: + commodity: electricity + commodity_stream: fin_combiner + finance_groups: [profast_lco] + technologies: [wind, battery, natural_gas_plant, ng_feedstock] + cost_adjustment_parameters: + cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year + target_dollar_year: 2022 diff --git a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py new file mode 100644 index 000000000..6b184eb4d --- /dev/null +++ b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py @@ -0,0 +1,55 @@ +import numpy as np +import matplotlib.pyplot as plt + +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +################################## +# Create an H2I model with a fixed electricity load demand +h2i = H2IntegrateModel("wind_ng_demand.yaml") + +# Run the model +h2i.run() + +# Post-process the results +h2i.post_process() + +# Plot the first 168 hours (1 week) +n_hours = 168 +hours = np.arange(n_hours) + +wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] +ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] +batt_charge = h2i.prob.get_val("plant.battery.storage_electricity_charge")[:n_hours] +batt_discharge = h2i.prob.get_val("plant.battery.storage_electricity_discharge")[:n_hours] +batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] +curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] + +fig, axes = plt.subplots(6, 1, figsize=(12, 14), sharex=True) + +axes[0].plot(hours, wind_out, color="tab:blue") +axes[0].set_ylabel("Wind (kW)") +axes[0].set_title("System-Level Control: First 168 Hours") + +axes[1].plot(hours, ng_out, color="tab:orange") +axes[1].set_ylabel("Natural Gas (kW)") + +axes[2].plot(hours, batt_charge, color="tab:green") +axes[2].set_ylabel("Battery Charge (kW)") + +axes[3].plot(hours, batt_discharge, color="tab:purple") +axes[3].set_ylabel("Battery Discharge (kW)") + +axes[4].plot(hours, batt_soc, color="tab:cyan") +axes[4].set_ylabel("Battery SOC (%)") + +axes[5].plot(hours, curtailed, color="tab:red") +axes[5].set_ylabel("Curtailed (kW)") +axes[5].set_xlabel("Hour") + +for ax in axes: + ax.grid(True, alpha=0.3) + +plt.tight_layout() +plt.savefig("slc_results.png", dpi=150) +plt.show() diff --git a/examples/35_system_level_control/yes_battery/tech_config.yaml b/examples/35_system_level_control/yes_battery/tech_config.yaml new file mode 100644 index 000000000..870889a0d --- /dev/null +++ b/examples/35_system_level_control/yes_battery/tech_config.yaml @@ -0,0 +1,109 @@ +name: technology_config +description: This plant produces electricity with wind, solar, and a natural gas power plant to meet a fixed electrical load + demand. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. # MMBtu + cost_parameters: + cost_year: 2023 + price: 4.2 # USD/MMBtu + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 # MMBtu/MWh - typical for NGCC + system_capacity_mw: 100. # MW + cost_parameters: + capex_per_kw: 1000 # $/kW - typical for NGCC + fixed_opex_per_kw_per_year: 10.0 # $/kW/year + variable_opex_per_mwh: 0.0 # $/MWh + cost_year: 2023 + electrical_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 50000 + combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + battery: + performance_model: + model: PySAMBatteryPerformanceModel + cost_model: + model: ATBBatteryCostModel + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 50000 # kW (50 MW) + max_capacity: 200000 # kWh (200 MWh, 4-hour duration) + init_soc_fraction: 0.5 + max_soc_fraction: 1.0 + min_soc_fraction: 0.1 + performance_parameters: + chemistry: LFPGraphite + demand_profile: 50000 # kW, required by storage base config + cost_parameters: + cost_year: 2022 + energy_capex: 310 # $/kWh + power_capex: 311 # $/kW + opex_fraction: 0.025 + fin_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 3 diff --git a/examples/35_system_level_control/yes_battery/wind_ng_demand.yaml b/examples/35_system_level_control/yes_battery/wind_ng_demand.yaml new file mode 100644 index 000000000..f2b5599a0 --- /dev/null +++ b/examples/35_system_level_control/yes_battery/wind_ng_demand.yaml @@ -0,0 +1,5 @@ +name: H2Integrate_config +system_summary: This example uses wind, solar and a natural gas power plant to meet a fixed electrical load demand. +driver_config: driver_config.yaml +technology_config: tech_config.yaml +plant_config: plant_config.yaml diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index 0184ae35a..555b1f9dc 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -126,9 +126,11 @@ def setup(self): self.storage_input_names = [] self.storage_output_names = [] + self.storage_rated_names = [] for tech_name in self.storage_techs: in_name = f"{tech_name}_{self.commodity}_out" out_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, val=0.0, @@ -136,6 +138,12 @@ def setup(self): units=self.commodity_units, desc=f"{self.commodity} output from {tech_name}", ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) self.add_output( out_name, val=0.0, @@ -145,6 +153,7 @@ def setup(self): ) self.storage_input_names.append(in_name) self.storage_output_names.append(out_name) + self.storage_rated_names.append(rated_name) def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() @@ -159,16 +168,25 @@ def compute(self, inputs, outputs): outputs[out_name] = inputs[rated_name] * np.ones(self.n_timesteps) demand -= curtailable_output - # Remaining demand after curtailable production + # 2. Storage dispatch: set_point = net demand per storage tech + # positive set_point → discharge, negative → charge + # The storage model's simulate() handles rate/SOC/availability clipping + # internally, so we pass the raw demand signal here. + n_storage = len(self.storage_output_names) + if n_storage > 0: + storage_share = demand / n_storage + for out_name in self.storage_output_names: + outputs[out_name] = storage_share + + # Subtract actual storage output from demand + # (electricity_out > 0 when discharging, < 0 when charging) + for in_name in self.storage_input_names: + demand -= inputs[in_name] + + # 3. Remaining demand after curtailable + storage → dispatchable techs remaining = np.maximum(demand, 0.0) - - # 2. Distribute remaining demand equally across dispatchable techs n_dispatchable = len(self.dispatchable_output_names) if n_dispatchable > 0: share = remaining / n_dispatchable for out_name in self.dispatchable_output_names: outputs[out_name] = share - - # 3. Storage techs get zero set_point for now - for out_name in self.storage_output_names: - outputs[out_name] = np.zeros(self.n_timesteps) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 0ed6d0577..2445d256c 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -597,12 +597,13 @@ def add_system_level_controller(self): f"{tech_name}.{commodity}_set_point", ) - # Dispatchable techs: also connect rated production - for tech_name in slc_config["dispatchable_techs"]: - self.plant.connect( - f"{tech_name}.rated_{commodity}_production", - f"system_level_controller.{tech_name}_rated_{commodity}_production", - ) + # Dispatchable and storage techs: also connect rated production + for tech_list in ["dispatchable_techs", "storage_techs"]: + for tech_name in slc_config[tech_list]: + self.plant.connect( + f"{tech_name}.rated_{commodity}_production", + f"system_level_controller.{tech_name}_rated_{commodity}_production", + ) ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. From efd309393ddfc0d61be81996f5bb5acbd4485f26 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 12:19:53 -0600 Subject: [PATCH 017/132] Improving plotting for battery SLC example --- .../yes_battery/run_wind_ng_demand.py | 48 +++++++++++-------- .../yes_battery/tech_config.yaml | 2 +- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py index 6b184eb4d..a70f69372 100644 --- a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py +++ b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py @@ -20,32 +20,42 @@ wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] -batt_charge = h2i.prob.get_val("plant.battery.storage_electricity_charge")[:n_hours] batt_discharge = h2i.prob.get_val("plant.battery.storage_electricity_discharge")[:n_hours] batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] +demand = h2i.prob.get_val("plant.electrical_load_demand.electricity_demand")[:n_hours] curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] -fig, axes = plt.subplots(6, 1, figsize=(12, 14), sharex=True) - -axes[0].plot(hours, wind_out, color="tab:blue") -axes[0].set_ylabel("Wind (kW)") +fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True) + +# Stacked area: wind + battery discharge + NG = total supply +axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") +axes[0].fill_between( + hours, + wind_out, + wind_out + batt_discharge, + alpha=0.7, + color="tab:purple", + label="Battery Discharge", +) +axes[0].fill_between( + hours, + wind_out + batt_discharge, + wind_out + batt_discharge + ng_out, + alpha=0.7, + color="tab:orange", + label="Natural Gas", +) +axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") +axes[0].set_ylabel("Power (kW)") axes[0].set_title("System-Level Control: First 168 Hours") +axes[0].legend(loc="upper right") -axes[1].plot(hours, ng_out, color="tab:orange") -axes[1].set_ylabel("Natural Gas (kW)") - -axes[2].plot(hours, batt_charge, color="tab:green") -axes[2].set_ylabel("Battery Charge (kW)") - -axes[3].plot(hours, batt_discharge, color="tab:purple") -axes[3].set_ylabel("Battery Discharge (kW)") - -axes[4].plot(hours, batt_soc, color="tab:cyan") -axes[4].set_ylabel("Battery SOC (%)") +axes[1].plot(hours, batt_soc, color="tab:cyan") +axes[1].set_ylabel("Battery SOC (%)") -axes[5].plot(hours, curtailed, color="tab:red") -axes[5].set_ylabel("Curtailed (kW)") -axes[5].set_xlabel("Hour") +axes[2].plot(hours, curtailed, color="tab:red") +axes[2].set_ylabel("Curtailed (kW)") +axes[2].set_xlabel("Hour") for ax in axes: ax.grid(True, alpha=0.3) diff --git a/examples/35_system_level_control/yes_battery/tech_config.yaml b/examples/35_system_level_control/yes_battery/tech_config.yaml index 870889a0d..137668e15 100644 --- a/examples/35_system_level_control/yes_battery/tech_config.yaml +++ b/examples/35_system_level_control/yes_battery/tech_config.yaml @@ -69,7 +69,7 @@ technologies: performance_parameters: commodity: electricity commodity_rate_units: kW - demand_profile: 50000 + demand_profile: 30000 combiner: performance_model: model: GenericCombinerPerformanceModel From 59f9b1642b542fb2bfeee3262c11850229d23c98 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 12:48:30 -0600 Subject: [PATCH 018/132] Moved combiner and changed battery model --- .../yes_battery/plant_config.yaml | 17 +++++++++-------- .../yes_battery/tech_config.yaml | 17 +++++------------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml index 821d07237..72331d352 100644 --- a/examples/35_system_level_control/yes_battery/plant_config.yaml +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -14,17 +14,18 @@ sites: # with the reverse definition. # this will naturally grow as we mature the interconnected tech technology_interconnections: - - [wind, combiner, electricity, cable] - # source_tech, dest_tech, transport_item, transport_type = connection - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect NG feedstock to NG plant - - [combiner, battery, electricity, cable] - # wind available for battery charging - - [combiner, electrical_load_demand, electricity, cable] - # subtract wind from demand - - [combiner, fin_combiner, electricity, cable] + - [wind, battery, electricity, cable] + # wind output available for battery charging (electricity_in) + - [wind, fin_combiner, electricity, cable] + # wind to combined output - [battery, fin_combiner, electricity, cable] + # battery net output to combined output - [natural_gas_plant, fin_combiner, electricity, cable] + # NG to combined output + - [fin_combiner, electrical_load_demand, electricity, cable] + # combined supply to demand resource_to_tech_connections: # connect the wind resource to the wind technology - [site.wind_resource, wind, wind_resource_data] @@ -88,7 +89,7 @@ finance_parameters: finance_subgroups: renewables: commodity: electricity - commodity_stream: combiner + commodity_stream: wind finance_groups: [profast_lco, profast_npv] technologies: [wind] natural_gas: diff --git a/examples/35_system_level_control/yes_battery/tech_config.yaml b/examples/35_system_level_control/yes_battery/tech_config.yaml index 137668e15..0805b5e52 100644 --- a/examples/35_system_level_control/yes_battery/tech_config.yaml +++ b/examples/35_system_level_control/yes_battery/tech_config.yaml @@ -70,18 +70,11 @@ technologies: commodity: electricity commodity_rate_units: kW demand_profile: 30000 - combiner: - performance_model: - model: GenericCombinerPerformanceModel - model_inputs: - performance_parameters: - commodity: electricity - commodity_rate_units: kW battery: performance_model: - model: PySAMBatteryPerformanceModel + model: StoragePerformanceModel cost_model: - model: ATBBatteryCostModel + model: GenericStorageCostModel model_inputs: shared_parameters: commodity: electricity @@ -92,12 +85,12 @@ technologies: max_soc_fraction: 1.0 min_soc_fraction: 0.1 performance_parameters: - chemistry: LFPGraphite + round_trip_efficiency: 0.90 demand_profile: 50000 # kW, required by storage base config cost_parameters: cost_year: 2022 - energy_capex: 310 # $/kWh - power_capex: 311 # $/kW + capacity_capex: 310 # $/kWh + charge_capex: 311 # $/kW opex_fraction: 0.025 fin_combiner: performance_model: From 0fdfde2b534caf6d3f3d757750b18b4cd7ea6e64 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 12:51:00 -0600 Subject: [PATCH 019/132] Changed example so wind power is sometimes curtailed after charging battery --- .../35_system_level_control/yes_battery/tech_config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/35_system_level_control/yes_battery/tech_config.yaml b/examples/35_system_level_control/yes_battery/tech_config.yaml index 0805b5e52..acda181e3 100644 --- a/examples/35_system_level_control/yes_battery/tech_config.yaml +++ b/examples/35_system_level_control/yes_battery/tech_config.yaml @@ -79,14 +79,14 @@ technologies: shared_parameters: commodity: electricity commodity_rate_units: kW - max_charge_rate: 50000 # kW (50 MW) - max_capacity: 200000 # kWh (200 MWh, 4-hour duration) + max_charge_rate: 20000 # kW (20 MW) + max_capacity: 80000 # kWh (80 MWh, 4-hour duration) init_soc_fraction: 0.5 max_soc_fraction: 1.0 min_soc_fraction: 0.1 performance_parameters: round_trip_efficiency: 0.90 - demand_profile: 50000 # kW, required by storage base config + demand_profile: 20000 # kW, required by storage base config cost_parameters: cost_year: 2022 capacity_capex: 310 # $/kWh From 2e428b337f481afb53aa75f912dbc95d6027d94c Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 13:35:34 -0600 Subject: [PATCH 020/132] updated plotting script --- .../35_system_level_control/yes_battery/run_wind_ng_demand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py index a70f69372..b536e660b 100644 --- a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py +++ b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py @@ -48,7 +48,7 @@ axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") axes[0].set_ylabel("Power (kW)") axes[0].set_title("System-Level Control: First 168 Hours") -axes[0].legend(loc="upper right") +axes[0].legend() axes[1].plot(hours, batt_soc, color="tab:cyan") axes[1].set_ylabel("Battery SOC (%)") From 237df21cde7d14a70e410795605235b05dfd4c3a Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:01:31 -0600 Subject: [PATCH 021/132] added marker to curtailment component test --- .../converters/test/test_curtailable_component.py | 2 ++ h2integrate/core/h2integrate_model.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py index a08b37774..a0042effd 100644 --- a/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py +++ b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py @@ -1,4 +1,5 @@ import numpy as np +import pytest import openmdao.api as om from pytest import fixture @@ -24,6 +25,7 @@ def plant_config_base(): return plant_config +@pytest.mark.unit def test_curtailable_component(plant_config_base, subtests): prob = om.Problem() diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 2445d256c..2bdbd7a21 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -485,7 +485,7 @@ def _classify_slc_technologies(self): commodity_units = None for tech_name, tech_def in technologies.items(): model_name = tech_def.get("performance_model", {}).get("model", "") - if "Demand" not in model_name: + if "DemandComponent" not in model_name: continue model_inputs = tech_def.get("model_inputs", {}) From cb9d0535a0f8a24a8f3cf274a604a2fdf14464f8 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:02:03 -0600 Subject: [PATCH 022/132] added super basic SLC tests to make sure examples dont break --- .../system_level/test/test_slc_examples.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 h2integrate/control/control_strategies/system_level/test/test_slc_examples.py diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py new file mode 100644 index 000000000..259ad9a5a --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -0,0 +1,37 @@ +import pytest + +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("35_system_level_control/no_battery", None)] +) +def test_slc_no_battery(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") + + model.run() + + wind_out = model.prob.get_val("plant.wind.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("35_system_level_control/yes_battery", None)] +) +def test_slc_yes_battery(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") + + model.run() + + wind_out = model.prob.get_val("plant.wind.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 From 1ef9743d77115c23688f9e75ebf480bccfaeb7da Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:06:10 -0600 Subject: [PATCH 023/132] fixed example tests --- .../control_strategies/system_level/test/conftest.py | 7 +++++++ .../system_level/test/test_slc_examples.py | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 h2integrate/control/control_strategies/system_level/test/conftest.py diff --git a/h2integrate/control/control_strategies/system_level/test/conftest.py b/h2integrate/control/control_strategies/system_level/test/conftest.py new file mode 100644 index 000000000..3380e4e17 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/test/conftest.py @@ -0,0 +1,7 @@ +from test.conftest import ( # noqa: F401 + temp_dir, + temp_dir_module, + temp_copy_of_example, + pytest_collection_modifyitems, + temp_copy_of_example_module_scope, +) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 259ad9a5a..502be050b 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -14,7 +14,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): model.run() - wind_out = model.prob.get_val("plant.wind.electricity_out") + wind_out = model.prob.get_val("wind.electricity_out") with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 @@ -31,7 +31,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): model.run() - wind_out = model.prob.get_val("plant.wind.electricity_out") + wind_out = model.prob.get_val("wind.electricity_out") with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 From 748be3206ce46d57f07985d8ca332ae97210184d Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 16:37:47 -0600 Subject: [PATCH 024/132] Minor name clarifications within SLC --- .../system_level/system_level_control.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index 555b1f9dc..dc758a208 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -53,11 +53,11 @@ def setup(self): # ---- Add OpenMDAO inputs / outputs per tech category ---- # Curtailable techs: read output + rated production, write set_point self.curtailable_input_names = [] - self.curtailable_output_names = [] + self.curtailable_set_point_names = [] self.curtailable_rated_names = [] for tech_name in self.curtailable_techs: in_name = f"{tech_name}_{self.commodity}_out" - out_name = f"{tech_name}_{self.commodity}_set_point" + set_point_name = f"{tech_name}_{self.commodity}_set_point" rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, @@ -73,14 +73,14 @@ def setup(self): desc=f"Rated {self.commodity} production for {tech_name}", ) self.add_output( - out_name, + set_point_name, val=0.0, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} curtailment", ) self.curtailable_input_names.append(in_name) - self.curtailable_output_names.append(out_name) + self.curtailable_set_point_names.append(set_point_name) self.curtailable_rated_names.append(rated_name) # Compute a reasonable initial set_point for dispatchable techs @@ -94,11 +94,11 @@ def setup(self): initial_set_point = 0.0 self.dispatchable_input_names = [] - self.dispatchable_output_names = [] + self.dispatchable_set_point_names = [] self.dispatchable_rated_names = [] for tech_name in self.dispatchable_techs: in_name = f"{tech_name}_{self.commodity}_out" - out_name = f"{tech_name}_{self.commodity}_set_point" + set_point_name = f"{tech_name}_{self.commodity}_set_point" rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, @@ -114,22 +114,22 @@ def setup(self): desc=f"Rated {self.commodity} production for {tech_name}", ) self.add_output( - out_name, + set_point_name, val=initial_set_point, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} production", ) self.dispatchable_input_names.append(in_name) - self.dispatchable_output_names.append(out_name) + self.dispatchable_set_point_names.append(set_point_name) self.dispatchable_rated_names.append(rated_name) self.storage_input_names = [] - self.storage_output_names = [] + self.storage_set_point_names = [] self.storage_rated_names = [] for tech_name in self.storage_techs: in_name = f"{tech_name}_{self.commodity}_out" - out_name = f"{tech_name}_{self.commodity}_set_point" + set_point_name = f"{tech_name}_{self.commodity}_set_point" rated_name = f"{tech_name}_rated_{self.commodity}_production" self.add_input( in_name, @@ -145,38 +145,38 @@ def setup(self): desc=f"Rated {self.commodity} production for {tech_name}", ) self.add_output( - out_name, + set_point_name, val=0.0, shape=self.n_timesteps, units=self.commodity_units, desc=f"Set point for {tech_name} {self.commodity} production", ) self.storage_input_names.append(in_name) - self.storage_output_names.append(out_name) + self.storage_set_point_names.append(set_point_name) self.storage_rated_names.append(rated_name) def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() # 1. Curtailable techs: set_point = rated production (no curtailment) - for in_name, out_name, rated_name in zip( + for in_name, set_point_name, rated_name in zip( self.curtailable_input_names, - self.curtailable_output_names, + self.curtailable_set_point_names, self.curtailable_rated_names, ): curtailable_output = inputs[in_name] - outputs[out_name] = inputs[rated_name] * np.ones(self.n_timesteps) + outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) demand -= curtailable_output # 2. Storage dispatch: set_point = net demand per storage tech # positive set_point → discharge, negative → charge # The storage model's simulate() handles rate/SOC/availability clipping # internally, so we pass the raw demand signal here. - n_storage = len(self.storage_output_names) + n_storage = len(self.storage_set_point_names) if n_storage > 0: storage_share = demand / n_storage - for out_name in self.storage_output_names: - outputs[out_name] = storage_share + for set_point_name in self.storage_set_point_names: + outputs[set_point_name] = storage_share # Subtract actual storage output from demand # (electricity_out > 0 when discharging, < 0 when charging) @@ -185,8 +185,8 @@ def compute(self, inputs, outputs): # 3. Remaining demand after curtailable + storage → dispatchable techs remaining = np.maximum(demand, 0.0) - n_dispatchable = len(self.dispatchable_output_names) + n_dispatchable = len(self.dispatchable_set_point_names) if n_dispatchable > 0: share = remaining / n_dispatchable - for out_name in self.dispatchable_output_names: - outputs[out_name] = share + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = share From f8294c6667dbc516d43943493a1d66e156e01fa0 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 17:18:00 -0600 Subject: [PATCH 025/132] Adding a notion of price-considering SLCs --- .../system_level/cost_minimization_control.py | 67 ++++++ .../system_level/demand_following_control.py | 35 +++ .../profit_maximization_control.py | 86 ++++++++ .../system_level/system_level_control.py | 199 +----------------- .../system_level/system_level_control_base.py | 195 +++++++++++++++++ h2integrate/core/h2integrate_model.py | 58 ++++- 6 files changed, 441 insertions(+), 199 deletions(-) create mode 100644 h2integrate/control/control_strategies/system_level/cost_minimization_control.py create mode 100644 h2integrate/control/control_strategies/system_level/demand_following_control.py create mode 100644 h2integrate/control/control_strategies/system_level/profit_maximization_control.py create mode 100644 h2integrate/control/control_strategies/system_level/system_level_control_base.py diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py new file mode 100644 index 000000000..4855c1d77 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -0,0 +1,67 @@ +import numpy as np + +from h2integrate.control.control_strategies.system_level.system_level_control_base import ( + SystemLevelControlBase, +) + + +class CostMinimizationControl(SystemLevelControlBase): + """Cost-minimizing system-level controller. + + Meets demand at minimum variable cost using merit-order dispatch: + + 1. Curtailable techs run at rated capacity (zero marginal cost). + 2. Storage absorbs surplus / provides deficit. + 3. Dispatchable techs are dispatched in ascending marginal-cost order, + each up to its rated capacity, until remaining demand is met. + + Each dispatchable technology must have a ``marginal_cost`` input + ($/commodity_rate_unit·h, e.g. $/kWh) representing its variable cost + per unit of production. These are connected from cost model outputs + or set as defaults in the plant config. + """ + + def setup(self): + super().setup() + + # Add marginal cost inputs for dispatchable techs + self.dispatchable_marginal_cost_names = [] + for tech_name in self.dispatchable_techs: + mc_name = f"{tech_name}_marginal_cost" + self.add_input( + mc_name, + val=0.0, + units=f"USD/({self.commodity_units}*h)", + desc=f"Marginal cost of {self.commodity} from {tech_name}", + ) + self.dispatchable_marginal_cost_names.append(mc_name) + + def compute(self, inputs, outputs): + demand = inputs[self.demand_input_name].copy() + + # 1. Curtailable techs: full production + demand = self._subtract_curtailable(inputs, outputs, demand) + + # 2. Storage dispatch + demand = self._dispatch_storage(inputs, outputs, demand) + + # 3. Merit-order dispatch: cheapest dispatchable first + remaining = np.maximum(demand, 0.0) + + # Collect marginal costs and sort by ascending cost + marginal_costs = np.array([inputs[mc][0] for mc in self.dispatchable_marginal_cost_names]) + dispatch_order = np.argsort(marginal_costs) + + # Initialize all dispatchable set_points to zero + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) + + # Dispatch in merit order + for idx in dispatch_order: + set_point_name = self.dispatchable_set_point_names[idx] + rated_name = self.dispatchable_rated_names[idx] + rated = inputs[rated_name] + + dispatch = np.minimum(remaining, rated) + outputs[set_point_name] = dispatch + remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py new file mode 100644 index 000000000..0864d879a --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -0,0 +1,35 @@ +import numpy as np + +from h2integrate.control.control_strategies.system_level.system_level_control_base import ( + SystemLevelControlBase, +) + + +class DemandFollowingControl(SystemLevelControlBase): + """Demand-following system-level controller. + + Dispatch priority: + 1. Curtailable techs run at rated capacity (zero marginal cost). + 2. Storage absorbs surplus / provides deficit (set_point = net demand). + 3. Remaining demand is split equally across dispatchable techs. + + This strategy always attempts to meet demand exactly; it does not + consider costs. + """ + + def compute(self, inputs, outputs): + demand = inputs[self.demand_input_name].copy() + + # 1. Curtailable techs: full production + demand = self._subtract_curtailable(inputs, outputs, demand) + + # 2. Storage dispatch + demand = self._dispatch_storage(inputs, outputs, demand) + + # 3. Dispatchable techs: equal share of remaining demand + remaining = np.maximum(demand, 0.0) + n_dispatchable = len(self.dispatchable_set_point_names) + if n_dispatchable > 0: + share = remaining / n_dispatchable + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = share diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py new file mode 100644 index 000000000..a585c3db3 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -0,0 +1,86 @@ +import numpy as np + +from h2integrate.control.control_strategies.system_level.system_level_control_base import ( + SystemLevelControlBase, +) + + +class ProfitMaximizationControl(SystemLevelControlBase): + """Profit-maximizing system-level controller. + + Dispatches technologies only when the commodity sell price exceeds + the marginal cost of production: + + 1. Curtailable techs run at rated capacity (zero marginal cost, + always profitable to produce). + 2. Storage absorbs surplus / provides deficit. + 3. Dispatchable techs are dispatched in merit order (cheapest first), + but **only if** their marginal cost is below the sell price. + Demand may go unmet if dispatch is unprofitable. + + Configuration: + ``plant_config["system_level_control"]["commodity_sell_price"]`` + must be set ($/commodity_rate_unit·h, e.g. $/kWh). + + Each dispatchable technology must have a ``marginal_cost`` input + representing its variable cost per unit of production. + """ + + def setup(self): + super().setup() + + slc_config = self.options["plant_config"]["system_level_control"] + + # Commodity sell price — user-set in config + default_sell_price = slc_config.get("commodity_sell_price", 0.0) + self.add_input( + "commodity_sell_price", + val=default_sell_price, + units=f"USD/({self.commodity_units}*h)", + desc=f"Sell price per unit of {self.commodity}", + ) + + # Add marginal cost inputs for dispatchable techs + self.dispatchable_marginal_cost_names = [] + for tech_name in self.dispatchable_techs: + mc_name = f"{tech_name}_marginal_cost" + self.add_input( + mc_name, + val=0.0, + units=f"USD/({self.commodity_units}*h)", + desc=f"Marginal cost of {self.commodity} from {tech_name}", + ) + self.dispatchable_marginal_cost_names.append(mc_name) + + def compute(self, inputs, outputs): + demand = inputs[self.demand_input_name].copy() + sell_price = inputs["commodity_sell_price"][0] + + # 1. Curtailable techs: full production (always profitable) + demand = self._subtract_curtailable(inputs, outputs, demand) + + # 2. Storage dispatch + demand = self._dispatch_storage(inputs, outputs, demand) + + # 3. Profit-driven merit-order dispatch + remaining = np.maximum(demand, 0.0) + + marginal_costs = np.array([inputs[mc][0] for mc in self.dispatchable_marginal_cost_names]) + dispatch_order = np.argsort(marginal_costs) + + # Initialize all dispatchable set_points to zero + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) + + # Dispatch only if profitable + for idx in dispatch_order: + if marginal_costs[idx] >= sell_price: + break # remaining techs are even more expensive + + set_point_name = self.dispatchable_set_point_names[idx] + rated_name = self.dispatchable_rated_names[idx] + rated = inputs[rated_name] + + dispatch = np.minimum(remaining, rated) + outputs[set_point_name] = dispatch + remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py index dc758a208..eeb51065d 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control.py @@ -1,192 +1,11 @@ -import numpy as np -import openmdao.api as om +"""Backward-compatible alias for :class:`DemandFollowingControl`. +The ``SystemLevelControl`` name is kept so that existing imports +(e.g. ``from ...system_level_control import SystemLevelControl``) +continue to work. New code should import the specific controller +class directly. +""" -class SystemLevelControl(om.ExplicitComponent): - """System-level control that satisfies demand across all technologies. - - Reads pre-computed technology classification from - ``plant_config["system_level_control"]``, which must contain: - - - ``commodity``: the commodity being controlled (e.g. "electricity") - - ``commodity_units``: units string (or None) - - ``demand_tech``: name of the demand technology - - ``curtailable_techs``: list of curtailable technology names - - ``dispatchable_techs``: list of dispatchable technology names - - ``storage_techs``: list of storage technology names - - Only one commodity demand stream is supported. At each timestep, - curtailable production is applied first, then the remaining demand - is distributed equally across dispatchable technologies. - """ - - def initialize(self): - self.options.declare("driver_config", types=dict) - self.options.declare("plant_config", types=dict) - self.options.declare("tech_config", types=dict) - - def setup(self): - plant_config = self.options["plant_config"] - slc_config = plant_config["system_level_control"] - - self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] - - # Read pre-computed classification from plant_config - self.commodity = slc_config["commodity"] - self.commodity_units = slc_config.get("commodity_units", None) - self.demand_tech = slc_config["demand_tech"] - self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) - self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) - self.storage_techs = list(slc_config.get("storage_techs", [])) - - # Input: demand profile (default value from config) - demand_profile = slc_config.get("demand_profile", 0.0) - self.demand_input_name = f"{self.commodity}_demand" - self.add_input( - self.demand_input_name, - val=demand_profile, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Demand profile of {self.commodity}", - ) - - # ---- Add OpenMDAO inputs / outputs per tech category ---- - # Curtailable techs: read output + rated production, write set_point - self.curtailable_input_names = [] - self.curtailable_set_point_names = [] - self.curtailable_rated_names = [] - for tech_name in self.curtailable_techs: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} curtailment", - ) - self.curtailable_input_names.append(in_name) - self.curtailable_set_point_names.append(set_point_name) - self.curtailable_rated_names.append(rated_name) - - # Compute a reasonable initial set_point for dispatchable techs - n_dispatchable = len(self.dispatchable_techs) - if n_dispatchable > 0: - if np.isscalar(demand_profile): - initial_set_point = demand_profile / n_dispatchable - else: - initial_set_point = np.array(demand_profile) / n_dispatchable - else: - initial_set_point = 0.0 - - self.dispatchable_input_names = [] - self.dispatchable_set_point_names = [] - self.dispatchable_rated_names = [] - for tech_name in self.dispatchable_techs: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=initial_set_point, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} production", - ) - self.dispatchable_input_names.append(in_name) - self.dispatchable_set_point_names.append(set_point_name) - self.dispatchable_rated_names.append(rated_name) - - self.storage_input_names = [] - self.storage_set_point_names = [] - self.storage_rated_names = [] - for tech_name in self.storage_techs: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} production", - ) - self.storage_input_names.append(in_name) - self.storage_set_point_names.append(set_point_name) - self.storage_rated_names.append(rated_name) - - def compute(self, inputs, outputs): - demand = inputs[self.demand_input_name].copy() - - # 1. Curtailable techs: set_point = rated production (no curtailment) - for in_name, set_point_name, rated_name in zip( - self.curtailable_input_names, - self.curtailable_set_point_names, - self.curtailable_rated_names, - ): - curtailable_output = inputs[in_name] - outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) - demand -= curtailable_output - - # 2. Storage dispatch: set_point = net demand per storage tech - # positive set_point → discharge, negative → charge - # The storage model's simulate() handles rate/SOC/availability clipping - # internally, so we pass the raw demand signal here. - n_storage = len(self.storage_set_point_names) - if n_storage > 0: - storage_share = demand / n_storage - for set_point_name in self.storage_set_point_names: - outputs[set_point_name] = storage_share - - # Subtract actual storage output from demand - # (electricity_out > 0 when discharging, < 0 when charging) - for in_name in self.storage_input_names: - demand -= inputs[in_name] - - # 3. Remaining demand after curtailable + storage → dispatchable techs - remaining = np.maximum(demand, 0.0) - n_dispatchable = len(self.dispatchable_set_point_names) - if n_dispatchable > 0: - share = remaining / n_dispatchable - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = share +from h2integrate.control.control_strategies.system_level.demand_following_control import ( # noqa: F401 + DemandFollowingControl as SystemLevelControl, +) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py new file mode 100644 index 000000000..61afd1f97 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -0,0 +1,195 @@ +import numpy as np +import openmdao.api as om + + +class SystemLevelControlBase(om.ExplicitComponent): + """Base class for system-level controllers. + + Provides common setup logic shared by all system-level control strategies: + demand input, curtailable/dispatchable/storage technology I/O creation, + and technology classification reading from ``plant_config``. + + Subclasses must implement ``compute()`` with their dispatch strategy. + + Configuration is read from ``plant_config["system_level_control"]``, + which must contain: + + - ``commodity``: the commodity being controlled (e.g. "electricity") + - ``commodity_units``: units string (or None) + - ``demand_tech``: name of the demand technology + - ``curtailable_techs``: list of curtailable technology names + - ``dispatchable_techs``: list of dispatchable technology names + - ``storage_techs``: list of storage technology names + """ + + def initialize(self): + self.options.declare("driver_config", types=dict) + self.options.declare("plant_config", types=dict) + self.options.declare("tech_config", types=dict) + + def setup(self): + plant_config = self.options["plant_config"] + slc_config = plant_config["system_level_control"] + + self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] + + # Read pre-computed classification from plant_config + self.commodity = slc_config["commodity"] + self.commodity_units = slc_config.get("commodity_units", None) + self.demand_tech = slc_config["demand_tech"] + self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) + self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) + self.storage_techs = list(slc_config.get("storage_techs", [])) + + # Input: demand profile (default value from config) + demand_profile = slc_config.get("demand_profile", 0.0) + self.demand_input_name = f"{self.commodity}_demand" + self.add_input( + self.demand_input_name, + val=demand_profile, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Demand profile of {self.commodity}", + ) + + self._setup_curtailable_techs() + self._setup_dispatchable_techs(demand_profile) + self._setup_storage_techs() + + def _setup_curtailable_techs(self): + """Create I/O for curtailable technologies.""" + self.curtailable_input_names = [] + self.curtailable_set_point_names = [] + self.curtailable_rated_names = [] + for tech_name in self.curtailable_techs: + in_name = f"{tech_name}_{self.commodity}_out" + set_point_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) + self.add_output( + set_point_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} curtailment", + ) + self.curtailable_input_names.append(in_name) + self.curtailable_set_point_names.append(set_point_name) + self.curtailable_rated_names.append(rated_name) + + def _setup_dispatchable_techs(self, demand_profile): + """Create I/O for dispatchable technologies.""" + n_dispatchable = len(self.dispatchable_techs) + if n_dispatchable > 0: + if np.isscalar(demand_profile): + initial_set_point = demand_profile / n_dispatchable + else: + initial_set_point = np.array(demand_profile) / n_dispatchable + else: + initial_set_point = 0.0 + + self.dispatchable_input_names = [] + self.dispatchable_set_point_names = [] + self.dispatchable_rated_names = [] + for tech_name in self.dispatchable_techs: + in_name = f"{tech_name}_{self.commodity}_out" + set_point_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) + self.add_output( + set_point_name, + val=initial_set_point, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} production", + ) + self.dispatchable_input_names.append(in_name) + self.dispatchable_set_point_names.append(set_point_name) + self.dispatchable_rated_names.append(rated_name) + + def _setup_storage_techs(self): + """Create I/O for storage technologies.""" + self.storage_input_names = [] + self.storage_set_point_names = [] + self.storage_rated_names = [] + for tech_name in self.storage_techs: + in_name = f"{tech_name}_{self.commodity}_out" + set_point_name = f"{tech_name}_{self.commodity}_set_point" + rated_name = f"{tech_name}_rated_{self.commodity}_production" + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"{self.commodity} output from {tech_name}", + ) + self.add_input( + rated_name, + val=0.0, + units=self.commodity_units, + desc=f"Rated {self.commodity} production for {tech_name}", + ) + self.add_output( + set_point_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodity_units, + desc=f"Set point for {tech_name} {self.commodity} production", + ) + self.storage_input_names.append(in_name) + self.storage_set_point_names.append(set_point_name) + self.storage_rated_names.append(rated_name) + + def _subtract_curtailable(self, inputs, outputs, demand): + """Apply curtailable techs: set_point = rated, subtract output from demand. + + Returns the updated demand array. + """ + for in_name, set_point_name, rated_name in zip( + self.curtailable_input_names, + self.curtailable_set_point_names, + self.curtailable_rated_names, + ): + outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) + demand -= inputs[in_name] + return demand + + def _dispatch_storage(self, inputs, outputs, demand): + """Dispatch storage techs proportionally and subtract actual output from demand. + + Positive set_point = discharge, negative = charge. + Returns the updated demand array. + """ + n_storage = len(self.storage_set_point_names) + if n_storage > 0: + storage_share = demand / n_storage + for set_point_name in self.storage_set_point_names: + outputs[set_point_name] = storage_share + + for in_name in self.storage_input_names: + demand -= inputs[in_name] + return demand diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 2bdbd7a21..028209ad5 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -23,12 +23,18 @@ multivariable_streams, is_electricity_producer, ) -from h2integrate.control.control_strategies.system_level.system_level_control import ( - SystemLevelControl, -) from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import ( PyomoStorageControllerBaseClass, ) +from h2integrate.control.control_strategies.system_level.demand_following_control import ( + DemandFollowingControl, +) +from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( + CostMinimizationControl, +) +from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( + ProfitMaximizationControl, +) try: @@ -529,13 +535,22 @@ def add_system_level_controller(self): """Add the SystemLevelControl component and configure the plant solver. This method: - 1. Adds a ``SystemLevelControl`` subsystem to the plant group - 2. Configures the nonlinear solver on the plant group based on - ``plant_config["system_level_control"]`` parameters - 3. Creates connections between the controller and each technology + 1. Selects the appropriate controller class based on ``control_strategy`` + 2. Adds it as a subsystem to the plant group + 3. Configures the nonlinear solver on the plant group + 4. Creates connections between the controller and each technology + 5. For cost/profit strategies, connects marginal cost inputs """ slc_config = self.plant_config["system_level_control"] + # Map control_strategy config values to controller classes + strategy_map = { + "demand_following": DemandFollowingControl, + "load_meeting": DemandFollowingControl, # alias + "cost_minimization": CostMinimizationControl, + "profit_maximization": ProfitMaximizationControl, + } + # Map user-facing solver names to OpenMDAO solver classes solver_map = { "gauss_seidel": om.NonlinearBlockGS, @@ -543,8 +558,16 @@ def add_system_level_controller(self): "block_jacobi": om.NonlinearBlockJac, } - # 1. Add the controller as the first subsystem in the plant group - slc_comp = SystemLevelControl( + # 1. Select controller class based on strategy + strategy_name = slc_config.get("control_strategy", "demand_following") + slc_cls = strategy_map.get(strategy_name) + if slc_cls is None: + raise ValueError( + f"Unknown control_strategy '{strategy_name}' in system_level_control. " + f"Supported: {list(strategy_map.keys())}" + ) + + slc_comp = slc_cls( driver_config=self.driver_config, plant_config=self.plant_config, tech_config=self.technology_config, @@ -605,6 +628,23 @@ def add_system_level_controller(self): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) + # 4. For cost-aware strategies, connect marginal costs + # Marginal cost defaults are set from tech_config; they can also be + # connected from cost model outputs if available. + if strategy_name in ("cost_minimization", "profit_maximization"): + technologies = self.technology_config.get("technologies", {}) + for tech_name in slc_config["dispatchable_techs"]: + tech_def = technologies.get(tech_name, {}) + model_inputs = tech_def.get("model_inputs", {}) + shared = model_inputs.get("shared_parameters", {}) + cost_params = model_inputs.get("cost_parameters", {}) + all_params = {**shared, **cost_params} + + mc = all_params.get("marginal_cost", None) + if mc is not None: + mc_input = f"system_level_controller.{tech_name}_marginal_cost" + self.prob.set_val(mc_input, mc) + ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. # # Connect demand profile to the controller From 3bcbc2f598366ca3697d63931b7eca21e646d444 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 17:52:23 -0600 Subject: [PATCH 026/132] WIP: working on marginal costs for SLC --- .../profit_maximization_control.py | 15 ++++++------- h2integrate/core/h2integrate_model.py | 21 ++++++------------- h2integrate/core/model_baseclasses.py | 13 ++++++++++++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index a585c3db3..a5561c7d0 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -20,7 +20,7 @@ class ProfitMaximizationControl(SystemLevelControlBase): Configuration: ``plant_config["system_level_control"]["commodity_sell_price"]`` - must be set ($/commodity_rate_unit·h, e.g. $/kWh). + must be set ($/(commodity_rate_unit*h), e.g. $/kWh). Each dispatchable technology must have a ``marginal_cost`` input representing its variable cost per unit of production. @@ -31,11 +31,12 @@ def setup(self): slc_config = self.options["plant_config"]["system_level_control"] - # Commodity sell price — user-set in config + # Commodity sell price — user-set in config, can be scalar or time-varying default_sell_price = slc_config.get("commodity_sell_price", 0.0) self.add_input( "commodity_sell_price", val=default_sell_price, + shape=self.n_timesteps, units=f"USD/({self.commodity_units}*h)", desc=f"Sell price per unit of {self.commodity}", ) @@ -54,7 +55,7 @@ def setup(self): def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() - sell_price = inputs["commodity_sell_price"][0] + sell_price = inputs["commodity_sell_price"] # shape (n_timesteps,) # 1. Curtailable techs: full production (always profitable) demand = self._subtract_curtailable(inputs, outputs, demand) @@ -72,15 +73,15 @@ def compute(self, inputs, outputs): for set_point_name in self.dispatchable_set_point_names: outputs[set_point_name] = np.zeros(self.n_timesteps) - # Dispatch only if profitable + # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: - if marginal_costs[idx] >= sell_price: - break # remaining techs are even more expensive + mc = marginal_costs[idx] + profitable = mc < sell_price # boolean mask per timestep set_point_name = self.dispatchable_set_point_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] - dispatch = np.minimum(remaining, rated) + dispatch = np.where(profitable, np.minimum(remaining, rated), 0.0) outputs[set_point_name] = dispatch remaining -= dispatch diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 028209ad5..2885dff63 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -628,22 +628,13 @@ def add_system_level_controller(self): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) - # 4. For cost-aware strategies, connect marginal costs - # Marginal cost defaults are set from tech_config; they can also be - # connected from cost model outputs if available. + # 4. For cost-aware strategies, connect marginal costs from cost models if strategy_name in ("cost_minimization", "profit_maximization"): - technologies = self.technology_config.get("technologies", {}) for tech_name in slc_config["dispatchable_techs"]: - tech_def = technologies.get(tech_name, {}) - model_inputs = tech_def.get("model_inputs", {}) - shared = model_inputs.get("shared_parameters", {}) - cost_params = model_inputs.get("cost_parameters", {}) - all_params = {**shared, **cost_params} - - mc = all_params.get("marginal_cost", None) - if mc is not None: - mc_input = f"system_level_controller.{tech_name}_marginal_cost" - self.prob.set_val(mc_input, mc) + self.plant.connect( + f"{tech_name}.marginal_cost", + f"system_level_controller.{tech_name}_marginal_cost", + ) ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. @@ -1625,7 +1616,7 @@ def run(self): # do model setup based on the driver config # might add a recorder, driver, set solver tolerances, etc if self.state < State.SETUP: - self.prob.setup() + self.setup() if self.state < State.RUN: # OpenMDAO will skip this step if it encounters an issue leading to silent failures diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 45d8b98da..f4ad59d4c 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -152,6 +152,7 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): @define(kw_only=True) class CostModelBaseConfig(BaseConfig): cost_year: int = field(converter=int) + marginal_cost: float = field(default=0.0) class CostModelBaseClass(om.ExplicitComponent): @@ -164,6 +165,7 @@ class CostModelBaseClass(om.ExplicitComponent): - CapEx (float): capital expenditure costs in $ - OpEx (float): annual fixed operating expenditure costs in $/year - VarOpEx (float): annual variable operating expenditure costs in $/year + - marginal_cost (float): marginal cost of production for dispatch decisions Discrete Outputs: - cost_year (int): dollar-year corresponding to CapEx and OpEx values. @@ -192,6 +194,17 @@ def setup(self): "cost_year", val=self.config.cost_year, desc="Dollar year for costs" ) + # Marginal cost output for dispatch decisions + model_inputs = self.options["tech_config"].get("model_inputs", {}) + shared = model_inputs.get("shared_parameters", {}) + commodity_rate_units = shared.get("commodity_rate_units", "kW") + self.add_output( + "marginal_cost", + val=self.config.marginal_cost, + units=f"USD/({commodity_rate_units}*h)", + desc="Marginal cost of production for dispatch decisions", + ) + # dt is seconds per timestep self.dt = int(self.options["plant_config"]["plant"]["simulation"]["dt"]) From 6dff23693757866e32feacbb3c56e4f380fe21f9 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 17:57:41 -0600 Subject: [PATCH 027/132] Updating SLC example to be simpler --- .../profit_maximization/driver_config.yaml | 4 + .../profit_maximization/plant_config.yaml | 30 +++++ .../profit_maximization/run_profit_max.py | 105 ++++++++++++++++++ .../profit_maximization/tech_config.yaml | 104 +++++++++++++++++ .../profit_maximization/wind_ng_demand.yaml | 4 + 5 files changed, 247 insertions(+) create mode 100644 examples/35_system_level_control/profit_maximization/driver_config.yaml create mode 100644 examples/35_system_level_control/profit_maximization/plant_config.yaml create mode 100644 examples/35_system_level_control/profit_maximization/run_profit_max.py create mode 100644 examples/35_system_level_control/profit_maximization/tech_config.yaml create mode 100644 examples/35_system_level_control/profit_maximization/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/profit_maximization/driver_config.yaml b/examples/35_system_level_control/profit_maximization/driver_config.yaml new file mode 100644 index 000000000..d7190b031 --- /dev/null +++ b/examples/35_system_level_control/profit_maximization/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: Profit-maximization dispatch with diurnal pricing +general: + folder_output: outputs diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml new file mode 100644 index 000000000..6ab2093d7 --- /dev/null +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -0,0 +1,30 @@ +name: plant_config +description: Wind + NG plant with profit-maximization control and diurnal pricing. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 +technology_interconnections: + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + - [wind, battery, electricity, cable] + - [wind, fin_combiner, electricity, cable] + - [battery, fin_combiner, electricity, cable] + - [natural_gas_plant, fin_combiner, electricity, cable] + - [fin_combiner, electrical_load_demand, electricity, cable] +resource_to_tech_connections: + - [site.wind_resource, wind, wind_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +system_level_control: + control_strategy: profit_maximization + commodity_sell_price: 0.06 # $/kWh default; overridden in run script + solver_name: gauss_seidel + max_iter: 20 diff --git a/examples/35_system_level_control/profit_maximization/run_profit_max.py b/examples/35_system_level_control/profit_maximization/run_profit_max.py new file mode 100644 index 000000000..77e404933 --- /dev/null +++ b/examples/35_system_level_control/profit_maximization/run_profit_max.py @@ -0,0 +1,105 @@ +""" +Profit-maximization example with diurnal electricity sell prices. + +The NG plant has a fixed marginal cost of $0.05/kWh. The electricity sell +price follows a diurnal pattern that swings above and below this cost: + - Night (22:00-16:00): $0.03/kWh, NG is unprofitable, not dispatched + - Peak (16:00-22:00): $0.08/kWh, NG is profitable, dispatched + +The controller dispatches the NG plant only during hours when the sell price +exceeds the marginal cost, demonstrating profit-driven curtailment of +dispatchable generation. +""" + +import numpy as np +import matplotlib.pyplot as plt + +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +# -- Build diurnal sell-price profile ($/kWh) -- +n_timesteps = 8760 +sell_price = np.zeros(n_timesteps) +for h in range(n_timesteps): + hour_of_day = h % 24 + if 16 <= hour_of_day < 22: + sell_price[h] = 0.08 # peak + else: + sell_price[h] = 0.03 # night (cheap) + +# -- Create and run model -- +h2i = H2IntegrateModel("wind_ng_demand.yaml") + +# Setup first so we can set values +h2i.setup() + +# Override the sell price with our diurnal profile +h2i.prob.set_val( + "plant.system_level_controller.commodity_sell_price", + sell_price, + units="USD/(kW*h)", +) + +h2i.run() +h2i.post_process() + +# -- Extract results -- +n_hours = 168 # first week +hours = np.arange(n_hours) + +wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] +ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] +batt_discharge = h2i.prob.get_val("plant.battery.storage_electricity_discharge")[:n_hours] +batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] +demand = h2i.prob.get_val("plant.electrical_load_demand.electricity_demand")[:n_hours] +curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] +price = sell_price[:n_hours] + +# -- Plot -- +fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True) + +# Panel 1: stacked supply vs demand +axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") +axes[0].fill_between( + hours, + wind_out, + wind_out + batt_discharge, + alpha=0.7, + color="tab:purple", + label="Battery Discharge", +) +axes[0].fill_between( + hours, + wind_out + batt_discharge, + wind_out + batt_discharge + ng_out, + alpha=0.7, + color="tab:orange", + label="Natural Gas", +) +axes[0].plot(hours, demand, "k--", linewidth=1.5, label="Demand") +axes[0].set_ylabel("Power (kW)") +axes[0].set_title("Profit Maximization: First 168 Hours") +axes[0].legend(loc="upper right") + +# Panel 2: battery SOC +axes[1].plot(hours, batt_soc, color="tab:green") +axes[1].set_ylabel("SOC (kWh)") +axes[1].set_title("Battery State of Charge") + +# Panel 3: sell price vs NG marginal cost +axes[2].plot(hours, price * 100, color="tab:red", label="Sell Price") +axes[2].axhline(y=5.0, color="tab:orange", linestyle="--", label="NG Marginal Cost (5 ¢/kWh)") +axes[2].set_ylabel("Price (¢/kWh)") +axes[2].set_title("Electricity Sell Price vs NG Marginal Cost") +axes[2].legend(loc="upper right") + +# Panel 4: curtailed energy +axes[3].plot(hours, curtailed, color="tab:gray") +axes[3].set_ylabel("Curtailed (kW)") +axes[3].set_xlabel("Hour") +axes[3].set_title("Curtailed Electricity") + +plt.tight_layout() +plt.savefig("profit_max_results.png", dpi=150) +print("Plot saved to profit_max_results.png") +# plt.show() diff --git a/examples/35_system_level_control/profit_maximization/tech_config.yaml b/examples/35_system_level_control/profit_maximization/tech_config.yaml new file mode 100644 index 000000000..c9097a505 --- /dev/null +++ b/examples/35_system_level_control/profit_maximization/tech_config.yaml @@ -0,0 +1,104 @@ +name: technology_config +description: > + Wind farm, battery, NG plant with marginal cost for profit-maximization dispatch, + and a fixed electrical demand. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. + cost_parameters: + cost_year: 2023 + price: 4.2 + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 + system_capacity_mw: 100. + cost_parameters: + capex_per_kw: 1000 + fixed_opex_per_kw_per_year: 10.0 + variable_opex_per_mwh: 0.0 + cost_year: 2023 + marginal_cost: 0.05 # $/kWh — NG dispatch cost + electrical_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 30000 + battery: + performance_model: + model: StoragePerformanceModel + cost_model: + model: GenericStorageCostModel + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 20000 + max_capacity: 80000 + init_soc_fraction: 0.5 + max_soc_fraction: 1.0 + min_soc_fraction: 0.1 + performance_parameters: + round_trip_efficiency: 0.90 + demand_profile: 20000 + cost_parameters: + cost_year: 2022 + capacity_capex: 310 + charge_capex: 311 + opex_fraction: 0.025 + fin_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 3 diff --git a/examples/35_system_level_control/profit_maximization/wind_ng_demand.yaml b/examples/35_system_level_control/profit_maximization/wind_ng_demand.yaml new file mode 100644 index 000000000..e09f3dcda --- /dev/null +++ b/examples/35_system_level_control/profit_maximization/wind_ng_demand.yaml @@ -0,0 +1,4 @@ +name: H2Integrate_config +driver_config: driver_config.yaml +plant_config: plant_config.yaml +technology_config: tech_config.yaml From c2123f86968f91ee3eec1e2003e00a428a397f14 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 18:01:25 -0600 Subject: [PATCH 028/132] Removing prior SLC file --- .../no_battery/plant_config.yaml | 2 +- .../yes_battery/plant_config.yaml | 2 +- .../system_level/system_level_control.py | 11 ----------- h2integrate/core/h2integrate_model.py | 7 +++---- 4 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 h2integrate/control/control_strategies/system_level/system_level_control.py diff --git a/examples/35_system_level_control/no_battery/plant_config.yaml b/examples/35_system_level_control/no_battery/plant_config.yaml index 217d57a9b..92b0daa5c 100644 --- a/examples/35_system_level_control/no_battery/plant_config.yaml +++ b/examples/35_system_level_control/no_battery/plant_config.yaml @@ -31,7 +31,7 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: load_meeting + control_strategy: demand_following solver_name: gauss_seidel max_iter: 20 convergence_tolerance: 1.0e-6 diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml index 72331d352..a01166342 100644 --- a/examples/35_system_level_control/yes_battery/plant_config.yaml +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -35,7 +35,7 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: load_meeting + control_strategy: demand_following solver_name: gauss_seidel max_iter: 20 convergence_tolerance: 1.0e-6 diff --git a/h2integrate/control/control_strategies/system_level/system_level_control.py b/h2integrate/control/control_strategies/system_level/system_level_control.py deleted file mode 100644 index eeb51065d..000000000 --- a/h2integrate/control/control_strategies/system_level/system_level_control.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Backward-compatible alias for :class:`DemandFollowingControl`. - -The ``SystemLevelControl`` name is kept so that existing imports -(e.g. ``from ...system_level_control import SystemLevelControl``) -continue to work. New code should import the specific controller -class directly. -""" - -from h2integrate.control.control_strategies.system_level.demand_following_control import ( # noqa: F401 - DemandFollowingControl as SystemLevelControl, -) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 2885dff63..ffbe72710 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -480,7 +480,7 @@ def _classify_slc_technologies(self): Also identifies the single demand technology and its commodity. Results are written into ``self.plant_config["system_level_control"]`` so - they are available to the ``SystemLevelControl`` component at setup time. + they are available to the ``DemandFollowingControl`` component at setup time. """ slc_config = self.plant_config["system_level_control"] technologies = self.technology_config.get("technologies", {}) @@ -501,7 +501,7 @@ def _classify_slc_technologies(self): if commodity is not None: raise ValueError( - "SystemLevelControl currently supports only one demand " + "DemandFollowingControl currently supports only one demand " f"stream, but found demands for both '{commodity}' " f"and '{all_params.get('commodity', tech_name)}'." ) @@ -532,7 +532,7 @@ def _classify_slc_technologies(self): slc_config["storage_techs"] = storage_techs def add_system_level_controller(self): - """Add the SystemLevelControl component and configure the plant solver. + """Add the DemandFollowingControl component and configure the plant solver. This method: 1. Selects the appropriate controller class based on ``control_strategy`` @@ -546,7 +546,6 @@ def add_system_level_controller(self): # Map control_strategy config values to controller classes strategy_map = { "demand_following": DemandFollowingControl, - "load_meeting": DemandFollowingControl, # alias "cost_minimization": CostMinimizationControl, "profit_maximization": ProfitMaximizationControl, } From 9df4fd73fda3b6dae0c055ef3a48aaa9c2600d23 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 21:42:42 -0600 Subject: [PATCH 029/132] Consolidating methods for SLC --- .../system_level/cost_minimization_control.py | 4 +- .../system_level/system_level_control_base.py | 137 +++++++----------- 2 files changed, 55 insertions(+), 86 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 4855c1d77..3ba2d5366 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -10,13 +10,13 @@ class CostMinimizationControl(SystemLevelControlBase): Meets demand at minimum variable cost using merit-order dispatch: - 1. Curtailable techs run at rated capacity (zero marginal cost). + 1. Curtailable techs run at rated capacity (assuming zero marginal cost). 2. Storage absorbs surplus / provides deficit. 3. Dispatchable techs are dispatched in ascending marginal-cost order, each up to its rated capacity, until remaining demand is met. Each dispatchable technology must have a ``marginal_cost`` input - ($/commodity_rate_unit·h, e.g. $/kWh) representing its variable cost + ($/commodity_rate_unit*h, e.g. $/kWh) representing its variable cost per unit of production. These are connected from cost model outputs or set as defaults in the plant config. """ diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 61afd1f97..dffab3dfd 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -52,61 +52,58 @@ def setup(self): desc=f"Demand profile of {self.commodity}", ) - self._setup_curtailable_techs() - self._setup_dispatchable_techs(demand_profile) - self._setup_storage_techs() - - def _setup_curtailable_techs(self): - """Create I/O for curtailable technologies.""" - self.curtailable_input_names = [] - self.curtailable_set_point_names = [] - self.curtailable_rated_names = [] - for tech_name in self.curtailable_techs: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} curtailment", - ) - self.curtailable_input_names.append(in_name) - self.curtailable_set_point_names.append(set_point_name) - self.curtailable_rated_names.append(rated_name) - - def _setup_dispatchable_techs(self, demand_profile): - """Create I/O for dispatchable technologies.""" - n_dispatchable = len(self.dispatchable_techs) - if n_dispatchable > 0: + self._setup_tech_category("curtailable", self.curtailable_techs) + self._setup_tech_category("dispatchable", self.dispatchable_techs, demand_profile) + self._setup_tech_category("storage", self.storage_techs) + + def _setup_tech_category(self, category, tech_names, demand_profile=None): + """Create OpenMDAO I/O variables for a category of technologies. + + For each technology in the category, this method creates three variables: + + - ``{tech}_{commodity}_out``: an input for the technology's actual commodity + output at each timestep (shape ``n_timesteps``). + - ``{tech}_rated_{commodity}_production``: an input for the technology's + rated (maximum) production capacity (scalar). + - ``{tech}_{commodity}_set_point``: an output for the dispatch set-point + sent back to the technology at each timestep (shape ``n_timesteps``). + + The variable names are collected into three lists stored as instance + attributes named ``{category}_input_names``, + ``{category}_set_point_names``, and ``{category}_rated_names``. + + Args: + category: Technology classification label (e.g. ``"curtailable"``, + ``"dispatchable"``, ``"storage"``). Used to name the instance + attribute lists and the set-point description. + tech_names: Iterable of technology name strings belonging to this + category. + demand_profile: Optional demand profile used to initialize the + set-point output for dispatchable technologies. When provided, + the initial set-point is ``demand_profile / n_techs`` so that + the solver starts from a reasonable guess. Ignored (or + ``None``) for curtailable and storage categories, whose + set-points default to zero. + """ + # Compute initial set-point value + n_techs = len(tech_names) + if demand_profile is not None and n_techs > 0: if np.isscalar(demand_profile): - initial_set_point = demand_profile / n_dispatchable + initial_set_point = demand_profile / n_techs else: - initial_set_point = np.array(demand_profile) / n_dispatchable + initial_set_point = np.array(demand_profile) / n_techs else: initial_set_point = 0.0 - self.dispatchable_input_names = [] - self.dispatchable_set_point_names = [] - self.dispatchable_rated_names = [] - for tech_name in self.dispatchable_techs: + input_names = [] + set_point_names = [] + rated_names = [] + + for tech_name in tech_names: in_name = f"{tech_name}_{self.commodity}_out" set_point_name = f"{tech_name}_{self.commodity}_set_point" rated_name = f"{tech_name}_rated_{self.commodity}_production" + self.add_input( in_name, val=0.0, @@ -125,44 +122,16 @@ def _setup_dispatchable_techs(self, demand_profile): val=initial_set_point, shape=self.n_timesteps, units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} production", + desc=f"{category} set point for {tech_name} {self.commodity}", ) - self.dispatchable_input_names.append(in_name) - self.dispatchable_set_point_names.append(set_point_name) - self.dispatchable_rated_names.append(rated_name) - - def _setup_storage_techs(self): - """Create I/O for storage technologies.""" - self.storage_input_names = [] - self.storage_set_point_names = [] - self.storage_rated_names = [] - for tech_name in self.storage_techs: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=0.0, - shape=self.n_timesteps, - units=self.commodity_units, - desc=f"Set point for {tech_name} {self.commodity} production", - ) - self.storage_input_names.append(in_name) - self.storage_set_point_names.append(set_point_name) - self.storage_rated_names.append(rated_name) + + input_names.append(in_name) + set_point_names.append(set_point_name) + rated_names.append(rated_name) + + setattr(self, f"{category}_input_names", input_names) + setattr(self, f"{category}_set_point_names", set_point_names) + setattr(self, f"{category}_rated_names", rated_names) def _subtract_curtailable(self, inputs, outputs, demand): """Apply curtailable techs: set_point = rated, subtract output from demand. From 95673189675bfc6d10aa42c18d92d764712b13dc Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 29 Apr 2026 21:49:39 -0600 Subject: [PATCH 030/132] Moving SLC strategy definitions --- .../no_battery/plant_config.yaml | 2 +- .../profit_maximization/plant_config.yaml | 2 +- .../yes_battery/plant_config.yaml | 2 +- h2integrate/core/h2integrate_model.py | 24 ++++--------------- h2integrate/core/supported_models.py | 13 ++++++++++ 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/examples/35_system_level_control/no_battery/plant_config.yaml b/examples/35_system_level_control/no_battery/plant_config.yaml index 92b0daa5c..e6d3e8c7c 100644 --- a/examples/35_system_level_control/no_battery/plant_config.yaml +++ b/examples/35_system_level_control/no_battery/plant_config.yaml @@ -31,7 +31,7 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: demand_following + control_strategy: DemandFollowingControl solver_name: gauss_seidel max_iter: 20 convergence_tolerance: 1.0e-6 diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index 6ab2093d7..d3b56d109 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -24,7 +24,7 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: profit_maximization + control_strategy: ProfitMaximizationControl commodity_sell_price: 0.06 # $/kWh default; overridden in run script solver_name: gauss_seidel max_iter: 20 diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml index a01166342..d3c242b7b 100644 --- a/examples/35_system_level_control/yes_battery/plant_config.yaml +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -35,7 +35,7 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: demand_following + control_strategy: DemandFollowingControl solver_name: gauss_seidel max_iter: 20 convergence_tolerance: 1.0e-6 diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index ffbe72710..d68f890cc 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -26,15 +26,6 @@ from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import ( PyomoStorageControllerBaseClass, ) -from h2integrate.control.control_strategies.system_level.demand_following_control import ( - DemandFollowingControl, -) -from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( - CostMinimizationControl, -) -from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( - ProfitMaximizationControl, -) try: @@ -543,13 +534,6 @@ def add_system_level_controller(self): """ slc_config = self.plant_config["system_level_control"] - # Map control_strategy config values to controller classes - strategy_map = { - "demand_following": DemandFollowingControl, - "cost_minimization": CostMinimizationControl, - "profit_maximization": ProfitMaximizationControl, - } - # Map user-facing solver names to OpenMDAO solver classes solver_map = { "gauss_seidel": om.NonlinearBlockGS, @@ -558,12 +542,12 @@ def add_system_level_controller(self): } # 1. Select controller class based on strategy - strategy_name = slc_config.get("control_strategy", "demand_following") - slc_cls = strategy_map.get(strategy_name) + strategy_name = slc_config.get("control_strategy", "DemandFollowingControl") + slc_cls = self.supported_models.get(strategy_name) if slc_cls is None: raise ValueError( f"Unknown control_strategy '{strategy_name}' in system_level_control. " - f"Supported: {list(strategy_map.keys())}" + f"Must be a valid model name in supported_models." ) slc_comp = slc_cls( @@ -628,7 +612,7 @@ def add_system_level_controller(self): ) # 4. For cost-aware strategies, connect marginal costs from cost models - if strategy_name in ("cost_minimization", "profit_maximization"): + if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): for tech_name in slc_config["dispatchable_techs"]: self.plant.connect( f"{tech_name}.marginal_cost", diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 98249fb09..0f357f5eb 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -174,12 +174,21 @@ from h2integrate.control.control_strategies.storage.simple_openloop_controller import ( SimpleStorageOpenLoopController, ) +from h2integrate.control.control_strategies.system_level.demand_following_control import ( + DemandFollowingControl, +) +from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( + CostMinimizationControl, +) from h2integrate.control.control_strategies.storage.plm_openloop_storage_controller import ( PeakLoadManagementHeuristicOpenLoopStorageController, ) from h2integrate.control.control_rules.storage.pyomo_storage_rule_min_operating_cost import ( PyomoRuleStorageMinOperatingCosts, ) +from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( + ProfitMaximizationControl, +) from h2integrate.control.control_rules.converters.generic_converter_min_operating_cost import ( PyomoDispatchGenericConverterMinOperatingCosts, ) @@ -307,6 +316,10 @@ "OptimizedDispatchStorageController": OptimizedDispatchStorageController, "GenericDemandComponent": GenericDemandComponent, "FlexibleDemandComponent": FlexibleDemandComponent, + # System-level control strategies + "DemandFollowingControl": DemandFollowingControl, + "CostMinimizationControl": CostMinimizationControl, + "ProfitMaximizationControl": ProfitMaximizationControl, # Dispatch "PyomoDispatchGenericConverter": PyomoDispatchGenericConverter, "PyomoRuleStorageBaseclass": PyomoRuleStorageBaseclass, From 8910d363b6213e0c77d2d8e6b99ed6f4071347f3 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Fri, 1 May 2026 15:36:02 -0600 Subject: [PATCH 031/132] moved solver options to a config class --- .../no_battery/plant_config.yaml | 9 +-- .../profit_maximization/plant_config.yaml | 7 +- .../yes_battery/plant_config.yaml | 9 +-- .../system_level/solver_options.py | 47 ++++++++++++++ .../system_level/system_level_control_base.py | 8 +++ h2integrate/core/h2integrate_model.py | 64 ++++++++++--------- h2integrate/core/supported_models.py | 16 +++++ 7 files changed, 118 insertions(+), 42 deletions(-) create mode 100644 h2integrate/control/control_strategies/system_level/solver_options.py diff --git a/examples/35_system_level_control/no_battery/plant_config.yaml b/examples/35_system_level_control/no_battery/plant_config.yaml index 92b0daa5c..c5eca242c 100644 --- a/examples/35_system_level_control/no_battery/plant_config.yaml +++ b/examples/35_system_level_control/no_battery/plant_config.yaml @@ -31,10 +31,11 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: demand_following - solver_name: gauss_seidel - max_iter: 20 - convergence_tolerance: 1.0e-6 + control_strategy: DemandFollowingControl + solver_options: + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 finance_parameters: finance_groups: profast_lco: diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index 6ab2093d7..0a63d1765 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -24,7 +24,8 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: profit_maximization + control_strategy: ProfitMaximizationControl commodity_sell_price: 0.06 # $/kWh default; overridden in run script - solver_name: gauss_seidel - max_iter: 20 + solver_options: + solver_name: gauss_seidel + max_iter: 20 diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml index a01166342..a2967e397 100644 --- a/examples/35_system_level_control/yes_battery/plant_config.yaml +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -35,10 +35,11 @@ plant: n_timesteps: 8760 dt: 3600 system_level_control: - control_strategy: demand_following - solver_name: gauss_seidel - max_iter: 20 - convergence_tolerance: 1.0e-6 + control_strategy: DemandFollowingControl + solver_options: + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 finance_parameters: finance_groups: profast_lco: diff --git a/h2integrate/control/control_strategies/system_level/solver_options.py b/h2integrate/control/control_strategies/system_level/solver_options.py new file mode 100644 index 000000000..ae1d928e5 --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/solver_options.py @@ -0,0 +1,47 @@ +from typing import ClassVar + +import openmdao.api as om +from attrs import field, define + +from h2integrate.core.utilities import BaseConfig +from h2integrate.core.validators import gt_zero, contains, gte_zero + + +@define(kw_only=True) +class SLCSolverOptionsConfig(BaseConfig): + solver_name: str = field( + default="gauss_seidel", validator=contains["gauss_seidel", "newton", "block_jacobi"] + ) + maxiter: int = field(default=20, converter=int, validator=gte_zero()) + atol: float | None = field(default=None) + rtol: float | None = field(default=None) + convergence_tolerance: float = field(default=1e-6, validator=gt_zero()) + iprint: int = field(default=2) + solver_option_kwargs: dict = field(default={}) + + solver_map: ClassVar = { + "gauss_seidel": om.NonlinearBlockGS, + "newton": om.NewtonSolver, + "block_jacobi": om.NonlinearBlockJac, + } + + def __attrs_post_init__(self): + if self.atol is None: + self.atol = self.convergence_tolerance + if self.rtol is None: + self.rtol = self.convergence_tolerance + + def get_solver_options(self): + d = self.as_dict() + non_solver_option_attrs = [ + "solver_name", + "solver_map", + "solver_option_kwargs", + "convergence_tolerance", + ] + solver_options = {k: v for k, v in d.items() if k not in non_solver_option_attrs} + solver_options_full = solver_options | self.solver_option_kwargs + return solver_options_full + + def return_nonlinear_solver(self): + return self.solver_map[self.solver_name] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 61afd1f97..ea3f41669 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -1,5 +1,13 @@ import numpy as np import openmdao.api as om +from attrs import field, define + +from h2integrate.core.utilities import BaseConfig + + +@define(kw_only=True) +class SystemLevelControlBaseConfig(BaseConfig): + demand_tech: str | None = field(default=None) class SystemLevelControlBase(om.ExplicitComponent): diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index ffbe72710..e1006f506 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -12,6 +12,7 @@ from h2integrate.core.file_utils import get_path, find_file, load_yaml from h2integrate.finances.finances import AdjustedCapexOpexComp from h2integrate.core.supported_models import ( + strategy_map, no_cost_models, supported_models, no_replacement_schedule_models, @@ -23,18 +24,12 @@ multivariable_streams, is_electricity_producer, ) +from h2integrate.control.control_strategies.system_level.solver_options import ( + SLCSolverOptionsConfig, +) from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import ( PyomoStorageControllerBaseClass, ) -from h2integrate.control.control_strategies.system_level.demand_following_control import ( - DemandFollowingControl, -) -from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( - CostMinimizationControl, -) -from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( - ProfitMaximizationControl, -) try: @@ -544,21 +539,21 @@ def add_system_level_controller(self): slc_config = self.plant_config["system_level_control"] # Map control_strategy config values to controller classes - strategy_map = { - "demand_following": DemandFollowingControl, - "cost_minimization": CostMinimizationControl, - "profit_maximization": ProfitMaximizationControl, - } + # strategy_map = { + # "demand_following": DemandFollowingControl, + # "cost_minimization": CostMinimizationControl, + # "profit_maximization": ProfitMaximizationControl, + # } # Map user-facing solver names to OpenMDAO solver classes - solver_map = { - "gauss_seidel": om.NonlinearBlockGS, - "newton": om.NewtonSolver, - "block_jacobi": om.NonlinearBlockJac, - } + # solver_map = { + # "gauss_seidel": om.NonlinearBlockGS, + # "newton": om.NewtonSolver, + # "block_jacobi": om.NonlinearBlockJac, + # } # 1. Select controller class based on strategy - strategy_name = slc_config.get("control_strategy", "demand_following") + strategy_name = slc_config.get("control_strategy", "DemandFollowingControl") slc_cls = strategy_map.get(strategy_name) if slc_cls is None: raise ValueError( @@ -574,20 +569,27 @@ def add_system_level_controller(self): self.plant.add_subsystem("system_level_controller", slc_comp) # 2. Configure the nonlinear solver - solver_name = slc_config.get("solver_name", "gauss_seidel") - solver_cls = solver_map.get(solver_name) - if solver_cls is None: - raise ValueError( - f"Unknown solver_name '{solver_name}' in system_level_control. " - f"Supported: {list(solver_map.keys())}" - ) + solver_config = SLCSolverOptionsConfig.from_dict(slc_config.get("solver_options", {})) + solver_cls = solver_config.get_solver_options() solver = solver_cls() - solver.options["maxiter"] = slc_config.get("max_iter", 20) - solver.options["atol"] = slc_config.get("convergence_tolerance", 1e-6) - solver.options["rtol"] = slc_config.get("convergence_tolerance", 1e-6) - solver.options["iprint"] = 2 # print convergence at each iteration + solver_options = solver_config.get_solver_options() + for k, v in solver_options.items(): + solver.options[k] = v self.plant.nonlinear_solver = solver self.plant.linear_solver = om.DirectSolver() + # solver_name = slc_config.get("solver_name", "gauss_seidel") + # solver_cls = solver_map.get(solver_name) + + # if solver_cls is None: + # raise ValueError( + # f"Unknown solver_name '{solver_name}' in system_level_control. " + # f"Supported: {list(solver_map.keys())}" + # ) + + # solver.options["maxiter"] = slc_config.get("max_iter", 20) + # solver.options["atol"] = slc_config.get("convergence_tolerance", 1e-6) + # solver.options["rtol"] = slc_config.get("convergence_tolerance", 1e-6) + # solver.options["iprint"] = 2 # print convergence at each iteration # 3. Connect the controller's inputs/outputs to technology models commodity = slc_config["commodity"] diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 98249fb09..072004900 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -174,12 +174,21 @@ from h2integrate.control.control_strategies.storage.simple_openloop_controller import ( SimpleStorageOpenLoopController, ) +from h2integrate.control.control_strategies.system_level.demand_following_control import ( + DemandFollowingControl, +) +from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( + CostMinimizationControl, +) from h2integrate.control.control_strategies.storage.plm_openloop_storage_controller import ( PeakLoadManagementHeuristicOpenLoopStorageController, ) from h2integrate.control.control_rules.storage.pyomo_storage_rule_min_operating_cost import ( PyomoRuleStorageMinOperatingCosts, ) +from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( + ProfitMaximizationControl, +) from h2integrate.control.control_rules.converters.generic_converter_min_operating_cost import ( PyomoDispatchGenericConverterMinOperatingCosts, ) @@ -351,3 +360,10 @@ no_replacement_schedule_models = { "IronTransportPerformanceComponent", } + +# System-level controllers +strategy_map = { + "DemandFollowingControl": DemandFollowingControl, + "CostMinimizationControl": CostMinimizationControl, + "ProfitMaximizationControl": ProfitMaximizationControl, +} From 553ed206b2be09971ae71e97967fc1403eaf1ab9 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Fri, 1 May 2026 15:42:53 -0600 Subject: [PATCH 032/132] minor fixes --- .../control_strategies/system_level/solver_options.py | 11 +++++++---- h2integrate/core/h2integrate_model.py | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/solver_options.py b/h2integrate/control/control_strategies/system_level/solver_options.py index ae1d928e5..58817b36b 100644 --- a/h2integrate/control/control_strategies/system_level/solver_options.py +++ b/h2integrate/control/control_strategies/system_level/solver_options.py @@ -10,12 +10,12 @@ @define(kw_only=True) class SLCSolverOptionsConfig(BaseConfig): solver_name: str = field( - default="gauss_seidel", validator=contains["gauss_seidel", "newton", "block_jacobi"] + default="gauss_seidel", validator=contains(["gauss_seidel", "newton", "block_jacobi"]) ) - maxiter: int = field(default=20, converter=int, validator=gte_zero()) + max_iter: int = field(default=20, converter=int, validator=gte_zero) atol: float | None = field(default=None) rtol: float | None = field(default=None) - convergence_tolerance: float = field(default=1e-6, validator=gt_zero()) + convergence_tolerance: float = field(default=1e-6, validator=gt_zero) iprint: int = field(default=2) solver_option_kwargs: dict = field(default={}) @@ -38,9 +38,12 @@ def get_solver_options(self): "solver_map", "solver_option_kwargs", "convergence_tolerance", + "max_iter", ] solver_options = {k: v for k, v in d.items() if k not in non_solver_option_attrs} - solver_options_full = solver_options | self.solver_option_kwargs + solver_options_full = ( + solver_options | self.solver_option_kwargs | {"maxiter": self.max_iter} + ) return solver_options_full def return_nonlinear_solver(self): diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index e1006f506..464ae372f 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -570,7 +570,7 @@ def add_system_level_controller(self): # 2. Configure the nonlinear solver solver_config = SLCSolverOptionsConfig.from_dict(slc_config.get("solver_options", {})) - solver_cls = solver_config.get_solver_options() + solver_cls = solver_config.return_nonlinear_solver() solver = solver_cls() solver_options = solver_config.get_solver_options() for k, v in solver_options.items(): From 2a741ba9d725665d4386ddd85e34c1c87ca638bc Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 4 May 2026 16:47:04 -0600 Subject: [PATCH 033/132] Multi-commodity systems for SLC (#717) * minor notes added to h2i model * added test for profit maximization example * updated slc base and h2i to handle multiple commodity streams * added test for multiple commodity streams * added test for multicommodity example, unsure if works * fixed example and updated non-demand commodity units handling in slc baseclass * some fixes in baseclass and tried to add logic for controlling multi-commodities * tried to update control logic to handle multiple commods * working on debugging whatever issue I caused * minor fixes for debugging * fixed bug fully * made electrolyzer capacity smaller * updated electrolyzer to not outputs nans * commented out finances for example 35 with hydrogen * aded output check for nans or infs * cleanups to slc baseclass * added docstrings and inline comments * added tiny comment * minor update to use self.technology_graph attribute * added use of _get_commodity_for_tech * Minor changes for clarity * Combining the three setup methods in SLC base * removed old keys in slc_config --------- Co-authored-by: John Jasa --- .../yes_hydrogen/driver_config.yaml | 4 + .../yes_hydrogen/plant_config.yaml | 96 +++++ .../yes_hydrogen/run_multi_commodity.py | 19 + .../yes_hydrogen/tech_config.yaml | 156 +++++++++ .../yes_hydrogen/wind_ng_demand.yaml | 4 + .../system_level/demand_following_control.py | 26 +- .../system_level/system_level_control_base.py | 331 ++++++++++++++---- .../system_level/test/test_slc_examples.py | 62 ++++ .../converters/hydrogen/pem_electrolyzer.py | 10 +- h2integrate/core/h2integrate_model.py | 114 +++--- 10 files changed, 707 insertions(+), 115 deletions(-) create mode 100644 examples/35_system_level_control/yes_hydrogen/driver_config.yaml create mode 100644 examples/35_system_level_control/yes_hydrogen/plant_config.yaml create mode 100644 examples/35_system_level_control/yes_hydrogen/run_multi_commodity.py create mode 100644 examples/35_system_level_control/yes_hydrogen/tech_config.yaml create mode 100644 examples/35_system_level_control/yes_hydrogen/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/yes_hydrogen/driver_config.yaml b/examples/35_system_level_control/yes_hydrogen/driver_config.yaml new file mode 100644 index 000000000..5b6b7e05a --- /dev/null +++ b/examples/35_system_level_control/yes_hydrogen/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: This analysis runs a natural gas power plant +general: + folder_output: outputs diff --git a/examples/35_system_level_control/yes_hydrogen/plant_config.yaml b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml new file mode 100644 index 000000000..14e1878ec --- /dev/null +++ b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml @@ -0,0 +1,96 @@ +name: plant_config +description: This plant is located in Texas, USA. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 +# array of arrays containing left-to-right technology +# interconnections; can support bidirectional connections +# with the reverse definition. +# this will naturally grow as we mature the interconnected tech +technology_interconnections: + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + # connect NG feedstock to NG plant + - [wind, battery, electricity, cable] + # wind output available for battery charging (electricity_in) + - [wind, elec_combiner, electricity, cable] + # wind to combined output + - [battery, elec_combiner, electricity, cable] + # battery net output to combined output + - [natural_gas_plant, elec_combiner, electricity, cable] + # electricity to electrolyzer + - [elec_combiner, electrolyzer, electricity, cable] + # electrolyzer to storage + - [electrolyzer, h2_storage, hydrogen, pipe] + # combine hydrogen streams + - [electrolyzer, h2_combiner, hydrogen, pipe] + - [h2_storage, h2_combiner, hydrogen, pipe] + # send hydrogen to load + - [h2_combiner, h2_load_demand, hydrogen, pipe] + # combined supply to demand +resource_to_tech_connections: + # connect the wind resource to the wind technology + - [site.wind_resource, wind, wind_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +system_level_control: + control_strategy: DemandFollowingControl + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 +# finance_parameters: +# finance_groups: +# profast_lco: +# 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.] +# finance_subgroups: +# # renewables: +# # commodity: electricity +# # commodity_stream: wind +# # finance_groups: [profast_lco] +# # technologies: [wind] +# # natural_gas: +# # commodity: electricity +# # commodity_stream: natural_gas_plant +# # finance_groups: [profast_lco] +# # technologies: [natural_gas_plant, ng_feedstock] +# electricity: +# commodity: electricity +# commodity_stream: elec_combiner +# finance_groups: [profast_lco] +# technologies: [wind, battery, natural_gas_plant, ng_feedstock] +# # hydrogen: +# # commodity: hydrogen +# # commodity_stream: h2_combiner +# # finance_groups: [profast_lco] +# # technologies: [wind, battery, natural_gas_plant, ng_feedstock, electrolyzer, h2_storage] +# cost_adjustment_parameters: +# cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year +# target_dollar_year: 2022 diff --git a/examples/35_system_level_control/yes_hydrogen/run_multi_commodity.py b/examples/35_system_level_control/yes_hydrogen/run_multi_commodity.py new file mode 100644 index 000000000..d6662e37c --- /dev/null +++ b/examples/35_system_level_control/yes_hydrogen/run_multi_commodity.py @@ -0,0 +1,19 @@ +import os + +from h2integrate import EXAMPLE_DIR +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +os.chdir(EXAMPLE_DIR / "35_system_level_control" / "yes_hydrogen") + +################################## +# Create an H2I model with a fixed electricity load demand +h2i = H2IntegrateModel("wind_ng_demand.yaml") + +h2i.setup() + +# Run the model +h2i.run() + +# Post-process the results +h2i.post_process() diff --git a/examples/35_system_level_control/yes_hydrogen/tech_config.yaml b/examples/35_system_level_control/yes_hydrogen/tech_config.yaml new file mode 100644 index 000000000..739b34083 --- /dev/null +++ b/examples/35_system_level_control/yes_hydrogen/tech_config.yaml @@ -0,0 +1,156 @@ +name: technology_config +description: This plant produces electricity with wind, solar, and a natural gas power plant to meet a fixed electrical load + demand. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. # MMBtu + cost_parameters: + cost_year: 2023 + price: 4.2 # USD/MMBtu + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 # MMBtu/MWh - typical for NGCC + system_capacity_mw: 100. # MW + cost_parameters: + capex_per_kw: 1000 # $/kW - typical for NGCC + fixed_opex_per_kw_per_year: 10.0 # $/kW/year + variable_opex_per_mwh: 0.0 # $/MWh + cost_year: 2023 + battery: + performance_model: + model: StoragePerformanceModel + cost_model: + model: GenericStorageCostModel + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 20000 # kW (20 MW) + max_capacity: 80000 # kWh (80 MWh, 4-hour duration) + init_soc_fraction: 0.5 + max_soc_fraction: 1.0 + min_soc_fraction: 0.1 + performance_parameters: + round_trip_efficiency: 0.90 + demand_profile: 20000 # kW, required by storage base config + cost_parameters: + cost_year: 2022 + capacity_capex: 310 # $/kWh + charge_capex: 311 # $/kW + opex_fraction: 0.025 + elec_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 3 + electrolyzer: + performance_model: + model: ECOElectrolyzerPerformanceModel + cost_model: + model: SingliticoCostModel + model_inputs: + shared_parameters: + location: onshore + electrolyzer_capex: 1295 # $/kW overnight installed capital costs for a 1 MW system in 2022 USD/kW (DOE hydrogen program record 24005 Clean Hydrogen Production Cost Scenarios with PEM Electrolyzer Technology 05/20/24) (https://www.hydrogen.energy.gov/docs/hydrogenprogramlibraries/pdfs/24005-clean-hydrogen-production-cost-pem-electrolyzer.pdf?sfvrsn=8cb10889_1) + performance_parameters: + size_mode: normal + n_clusters: 10 + cluster_rating_MW: 3 + eol_eff_percent_loss: 10 # eol defined as x% change in efficiency from bol + uptime_hours_until_eol: 80000. # number of 'on' hours until electrolyzer reaches eol + include_degradation_penalty: true # include degradation + turndown_ratio: 0.1 # turndown_ratio = minimum_cluster_power/cluster_rating_MW + financial_parameters: + capital_items: + depr_period: 7 # based on PEM Electrolysis H2A Production Case Study Documentation estimate of 7 years. also see https://www.irs.gov/publications/p946#en_US_2020_publink1000107507 + replacement_cost_percent: 0.15 # percent of capex - H2A default case + h2_storage: + performance_model: + model: StoragePerformanceModel + cost_model: + model: GenericStorageCostModel + # control_strategy: + # model: DemandOpenLoopStorageController + model_inputs: + shared_parameters: + commodity: hydrogen + commodity_rate_units: kg/h + max_charge_rate: 100.0 # kg/time step + max_capacity: 300.0 # kg + performance_parameters: + max_soc_fraction: 1.0 # fraction (0-1) + min_soc_fraction: 0.1 # fraction (0-1) + init_soc_fraction: 0.1 # fraction (0-1) + max_discharge_rate: 100.0 # kg/time step + charge_efficiency: 1.0 # fraction (0-1) + discharge_efficiency: 1.0 # fraction (0-1) + demand_profile: 500.0 # constant demand of 5000 kg per hour (see commodity_rate_units) + cost_parameters: + cost_year: 2022 + capacity_capex: 100 # $/kg + charge_capex: 100 # $/kg/h + opex_fraction: 0.025 + h2_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: hydrogen + commodity_rate_units: kg/h + h2_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: hydrogen + commodity_rate_units: kg/h + demand_profile: 500.0 diff --git a/examples/35_system_level_control/yes_hydrogen/wind_ng_demand.yaml b/examples/35_system_level_control/yes_hydrogen/wind_ng_demand.yaml new file mode 100644 index 000000000..e09f3dcda --- /dev/null +++ b/examples/35_system_level_control/yes_hydrogen/wind_ng_demand.yaml @@ -0,0 +1,4 @@ +name: H2Integrate_config +driver_config: driver_config.yaml +plant_config: plant_config.yaml +technology_config: tech_config.yaml diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 0864d879a..209a05312 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -28,8 +28,28 @@ def compute(self, inputs, outputs): # 3. Dispatchable techs: equal share of remaining demand remaining = np.maximum(demand, 0.0) - n_dispatchable = len(self.dispatchable_set_point_names) + n_dispatchable = len( + [ + s + for s in self.dispatchable_techs + if self.commodity in self._get_commodity_for_tech(s) + ] + ) + + # calculate the number of dispatchable technologies that + # produce the demanded commodity if n_dispatchable > 0: share = remaining / n_dispatchable - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = share + for set_point_name, commodity in zip( + self.dispatchable_set_point_names, self.dispatchable_commodity_names + ): + if commodity == self.commodity: + outputs[set_point_name] = share + + # Check for nans or inf + if not all(np.isfinite(c).all() for k, c in outputs.items()): + bad_outputs = [k for k, c in outputs.items() if not np.isfinite(c).all()] + raise ValueError(f"These outputs contain non-finite values: {bad_outputs}") + if not all(np.isfinite(c).all() for k, c in inputs.items()): + bad_inputs = [k for k, c in inputs.items() if not np.isfinite(c).all()] + raise ValueError(f"These inputs contain non-finite values: {bad_inputs}") diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index dffab3dfd..99bba05e9 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -34,8 +34,8 @@ def setup(self): self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] # Read pre-computed classification from plant_config - self.commodity = slc_config["commodity"] - self.commodity_units = slc_config.get("commodity_units", None) + self.commodity = slc_config["demand_commodity"] + self.commodity_units = slc_config.get("demand_commodity_rate_units", None) self.demand_tech = slc_config["demand_tech"] self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) @@ -52,99 +52,274 @@ def setup(self): desc=f"Demand profile of {self.commodity}", ) - self._setup_tech_category("curtailable", self.curtailable_techs) - self._setup_tech_category("dispatchable", self.dispatchable_techs, demand_profile) - self._setup_tech_category("storage", self.storage_techs) + self.techs_to_commodities = slc_config["tech_to_commodity"] - def _setup_tech_category(self, category, tech_names, demand_profile=None): - """Create OpenMDAO I/O variables for a category of technologies. + # There are multiple commodities being produced by technologies in the system + self.multi_commodity_system = ( + True if len({e[-1] for e in self.techs_to_commodities}) > 1 else False + ) - For each technology in the category, this method creates three variables: + self.commodities_to_units = {self.commodity: self.commodity_units} + self.commodities_to_ref_var = {} + self._setup_tech_category("curtailable", self.curtailable_techs) + self._setup_tech_category( + "dispatchable", self.dispatchable_techs, demand_profile=demand_profile + ) + self._setup_tech_category("storage", self.storage_techs) - - ``{tech}_{commodity}_out``: an input for the technology's actual commodity - output at each timestep (shape ``n_timesteps``). - - ``{tech}_rated_{commodity}_production``: an input for the technology's - rated (maximum) production capacity (scalar). - - ``{tech}_{commodity}_set_point``: an output for the dispatch set-point - sent back to the technology at each timestep (shape ``n_timesteps``). + def _setup_commodity_for_given_units( + self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=0.0 + ): + """Adds inputs and outputs for a commodity when the units are known. + The inputs and outputs that are added have the below naming convention: - The variable names are collected into three lists stored as instance - attributes named ``{category}_input_names``, - ``{category}_set_point_names``, and ``{category}_rated_names``. + - ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name + - ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production + capacity of tech_name + - ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name Args: - category: Technology classification label (e.g. ``"curtailable"``, - ``"dispatchable"``, ``"storage"``). Used to name the instance - attribute lists and the set-point description. - tech_names: Iterable of technology name strings belonging to this - category. - demand_profile: Optional demand profile used to initialize the - set-point output for dispatchable technologies. When provided, - the initial set-point is ``demand_profile / n_techs`` so that - the solver starts from a reasonable guess. Ignored (or - ``None``) for curtailable and storage categories, whose - set-points default to zero. + tech_name (str): name of technology + commodity (str): commodity of the technology described by `tech_name` + commodity_units (str): units of commodity + add_in_name (bool, optional): If True, add the input for the in_name variable. + Defaults to True. + initial_set_point (float, optional): Add as the initial value for the + set_point variable. Defaults to 0.0. + Returns: + tuple(str, str, str): tuple of in_name, set_point_name, and rated_name """ - # Compute initial set-point value - n_techs = len(tech_names) - if demand_profile is not None and n_techs > 0: - if np.isscalar(demand_profile): - initial_set_point = demand_profile / n_techs - else: - initial_set_point = np.array(demand_profile) / n_techs - else: - initial_set_point = 0.0 - - input_names = [] - set_point_names = [] - rated_names = [] - - for tech_name in tech_names: - in_name = f"{tech_name}_{self.commodity}_out" - set_point_name = f"{tech_name}_{self.commodity}_set_point" - rated_name = f"{tech_name}_rated_{self.commodity}_production" + in_name = f"{tech_name}_{commodity}_out" + set_point_name = f"{tech_name}_{commodity}_set_point" + rated_name = f"{tech_name}_rated_{commodity}_production" + if add_in_name: self.add_input( in_name, val=0.0, shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{self.commodity} output from {tech_name}", + units=commodity_units, + desc=f"{commodity} output from {tech_name}", ) + self.add_input( + rated_name, + val=0.0, + units=commodity_units, + desc=f"Rated {commodity} production for {tech_name}", + ) + self.add_output( + set_point_name, + val=initial_set_point, + shape=self.n_timesteps, + units=commodity_units, + desc=f"Set point for {tech_name} {commodity} curtailment", + ) + + return in_name, set_point_name, rated_name + + def _setup_commodity_for_copy_units( + self, tech_name, commodity, commodity_reference_var, add_in_name=True, initial_set_point=0.0 + ): + """Adds inputs and outputs for a commodity where the units are based on a reference + input variable. The inputs and outputs that are added have the below + naming convention: + + - ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name + - ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production + capacity of tech_name + - ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name + + Args: + tech_name (str): name of technology + commodity (str): commodity of the technology described by `tech_name` + commodity_reference_var (str): name of input to copy units from + add_in_name (bool, optional): If True, add the input for the in_name variable. + Defaults to True. + initial_set_point (float, optional): Add as the initial value for the + set_point variable. Defaults to 0.0. + + Returns: + tuple(str, str, str): tuple of in_name, set_point_name, and rated_name + """ + in_name = f"{tech_name}_{commodity}_out" + set_point_name = f"{tech_name}_{commodity}_set_point" + rated_name = f"{tech_name}_rated_{commodity}_production" + + if add_in_name: self.add_input( - rated_name, + in_name, val=0.0, - units=self.commodity_units, - desc=f"Rated {self.commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=initial_set_point, shape=self.n_timesteps, - units=self.commodity_units, - desc=f"{category} set point for {tech_name} {self.commodity}", + units=None, + copy_units=commodity_reference_var, + desc=f"{commodity} output from {tech_name}", ) + self.add_input( + rated_name, + val=0.0, + units=None, + copy_units=commodity_reference_var, + desc=f"Rated {commodity} production for {tech_name}", + ) + self.add_output( + set_point_name, + val=initial_set_point, + shape=self.n_timesteps, + units=None, + copy_units=commodity_reference_var, + desc=f"Set point for {tech_name} {commodity} curtailment", + ) + + return in_name, set_point_name, rated_name + + def _setup_tech_category(self, category, tech_list, demand_profile=None): + """Create OpenMDAO I/O variables for all technologies in a given category. + + This single method handles curtailable, dispatchable, and storage + technologies. The logic is identical for all three categories — + iterate over each technology's commodities and register the + appropriate inputs (production output, rated capacity) and output + (control set-point) — with one difference: + + * **Curtailable / Storage** (``demand_profile is None``): + ``initial_set_point`` is ``0.0``. Curtailable techs are later + assigned set-points equal to their rated production; storage techs + get set-points computed at run-time in ``_dispatch_storage``. + + * **Dispatchable** (``demand_profile`` is provided): + ``initial_set_point`` is the demand evenly divided among the + dispatchable techs that produce the demanded commodity, giving + the solver a reasonable starting guess. + + After this method returns, four lists are stored on ``self`` under + names produced by the *category* prefix: + + ``self.{category}_input_names`` + ``self.{category}_set_point_names`` + ``self.{category}_rated_names`` + ``self.{category}_commodity_names`` + + These lists are consumed by ``compute()`` and the helper methods + ``_subtract_curtailable`` and ``_dispatch_storage``. + + Args: + category (str): One of ``"curtailable"``, ``"dispatchable"``, + or ``"storage"``. Used to name the attribute lists. + tech_list (list[str]): Technology names belonging to this category + (e.g. ``self.curtailable_techs``). + demand_profile (float | np.ndarray | None, optional): + Only relevant for **dispatchable** techs. When provided, the + demand is split equally among dispatchable techs that produce + the demanded commodity to set a non-zero ``initial_set_point``. + For curtailable and storage techs, leave as ``None`` (default). + """ + # --- Compute initial_set_point -------------------------------- + # Dispatchable techs: split demand equally among those that produce + # the demanded commodity so the solver starts from a feasible guess. + # Curtailable and storage techs always start at 0. + if demand_profile is not None: + n_producing = len( + [t for t in tech_list if self.commodity in self._get_commodity_for_tech(t)] + ) + if n_producing > 0: + if np.isscalar(demand_profile): + initial_set_point = demand_profile / n_producing + else: + initial_set_point = np.array(demand_profile) / n_producing + else: + initial_set_point = 0.0 + else: + initial_set_point = 0.0 + + # --- Initialize the four per-category bookkeeping lists ------- + input_names = [] + set_point_names = [] + rated_names = [] + commodity_names = [] + + # --- Register I/O for every (tech, commodity) pair ------------ + for tech_name in tech_list: + tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] + for commodity in tech_commodities: + if commodity in self.commodities_to_units: + # Units are already known explicitly + in_name, set_point_name, rated_name = self._setup_commodity_for_given_units( + tech_name, + commodity, + self.commodities_to_units[commodity], + add_in_name=True, + initial_set_point=initial_set_point, + ) + elif commodity in self.commodities_to_ref_var: + # Units are inferred from a previously-registered reference variable + in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units( + tech_name, + commodity, + self.commodities_to_ref_var[commodity], + add_in_name=True, + initial_set_point=initial_set_point, + ) + else: + # Units are unknown; try to discover them from the connection + in_name = f"{tech_name}_{commodity}_out" + meta_data = self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=None, + units_by_conn=True, + desc=f"{commodity} output from {tech_name}", + ) + if meta_data["units"] is None: + # Still unknown: register in_name as the reference + # variable so later techs with this commodity can + # copy its units. + self.commodities_to_ref_var[commodity] = in_name + in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units( + tech_name, + commodity, + self.commodities_to_ref_var[commodity], + add_in_name=False, + initial_set_point=initial_set_point, + ) + else: + # Connection provided units — record them for future use + self.commodities_to_units[commodity] = meta_data["units"] + in_name, set_point_name, rated_name = self._setup_commodity_for_given_units( + tech_name, + commodity, + self.commodities_to_units[commodity], + add_in_name=False, + initial_set_point=initial_set_point, + ) - input_names.append(in_name) - set_point_names.append(set_point_name) - rated_names.append(rated_name) + commodity_names.append(commodity) + input_names.append(in_name) + set_point_names.append(set_point_name) + rated_names.append(rated_name) + # --- Store lists as self._ attributes ------- setattr(self, f"{category}_input_names", input_names) setattr(self, f"{category}_set_point_names", set_point_names) setattr(self, f"{category}_rated_names", rated_names) + setattr(self, f"{category}_commodity_names", commodity_names) def _subtract_curtailable(self, inputs, outputs, demand): """Apply curtailable techs: set_point = rated, subtract output from demand. Returns the updated demand array. """ - for in_name, set_point_name, rated_name in zip( + for in_name, set_point_name, rated_name, commodity in zip( self.curtailable_input_names, self.curtailable_set_point_names, self.curtailable_rated_names, + self.curtailable_commodity_names, ): + # Output the set-point as the rated production of that technology outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) - demand -= inputs[in_name] + if commodity == self.commodity: + demand -= inputs[in_name] + return demand def _dispatch_storage(self, inputs, outputs, demand): @@ -153,12 +328,34 @@ def _dispatch_storage(self, inputs, outputs, demand): Positive set_point = discharge, negative = charge. Returns the updated demand array. """ - n_storage = len(self.storage_set_point_names) + # calculate the number of storage technologies that + # produce the demanded commodity + n_storage = len( + [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + ) if n_storage > 0: storage_share = demand / n_storage - for set_point_name in self.storage_set_point_names: - outputs[set_point_name] = storage_share + for set_point_name, commodity in zip( + self.storage_set_point_names, self.storage_commodity_names + ): + if commodity == self.commodity: + outputs[set_point_name] = storage_share + + for tech_name, in_name in zip(self.storage_techs, self.storage_input_names): + if self.commodity in self._get_commodity_for_tech(tech_name): + demand -= inputs[in_name] - for in_name in self.storage_input_names: - demand -= inputs[in_name] return demand + + def _get_commodity_for_tech(self, tech_name): + """Get a list of the commodities produced for a technology. + + Args: + tech_name (str): name of technology + + Returns: + list[str]: list of commodities produced by the tech_name + """ + tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] + + return tech_commodities diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 502be050b..22e2340b3 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -1,3 +1,4 @@ +import numpy as np import pytest from h2integrate.core.h2integrate_model import H2IntegrateModel @@ -35,3 +36,64 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 + + with subtests.test("lcoe"): + assert ( + pytest.approx( + model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), + rel=1e-6, + ) + == 0.10902004 + ) + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", + [("35_system_level_control/profit_maximization", None)], +) +def test_slc_profit_max(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") + + n_timesteps = 8760 + sell_price = np.zeros(n_timesteps) + for h in range(n_timesteps): + hour_of_day = h % 24 + if 16 <= hour_of_day < 22: + sell_price[h] = 0.08 # peak + else: + sell_price[h] = 0.03 # night (cheap) + + model.setup() + + model.prob.set_val( + "plant.system_level_controller.commodity_sell_price", + sell_price, + units="USD/(kW*h)", + ) + + model.run() + + wind_out = model.prob.get_val("wind.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("35_system_level_control/yes_hydrogen", None)] +) +def test_slc_yes_hydrogen(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") + + model.run() + + wind_out = model.prob.get_val("wind.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index d09d6d65c..8621613be 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -176,12 +176,17 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): # 1 gal H2O = 3.79 kg H2O outputs["water_consumed"] = 3.79 * H2_Results["Water Hourly Consumption [kg/hr]"] outputs["total_hydrogen_produced"] = outputs["hydrogen_out"].sum() - outputs["efficiency"] = H2_Results["Sim: Average Efficiency [%-HHV]"] + if not np.isfinite(H2_Results["Sim: Average Efficiency [%-HHV]"]).all(): + outputs["efficiency"] = 0.0 + else: + outputs["efficiency"] = H2_Results["Sim: Average Efficiency [%-HHV]"] refurb_schedule = np.zeros(self.plant_life) if np.isnan(H2_Results["Time Until Replacement [hrs]"]): - refurb_period = round(80000 / (24 * 365)) + refurb_period = round(self.config.uptime_hours_until_eol / (24 * 365)) + outputs["time_until_replacement"] = self.config.uptime_hours_until_eol else: refurb_period = round(float(H2_Results["Time Until Replacement [hrs]"]) / (24 * 365)) + outputs["time_until_replacement"] = H2_Results["Time Until Replacement [hrs]"] refurb_schedule[refurb_period : self.plant_life : refurb_period] = 1 @@ -197,7 +202,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): # ) # TODO: remove time_until_replacement as output after finance model(s) have been updated to not use it - outputs["time_until_replacement"] = H2_Results["Time Until Replacement [hrs]"] outputs["rated_hydrogen_production"] = H2_Results["Rated BOL: H2 Production [kg/hr]"] outputs["electrolyzer_size_mw"] = electrolyzer_actual_capacity_MW diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index b11c4455a..4327bcb47 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -482,9 +482,9 @@ def _classify_slc_technologies(self): technologies = self.technology_config.get("technologies", {}) # Identify the (single) demand technology - commodity = None demand_tech = None - commodity_units = None + demand_commodity = None + demand_commodity_rate_units = None for tech_name, tech_def in technologies.items(): model_name = tech_def.get("performance_model", {}).get("model", "") if "DemandComponent" not in model_name: @@ -495,16 +495,45 @@ def _classify_slc_technologies(self): shared_params = model_inputs.get("shared_parameters", {}) all_params = {**shared_params, **perf_params} - if commodity is not None: + if demand_commodity is not None: + # NOTE: this error should only be raised if two demand components + # are in the tech connections raise ValueError( "DemandFollowingControl currently supports only one demand " - f"stream, but found demands for both '{commodity}' " + f"stream, but found demands for both '{demand_commodity}' " f"and '{all_params.get('commodity', tech_name)}'." ) - commodity = all_params["commodity"] - commodity_units = all_params.get("commodity_rate_units", None) + + demand_commodity = all_params["commodity"] + demand_commodity_rate_units = all_params.get("commodity_rate_units", None) demand_profile = all_params.get("demand_profile", 0.0) demand_tech = tech_name + # Check that the demand tech is in the technology_interconnections + tech_interconnections = self.plant_config["technology_interconnections"] + demand_is_source_connection = [ + tech_connection + for tech_connection in tech_interconnections + if tech_connection[0] == demand_tech + ] + demand_is_destination_connection = [ + tech_connection + for tech_connection in tech_interconnections + if tech_connection[1] == demand_tech + ] + if len(demand_is_source_connection) == 0 and len(demand_is_destination_connection) == 0: + # demand is not in tech interconnections + demand_tech = None + demand_commodity = None + + demand_commodity_rate_units = None + + # Raise error if no demand commodity was defined + if demand_tech is None: + msg = ( + "No demand commodity was found in the technology interconnections. " + "Please define a demand component." + ) + raise ValueError(msg) # Classify technologies using pre-computed classifiers curtailable_techs = [] @@ -518,14 +547,29 @@ def _classify_slc_technologies(self): elif classifier == "storage": storage_techs.append(tech_name) + # Classify technologies based on their output commodity (or commodities) + # Use a set to remove duplicates (in case one tech produces multiple commodities) + sources_to_commodities = { + (e[0], e[-1]) + for e in self.technology_graph.edges(data="commodity") + if e[-1] is not None + } + + # Remove feedstocks and connectors + techs_to_connect = set(curtailable_techs + dispatchable_techs + storage_techs) + tech_to_commodities = { + (e[0], e[-1]) for e in sources_to_commodities if e[0] in techs_to_connect + } + # Store classification results in plant_config for SLC component - slc_config["commodity"] = commodity - slc_config["commodity_units"] = commodity_units slc_config["demand_tech"] = demand_tech slc_config["demand_profile"] = demand_profile + slc_config["demand_commodity"] = demand_commodity + slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units slc_config["curtailable_techs"] = curtailable_techs slc_config["dispatchable_techs"] = dispatchable_techs slc_config["storage_techs"] = storage_techs + slc_config["tech_to_commodity"] = tech_to_commodities def add_system_level_controller(self): """Add the DemandFollowingControl component and configure the plant solver. @@ -571,6 +615,7 @@ def add_system_level_controller(self): f"Supported: {list(solver_map.keys())}" ) solver = solver_cls() + # TODO: make a config for the below defaults solver.options["maxiter"] = slc_config.get("max_iter", 20) solver.options["atol"] = slc_config.get("convergence_tolerance", 1e-6) solver.options["rtol"] = slc_config.get("convergence_tolerance", 1e-6) @@ -579,42 +624,26 @@ def add_system_level_controller(self): self.plant.linear_solver = om.DirectSolver() # 3. Connect the controller's inputs/outputs to technology models - commodity = slc_config["commodity"] - - # Curtailable techs: read their output and write set_point - for tech_name in slc_config["curtailable_techs"]: - self.plant.connect( - f"{tech_name}.{commodity}_out", - f"system_level_controller.{tech_name}_{commodity}_out", - ) - self.plant.connect( - f"{tech_name}.rated_{commodity}_production", - f"system_level_controller.{tech_name}_rated_{commodity}_production", - ) - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_set_point", - ) - # Dispatchable and storage techs: read output and write set_point - for tech_list in ["dispatchable_techs", "storage_techs"]: + # Curtailable, dispatchable, and storage techs: read output and write set_point + for tech_list in ["curtailable_techs", "dispatchable_techs", "storage_techs"]: for tech_name in slc_config[tech_list]: - self.plant.connect( - f"{tech_name}.{commodity}_out", - f"system_level_controller.{tech_name}_{commodity}_out", - ) - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_set_point", - ) + tech_commodities = self._get_commodity_for_tech(tech_name) + for commodity in tech_commodities: + self.plant.connect( + f"{tech_name}.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) - # Dispatchable and storage techs: also connect rated production - for tech_list in ["dispatchable_techs", "storage_techs"]: - for tech_name in slc_config[tech_list]: - self.plant.connect( - f"{tech_name}.rated_{commodity}_production", - f"system_level_controller.{tech_name}_rated_{commodity}_production", - ) + self.plant.connect( + f"{tech_name}.rated_{commodity}_production", + f"system_level_controller.{tech_name}_rated_{commodity}_production", + ) + + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) # 4. For cost-aware strategies, connect marginal costs from cost models if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): @@ -628,6 +657,7 @@ def add_system_level_controller(self): ### components in the new SLC paradigm. # # Connect demand profile to the controller # demand_tech = slc_config["demand_tech"] + # demand_commodity = slc_config["demand_commodity"] # self.plant.connect( # f"{demand_tech}.{commodity}_demand", # f"system_level_controller.{commodity}_demand", @@ -701,7 +731,7 @@ def create_technology_models(self): tech_config=individual_tech_config, ) self._check_time_step(perf_model, comp) - self.tech_control_classifiers.update({tech_name: "feedback"}) + self.tech_control_classifiers.update({tech_name: "feedstock"}) self.plant.add_subsystem(f"{tech_name}_source", comp) else: tech_group = self.plant.add_subsystem(tech_name, om.Group()) From 8b6f2c103775d3fc143a0494b604dc1b9ecc7e42 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 14:45:11 -0600 Subject: [PATCH 034/132] added framework to interface with storage controllers and example --- .../driver_config.yaml | 4 + .../battery_with_controller/plant_config.yaml | 107 ++++++++++++++++++ .../run_wind_ng_demand.py | 65 +++++++++++ .../battery_with_controller/tech_config.yaml | 104 +++++++++++++++++ .../wind_ng_demand.yaml | 5 + .../system_level/system_level_control_base.py | 35 +++++- .../system_level/test/test_slc_examples.py | 19 ++++ h2integrate/core/h2integrate_model.py | 41 ++++++- 8 files changed, 373 insertions(+), 7 deletions(-) create mode 100644 examples/35_system_level_control/battery_with_controller/driver_config.yaml create mode 100644 examples/35_system_level_control/battery_with_controller/plant_config.yaml create mode 100644 examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py create mode 100644 examples/35_system_level_control/battery_with_controller/tech_config.yaml create mode 100644 examples/35_system_level_control/battery_with_controller/wind_ng_demand.yaml diff --git a/examples/35_system_level_control/battery_with_controller/driver_config.yaml b/examples/35_system_level_control/battery_with_controller/driver_config.yaml new file mode 100644 index 000000000..5b6b7e05a --- /dev/null +++ b/examples/35_system_level_control/battery_with_controller/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: This analysis runs a natural gas power plant +general: + folder_output: outputs diff --git a/examples/35_system_level_control/battery_with_controller/plant_config.yaml b/examples/35_system_level_control/battery_with_controller/plant_config.yaml new file mode 100644 index 000000000..d3c242b7b --- /dev/null +++ b/examples/35_system_level_control/battery_with_controller/plant_config.yaml @@ -0,0 +1,107 @@ +name: plant_config +description: This plant is located in Texas, USA. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 +# array of arrays containing left-to-right technology +# interconnections; can support bidirectional connections +# with the reverse definition. +# this will naturally grow as we mature the interconnected tech +technology_interconnections: + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + # connect NG feedstock to NG plant + - [wind, battery, electricity, cable] + # wind output available for battery charging (electricity_in) + - [wind, fin_combiner, electricity, cable] + # wind to combined output + - [battery, fin_combiner, electricity, cable] + # battery net output to combined output + - [natural_gas_plant, fin_combiner, electricity, cable] + # NG to combined output + - [fin_combiner, electrical_load_demand, electricity, cable] + # combined supply to demand +resource_to_tech_connections: + # connect the wind resource to the wind technology + - [site.wind_resource, wind, wind_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +system_level_control: + control_strategy: DemandFollowingControl + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 +finance_parameters: + finance_groups: + profast_lco: + 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.] + profast_npv: + finance_model: ProFastNPV + model_inputs: + commodity_sell_price: 0.05167052 + 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.] + finance_subgroups: + renewables: + commodity: electricity + commodity_stream: wind + finance_groups: [profast_lco, profast_npv] + technologies: [wind] + natural_gas: + commodity: electricity + commodity_stream: natural_gas_plant + finance_groups: [profast_lco] + technologies: [natural_gas_plant, ng_feedstock] + electricity: + commodity: electricity + commodity_stream: fin_combiner + finance_groups: [profast_lco] + technologies: [wind, battery, natural_gas_plant, ng_feedstock] + cost_adjustment_parameters: + cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year + target_dollar_year: 2022 diff --git a/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py b/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py new file mode 100644 index 000000000..b536e660b --- /dev/null +++ b/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py @@ -0,0 +1,65 @@ +import numpy as np +import matplotlib.pyplot as plt + +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +################################## +# Create an H2I model with a fixed electricity load demand +h2i = H2IntegrateModel("wind_ng_demand.yaml") + +# Run the model +h2i.run() + +# Post-process the results +h2i.post_process() + +# Plot the first 168 hours (1 week) +n_hours = 168 +hours = np.arange(n_hours) + +wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] +ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] +batt_discharge = h2i.prob.get_val("plant.battery.storage_electricity_discharge")[:n_hours] +batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] +demand = h2i.prob.get_val("plant.electrical_load_demand.electricity_demand")[:n_hours] +curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] + +fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True) + +# Stacked area: wind + battery discharge + NG = total supply +axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") +axes[0].fill_between( + hours, + wind_out, + wind_out + batt_discharge, + alpha=0.7, + color="tab:purple", + label="Battery Discharge", +) +axes[0].fill_between( + hours, + wind_out + batt_discharge, + wind_out + batt_discharge + ng_out, + alpha=0.7, + color="tab:orange", + label="Natural Gas", +) +axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") +axes[0].set_ylabel("Power (kW)") +axes[0].set_title("System-Level Control: First 168 Hours") +axes[0].legend() + +axes[1].plot(hours, batt_soc, color="tab:cyan") +axes[1].set_ylabel("Battery SOC (%)") + +axes[2].plot(hours, curtailed, color="tab:red") +axes[2].set_ylabel("Curtailed (kW)") +axes[2].set_xlabel("Hour") + +for ax in axes: + ax.grid(True, alpha=0.3) + +plt.tight_layout() +plt.savefig("slc_results.png", dpi=150) +plt.show() diff --git a/examples/35_system_level_control/battery_with_controller/tech_config.yaml b/examples/35_system_level_control/battery_with_controller/tech_config.yaml new file mode 100644 index 000000000..c5ca7a20f --- /dev/null +++ b/examples/35_system_level_control/battery_with_controller/tech_config.yaml @@ -0,0 +1,104 @@ +name: technology_config +description: This plant produces electricity with wind, solar, and a natural gas power plant to meet a fixed electrical load + demand. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. # MMBtu + cost_parameters: + cost_year: 2023 + price: 4.2 # USD/MMBtu + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 # MMBtu/MWh - typical for NGCC + system_capacity_mw: 100. # MW + cost_parameters: + capex_per_kw: 1000 # $/kW - typical for NGCC + fixed_opex_per_kw_per_year: 10.0 # $/kW/year + variable_opex_per_mwh: 0.0 # $/MWh + cost_year: 2023 + electrical_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 30000 + battery: + performance_model: + model: StoragePerformanceModel + cost_model: + model: GenericStorageCostModel + control_strategy: + model: DemandOpenLoopStorageController + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 20000 # kW (20 MW) + max_capacity: 80000 # kWh (80 MWh, 4-hour duration) + init_soc_fraction: 0.5 + max_soc_fraction: 1.0 + min_soc_fraction: 0.1 + # performance_parameters: + round_trip_efficiency: 0.90 + demand_profile: 20000 # kW, required by storage base config + cost_parameters: + cost_year: 2022 + capacity_capex: 310 # $/kWh + charge_capex: 311 # $/kW + opex_fraction: 0.025 + fin_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 3 diff --git a/examples/35_system_level_control/battery_with_controller/wind_ng_demand.yaml b/examples/35_system_level_control/battery_with_controller/wind_ng_demand.yaml new file mode 100644 index 000000000..f2b5599a0 --- /dev/null +++ b/examples/35_system_level_control/battery_with_controller/wind_ng_demand.yaml @@ -0,0 +1,5 @@ +name: H2Integrate_config +system_summary: This example uses wind, solar and a natural gas power plant to meet a fixed electrical load demand. +driver_config: driver_config.yaml +technology_config: tech_config.yaml +plant_config: plant_config.yaml diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 99bba05e9..47157f9b7 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -40,6 +40,8 @@ def setup(self): self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) self.storage_techs = list(slc_config.get("storage_techs", [])) + self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) + self.technology_graph = slc_config["technology_graph"] # Input: demand profile (default value from config) demand_profile = slc_config.get("demand_profile", 0.0) @@ -67,6 +69,9 @@ def setup(self): ) self._setup_tech_category("storage", self.storage_techs) + # def _get_upstream_techs(self, inputs, tech_name): + # tech_commodities = self._get_commodity_for_tech(tech_name) + def _setup_commodity_for_given_units( self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=0.0 ): @@ -90,9 +95,16 @@ def _setup_commodity_for_given_units( tuple(str, str, str): tuple of in_name, set_point_name, and rated_name """ in_name = f"{tech_name}_{commodity}_out" - set_point_name = f"{tech_name}_{commodity}_set_point" rated_name = f"{tech_name}_rated_{commodity}_production" + if self.storage_techs_to_control.get(tech_name, False): + # tech_name is storage and does have an attached controller + set_point_name = f"{tech_name}_{commodity}_demand" + else: + # if tech_name is not in storage_techs_to_control + # or storage tech does not have an attached controller + set_point_name = f"{tech_name}_{commodity}_set_point" + if add_in_name: self.add_input( in_name, @@ -142,9 +154,16 @@ def _setup_commodity_for_copy_units( tuple(str, str, str): tuple of in_name, set_point_name, and rated_name """ in_name = f"{tech_name}_{commodity}_out" - set_point_name = f"{tech_name}_{commodity}_set_point" rated_name = f"{tech_name}_rated_{commodity}_production" + if self.storage_techs_to_control.get(tech_name, False): + # tech_name is storage and does have an attached controller + set_point_name = f"{tech_name}_{commodity}_demand" + else: + # if tech_name is not in storage_techs_to_control + # or storage tech does not have an attached controller + set_point_name = f"{tech_name}_{commodity}_set_point" + if add_in_name: self.add_input( in_name, @@ -334,12 +353,22 @@ def _dispatch_storage(self, inputs, outputs, demand): [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] ) if n_storage > 0: + # split the demand across the storage technologies storage_share = demand / n_storage for set_point_name, commodity in zip( self.storage_set_point_names, self.storage_commodity_names ): if commodity == self.commodity: - outputs[set_point_name] = storage_share + if f"_{commodity}_demand" in set_point_name: + # storage tech has a controller, output combined demand (always positive) + # TODO: update to output whatever is input to storage + storage_share + outputs[set_point_name] = np.clip(storage_share, a_min=0.0, a_max=None) + else: + # storage tech does not have a controller, + # output set point (charge/discharge) command + # charge when remaining demand is negative + # discharge when remaining demand is positive + outputs[set_point_name] = storage_share for tech_name, in_name in zip(self.storage_techs, self.storage_input_names): if self.commodity in self._get_commodity_for_tech(tech_name): diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 22e2340b3..79c1e56ef 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -97,3 +97,22 @@ def test_slc_yes_hydrogen(subtests, temp_copy_of_example): with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", + [("35_system_level_control/battery_with_controller", None)], +) +def test_slc_battery_with_controller(subtests, temp_copy_of_example): + # TODO: this test still needs to be completed! + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") + + model.run() + + wind_out = model.prob.get_val("wind.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 4327bcb47..eb487fe57 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -555,6 +555,20 @@ def _classify_slc_technologies(self): if e[-1] is not None } + # Check if storage models have a controller + storage_tech_to_control = {} + for tech in storage_techs: + control_model = ( + self.technology_config["technologies"][tech] + .get("control_strategy", {}) + .get("model", None) + ) + if control_model is None: + storage_tech_to_control[tech] = False + else: + # storage model does use a controller + storage_tech_to_control[tech] = True + # Remove feedstocks and connectors techs_to_connect = set(curtailable_techs + dispatchable_techs + storage_techs) tech_to_commodities = { @@ -570,6 +584,8 @@ def _classify_slc_technologies(self): slc_config["dispatchable_techs"] = dispatchable_techs slc_config["storage_techs"] = storage_techs slc_config["tech_to_commodity"] = tech_to_commodities + slc_config["storage_techs_to_control"] = storage_tech_to_control + slc_config["technology_graph"] = self.technology_graph def add_system_level_controller(self): """Add the DemandFollowingControl component and configure the plant solver. @@ -640,10 +656,27 @@ def add_system_level_controller(self): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_set_point", - ) + if tech_list == "storage_techs": + if slc_config["storage_techs_to_control"][tech_name]: + # storage has its own controller + # provide demand to storage controller, + # storage controller will provide set-point to performance model + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_demand", + f"{tech_name}.{commodity}_demand", + ) + + else: + # storage doesnt have its own controller, it takes in set-point + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) + else: + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) # 4. For cost-aware strategies, connect marginal costs from cost models if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): From 23a251a37c16d7df9dfff676d7e192b3e4f0c149 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 15:48:12 -0600 Subject: [PATCH 035/132] fix so curtailment only applied if using SLC --- h2integrate/core/model_baseclasses.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index f4ad59d4c..77a1f42b6 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -126,18 +126,19 @@ def apply_curtailment(self, outputs): Should be called at the end of each curtailable model's ``compute()`` method after the raw production has been written to ``outputs[f"{commodity}_out"]``. """ - if getattr(self, "_control_classifier", None) != "curtailable": - return + if "system_level_controller" in self.options["plant_config"]: + if getattr(self, "_control_classifier", None) != "curtailable": + return - commodity_out_key = f"{self.commodity}_out" - uncurtailed_key = f"uncurtailed_{self.commodity}_out" - set_point_key = f"{self.commodity}_set_point" + commodity_out_key = f"{self.commodity}_out" + uncurtailed_key = f"uncurtailed_{self.commodity}_out" + set_point_key = f"{self.commodity}_set_point" - uncurtailed = np.array(outputs[commodity_out_key]) - outputs[uncurtailed_key] = uncurtailed + uncurtailed = np.array(outputs[commodity_out_key]) + outputs[uncurtailed_key] = uncurtailed - set_point = self._inputs[set_point_key] - outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) + set_point = self._inputs[set_point_key] + outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """ From b271026e6df8475d8f045a421d0666fb16c73132 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 16:24:00 -0600 Subject: [PATCH 036/132] made slc_config an input option --- .../system_level/system_level_control_base.py | 3 ++- h2integrate/core/h2integrate_model.py | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 47157f9b7..67145ae75 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -26,10 +26,11 @@ def initialize(self): self.options.declare("driver_config", types=dict) self.options.declare("plant_config", types=dict) self.options.declare("tech_config", types=dict) + self.options.declare("slc_config", types=dict) def setup(self): plant_config = self.options["plant_config"] - slc_config = plant_config["system_level_control"] + slc_config = self.options["slc_config"] self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index eb487fe57..e10d05fb1 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -88,8 +88,8 @@ def __init__(self, config_input): # add system-level controller if configured if self.slc: - self._classify_slc_technologies() - self.add_system_level_controller() + slc_config = self._classify_slc_technologies() + self.add_system_level_controller(slc_config) # connect technologies # technologies are connected within the `technology_interconnections` section of the @@ -478,7 +478,7 @@ def _classify_slc_technologies(self): Results are written into ``self.plant_config["system_level_control"]`` so they are available to the ``DemandFollowingControl`` component at setup time. """ - slc_config = self.plant_config["system_level_control"] + slc_config = {} # self.plant_config["system_level_control"] technologies = self.technology_config.get("technologies", {}) # Identify the (single) demand technology @@ -586,8 +586,9 @@ def _classify_slc_technologies(self): slc_config["tech_to_commodity"] = tech_to_commodities slc_config["storage_techs_to_control"] = storage_tech_to_control slc_config["technology_graph"] = self.technology_graph + return slc_config - def add_system_level_controller(self): + def add_system_level_controller(self, slc_config): """Add the DemandFollowingControl component and configure the plant solver. This method: @@ -597,7 +598,6 @@ def add_system_level_controller(self): 4. Creates connections between the controller and each technology 5. For cost/profit strategies, connects marginal cost inputs """ - slc_config = self.plant_config["system_level_control"] # Map user-facing solver names to OpenMDAO solver classes solver_map = { From c4d95bbeac19ed7c86f1ebcddf8e0b1d407c264d Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 16:40:40 -0600 Subject: [PATCH 037/132] actually make it so slc get option of slc conig and fixed bug in apply_curtailment --- .../profit_maximization/plant_config.yaml | 3 ++- .../system_level/profit_maximization_control.py | 15 +++++++++++---- .../system_level/test/test_slc_examples.py | 2 +- h2integrate/core/h2integrate_model.py | 5 ++++- h2integrate/core/model_baseclasses.py | 2 +- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index d3b56d109..5aa2635d9 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -25,6 +25,7 @@ plant: dt: 3600 system_level_control: control_strategy: ProfitMaximizationControl - commodity_sell_price: 0.06 # $/kWh default; overridden in run script + control_parameters: + commodity_sell_price: 0.06 # $/kWh default; overridden in run script solver_name: gauss_seidel max_iter: 20 diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index a5561c7d0..0d3c12733 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -1,10 +1,17 @@ import numpy as np +from attrs import field, define +from h2integrate.core.utilities import BaseConfig from h2integrate.control.control_strategies.system_level.system_level_control_base import ( SystemLevelControlBase, ) +@define(kw_only=True) +class ProfitMaximizationControlConfig(BaseConfig): + commodity_sell_price: float = field(default=0.0) + + class ProfitMaximizationControl(SystemLevelControlBase): """Profit-maximizing system-level controller. @@ -29,13 +36,13 @@ class ProfitMaximizationControl(SystemLevelControlBase): def setup(self): super().setup() - slc_config = self.options["plant_config"]["system_level_control"] - + config = ProfitMaximizationControlConfig.from_dict( + self.options["plant_config"]["system_level_control"]["control_parameters"] + ) # Commodity sell price — user-set in config, can be scalar or time-varying - default_sell_price = slc_config.get("commodity_sell_price", 0.0) self.add_input( "commodity_sell_price", - val=default_sell_price, + val=config.commodity_sell_price, shape=self.n_timesteps, units=f"USD/({self.commodity_units}*h)", desc=f"Sell price per unit of {self.commodity}", diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 79c1e56ef..e973163d8 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -69,7 +69,7 @@ def test_slc_profit_max(subtests, temp_copy_of_example): model.setup() model.prob.set_val( - "plant.system_level_controller.commodity_sell_price", + "system_level_controller.commodity_sell_price", sell_price, units="USD/(kW*h)", ) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index e10d05fb1..b1b434c99 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -607,7 +607,9 @@ def add_system_level_controller(self, slc_config): } # 1. Select controller class based on strategy - strategy_name = slc_config.get("control_strategy", "DemandFollowingControl") + strategy_name = self.plant_config["system_level_control"].get( + "control_strategy", "DemandFollowingControl" + ) slc_cls = self.supported_models.get(strategy_name) if slc_cls is None: raise ValueError( @@ -619,6 +621,7 @@ def add_system_level_controller(self, slc_config): driver_config=self.driver_config, plant_config=self.plant_config, tech_config=self.technology_config, + slc_config=slc_config, ) self.plant.add_subsystem("system_level_controller", slc_comp) diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 77a1f42b6..3cbe96e18 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -126,7 +126,7 @@ def apply_curtailment(self, outputs): Should be called at the end of each curtailable model's ``compute()`` method after the raw production has been written to ``outputs[f"{commodity}_out"]``. """ - if "system_level_controller" in self.options["plant_config"]: + if "system_level_control" in self.options["plant_config"]: if getattr(self, "_control_classifier", None) != "curtailable": return From 8de0ff193e21e48edbcf8ee2a87a69598a775dc1 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 16:42:24 -0600 Subject: [PATCH 038/132] added check for slc in apply_curtailment() method --- h2integrate/core/model_baseclasses.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index f4ad59d4c..3cbe96e18 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -126,18 +126,19 @@ def apply_curtailment(self, outputs): Should be called at the end of each curtailable model's ``compute()`` method after the raw production has been written to ``outputs[f"{commodity}_out"]``. """ - if getattr(self, "_control_classifier", None) != "curtailable": - return + if "system_level_control" in self.options["plant_config"]: + if getattr(self, "_control_classifier", None) != "curtailable": + return - commodity_out_key = f"{self.commodity}_out" - uncurtailed_key = f"uncurtailed_{self.commodity}_out" - set_point_key = f"{self.commodity}_set_point" + commodity_out_key = f"{self.commodity}_out" + uncurtailed_key = f"uncurtailed_{self.commodity}_out" + set_point_key = f"{self.commodity}_set_point" - uncurtailed = np.array(outputs[commodity_out_key]) - outputs[uncurtailed_key] = uncurtailed + uncurtailed = np.array(outputs[commodity_out_key]) + outputs[uncurtailed_key] = uncurtailed - set_point = self._inputs[set_point_key] - outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) + set_point = self._inputs[set_point_key] + outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """ From 7a4752a838f092a12139012a86c61de627a44aa5 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 17:09:43 -0600 Subject: [PATCH 039/132] updated so slc_config is an input option and added control config class for profit max --- .../profit_maximization/plant_config.yaml | 3 ++- .../profit_maximization_control.py | 14 ++++++++--- .../system_level/system_level_control_base.py | 3 ++- h2integrate/core/h2integrate_model.py | 25 ++++++++++++------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index d3b56d109..5aa2635d9 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -25,6 +25,7 @@ plant: dt: 3600 system_level_control: control_strategy: ProfitMaximizationControl - commodity_sell_price: 0.06 # $/kWh default; overridden in run script + control_parameters: + commodity_sell_price: 0.06 # $/kWh default; overridden in run script solver_name: gauss_seidel max_iter: 20 diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index a5561c7d0..5e289ee84 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -1,10 +1,17 @@ import numpy as np +from attrs import field, define +from h2integrate.core.utilities import BaseConfig from h2integrate.control.control_strategies.system_level.system_level_control_base import ( SystemLevelControlBase, ) +@define(kw_only=True) +class ProfitMaximizationControlConfig(BaseConfig): + commodity_sell_price: float = field(default=0.0) + + class ProfitMaximizationControl(SystemLevelControlBase): """Profit-maximizing system-level controller. @@ -29,13 +36,14 @@ class ProfitMaximizationControl(SystemLevelControlBase): def setup(self): super().setup() - slc_config = self.options["plant_config"]["system_level_control"] + config = ProfitMaximizationControlConfig.from_dict( + self.options["plant_config"]["system_level_control"]["control_parameters"] + ) # Commodity sell price — user-set in config, can be scalar or time-varying - default_sell_price = slc_config.get("commodity_sell_price", 0.0) self.add_input( "commodity_sell_price", - val=default_sell_price, + val=config.commodity_sell_price, shape=self.n_timesteps, units=f"USD/({self.commodity_units}*h)", desc=f"Sell price per unit of {self.commodity}", diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 99bba05e9..dfc9dc1ef 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -26,10 +26,11 @@ def initialize(self): self.options.declare("driver_config", types=dict) self.options.declare("plant_config", types=dict) self.options.declare("tech_config", types=dict) + self.options.declare("slc_config", types=dict) def setup(self): plant_config = self.options["plant_config"] - slc_config = plant_config["system_level_control"] + slc_config = self.options["slc_config"] self.n_timesteps = plant_config["plant"]["simulation"]["n_timesteps"] diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 4327bcb47..e0c71c9de 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -88,8 +88,8 @@ def __init__(self, config_input): # add system-level controller if configured if self.slc: - self._classify_slc_technologies() - self.add_system_level_controller() + slc_config = self._classify_slc_technologies() + self.add_system_level_controller(slc_config) # connect technologies # technologies are connected within the `technology_interconnections` section of the @@ -478,7 +478,7 @@ def _classify_slc_technologies(self): Results are written into ``self.plant_config["system_level_control"]`` so they are available to the ``DemandFollowingControl`` component at setup time. """ - slc_config = self.plant_config["system_level_control"] + slc_config = {} technologies = self.technology_config.get("technologies", {}) # Identify the (single) demand technology @@ -570,8 +570,9 @@ def _classify_slc_technologies(self): slc_config["dispatchable_techs"] = dispatchable_techs slc_config["storage_techs"] = storage_techs slc_config["tech_to_commodity"] = tech_to_commodities + return slc_config - def add_system_level_controller(self): + def add_system_level_controller(self, slc_config): """Add the DemandFollowingControl component and configure the plant solver. This method: @@ -581,7 +582,6 @@ def add_system_level_controller(self): 4. Creates connections between the controller and each technology 5. For cost/profit strategies, connects marginal cost inputs """ - slc_config = self.plant_config["system_level_control"] # Map user-facing solver names to OpenMDAO solver classes solver_map = { @@ -591,7 +591,9 @@ def add_system_level_controller(self): } # 1. Select controller class based on strategy - strategy_name = slc_config.get("control_strategy", "DemandFollowingControl") + strategy_name = self.plant_config["system_level_control"].get( + "control_strategy", "DemandFollowingControl" + ) slc_cls = self.supported_models.get(strategy_name) if slc_cls is None: raise ValueError( @@ -603,6 +605,7 @@ def add_system_level_controller(self): driver_config=self.driver_config, plant_config=self.plant_config, tech_config=self.technology_config, + slc_config=slc_config, ) self.plant.add_subsystem("system_level_controller", slc_comp) @@ -616,9 +619,13 @@ def add_system_level_controller(self): ) solver = solver_cls() # TODO: make a config for the below defaults - solver.options["maxiter"] = slc_config.get("max_iter", 20) - solver.options["atol"] = slc_config.get("convergence_tolerance", 1e-6) - solver.options["rtol"] = slc_config.get("convergence_tolerance", 1e-6) + solver.options["maxiter"] = self.plant_config["system_level_control"].get("max_iter", 20) + solver.options["atol"] = self.plant_config["system_level_control"].get( + "convergence_tolerance", 1e-6 + ) + solver.options["rtol"] = self.plant_config["system_level_control"].get( + "convergence_tolerance", 1e-6 + ) solver.options["iprint"] = 2 # print convergence at each iteration self.plant.nonlinear_solver = solver self.plant.linear_solver = om.DirectSolver() From 5881e07c56f358e1ff97f8f4623100a6bc6f2786 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 5 May 2026 17:15:11 -0600 Subject: [PATCH 040/132] Adding marginal_cost calcs --- .../profit_maximization/plant_config.yaml | 2 + .../profit_maximization/run_profit_max.py | 14 +- .../profit_maximization/tech_config.yaml | 1 - .../system_level/cost_minimization_control.py | 32 +- .../profit_maximization_control.py | 31 +- .../system_level/system_level_control_base.py | 239 +++++++- .../system_level/test/test_slc_controllers.py | 539 ++++++++++++++++++ h2integrate/core/h2integrate_model.py | 31 +- h2integrate/core/model_baseclasses.py | 13 - 9 files changed, 838 insertions(+), 64 deletions(-) create mode 100644 h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index d3b56d109..532ba7391 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -26,5 +26,7 @@ plant: system_level_control: control_strategy: ProfitMaximizationControl commodity_sell_price: 0.06 # $/kWh default; overridden in run script + cost_per_tech: + natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx solver_name: gauss_seidel max_iter: 20 diff --git a/examples/35_system_level_control/profit_maximization/run_profit_max.py b/examples/35_system_level_control/profit_maximization/run_profit_max.py index 77e404933..1aa35b721 100644 --- a/examples/35_system_level_control/profit_maximization/run_profit_max.py +++ b/examples/35_system_level_control/profit_maximization/run_profit_max.py @@ -59,22 +59,22 @@ fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True) # Panel 1: stacked supply vs demand -axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") +axes[0].fill_between(hours, 0, ng_out, alpha=0.7, color="tab:orange", label="Natural Gas") axes[0].fill_between( hours, - wind_out, - wind_out + batt_discharge, + ng_out, + ng_out + batt_discharge, alpha=0.7, color="tab:purple", label="Battery Discharge", ) axes[0].fill_between( hours, - wind_out + batt_discharge, - wind_out + batt_discharge + ng_out, + ng_out + batt_discharge, + ng_out + batt_discharge + wind_out, alpha=0.7, - color="tab:orange", - label="Natural Gas", + color="tab:blue", + label="Wind", ) axes[0].plot(hours, demand, "k--", linewidth=1.5, label="Demand") axes[0].set_ylabel("Power (kW)") diff --git a/examples/35_system_level_control/profit_maximization/tech_config.yaml b/examples/35_system_level_control/profit_maximization/tech_config.yaml index c9097a505..b498acf4a 100644 --- a/examples/35_system_level_control/profit_maximization/tech_config.yaml +++ b/examples/35_system_level_control/profit_maximization/tech_config.yaml @@ -63,7 +63,6 @@ technologies: fixed_opex_per_kw_per_year: 10.0 variable_opex_per_mwh: 0.0 cost_year: 2023 - marginal_cost: 0.05 # $/kWh — NG dispatch cost electrical_load_demand: performance_model: model: GenericDemandComponent diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 3ba2d5366..3c125d305 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -15,26 +15,20 @@ class CostMinimizationControl(SystemLevelControlBase): 3. Dispatchable techs are dispatched in ascending marginal-cost order, each up to its rated capacity, until remaining demand is met. - Each dispatchable technology must have a ``marginal_cost`` input - ($/commodity_rate_unit*h, e.g. $/kWh) representing its variable cost - per unit of production. These are connected from cost model outputs - or set as defaults in the plant config. + Marginal costs are configured via ``cost_per_tech`` in the + ``system_level_control`` section of ``plant_config``. Each + dispatchable technology's entry can be: + + - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) + - ``"buy_price"`` - use the technology's purchase price + - ``"VarOpEx"`` - derive from VarOpEx / total production """ def setup(self): super().setup() - # Add marginal cost inputs for dispatchable techs - self.dispatchable_marginal_cost_names = [] - for tech_name in self.dispatchable_techs: - mc_name = f"{tech_name}_marginal_cost" - self.add_input( - mc_name, - val=0.0, - units=f"USD/({self.commodity_units}*h)", - desc=f"Marginal cost of {self.commodity} from {tech_name}", - ) - self.dispatchable_marginal_cost_names.append(mc_name) + # Set up marginal cost inputs based on cost_per_tech config + self._setup_marginal_costs() def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() @@ -48,9 +42,11 @@ def compute(self, inputs, outputs): # 3. Merit-order dispatch: cheapest dispatchable first remaining = np.maximum(demand, 0.0) - # Collect marginal costs and sort by ascending cost - marginal_costs = np.array([inputs[mc][0] for mc in self.dispatchable_marginal_cost_names]) - dispatch_order = np.argsort(marginal_costs) + marginal_costs = self._compute_marginal_costs(inputs) + + # Merit order: sort by mean marginal cost (cheapest first) + mean_costs = np.array([mc.mean() for mc in marginal_costs]) + dispatch_order = np.argsort(mean_costs) # Initialize all dispatchable set_points to zero for set_point_name in self.dispatchable_set_point_names: diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index a5561c7d0..9ad50feed 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -22,8 +22,13 @@ class ProfitMaximizationControl(SystemLevelControlBase): ``plant_config["system_level_control"]["commodity_sell_price"]`` must be set ($/(commodity_rate_unit*h), e.g. $/kWh). - Each dispatchable technology must have a ``marginal_cost`` input - representing its variable cost per unit of production. + Marginal costs are configured via ``cost_per_tech`` in the + ``system_level_control`` section of ``plant_config``. Each + dispatchable technology's entry can be: + + - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) + - ``"buy_price"`` — use the technology's purchase price + - ``"VarOpEx"`` — derive from VarOpEx / total production """ def setup(self): @@ -41,17 +46,8 @@ def setup(self): desc=f"Sell price per unit of {self.commodity}", ) - # Add marginal cost inputs for dispatchable techs - self.dispatchable_marginal_cost_names = [] - for tech_name in self.dispatchable_techs: - mc_name = f"{tech_name}_marginal_cost" - self.add_input( - mc_name, - val=0.0, - units=f"USD/({self.commodity_units}*h)", - desc=f"Marginal cost of {self.commodity} from {tech_name}", - ) - self.dispatchable_marginal_cost_names.append(mc_name) + # Set up marginal cost inputs based on cost_per_tech config + self._setup_marginal_costs() def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() @@ -66,8 +62,11 @@ def compute(self, inputs, outputs): # 3. Profit-driven merit-order dispatch remaining = np.maximum(demand, 0.0) - marginal_costs = np.array([inputs[mc][0] for mc in self.dispatchable_marginal_cost_names]) - dispatch_order = np.argsort(marginal_costs) + marginal_costs = self._compute_marginal_costs(inputs) + + # Merit order: sort by mean marginal cost (cheapest first) + mean_costs = np.array([mc.mean() for mc in marginal_costs]) + dispatch_order = np.argsort(mean_costs) # Initialize all dispatchable set_points to zero for set_point_name in self.dispatchable_set_point_names: @@ -75,7 +74,7 @@ def compute(self, inputs, outputs): # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: - mc = marginal_costs[idx] + mc = marginal_costs[idx] # per-timestep array profitable = mc < sell_price # boolean mask per timestep set_point_name = self.dispatchable_set_point_names[idx] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 99bba05e9..7947a23db 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -176,13 +176,13 @@ def _setup_tech_category(self, category, tech_list, demand_profile=None): """Create OpenMDAO I/O variables for all technologies in a given category. This single method handles curtailable, dispatchable, and storage - technologies. The logic is identical for all three categories — + technologies. The logic is identical for all three categories — iterate over each technology's commodities and register the appropriate inputs (production output, rated capacity) and output (control set-point) — with one difference: * **Curtailable / Storage** (``demand_profile is None``): - ``initial_set_point`` is ``0.0``. Curtailable techs are later + ``initial_set_point`` is ``0.0``. Curtailable techs are later assigned set-points equal to their rated production; storage techs get set-points computed at run-time in ``_dispatch_storage``. @@ -204,11 +204,11 @@ def _setup_tech_category(self, category, tech_list, demand_profile=None): Args: category (str): One of ``"curtailable"``, ``"dispatchable"``, - or ``"storage"``. Used to name the attribute lists. + or ``"storage"``. Used to name the attribute lists. tech_list (list[str]): Technology names belonging to this category (e.g. ``self.curtailable_techs``). demand_profile (float | np.ndarray | None, optional): - Only relevant for **dispatchable** techs. When provided, the + Only relevant for **dispatchable** techs. When provided, the demand is split equally among dispatchable techs that produce the demanded commodity to set a non-zero ``initial_set_point``. For curtailable and storage techs, leave as ``None`` (default). @@ -359,3 +359,234 @@ def _get_commodity_for_tech(self, tech_name): tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] return tech_commodities + + # ------------------------------------------------------------------ + # Marginal-cost helpers for cost-aware controllers + # ------------------------------------------------------------------ + + def _setup_marginal_costs(self): + """Set up marginal cost inputs for dispatchable techs based on ``cost_per_tech``. + + Should be called from ``setup()`` of cost-aware controllers + (e.g., ``CostMinimizationControl``, ``ProfitMaximizationControl``). + + Reads ``cost_per_tech`` from + ``plant_config["system_level_control"]`` and creates appropriate + OpenMDAO inputs for each dispatchable technology: + + - Numeric value (e.g. ``0.05``): used directly as a constant + marginal cost in ``USD/(commodity_rate_unit*h)``. No additional + inputs or connections are required. + - ``"buy_price"``: creates a ``{tech_name}_buy_price`` input + whose default value is read from the technology's cost config + (``electricity_buy_price`` for Grid, ``price`` for Feedstock). + Can be scalar or time-varying and may be overridden at runtime + via ``prob.set_val()``. + - ``"VarOpEx"``: creates a ``{tech_name}_VarOpEx`` input + connected to the cost model's ``VarOpEx`` output. The + per-unit marginal cost is computed at run time by dividing + ``VarOpEx`` by the total production. + - ``"feedstock"``: looks up ``technology_interconnections`` to + find all feedstock technologies connected upstream of the + dispatchable tech, sums their ``VarOpEx`` outputs, and + divides by the tech's total production. Handles the common + single-feedstock case as well as multiple feedstock streams. + """ + slc_config = self.options["plant_config"]["system_level_control"] + self.cost_per_tech = slc_config.get("cost_per_tech", {}) + self.dt_hours = self.options["plant_config"]["plant"]["simulation"]["dt"] / 3600 + hours_simulated = self.dt_hours * self.n_timesteps + self.fraction_of_year_simulated = hours_simulated / 8760 + plant_life = int(self.options["plant_config"]["plant"]["plant_life"]) + + self.dispatchable_marginal_cost_types = [] + + for tech_name in self.dispatchable_techs: + cost_spec = self.cost_per_tech.get(tech_name, 0.0) + + if isinstance(cost_spec, int | float): + self.dispatchable_marginal_cost_types.append(("scalar", cost_spec)) + + elif cost_spec == "buy_price": + # Read default buy price from tech config + tech_config = self.options["tech_config"] + tech_def = tech_config.get("technologies", {}).get(tech_name, {}) + model_inputs = tech_def.get("model_inputs", {}) + cost_params = model_inputs.get("cost_parameters", {}) + shared_params = model_inputs.get("shared_parameters", {}) + all_params = {**shared_params, **cost_params} + + default_price = all_params.get( + "electricity_buy_price", + all_params.get("price", 0.0), + ) + + self.add_input( + f"{tech_name}_buy_price", + val=default_price, + shape=self.n_timesteps, + units=f"USD/({self.commodity_units}*h)", + desc=f"Buy price for {tech_name}", + ) + self.dispatchable_marginal_cost_types.append(("buy_price", tech_name)) + + elif cost_spec == "VarOpEx": + self.add_input( + f"{tech_name}_VarOpEx", + val=0.0, + shape=plant_life, + units="USD/year", + desc=f"Variable operating expenditure from {tech_name}", + ) + self.dispatchable_marginal_cost_types.append(("VarOpEx", tech_name)) + + elif cost_spec == "feedstock": + # Find feedstock techs connected upstream of this tech + feedstock_names = self._find_feedstock_techs(tech_name) + if not feedstock_names: + raise ValueError( + f"cost_per_tech '{cost_spec}' for '{tech_name}' requires " + f"at least one feedstock connected upstream in " + f"technology_interconnections, but none were found." + ) + for feedstock_name in feedstock_names: + self.add_input( + f"{feedstock_name}_VarOpEx", + val=0.0, + shape=plant_life, + units="USD/year", + desc=f"Variable operating expenditure from feedstock {feedstock_name}", + ) + self.dispatchable_marginal_cost_types.append( + ("feedstock", (tech_name, feedstock_names)) + ) + + else: + raise ValueError( + f"Unknown cost_per_tech value '{cost_spec}' for '{tech_name}'. " + f"Must be a numeric value, 'buy_price', 'VarOpEx', or 'feedstock'." + ) + + def _compute_marginal_costs(self, inputs): + """Compute per-timestep marginal costs for each dispatchable tech. + + Returns: + list[np.ndarray]: marginal cost arrays, one per dispatchable + tech, each of shape ``(n_timesteps,)``. + """ + marginal_costs = [] + + for marginal_cost_type, marginal_cost_data in self.dispatchable_marginal_cost_types: + if marginal_cost_type == "scalar": + marginal_cost = np.full(self.n_timesteps, marginal_cost_data) + elif marginal_cost_type == "buy_price": + marginal_cost = self._buy_price_marginal_cost(inputs, marginal_cost_data) + elif marginal_cost_type == "VarOpEx": + marginal_cost = self._varopex_marginal_cost(inputs, marginal_cost_data) + elif marginal_cost_type == "feedstock": + marginal_cost = self._feedstock_marginal_cost(inputs, marginal_cost_data) + else: + marginal_cost = np.zeros(self.n_timesteps) + + marginal_costs.append(marginal_cost) + + return marginal_costs + + def _buy_price_marginal_cost(self, inputs, tech_name): + """Compute marginal cost from buy price. + + Returns a per-timestep marginal cost array equal to the + technology's buy price (scalar or time-varying). + """ + return np.broadcast_to(inputs[f"{tech_name}_buy_price"], self.n_timesteps).copy() + + def _varopex_marginal_cost(self, inputs, tech_name): + """Compute marginal cost from VarOpEx and commodity output. + + Divides the first-year ``VarOpEx`` (``$/year``) by the + annualized total production to obtain an average marginal cost + in ``$/(commodity_amount_unit)``. + + Returns a constant per-timestep array. + """ + varopex = inputs[f"{tech_name}_VarOpEx"] # $/year, shape=plant_life + + # Use commodity_out already connected for this dispatchable tech + tech_commodities = self._get_commodity_for_tech(tech_name) + commodity = tech_commodities[0] if tech_commodities else self.commodity + + production = inputs[f"{tech_name}_{commodity}_out"] # rate units, shape=n_timesteps + total_production = production.sum() * self.dt_hours + + if total_production > 0: + annual_production = total_production / self.fraction_of_year_simulated + marginal_cost_scalar = varopex[0] / annual_production + else: + marginal_cost_scalar = 0.0 + + return np.full(self.n_timesteps, marginal_cost_scalar) + + def _find_feedstock_techs(self, tech_name): + """Find feedstock technologies connected upstream of tech_name. + + Scans ``technology_interconnections`` for connections whose + destination is tech_name and whose source uses + ``FeedstockPerformanceModel`` or ``FeedstockCostModel``. + + Args: + tech_name (str): the dispatchable technology name. + + Returns: + list[str]: names of upstream feedstock technologies. + """ + tech_config = self.options["tech_config"] + technologies = tech_config.get("technologies", {}) + interconnections = self.options["plant_config"].get("technology_interconnections", []) + + # Upstream tech names for this dispatchable tech + upstream_techs = [conn[0] for conn in interconnections if conn[1] == tech_name] + + feedstock_names = [] + for upstream in upstream_techs: + tech_def = technologies.get(upstream, {}) + perf_model = tech_def.get("performance_model", {}).get("model", "") + cost_model = tech_def.get("cost_model", {}).get("model", "") + if "Feedstock" in perf_model or "Feedstock" in cost_model: + feedstock_names.append(upstream) + + return feedstock_names + + def _feedstock_marginal_cost(self, inputs, marginal_cost_data): + """Compute marginal cost from upstream feedstock VarOpEx values. + + Sums the first-year ``VarOpEx`` from all feedstock technologies + connected to the dispatchable tech, then divides by the tech's + annualized total production. + + Args: + marginal_cost_data (tuple): ``(tech_name, feedstock_names)`` where + tech_name is the dispatchable tech and feedstock_names + is a list of upstream feedstock technology names. + + Returns: + np.ndarray: constant per-timestep marginal cost array. + """ + tech_name, feedstock_names = marginal_cost_data + + # Sum VarOpEx from all connected feedstocks (first year) + total_varopex = sum(inputs[f"{fs}_VarOpEx"][0] for fs in feedstock_names) + + # Get the tech's production + tech_commodities = self._get_commodity_for_tech(tech_name) + commodity = tech_commodities[0] if tech_commodities else self.commodity + + production = inputs[f"{tech_name}_{commodity}_out"] + total_production = production.sum() * self.dt_hours + + if total_production > 0: + annual_production = total_production / self.fraction_of_year_simulated + marginal_cost_scalar = total_varopex / annual_production + else: + marginal_cost_scalar = 0.0 + + return np.full(self.n_timesteps, marginal_cost_scalar) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py new file mode 100644 index 000000000..6d7b5a83b --- /dev/null +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -0,0 +1,539 @@ +"""Unit tests for system-level control base class and all controller strategies.""" + +import numpy as np +import pytest +import openmdao.api as om + +from h2integrate.control.control_strategies.system_level.demand_following_control import ( + DemandFollowingControl, +) +from h2integrate.control.control_strategies.system_level.cost_minimization_control import ( + CostMinimizationControl, +) +from h2integrate.control.control_strategies.system_level.profit_maximization_control import ( + ProfitMaximizationControl, +) + + +def _make_plant_config( + n_timesteps=4, + demand=50000, + curtailable=None, + dispatchable=None, + storage=None, + sell_price=0.06, + cost_per_tech=None, + technology_interconnections=None, +): + """Build a minimal plant_config dict for controller tests.""" + all_techs = (curtailable or []) + (dispatchable or []) + (storage or []) + tech_to_commodity = {(t, "electricity") for t in all_techs} + config = { + "plant": {"simulation": {"n_timesteps": n_timesteps, "dt": 3600}, "plant_life": 30}, + "system_level_control": { + "demand_commodity": "electricity", + "demand_commodity_rate_units": "kW", + "demand_tech": "demand", + "demand_profile": demand, + "curtailable_techs": curtailable or [], + "dispatchable_techs": dispatchable or [], + "storage_techs": storage or [], + "tech_to_commodity": tech_to_commodity, + "commodity_sell_price": sell_price, + "cost_per_tech": cost_per_tech or {}, + }, + } + if technology_interconnections is not None: + config["technology_interconnections"] = technology_interconnections + return config + + +def _build_problem(slc_cls, plant_config, tech_config=None): + """Create and setup an OpenMDAO Problem with the given controller.""" + prob = om.Problem() + prob.model.add_subsystem( + "slc", + slc_cls( + driver_config={}, + plant_config=plant_config, + tech_config=tech_config or {}, + ), + ) + prob.setup() + return prob + + +# --------------------------------------------------------------------------- +# SystemLevelControlBase +# --------------------------------------------------------------------------- +@pytest.mark.unit +class TestSystemLevelControlBase: + """Tests for the abstract base class setup logic.""" + + def test_base_creates_curtailable_io(self): + pc = _make_plant_config(curtailable=["wind"]) + # Use DemandFollowingControl since base is abstract + prob = _build_problem(DemandFollowingControl, pc) + # _var_rel2meta uses relative names (no "slc." prefix) + assert "wind_electricity_out" in prob.model.slc._var_rel2meta + assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta + assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta + + def test_base_creates_dispatchable_io(self): + pc = _make_plant_config(dispatchable=["ng"]) + prob = _build_problem(DemandFollowingControl, pc) + assert "ng_electricity_out" in prob.model.slc._var_rel2meta + assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta + assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta + + def test_base_creates_storage_io(self): + pc = _make_plant_config(storage=["battery"]) + prob = _build_problem(DemandFollowingControl, pc) + assert "battery_electricity_out" in prob.model.slc._var_rel2meta + assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta + assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta + + def test_base_creates_demand_input(self): + pc = _make_plant_config() + prob = _build_problem(DemandFollowingControl, pc) + assert "electricity_demand" in prob.model.slc._var_rel2meta + + def test_backward_compat_alias(self): + """DemandFollowingControl should be an alias for DemandFollowingControl.""" + assert DemandFollowingControl is DemandFollowingControl + + +# --------------------------------------------------------------------------- +# DemandFollowingControl +# --------------------------------------------------------------------------- +@pytest.mark.unit +class TestDemandFollowingControl: + """Tests for the demand-following (equal-share) controller.""" + + def test_equal_share_two_dispatchable(self): + pc = _make_plant_config(dispatchable=["ng1", "ng2"]) + prob = _build_problem(DemandFollowingControl, pc) + prob.set_val("slc.ng1_rated_electricity_production", 80000) + prob.set_val("slc.ng2_rated_electricity_production", 40000) + prob.run_model() + + sp1 = prob.get_val("slc.ng1_electricity_set_point") + sp2 = prob.get_val("slc.ng2_electricity_set_point") + np.testing.assert_allclose(sp1, 25000) + np.testing.assert_allclose(sp2, 25000) + + def test_curtailable_reduces_demand(self): + pc = _make_plant_config(curtailable=["wind"], dispatchable=["ng"]) + prob = _build_problem(DemandFollowingControl, pc) + prob.set_val("slc.wind_electricity_out", [30000, 60000, 50000, 10000]) + prob.set_val("slc.wind_rated_electricity_production", 120000) + prob.set_val("slc.ng_rated_electricity_production", 100000) + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # demand=50k, wind outputs [30k,60k,50k,10k] → remaining = max(0, demand-wind) + expected = np.maximum(50000 - np.array([30000, 60000, 50000, 10000]), 0) + np.testing.assert_allclose(ng_sp, expected) + + def test_storage_absorbs_surplus(self): + pc = _make_plant_config(curtailable=["wind"], storage=["battery"], dispatchable=["ng"]) + prob = _build_problem(DemandFollowingControl, pc) + prob.set_val("slc.wind_electricity_out", [70000, 30000, 50000, 50000]) + prob.set_val("slc.wind_rated_electricity_production", 120000) + prob.set_val("slc.battery_electricity_out", [0, 0, 0, 0]) + prob.set_val("slc.battery_rated_electricity_production", 50000) + prob.set_val("slc.ng_rated_electricity_production", 100000) + prob.run_model() + + batt_sp = prob.get_val("slc.battery_electricity_set_point") + # demand - wind = [50k-70k, 50k-30k, 0, 0] = [-20k, 20k, 0, 0] + expected = np.array([-20000, 20000, 0, 0]) + np.testing.assert_allclose(batt_sp, expected) + + def test_no_techs_runs(self): + """Controller with no techs should still run without error.""" + pc = _make_plant_config() + prob = _build_problem(DemandFollowingControl, pc) + prob.run_model() # should not raise + + +# --------------------------------------------------------------------------- +# CostMinimizationControl +# --------------------------------------------------------------------------- +@pytest.mark.unit +class TestCostMinimizationControl: + """Tests for the merit-order cost-minimization controller.""" + + def test_cheapest_dispatched_first(self): + pc = _make_plant_config( + dispatchable=["cheap", "expensive"], + demand=50000, + cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + ) + prob = _build_problem(CostMinimizationControl, pc) + prob.set_val("slc.cheap_rated_electricity_production", 80000) + prob.set_val("slc.expensive_rated_electricity_production", 40000) + prob.run_model() + + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + # Cheap can handle all 50k (rated 80k), so expensive gets 0 + np.testing.assert_allclose(cheap_sp, 50000) + np.testing.assert_allclose(expensive_sp, 0) + + def test_overflow_to_expensive(self): + pc = _make_plant_config( + dispatchable=["cheap", "expensive"], + demand=50000, + cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + ) + prob = _build_problem(CostMinimizationControl, pc) + prob.set_val("slc.cheap_rated_electricity_production", 30000) + prob.set_val("slc.expensive_rated_electricity_production", 40000) + prob.run_model() + + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + # Cheap maxes at 30k, expensive picks up remaining 20k + np.testing.assert_allclose(cheap_sp, 30000) + np.testing.assert_allclose(expensive_sp, 20000) + + def test_with_curtailable_reduces_dispatch(self): + pc = _make_plant_config( + curtailable=["wind"], + dispatchable=["ng"], + demand=50000, + cost_per_tech={"ng": 0.05}, + ) + prob = _build_problem(CostMinimizationControl, pc) + prob.set_val("slc.wind_electricity_out", [40000, 40000, 40000, 40000]) + prob.set_val("slc.wind_rated_electricity_production", 120000) + prob.set_val("slc.ng_rated_electricity_production", 100000) + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # demand 50k - wind 40k = 10k remaining + np.testing.assert_allclose(ng_sp, 10000) + + +# --------------------------------------------------------------------------- +# ProfitMaximizationControl +# --------------------------------------------------------------------------- +@pytest.mark.unit +class TestProfitMaximizationControl: + """Tests for the profit-maximization controller.""" + + def test_unprofitable_tech_not_dispatched(self): + pc = _make_plant_config( + dispatchable=["cheap", "expensive"], + demand=50000, + sell_price=0.06, + cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.cheap_rated_electricity_production", 30000) + prob.set_val("slc.expensive_rated_electricity_production", 40000) + prob.set_val("slc.commodity_sell_price", 0.06) + prob.run_model() + + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + # Cheap (0.03 < 0.06) dispatched up to rated 30k + # Expensive (0.08 >= 0.06) NOT dispatched, demand unmet + np.testing.assert_allclose(cheap_sp, 30000) + np.testing.assert_allclose(expensive_sp, 0) + + def test_all_profitable(self): + pc = _make_plant_config( + dispatchable=["a", "b"], + demand=50000, + sell_price=0.10, + cost_per_tech={"a": 0.03, "b": 0.05}, + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.a_rated_electricity_production", 80000) + prob.set_val("slc.b_rated_electricity_production", 40000) + prob.set_val("slc.commodity_sell_price", 0.10) + prob.run_model() + + a_sp = prob.get_val("slc.a_electricity_set_point") + b_sp = prob.get_val("slc.b_electricity_set_point") + # Both profitable, cheapest first: a gets 50k (rated 80k), b gets 0 + np.testing.assert_allclose(a_sp, 50000) + np.testing.assert_allclose(b_sp, 0) + + def test_none_profitable(self): + pc = _make_plant_config( + dispatchable=["ng"], + demand=50000, + sell_price=0.01, + cost_per_tech={"ng": 0.05}, + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.ng_rated_electricity_production", 100000) + prob.set_val("slc.commodity_sell_price", 0.01) + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # NG cost (0.05) >= sell price (0.01), not dispatched + np.testing.assert_allclose(ng_sp, 0) + + def test_sell_price_from_config(self): + pc = _make_plant_config( + dispatchable=["ng"], + demand=50000, + sell_price=0.10, + cost_per_tech={"ng": 0.03}, + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.ng_rated_electricity_production", 100000) + # Don't set sell_price explicitly — should use config default 0.10 + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # Config sell_price=0.10 > marginal 0.03 → dispatched + np.testing.assert_allclose(ng_sp, 50000) + + def test_time_varying_sell_price(self): + pc = _make_plant_config( + dispatchable=["ng"], + demand=50000, + sell_price=0.06, + cost_per_tech={"ng": 0.05}, + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.ng_rated_electricity_production", 100000) + # Sell price varies: 2 profitable hours, 2 unprofitable + prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # mc=0.05: profitable when sell>0.05 (hours 0,2), not when sell<0.05 (hours 1,3) + np.testing.assert_allclose(ng_sp, [50000, 0, 50000, 0]) + + def test_buy_price_scalar(self): + """buy_price mode with a scalar buy price from tech config.""" + pc = _make_plant_config( + dispatchable=["grid"], + demand=50000, + sell_price=0.10, + cost_per_tech={"grid": "buy_price"}, + ) + # Add tech config with buy price + tech_config = { + "technologies": { + "grid": { + "model_inputs": { + "cost_parameters": {"electricity_buy_price": 0.04}, + } + } + } + } + prob = om.Problem() + prob.model.add_subsystem( + "slc", + ProfitMaximizationControl(driver_config={}, plant_config=pc, tech_config=tech_config), + ) + prob.setup() + prob.set_val("slc.grid_rated_electricity_production", 100000) + prob.set_val("slc.commodity_sell_price", 0.10) + prob.run_model() + + grid_sp = prob.get_val("slc.grid_electricity_set_point") + # buy_price=0.04 < sell_price=0.10 → dispatched + np.testing.assert_allclose(grid_sp, 50000) + + def test_buy_price_time_varying(self): + """buy_price mode with time-varying prices (override via set_val).""" + pc = _make_plant_config( + dispatchable=["grid"], + demand=50000, + sell_price=0.06, + cost_per_tech={"grid": "buy_price"}, + ) + tech_config = { + "technologies": { + "grid": { + "model_inputs": { + "cost_parameters": {"electricity_buy_price": 0.04}, + } + } + } + } + prob = om.Problem() + prob.model.add_subsystem( + "slc", + ProfitMaximizationControl(driver_config={}, plant_config=pc, tech_config=tech_config), + ) + prob.setup() + prob.set_val("slc.grid_rated_electricity_production", 100000) + prob.set_val("slc.commodity_sell_price", 0.06) + # Time-varying buy price: profitable at hours 0,2; unprofitable at hours 1,3 + prob.set_val("slc.grid_buy_price", [0.03, 0.08, 0.04, 0.09]) + prob.run_model() + + grid_sp = prob.get_val("slc.grid_electricity_set_point") + np.testing.assert_allclose(grid_sp, [50000, 0, 50000, 0]) + + def test_varopex_mode(self): + """VarOpEx mode computes marginal cost from VarOpEx / production.""" + pc = _make_plant_config( + dispatchable=["gen"], + demand=50000, + sell_price=0.10, + cost_per_tech={"gen": "VarOpEx"}, + ) + prob = _build_problem(CostMinimizationControl, pc) + prob.set_val("slc.gen_rated_electricity_production", 100000) + # Set VarOpEx ($/year, shape=plant_life=30) and production + prob.set_val("slc.gen_VarOpEx", np.full(30, 500000.0)) + # Simulate 4 hours of 100 MW production → 400 MWh + prob.set_val("slc.gen_electricity_out", np.full(4, 100000.0)) + prob.run_model() + + gen_sp = prob.get_val("slc.gen_electricity_set_point") + # VarOpEx=500k $/yr, production=100MW*4h=400MWh over 4h + # Annual production = 400 MWh / (4/8760) = 876,000 MWh + # mc = 500k / 876k ≈ 0.571 $/MWh ≈ 0.000571 $/kWh + # This is very cheap, so it should be dispatched fully + np.testing.assert_allclose(gen_sp, 50000) + + def test_cost_per_tech_default_zero(self): + """Techs not listed in cost_per_tech default to zero marginal cost.""" + pc = _make_plant_config( + dispatchable=["ng"], + demand=50000, + sell_price=0.10, + cost_per_tech={}, # Empty: ng defaults to 0.0 + ) + prob = _build_problem(ProfitMaximizationControl, pc) + prob.set_val("slc.ng_rated_electricity_production", 100000) + prob.set_val("slc.commodity_sell_price", 0.10) + prob.run_model() + + ng_sp = prob.get_val("slc.ng_electricity_set_point") + # mc=0.0 < sell_price=0.10 → dispatched + np.testing.assert_allclose(ng_sp, 50000) + + def test_feedstock_single(self): + """feedstock mode: single upstream feedstock drives marginal cost.""" + pc = _make_plant_config( + dispatchable=["ng_plant"], + demand=50000, + sell_price=0.10, + cost_per_tech={"ng_plant": "feedstock"}, + technology_interconnections=[ + ["ng_feed", "ng_plant", "natural_gas", "pipe"], + ], + ) + tech_config = { + "technologies": { + "ng_feed": { + "performance_model": {"model": "FeedstockPerformanceModel"}, + "cost_model": {"model": "FeedstockCostModel"}, + }, + } + } + prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config) + prob.set_val("slc.ng_plant_rated_electricity_production", 100000) + # Feedstock VarOpEx: $1M/yr; production: 100 MW * 4 h = 400 MWh + prob.set_val("slc.ng_feed_VarOpEx", np.full(30, 1_000_000.0)) + prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) + prob.run_model() + + sp = prob.get_val("slc.ng_plant_electricity_set_point") + # Annual production = 400 MWh / (4/8760) = 876,000 MWh + # mc = 1M / 876k ≈ 1.14 $/MWh ≈ 0.00114 $/kWh → very cheap + np.testing.assert_allclose(sp, 50000) + + def test_feedstock_multiple(self): + """feedstock mode: multiple upstream feedstocks are summed.""" + pc = _make_plant_config( + dispatchable=["plant"], + demand=50000, + sell_price=0.10, + cost_per_tech={"plant": "feedstock"}, + technology_interconnections=[ + ["feed_a", "plant", "gas_a", "pipe"], + ["feed_b", "plant", "gas_b", "pipe"], + ["other_tech", "plant", "something", "cable"], + ], + ) + tech_config = { + "technologies": { + "feed_a": { + "performance_model": {"model": "FeedstockPerformanceModel"}, + "cost_model": {"model": "FeedstockCostModel"}, + }, + "feed_b": { + "performance_model": {"model": "FeedstockPerformanceModel"}, + "cost_model": {"model": "FeedstockCostModel"}, + }, + "other_tech": { + "performance_model": {"model": "SomePerformanceModel"}, + }, + } + } + prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config) + prob.set_val("slc.plant_rated_electricity_production", 100000) + # Two feedstocks: $500k and $300k → total $800k/yr + prob.set_val("slc.feed_a_VarOpEx", np.full(30, 500_000.0)) + prob.set_val("slc.feed_b_VarOpEx", np.full(30, 300_000.0)) + prob.set_val("slc.plant_electricity_out", np.full(4, 100000.0)) + prob.run_model() + + sp = prob.get_val("slc.plant_electricity_set_point") + # Total VarOpEx = 800k, annual production = 876,000 MWh + # mc ≈ 0.913 $/MWh ≈ 0.000913 $/kWh → very cheap + np.testing.assert_allclose(sp, 50000) + + def test_feedstock_profit_max_unprofitable(self): + """feedstock mode in profit max: unprofitable when feedstock costs exceed sell price.""" + pc = _make_plant_config( + dispatchable=["ng_plant"], + demand=50000, + sell_price=0.01, # very low sell price + cost_per_tech={"ng_plant": "feedstock"}, + technology_interconnections=[ + ["ng_feed", "ng_plant", "natural_gas", "pipe"], + ], + ) + tech_config = { + "technologies": { + "ng_feed": { + "performance_model": {"model": "FeedstockPerformanceModel"}, + "cost_model": {"model": "FeedstockCostModel"}, + }, + } + } + prob = _build_problem(ProfitMaximizationControl, pc, tech_config=tech_config) + prob.set_val("slc.ng_plant_rated_electricity_production", 100000) + prob.set_val("slc.commodity_sell_price", 0.01) + # Very expensive feedstock: $100M/yr → high marginal cost + prob.set_val("slc.ng_feed_VarOpEx", np.full(30, 100_000_000.0)) + prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) + prob.run_model() + + sp = prob.get_val("slc.ng_plant_electricity_set_point") + # mc = 100M / 876k ≈ 114 $/MWh ≈ 0.114 $/kWh > sell 0.01 → NOT dispatched + np.testing.assert_allclose(sp, 0) + + def test_feedstock_no_feedstock_raises(self): + """feedstock mode raises ValueError when no feedstock is found upstream.""" + pc = _make_plant_config( + dispatchable=["ng_plant"], + demand=50000, + cost_per_tech={"ng_plant": "feedstock"}, + technology_interconnections=[ + ["some_tech", "ng_plant", "electricity", "cable"], + ], + ) + tech_config = { + "technologies": { + "some_tech": { + "performance_model": {"model": "SomePerformanceModel"}, + }, + } + } + with pytest.raises(ValueError, match="at least one feedstock"): + _build_problem(CostMinimizationControl, pc, tech_config=tech_config) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 4327bcb47..c60288e13 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -645,13 +645,34 @@ def add_system_level_controller(self): f"{tech_name}.{commodity}_set_point", ) - # 4. For cost-aware strategies, connect marginal costs from cost models + # 4. For cost-aware strategies, connect cost inputs based on cost_per_tech if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): + cost_per_tech = slc_config.get("cost_per_tech", {}) for tech_name in slc_config["dispatchable_techs"]: - self.plant.connect( - f"{tech_name}.marginal_cost", - f"system_level_controller.{tech_name}_marginal_cost", - ) + cost_spec = cost_per_tech.get(tech_name, 0.0) + if cost_spec == "VarOpEx": + self.plant.connect( + f"{tech_name}.VarOpEx", + f"system_level_controller.{tech_name}_VarOpEx", + ) + elif cost_spec == "feedstock": + # Connect VarOpEx from each upstream feedstock + interconnections = self.plant_config.get("technology_interconnections", []) + technologies = self.technology_config.get("technologies", {}) + for conn in interconnections: + if conn[1] != tech_name: + continue + upstream = conn[0] + tech_def = technologies.get(upstream, {}) + perf_model = tech_def.get("performance_model", {}).get("model", "") + cost_model = tech_def.get("cost_model", {}).get("model", "") + if "Feedstock" in perf_model or "Feedstock" in cost_model: + self.plant.connect( + f"{upstream}.VarOpEx", + f"system_level_controller.{upstream}_VarOpEx", + ) + # buy_price: defaults from tech config, overridable via set_val + # scalar: no connection needed ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index f4ad59d4c..45d8b98da 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -152,7 +152,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): @define(kw_only=True) class CostModelBaseConfig(BaseConfig): cost_year: int = field(converter=int) - marginal_cost: float = field(default=0.0) class CostModelBaseClass(om.ExplicitComponent): @@ -165,7 +164,6 @@ class CostModelBaseClass(om.ExplicitComponent): - CapEx (float): capital expenditure costs in $ - OpEx (float): annual fixed operating expenditure costs in $/year - VarOpEx (float): annual variable operating expenditure costs in $/year - - marginal_cost (float): marginal cost of production for dispatch decisions Discrete Outputs: - cost_year (int): dollar-year corresponding to CapEx and OpEx values. @@ -194,17 +192,6 @@ def setup(self): "cost_year", val=self.config.cost_year, desc="Dollar year for costs" ) - # Marginal cost output for dispatch decisions - model_inputs = self.options["tech_config"].get("model_inputs", {}) - shared = model_inputs.get("shared_parameters", {}) - commodity_rate_units = shared.get("commodity_rate_units", "kW") - self.add_output( - "marginal_cost", - val=self.config.marginal_cost, - units=f"USD/({commodity_rate_units}*h)", - desc="Marginal cost of production for dispatch decisions", - ) - # dt is seconds per timestep self.dt = int(self.options["plant_config"]["plant"]["simulation"]["dt"]) From d084f698b423c3bd0997eefebd0863f1a4ff0181 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 5 May 2026 17:24:10 -0600 Subject: [PATCH 041/132] replaced lists of tech control classifiers with the dictionary --- .../system_level/system_level_control_base.py | 12 +++- h2integrate/core/h2integrate_model.py | 65 ++++++++----------- 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index dfc9dc1ef..341719af5 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -38,9 +38,15 @@ def setup(self): self.commodity = slc_config["demand_commodity"] self.commodity_units = slc_config.get("demand_commodity_rate_units", None) self.demand_tech = slc_config["demand_tech"] - self.curtailable_techs = list(slc_config.get("curtailable_techs", [])) - self.dispatchable_techs = list(slc_config.get("dispatchable_techs", [])) - self.storage_techs = list(slc_config.get("storage_techs", [])) + self.curtailable_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "curtailable" + ] + self.dispatchable_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "dispatchable" + ] + self.storage_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "storage" + ] # Input: demand profile (default value from config) demand_profile = slc_config.get("demand_profile", 0.0) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index e0c71c9de..0a2b08b74 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -535,18 +535,6 @@ def _classify_slc_technologies(self): ) raise ValueError(msg) - # Classify technologies using pre-computed classifiers - curtailable_techs = [] - dispatchable_techs = [] - storage_techs = [] - for tech_name, classifier in self.tech_control_classifiers.items(): - if classifier == "curtailable": - curtailable_techs.append(tech_name) - elif classifier == "dispatchable": - dispatchable_techs.append(tech_name) - elif classifier == "storage": - storage_techs.append(tech_name) - # Classify technologies based on their output commodity (or commodities) # Use a set to remove duplicates (in case one tech produces multiple commodities) sources_to_commodities = { @@ -556,9 +544,11 @@ def _classify_slc_technologies(self): } # Remove feedstocks and connectors - techs_to_connect = set(curtailable_techs + dispatchable_techs + storage_techs) + control_classifiers_to_connect = ["curtailable", "dispatchable", "storage"] tech_to_commodities = { - (e[0], e[-1]) for e in sources_to_commodities if e[0] in techs_to_connect + (e[0], e[-1]) + for e in sources_to_commodities + if self.tech_control_classifiers[e[0]] in control_classifiers_to_connect } # Store classification results in plant_config for SLC component @@ -566,10 +556,9 @@ def _classify_slc_technologies(self): slc_config["demand_profile"] = demand_profile slc_config["demand_commodity"] = demand_commodity slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units - slc_config["curtailable_techs"] = curtailable_techs - slc_config["dispatchable_techs"] = dispatchable_techs - slc_config["storage_techs"] = storage_techs slc_config["tech_to_commodity"] = tech_to_commodities + slc_config["tech_control_classifiers"] = self.tech_control_classifiers + return slc_config def add_system_level_controller(self, slc_config): @@ -633,32 +622,32 @@ def add_system_level_controller(self, slc_config): # 3. Connect the controller's inputs/outputs to technology models # Curtailable, dispatchable, and storage techs: read output and write set_point - for tech_list in ["curtailable_techs", "dispatchable_techs", "storage_techs"]: - for tech_name in slc_config[tech_list]: - tech_commodities = self._get_commodity_for_tech(tech_name) - for commodity in tech_commodities: - self.plant.connect( - f"{tech_name}.{commodity}_out", - f"system_level_controller.{tech_name}_{commodity}_out", - ) + for tech_to_commodity in slc_config["tech_to_commodity"]: + tech_name, commodity = tech_to_commodity + self.plant.connect( + f"{tech_name}.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) - self.plant.connect( - f"{tech_name}.rated_{commodity}_production", - f"system_level_controller.{tech_name}_rated_{commodity}_production", - ) + self.plant.connect( + f"{tech_name}.rated_{commodity}_production", + f"system_level_controller.{tech_name}_rated_{commodity}_production", + ) - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_set_point", - ) + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", + ) # 4. For cost-aware strategies, connect marginal costs from cost models if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): - for tech_name in slc_config["dispatchable_techs"]: - self.plant.connect( - f"{tech_name}.marginal_cost", - f"system_level_controller.{tech_name}_marginal_cost", - ) + for tech_to_commodity in slc_config["tech_to_commodity"]: + tech_name, commodity = tech_to_commodity + if self.tech_control_classifiers[tech_name] == "dispatchable": + self.plant.connect( + f"{tech_name}.marginal_cost", + f"system_level_controller.{tech_name}_marginal_cost", + ) ### Commented out for now; we'll need to determine how to treat demand ### components in the new SLC paradigm. From a11e37c0751dbc1c6aaa8bd80cd50a4081b2e67d Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 5 May 2026 20:24:40 -0600 Subject: [PATCH 042/132] Directly connected demand profile --- h2integrate/core/h2integrate_model.py | 18 +++++++----------- h2integrate/demand/demand_base.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 4327bcb47..a743f5a94 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -506,7 +506,6 @@ def _classify_slc_technologies(self): demand_commodity = all_params["commodity"] demand_commodity_rate_units = all_params.get("commodity_rate_units", None) - demand_profile = all_params.get("demand_profile", 0.0) demand_tech = tech_name # Check that the demand tech is in the technology_interconnections tech_interconnections = self.plant_config["technology_interconnections"] @@ -563,7 +562,6 @@ def _classify_slc_technologies(self): # Store classification results in plant_config for SLC component slc_config["demand_tech"] = demand_tech - slc_config["demand_profile"] = demand_profile slc_config["demand_commodity"] = demand_commodity slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units slc_config["curtailable_techs"] = curtailable_techs @@ -653,15 +651,13 @@ def add_system_level_controller(self): f"system_level_controller.{tech_name}_marginal_cost", ) - ### Commented out for now; we'll need to determine how to treat demand - ### components in the new SLC paradigm. - # # Connect demand profile to the controller - # demand_tech = slc_config["demand_tech"] - # demand_commodity = slc_config["demand_commodity"] - # self.plant.connect( - # f"{demand_tech}.{commodity}_demand", - # f"system_level_controller.{commodity}_demand", - # ) + # Connect demand profile from the demand component to the controller + demand_tech = slc_config["demand_tech"] + demand_commodity = slc_config["demand_commodity"] + self.plant.connect( + f"{demand_tech}.{demand_commodity}_demand_out", + f"system_level_controller.{demand_commodity}_demand", + ) def create_technology_models(self): # Loop through each technology and instantiate an OpenMDAO object (assume it exists) diff --git a/h2integrate/demand/demand_base.py b/h2integrate/demand/demand_base.py index 09072594f..9417bdf83 100644 --- a/h2integrate/demand/demand_base.py +++ b/h2integrate/demand/demand_base.py @@ -94,6 +94,14 @@ def setup(self): desc=f"Excess production of {self.commodity}", ) + self.add_output( + f"{self.commodity}_demand_out", + val=self.config.demand_profile, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Pass-through of {self.commodity} demand profile", + ) + def compute(): """This method must be implemented by subclasses to define the demand component. @@ -125,6 +133,8 @@ def calculate_outputs(self, commodity_in, commodity_demand, outputs): array shape ``(n_timesteps,)``. """ + outputs[f"{self.commodity}_demand_out"] = commodity_demand + remaining_demand = commodity_demand - commodity_in # Calculate missed load and curtailed production From db9c9c0243986c15e69365212f2758d35edbd445 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 5 May 2026 21:42:10 -0600 Subject: [PATCH 043/132] Shared commodity sell price as input from finance subgroups --- .../profit_maximization/plant_config.yaml | 36 ++++++++++++++++++- .../profit_maximization/run_profit_max.py | 26 ++------------ .../profit_maximization_control.py | 36 +++++++++++++++++-- 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index d3b56d109..37c1bcb78 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -25,6 +25,40 @@ plant: dt: 3600 system_level_control: control_strategy: ProfitMaximizationControl - commodity_sell_price: 0.06 # $/kWh default; overridden in run script + commodity_sell_price: profast_npv # name of finance group whose commodity_sell_price to use solver_name: gauss_seidel max_iter: 20 +finance_parameters: + finance_groups: + profast_npv: + finance_model: ProFastNPV + model_inputs: + commodity_sell_price: 0.06 + 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.] + finance_subgroups: + electricity: + commodity: electricity + commodity_stream: fin_combiner + finance_groups: [profast_npv] + technologies: [wind, natural_gas_plant, ng_feedstock, battery] + cost_adjustment_parameters: + cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year + target_dollar_year: 2022 diff --git a/examples/35_system_level_control/profit_maximization/run_profit_max.py b/examples/35_system_level_control/profit_maximization/run_profit_max.py index 77e404933..2ac05f67a 100644 --- a/examples/35_system_level_control/profit_maximization/run_profit_max.py +++ b/examples/35_system_level_control/profit_maximization/run_profit_max.py @@ -1,10 +1,5 @@ """ -Profit-maximization example with diurnal electricity sell prices. - -The NG plant has a fixed marginal cost of $0.05/kWh. The electricity sell -price follows a diurnal pattern that swings above and below this cost: - - Night (22:00-16:00): $0.03/kWh, NG is unprofitable, not dispatched - - Peak (16:00-22:00): $0.08/kWh, NG is profitable, dispatched +Profit-maximization example with simple electricity price profiles. The controller dispatches the NG plant only during hours when the sell price exceeds the marginal cost, demonstrating profit-driven curtailment of @@ -17,29 +12,12 @@ from h2integrate.core.h2integrate_model import H2IntegrateModel -# -- Build diurnal sell-price profile ($/kWh) -- -n_timesteps = 8760 -sell_price = np.zeros(n_timesteps) -for h in range(n_timesteps): - hour_of_day = h % 24 - if 16 <= hour_of_day < 22: - sell_price[h] = 0.08 # peak - else: - sell_price[h] = 0.03 # night (cheap) - # -- Create and run model -- h2i = H2IntegrateModel("wind_ng_demand.yaml") # Setup first so we can set values h2i.setup() -# Override the sell price with our diurnal profile -h2i.prob.set_val( - "plant.system_level_controller.commodity_sell_price", - sell_price, - units="USD/(kW*h)", -) - h2i.run() h2i.post_process() @@ -53,7 +31,7 @@ batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] demand = h2i.prob.get_val("plant.electrical_load_demand.electricity_demand")[:n_hours] curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] -price = sell_price[:n_hours] +price = h2i.prob.get_val("system_level_controller.commodity_sell_price")[:n_hours] # -- Plot -- fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index a5561c7d0..164653d37 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -20,19 +20,49 @@ class ProfitMaximizationControl(SystemLevelControlBase): Configuration: ``plant_config["system_level_control"]["commodity_sell_price"]`` - must be set ($/(commodity_rate_unit*h), e.g. $/kWh). + must be set as either a numeric value ($/(commodity_rate_unit*h), + e.g. $/kWh) or the name of a finance group (e.g. ``"profast_npv"``) + whose ``model_inputs.commodity_sell_price`` will be used. Each dispatchable technology must have a ``marginal_cost`` input representing its variable cost per unit of production. """ + def _resolve_sell_price(self, slc_config): + """Resolve commodity_sell_price from config. + + If the value is a string, look it up from + ``finance_parameters.finance_groups..model_inputs.commodity_sell_price``. + Otherwise return it as-is (numeric). + """ + raw = slc_config.get("commodity_sell_price", 0.0) + if isinstance(raw, str): + finance_groups = ( + self.options["plant_config"].get("finance_parameters", {}).get("finance_groups", {}) + ) + group = finance_groups.get(raw) + if group is None: + raise ValueError( + f"commodity_sell_price references finance group '{raw}', " + f"but it was not found in finance_parameters.finance_groups. " + f"Available groups: {list(finance_groups.keys())}" + ) + price = group.get("model_inputs", {}).get("commodity_sell_price", None) + if price is None: + raise ValueError( + f"Finance group '{raw}' does not contain " f"model_inputs.commodity_sell_price." + ) + return price + return raw + def setup(self): super().setup() slc_config = self.options["plant_config"]["system_level_control"] - # Commodity sell price — user-set in config, can be scalar or time-varying - default_sell_price = slc_config.get("commodity_sell_price", 0.0) + # Commodity sell price - user-set in config, can be scalar or time-varying + # Accepts a numeric value or the name of a finance group to look up + default_sell_price = self._resolve_sell_price(slc_config) self.add_input( "commodity_sell_price", val=default_sell_price, From 887873fe0a8ec52954b22375ed77457c892cbadc Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 5 May 2026 22:22:27 -0600 Subject: [PATCH 044/132] Fixed bad set-point behavior --- .../system_level/system_level_control_base.py | 53 ++++--------------- h2integrate/core/model_baseclasses.py | 4 +- 2 files changed, 13 insertions(+), 44 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 341719af5..499c1909e 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -49,11 +49,10 @@ def setup(self): ] # Input: demand profile (default value from config) - demand_profile = slc_config.get("demand_profile", 0.0) self.demand_input_name = f"{self.commodity}_demand" self.add_input( self.demand_input_name, - val=demand_profile, + val=10.0, shape=self.n_timesteps, units=self.commodity_units, desc=f"Demand profile of {self.commodity}", @@ -69,13 +68,11 @@ def setup(self): self.commodities_to_units = {self.commodity: self.commodity_units} self.commodities_to_ref_var = {} self._setup_tech_category("curtailable", self.curtailable_techs) - self._setup_tech_category( - "dispatchable", self.dispatchable_techs, demand_profile=demand_profile - ) + self._setup_tech_category("dispatchable", self.dispatchable_techs) self._setup_tech_category("storage", self.storage_techs) def _setup_commodity_for_given_units( - self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=0.0 + self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=1.0 ): """Adds inputs and outputs for a commodity when the units are known. The inputs and outputs that are added have the below naming convention: @@ -92,7 +89,7 @@ def _setup_commodity_for_given_units( add_in_name (bool, optional): If True, add the input for the in_name variable. Defaults to True. initial_set_point (float, optional): Add as the initial value for the - set_point variable. Defaults to 0.0. + set_point variable. Defaults to 1.0. Returns: tuple(str, str, str): tuple of in_name, set_point_name, and rated_name """ @@ -125,7 +122,7 @@ def _setup_commodity_for_given_units( return in_name, set_point_name, rated_name def _setup_commodity_for_copy_units( - self, tech_name, commodity, commodity_reference_var, add_in_name=True, initial_set_point=0.0 + self, tech_name, commodity, commodity_reference_var, add_in_name=True, initial_set_point=1.0 ): """Adds inputs and outputs for a commodity where the units are based on a reference input variable. The inputs and outputs that are added have the below @@ -143,7 +140,7 @@ def _setup_commodity_for_copy_units( add_in_name (bool, optional): If True, add the input for the in_name variable. Defaults to True. initial_set_point (float, optional): Add as the initial value for the - set_point variable. Defaults to 0.0. + set_point variable. Defaults to 1.0. Returns: tuple(str, str, str): tuple of in_name, set_point_name, and rated_name @@ -179,24 +176,17 @@ def _setup_commodity_for_copy_units( return in_name, set_point_name, rated_name - def _setup_tech_category(self, category, tech_list, demand_profile=None): + def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. This single method handles curtailable, dispatchable, and storage technologies. The logic is identical for all three categories — iterate over each technology's commodities and register the appropriate inputs (production output, rated capacity) and output - (control set-point) — with one difference: - - * **Curtailable / Storage** (``demand_profile is None``): - ``initial_set_point`` is ``0.0``. Curtailable techs are later - assigned set-points equal to their rated production; storage techs - get set-points computed at run-time in ``_dispatch_storage``. + (control set-point). - * **Dispatchable** (``demand_profile`` is provided): - ``initial_set_point`` is the demand evenly divided among the - dispatchable techs that produce the demanded commodity, giving - the solver a reasonable starting guess. + All initial set-points are ``0.0``; the solver converges from there + using the connected rated-production inputs at run time. After this method returns, four lists are stored on ``self`` under names produced by the *category* prefix: @@ -214,29 +204,8 @@ def _setup_tech_category(self, category, tech_list, demand_profile=None): or ``"storage"``. Used to name the attribute lists. tech_list (list[str]): Technology names belonging to this category (e.g. ``self.curtailable_techs``). - demand_profile (float | np.ndarray | None, optional): - Only relevant for **dispatchable** techs. When provided, the - demand is split equally among dispatchable techs that produce - the demanded commodity to set a non-zero ``initial_set_point``. - For curtailable and storage techs, leave as ``None`` (default). """ - # --- Compute initial_set_point -------------------------------- - # Dispatchable techs: split demand equally among those that produce - # the demanded commodity so the solver starts from a feasible guess. - # Curtailable and storage techs always start at 0. - if demand_profile is not None: - n_producing = len( - [t for t in tech_list if self.commodity in self._get_commodity_for_tech(t)] - ) - if n_producing > 0: - if np.isscalar(demand_profile): - initial_set_point = demand_profile / n_producing - else: - initial_set_point = np.array(demand_profile) / n_producing - else: - initial_set_point = 0.0 - else: - initial_set_point = 0.0 + initial_set_point = 1.0 # --- Initialize the four per-category bookkeeping lists ------- input_names = [] diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 3cbe96e18..0869dd4b5 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -103,14 +103,14 @@ def setup(self): if getattr(self, "_control_classifier", None) == "curtailable": self.add_input( f"{self.commodity}_set_point", - val=0.0, + val=1.0, shape=self.n_timesteps, units=self.commodity_rate_units, desc=f"Set point for {self.commodity} production (curtailment limit)", ) self.add_output( f"uncurtailed_{self.commodity}_out", - val=0.0, + val=1.0, shape=self.n_timesteps, units=self.commodity_rate_units, desc=f"Full (uncurtailed) {self.commodity} output", From 93a69c0fe70dc4836fff3baefbc129e937f9ab1c Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 5 May 2026 22:29:10 -0600 Subject: [PATCH 045/132] Uploading complex profit maximization --- .../complex_profit_max.yaml | 8 + .../complex_profit_max/driver_config.yaml | 4 + .../complex_profit_max/plant_config.yaml | 50 +++++ .../run_complex_profit_max.py | 197 ++++++++++++++++++ .../complex_profit_max/tech_config.yaml | 149 +++++++++++++ .../system_level/system_level_control_base.py | 2 +- 6 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 examples/35_system_level_control/complex_profit_max/complex_profit_max.yaml create mode 100644 examples/35_system_level_control/complex_profit_max/driver_config.yaml create mode 100644 examples/35_system_level_control/complex_profit_max/plant_config.yaml create mode 100644 examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py create mode 100644 examples/35_system_level_control/complex_profit_max/tech_config.yaml diff --git a/examples/35_system_level_control/complex_profit_max/complex_profit_max.yaml b/examples/35_system_level_control/complex_profit_max/complex_profit_max.yaml new file mode 100644 index 000000000..cd142e5eb --- /dev/null +++ b/examples/35_system_level_control/complex_profit_max/complex_profit_max.yaml @@ -0,0 +1,8 @@ +name: H2Integrate_config +system_summary: > + Complex profit-maximization example using wind, solar, battery storage, + natural gas, and grid electricity to meet a time-varying demand with + realistic wholesale electricity pricing. +driver_config: driver_config.yaml +plant_config: plant_config.yaml +technology_config: tech_config.yaml diff --git a/examples/35_system_level_control/complex_profit_max/driver_config.yaml b/examples/35_system_level_control/complex_profit_max/driver_config.yaml new file mode 100644 index 000000000..4cfa2fe2d --- /dev/null +++ b/examples/35_system_level_control/complex_profit_max/driver_config.yaml @@ -0,0 +1,4 @@ +name: driver_config +description: Complex profit-maximization dispatch with variable pricing and demand +general: + folder_output: outputs diff --git a/examples/35_system_level_control/complex_profit_max/plant_config.yaml b/examples/35_system_level_control/complex_profit_max/plant_config.yaml new file mode 100644 index 000000000..b9379f090 --- /dev/null +++ b/examples/35_system_level_control/complex_profit_max/plant_config.yaml @@ -0,0 +1,50 @@ +name: plant_config +description: > + Wind + solar + battery + NG + grid plant in west Texas with + profit-maximization system-level control. Demonstrates complex + multi-source dispatch with realistic pricing. +sites: + site: + latitude: 30.6617 + longitude: -101.7096 + resources: + wind_resource: + resource_model: WTKNLRDeveloperAPIWindResource + resource_parameters: + resource_year: 2013 + solar_resource: + resource_model: OpenMeteoHistoricalSolarResource + resource_parameters: + resource_year: 2013 +technology_interconnections: + # Combine wind and solar into a single renewable stream + - [wind, renewable_combiner, electricity, cable] + - [solar, renewable_combiner, electricity, cable] + # Renewables charge the battery + - [renewable_combiner, battery, electricity, cable] + # Everything feeds into the final combiner + - [renewable_combiner, fin_combiner, electricity, cable] + - [battery, fin_combiner, electricity, cable] + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + - [natural_gas_plant, fin_combiner, electricity, cable] + - [grid_buy, fin_combiner, electricity, cable] + # Final combiner delivers to demand + - [fin_combiner, electrical_load_demand, electricity, cable] +resource_to_tech_connections: + - [site.wind_resource, wind, wind_resource_data] + - [site.solar_resource, solar, solar_resource_data] +plant: + plant_life: 30 + simulation: + n_timesteps: 8760 + dt: 3600 +system_level_control: + control_strategy: ProfitMaximizationControl + control_parameters: + commodity_sell_price: 0.06 # $/kWh default; overridden in run script + cost_per_tech: + natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx + grid_buy: buy_price # use electricity_buy_price from cost config + solver_name: gauss_seidel + max_iter: 30 + convergence_tolerance: 1.0e-6 diff --git a/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py new file mode 100644 index 000000000..1ca78c9d8 --- /dev/null +++ b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py @@ -0,0 +1,197 @@ +""" +Complex profit-maximization example with wind, solar, battery, NG, and grid. + +This example demonstrates profit-driven dispatch with: + - Wind + solar (curtailable) combined into a single renewable stream + - Battery storage (200 MWh) for renewable energy shifting + - Natural gas turbine with marginal cost of $0.05/kWh (dispatchable) + - Grid buying with time-varying marginal cost (dispatchable) + - Non-constant demand (commercial load profile with seasonal variation) + - Realistic wholesale electricity sell prices (ERCOT-like diurnal + seasonal) + +The controller dispatches NG and grid only during hours when the sell price +exceeds each source's marginal cost, preferring the cheaper source first +(merit-order dispatch). Renewables run at full capacity (zero marginal cost) +and the battery shifts energy toward high-price hours. +""" + +import numpy as np +import matplotlib.pyplot as plt + +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +# --------------------------------------------------------------------------- +# Build realistic time-varying profiles +# --------------------------------------------------------------------------- +n_timesteps = 8760 +hours_of_day = np.tile(np.arange(24), 365) +day_of_year = np.repeat(np.arange(365), 24) + +# --- Non-constant demand (commercial/industrial load) --- +# Base: 50 MW, business-hours bump to ~80 MW, summer cooling adds ~20 MW +base_demand = 50_000 # kW +daytime_bump = np.where((hours_of_day >= 7) & (hours_of_day < 21), 30_000, 0) +# Seasonal factor: 1.0 in winter, peaks at 1.4 in summer (day ~172 = June 21) +seasonal_demand = 1.0 + 0.4 * np.sin(2 * np.pi * (day_of_year - 172) / 365) +demand_profile = (base_demand + daytime_bump) * seasonal_demand + +# --- Realistic ERCOT-like wholesale sell price ($/kWh) --- +sell_price = np.zeros(n_timesteps) +for h in range(n_timesteps): + hour = hours_of_day[h] + day = day_of_year[h // 24] if h // 24 < 365 else day_of_year[-1] + # Seasonal base: higher in summer + season = 1.0 + 0.35 * np.sin(2 * np.pi * (day - 172) / 365) + + # Diurnal wholesale price shape (duck curve) + if hour < 6: + price = 0.025 # overnight trough + elif hour < 10: + price = 0.025 + (hour - 6) * 0.008 # morning ramp + elif hour < 15: + price = 0.035 # midday dip (solar flood) + elif hour < 20: + price = 0.035 + (hour - 15) * 0.018 # evening ramp to peak + else: + price = 0.125 - (hour - 20) * 0.025 # evening decline + + sell_price[h] = price * season + +# Add summer evening price spikes (simulate heat-wave scarcity) +for h in range(n_timesteps): + day = day_of_year[h // 24] if h // 24 < 365 else day_of_year[-1] + hour = hours_of_day[h] + if 150 <= day <= 250 and 17 <= hour <= 20 and day % 5 == 0: + sell_price[h] = max(sell_price[h], 0.20) + +# --- Grid buy marginal cost: tracks wholesale price + retail markup --- +grid_buy_price = sell_price + 0.02 # grid is always more expensive than selling + +# --------------------------------------------------------------------------- +# Create and run model +# --------------------------------------------------------------------------- +h2i = H2IntegrateModel("complex_profit_max.yaml") +h2i.setup() + +# Override demand profile +h2i.prob.set_val( + "plant.electrical_load_demand.electricity_demand", + demand_profile, +) + +# Override sell price with time-varying profile +h2i.prob.set_val( + "plant.system_level_controller.commodity_sell_price", + sell_price, + units="USD/(kW*h)", +) + +# Override grid buy price with time-varying profile +h2i.prob.set_val( + "plant.grid_buy.electricity_buy_price", + grid_buy_price, + units="USD/(kW*h)", +) + +h2i.run() +h2i.post_process() + +# --------------------------------------------------------------------------- +# Extract results +# --------------------------------------------------------------------------- +n_hours = 336 # two weeks for clearer patterns +hours = np.arange(n_hours) + +wind_out = h2i.prob.get_val("plant.wind.electricity_out")[:n_hours] +solar_out = h2i.prob.get_val("plant.solar.electricity_out")[:n_hours] +ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] +grid_out = h2i.prob.get_val("plant.grid_buy.electricity_out")[:n_hours] +batt_discharge = h2i.prob.get_val("plant.battery.storage_electricity_discharge")[:n_hours] +batt_soc = h2i.prob.get_val("plant.battery.SOC")[:n_hours] +demand = demand_profile[:n_hours] +price = sell_price[:n_hours] + +# --------------------------------------------------------------------------- +# Plot +# --------------------------------------------------------------------------- +fig, axes = plt.subplots(5, 1, figsize=(16, 16), sharex=True) + +# Panel 1: stacked supply vs demand +axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") +axes[0].fill_between( + hours, + wind_out, + wind_out + solar_out, + alpha=0.7, + color="gold", + label="Solar", +) +axes[0].fill_between( + hours, + wind_out + solar_out, + wind_out + solar_out + batt_discharge, + alpha=0.7, + color="tab:purple", + label="Battery", +) +axes[0].fill_between( + hours, + wind_out + solar_out + batt_discharge, + wind_out + solar_out + batt_discharge + ng_out, + alpha=0.7, + color="tab:orange", + label="Natural Gas", +) +axes[0].fill_between( + hours, + wind_out + solar_out + batt_discharge + ng_out, + wind_out + solar_out + batt_discharge + ng_out + grid_out, + alpha=0.7, + color="tab:gray", + label="Grid Buy", +) +axes[0].plot(hours, demand, "k--", linewidth=1.5, label="Demand") +axes[0].set_ylabel("Power (kW)") +axes[0].set_title("Complex Profit Maximization: First Two Weeks") +axes[0].legend(loc="upper right", ncol=3) + +# Panel 2: battery state of charge +axes[1].plot(hours, batt_soc, color="tab:green") +axes[1].set_ylabel("SOC (kWh)") +axes[1].set_title("Battery State of Charge") + +# Panel 3: sell price vs marginal costs +axes[2].plot(hours, price * 100, color="tab:red", linewidth=0.8, label="Sell Price") +axes[2].axhline( + y=5.0, color="tab:orange", linestyle="--", alpha=0.8, label="NG Marginal Cost (5 ¢/kWh)" +) +axes[2].plot( + hours, (price + 0.02) * 100, color="tab:gray", linewidth=0.6, alpha=0.7, label="Grid Buy Cost" +) +axes[2].set_ylabel("Price (¢/kWh)") +axes[2].set_title("Electricity Prices vs Dispatch Costs") +axes[2].legend(loc="upper right") + +# Panel 4: individual dispatch decisions +axes[3].plot(hours, ng_out / 1000, color="tab:orange", label="NG (MW)") +axes[3].plot(hours, grid_out / 1000, color="tab:gray", label="Grid Buy (MW)") +axes[3].set_ylabel("Power (MW)") +axes[3].set_title("Dispatchable Generation Decisions") +axes[3].legend(loc="upper right") + +# Panel 5: renewable generation +axes[4].plot(hours, wind_out / 1000, color="tab:blue", label="Wind (MW)") +axes[4].plot(hours, solar_out / 1000, color="gold", label="Solar (MW)") +axes[4].set_ylabel("Power (MW)") +axes[4].set_xlabel("Hour") +axes[4].set_title("Curtailable Renewable Generation") +axes[4].legend(loc="upper right") + +for ax in axes: + ax.grid(True, alpha=0.3) + +plt.tight_layout() +plt.savefig("complex_profit_max_results.png", dpi=150) +print("Plot saved to complex_profit_max_results.png") +# plt.show() diff --git a/examples/35_system_level_control/complex_profit_max/tech_config.yaml b/examples/35_system_level_control/complex_profit_max/tech_config.yaml new file mode 100644 index 000000000..56879ab71 --- /dev/null +++ b/examples/35_system_level_control/complex_profit_max/tech_config.yaml @@ -0,0 +1,149 @@ +name: technology_config +description: > + Wind + solar + battery + NG + grid with marginal costs for + profit-maximization dispatch. Non-constant demand and realistic + grid pricing create a challenging dispatch optimization problem. +technologies: + wind: + performance_model: + model: PYSAMWindPlantPerformanceModel + cost_model: + model: ATBWindPlantCostModel + model_inputs: + performance_parameters: + num_turbines: 20 + turbine_rating_kw: 6000 + hub_height: 115 + rotor_diameter: 170 + create_model_from: default + config_name: WindPowerSingleOwner + pysam_options: + Farm: + wind_farm_wake_model: 0 + Losses: + ops_strategies_loss: 10.0 + layout: + layout_mode: basicgrid + layout_options: + row_D_spacing: 5.0 + turbine_D_spacing: 5.0 + rotation_angle_deg: 0.0 + row_phase_offset: 0.0 + layout_shape: square + cost_parameters: + capex_per_kW: 1300 + opex_per_kW_per_year: 39 + cost_year: 2022 + solar: + performance_model: + model: PYSAMSolarPlantPerformanceModel + cost_model: + model: ATBUtilityPVCostModel + model_inputs: + performance_parameters: + pv_capacity_kWdc: 100000 # 100 MWdc + dc_ac_ratio: 1.3 + create_model_from: default + config_name: PVWattsSingleOwner + tilt_angle_func: lat-func + pysam_options: + SystemDesign: + inv_eff: 96.0 + module_type: 0 + losses: 14.08 + Lifetime: + dc_degradation: [0] + cost_parameters: + capex_per_kWac: 900 + opex_per_kWac_per_year: 15 + cost_year: 2024 + ng_feedstock: + performance_model: + model: FeedstockPerformanceModel + cost_model: + model: FeedstockCostModel + model_inputs: + shared_parameters: + commodity: natural_gas + commodity_rate_units: MMBtu/h + performance_parameters: + rated_capacity: 750. + cost_parameters: + cost_year: 2023 + price: 4.2 + annual_cost: 0. + start_up_cost: 0. + natural_gas_plant: + performance_model: + model: NaturalGasPerformanceModel + cost_model: + model: NaturalGasCostModel + model_inputs: + shared_parameters: + heat_rate_mmbtu_per_mwh: 7.5 + system_capacity_mw: 100. + cost_parameters: + capex_per_kw: 1000 + fixed_opex_per_kw_per_year: 10.0 + variable_opex_per_mwh: 0.0 + cost_year: 2023 + grid_buy: + performance_model: + model: GridPerformanceModel + cost_model: + model: GridCostModel + model_inputs: + shared_parameters: + interconnection_size: 200000. # 200 MW interconnection limit + cost_parameters: + cost_year: 2024 + electricity_buy_price: 0.06 # $/kWh default; overridden in run script + interconnection_capex_per_kw: 0.0 + interconnection_opex_per_kw: 0.0 + fixed_interconnection_cost: 0.0 + electrical_load_demand: + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 80000 # 80 MW default; overridden in run script + battery: + performance_model: + model: StoragePerformanceModel + cost_model: + model: GenericStorageCostModel + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 50000 # 50 MW charge rate + max_capacity: 200000 # 200 MWh capacity + init_soc_fraction: 0.5 + max_soc_fraction: 1.0 + min_soc_fraction: 0.1 + performance_parameters: + round_trip_efficiency: 0.90 + demand_profile: 50000 + cost_parameters: + cost_year: 2024 + capacity_capex: 280 + charge_capex: 300 + opex_fraction: 0.025 + renewable_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 2 + fin_combiner: + performance_model: + model: GenericCombinerPerformanceModel + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + in_streams: 4 diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 499c1909e..59ff62a3c 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -185,7 +185,7 @@ def _setup_tech_category(self, category, tech_list): appropriate inputs (production output, rated capacity) and output (control set-point). - All initial set-points are ``0.0``; the solver converges from there + All initial set-points are ``1.0``; the solver converges from there using the connected rated-production inputs at run time. After this method returns, four lists are stored on ``self`` under From e4a94bd8f11045394ef0bae030b617c982e346e9 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 6 May 2026 09:42:20 -0600 Subject: [PATCH 046/132] tried to add helper methods to slc baseclass --- .../system_level/system_level_control_base.py | 97 +++++++++++++++++++ h2integrate/core/h2integrate_model.py | 2 +- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 17d2f6aff..508a4f4e1 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -1,4 +1,5 @@ import numpy as np +import networkx as nx import openmdao.api as om @@ -51,6 +52,10 @@ def setup(self): k for k, v in slc_config["tech_control_classifiers"].items() if v == "storage" ] + self.input_techs = set( + self.curtailable_techs + self.dispatchable_techs + self.storage_techs + ) + # Input: demand profile (default value from config) demand_profile = slc_config.get("demand_profile", 0.0) self.demand_input_name = f"{self.commodity}_demand" @@ -396,3 +401,95 @@ def _get_commodity_for_tech(self, tech_name): tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] return tech_commodities + + def get_upstream_techs_for_commodity(self, tech_name: str, commodity: str): + """Get the name of technologies that are upstream + of `tech_name` and that output `commodity` + + Args: + tech_name (str): name of technology + commodity (str): commodity name + + Returns: + list[str]: list of technologies upstream of the tech_name that produce a given commodity + """ + # figure out where the upstream commodity is coming from + upstream_components = nx.ancestors(self.technology_graph, tech_name) + # iterates through a list of 3 length tuples (source, dest, commodity) + upstream_components_shared_commodity = [ + s[0] + for s in list(self.technology_graph.edges(data="commodity")) + if s[0] in upstream_components and s[2] == commodity + ] + # get the technologies that are available to the controller + upstream_techs = set(upstream_components_shared_commodity).intersection( + set(self.input_techs) + ) + return list(upstream_techs) + + def find_converter_techs(self): + """Get the name of the technology that transforms a commodity + + Returns: + set(tuple): set of converter technologies formatted as + (input_commodity, converter tech name, output_commodity) + """ + if not self.multi_commodity_system: + return + + converter_techs = set() + + edges = list(self.technology_graph.edges(data="commodity")) + upstream_converter = None + # for tech in self.input_techs: + for edge in edges: + tech, dest_tech, cmod = edge + if tech in self.input_techs: + tech_output_commodity = self._get_commodity_for_tech(tech) + + # NOTE: unsure how this would work for systems with tiered converters + # aka - maybe have to eliminate a converter once we've discovered it + if upstream_converter is None: + upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( + set(self.input_techs) + ) + else: + idx_upstream_converter = [ + i + for i, n in enumerate(self.technology_graph.__iter__()) + if n == upstream_converter + ] + downstream_of_previous_converter = [ + n + for i, n in enumerate(self.technology_graph.__iter__()) + if i > idx_upstream_converter + ] + all_upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( + set(self.input_techs) + ) + upstream_techs = all_upstream_techs.intersection( + set(downstream_of_previous_converter) + ) + + connected_upstream_techs = [ + t for t in upstream_techs if nx.has_path(self.technology_graph, t, tech) + ] + upstream_commodities = [ + self._get_commodity_for_tech(t) for t in connected_upstream_techs + ] + # symmetric difference + # commodities that are not in both + input_output_commodity = set(upstream_commodities) ^ set(tech_output_commodity) + if len(input_output_commodity) > 1: + input_commodity = list( + input_output_commodity.intersection(set(upstream_commodities)) + ) + output_commodity = list( + input_output_commodity.intersection(set(tech_output_commodity)) + ) + + # formatted as (input commodity, tech_name, output comodity) + converter_techs.add((input_commodity, tech, output_commodity)) + upstream_converter = tech + + return converter_techs diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index c1e1503a6..9c83a16b0 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -652,7 +652,7 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) - if slc_config["storage_techs_to_control"][tech_name]: + if slc_config["storage_techs_to_control"].get(tech_name, False): # storage has its own controller # provide demand to storage controller, # storage controller will provide set-point to performance model From 9a5cfdc1dfa7084a2ed23f1fc6b6379c745738b7 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 6 May 2026 09:49:04 -0600 Subject: [PATCH 047/132] added marginal cost to cost models that dont inherit costmodelbaseconfig --- h2integrate/converters/hopp/hopp_wrapper.py | 1 + h2integrate/converters/iron/iron_transport.py | 1 + h2integrate/core/model_baseclasses.py | 1 + h2integrate/storage/hydrogen/h2_storage_cost.py | 1 + h2integrate/storage/hydrogen/mch_storage.py | 1 + 5 files changed, 5 insertions(+) diff --git a/h2integrate/converters/hopp/hopp_wrapper.py b/h2integrate/converters/hopp/hopp_wrapper.py index 06579c601..b4fd4c33e 100644 --- a/h2integrate/converters/hopp/hopp_wrapper.py +++ b/h2integrate/converters/hopp/hopp_wrapper.py @@ -16,6 +16,7 @@ class HOPPComponentModelConfig(CacheBaseConfig): hopp_config: dict = field() cost_year: int = field(converter=int) electrolyzer_rating: int | float | None = field(default=None) + marginal_cost: float = field(default=0.0) class HOPPComponent(PerformanceModelBaseClass, CacheBaseClass): diff --git a/h2integrate/converters/iron/iron_transport.py b/h2integrate/converters/iron/iron_transport.py index 93223b453..ff823ecfa 100644 --- a/h2integrate/converters/iron/iron_transport.py +++ b/h2integrate/converters/iron/iron_transport.py @@ -165,6 +165,7 @@ def compute(self, inputs, outputs): class IronTransportCostConfig(BaseConfig): transport_year: int = field(converter=int, validator=range_val(2022, 2065)) cost_year: int = field(converter=int, validator=range_val(2010, 2024)) + marginal_cost: float = field(default=0.0) class IronTransportCostComponent(CostModelBaseClass): diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 0869dd4b5..00a374166 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -199,6 +199,7 @@ def setup(self): model_inputs = self.options["tech_config"].get("model_inputs", {}) shared = model_inputs.get("shared_parameters", {}) commodity_rate_units = shared.get("commodity_rate_units", "kW") + self.add_output( "marginal_cost", val=self.config.marginal_cost, diff --git a/h2integrate/storage/hydrogen/h2_storage_cost.py b/h2integrate/storage/hydrogen/h2_storage_cost.py index bbc29c796..9868797b3 100644 --- a/h2integrate/storage/hydrogen/h2_storage_cost.py +++ b/h2integrate/storage/hydrogen/h2_storage_cost.py @@ -51,6 +51,7 @@ class HydrogenStorageBaseCostModelConfig(BaseConfig): storage_pressure_bar: float = field(default=200, validator=range_val(0, 700)) cg_capex_per_kg_350_bar: float = field(default=1333.11625, validator=gte_zero) cg_capex_per_kg_700_bar: float = field(default=1999.67437, validator=gte_zero) + marginal_cost: float = field(default=0.0) def __attrs_post_init__(self): undefined_capacities = self.max_capacity is None or self.max_charge_rate is None diff --git a/h2integrate/storage/hydrogen/mch_storage.py b/h2integrate/storage/hydrogen/mch_storage.py index 4888519c4..7d6ae90af 100644 --- a/h2integrate/storage/hydrogen/mch_storage.py +++ b/h2integrate/storage/hydrogen/mch_storage.py @@ -24,6 +24,7 @@ class MCHTOLStorageCostModelConfig(BaseConfig): commodity_units: str = field(default="kg/h", validator=contains(["kg/h", "g/h", "t/h"])) cost_year: int = field(default=2024, converter=int, validator=contains([2024])) + marginal_cost: float = field(default=0.0) def __attrs_post_init__(self): if self.charge_equals_discharge: From afb0af383fcdd2348160aa8ed81553de9913e53d Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 6 May 2026 14:33:07 -0600 Subject: [PATCH 048/132] updated cost model baseclass handling of marginal cost --- h2integrate/core/model_baseclasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 00a374166..eafbd254a 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -202,7 +202,7 @@ def setup(self): self.add_output( "marginal_cost", - val=self.config.marginal_cost, + val=getattr(self.config, "marginal_cost", 0.0), units=f"USD/({commodity_rate_units}*h)", desc="Marginal cost of production for dispatch decisions", ) From a6a841d431962abdb6719b7be27de9f8bf88303e Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 6 May 2026 14:45:45 -0600 Subject: [PATCH 049/132] updated so that demand is properly output from slc for storage controllers --- .../battery_with_controller/tech_config.yaml | 7 +++++-- .../system_level/system_level_control_base.py | 11 +++++++++-- .../system_level/test/test_slc_examples.py | 8 ++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/examples/35_system_level_control/battery_with_controller/tech_config.yaml b/examples/35_system_level_control/battery_with_controller/tech_config.yaml index c5ca7a20f..21075c502 100644 --- a/examples/35_system_level_control/battery_with_controller/tech_config.yaml +++ b/examples/35_system_level_control/battery_with_controller/tech_config.yaml @@ -76,19 +76,22 @@ technologies: cost_model: model: GenericStorageCostModel control_strategy: - model: DemandOpenLoopStorageController + model: SimpleStorageOpenLoopController model_inputs: shared_parameters: commodity: electricity commodity_rate_units: kW + demand_profile: 20000 # kW, required by storage base config max_charge_rate: 20000 # kW (20 MW) max_capacity: 80000 # kWh (80 MWh, 4-hour duration) + performance_parameters: init_soc_fraction: 0.5 max_soc_fraction: 1.0 min_soc_fraction: 0.1 # performance_parameters: round_trip_efficiency: 0.90 - demand_profile: 20000 # kW, required by storage base config + control_parameters: + set_demand_as_avg_commodity_in: false cost_parameters: cost_year: 2022 capacity_capex: 310 # $/kWh diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 508a4f4e1..96461683e 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -374,8 +374,15 @@ def _dispatch_storage(self, inputs, outputs, demand): if commodity == self.commodity: if f"_{commodity}_demand" in set_point_name: # storage tech has a controller, output combined demand (always positive) - # TODO: update to output whatever is input to storage + storage_share - outputs[set_point_name] = np.clip(storage_share, a_min=0.0, a_max=None) + # demand should be what is input to storage + storage_share + storage_tech_name = set_point_name.split(f"_{commodity}_demand")[0] + upstream_techs = self.get_upstream_techs_for_commodity( + storage_tech_name, commodity + ) + commodity_into_storage = np.zeros(self.n_timesteps) + for tech_name in upstream_techs: + commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] + outputs[set_point_name] = commodity_into_storage + storage_share else: # storage tech does not have a controller, # output set point (charge/discharge) command diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index e973163d8..8e0d5222b 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -116,3 +116,11 @@ def test_slc_battery_with_controller(subtests, temp_copy_of_example): with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 + with subtests.test("lcoe"): + assert ( + pytest.approx( + model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), + rel=1e-6, + ) + == 0.10902004 + ) From 9984c704e2f3ad6af8330a2fba9c92489821df21 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 6 May 2026 15:50:05 -0600 Subject: [PATCH 050/132] fixed example 33 --- examples/33_peak_load_management/plant_config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/33_peak_load_management/plant_config.yaml b/examples/33_peak_load_management/plant_config.yaml index afcf590de..93be1cecf 100644 --- a/examples/33_peak_load_management/plant_config.yaml +++ b/examples/33_peak_load_management/plant_config.yaml @@ -8,6 +8,7 @@ plant: timezone: -6 start_time: 2025/07/01 00:00:00 technology_interconnections: + - [grid_buy, battery, electricity, cable] # include battery charge/discharge in the load - [battery, electrical_load_demand, [electricity_out, electricity_in]] # buy power from the grid to fulfill demand including to accommodate battery operation From fb219d515f6f01c09b5f58b0fcd5b7d0a0ee28d6 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 6 May 2026 16:29:20 -0600 Subject: [PATCH 051/132] Minor typographical changes --- .../battery_with_controller/driver_config.yaml | 2 +- .../system_level/system_level_control_base.py | 3 --- .../control_strategies/system_level/test/test_slc_examples.py | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/35_system_level_control/battery_with_controller/driver_config.yaml b/examples/35_system_level_control/battery_with_controller/driver_config.yaml index 5b6b7e05a..74ae9ca19 100644 --- a/examples/35_system_level_control/battery_with_controller/driver_config.yaml +++ b/examples/35_system_level_control/battery_with_controller/driver_config.yaml @@ -1,4 +1,4 @@ name: driver_config -description: This analysis runs a natural gas power plant +description: This analysis runs a battery with a simple controller general: folder_output: outputs diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 9df37cdbc..83d34bcb7 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -79,9 +79,6 @@ def setup(self): self._setup_tech_category("dispatchable", self.dispatchable_techs) self._setup_tech_category("storage", self.storage_techs) - # def _get_upstream_techs(self, inputs, tech_name): - # tech_commodities = self._get_commodity_for_tech(tech_name) - def _setup_commodity_for_given_units( self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=1.0 ): diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 8e0d5222b..4e23a67d6 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -105,7 +105,6 @@ def test_slc_yes_hydrogen(subtests, temp_copy_of_example): [("35_system_level_control/battery_with_controller", None)], ) def test_slc_battery_with_controller(subtests, temp_copy_of_example): - # TODO: this test still needs to be completed! example_folder = temp_copy_of_example model = H2IntegrateModel(example_folder / "wind_ng_demand.yaml") From f2e023b1b45d405936a9dadd217601cd213fb075 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 6 May 2026 22:38:37 -0600 Subject: [PATCH 052/132] Added control classifiers to all technologies --- h2integrate/converters/ammonia/simple_ammonia_model.py | 1 + h2integrate/converters/co2/marine/direct_ocean_capture.py | 1 + .../converters/co2/marine/ocean_alkalinity_enhancement.py | 1 + h2integrate/converters/hopp/hopp_wrapper.py | 1 + h2integrate/converters/hydrogen/electrolyzer_baseclass.py | 1 + .../hydrogen/geologic/h2_well_subsurface_baseclass.py | 2 ++ .../converters/hydrogen/geologic/h2_well_surface_baseclass.py | 2 ++ h2integrate/converters/hydrogen/h2_fuel_cell.py | 1 + h2integrate/converters/hydrogen/steam_methane_reformer.py | 1 + h2integrate/converters/iron/humbert_ewin_perf.py | 1 + h2integrate/converters/iron/iron_dri_base.py | 1 + h2integrate/converters/iron/martin_mine_perf_model.py | 1 + h2integrate/converters/methanol/methanol_baseclass.py | 1 + h2integrate/converters/natural_gas/dummy_gas_components.py | 2 ++ h2integrate/converters/nitrogen/simple_ASU.py | 1 + h2integrate/converters/nuclear/nuclear_plant.py | 1 + h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py | 1 + h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py | 1 + h2integrate/converters/steel/steel_baseclass.py | 1 + h2integrate/converters/steel/steel_eaf_base.py | 1 + h2integrate/converters/water/desal/desalination_baseclass.py | 1 + h2integrate/converters/water_power/hydro_plant_run_of_river.py | 1 + h2integrate/converters/water_power/tidal_pysam.py | 1 + h2integrate/converters/wind/wind_plant_ard.py | 1 + h2integrate/demand/demand_base.py | 1 + 25 files changed, 28 insertions(+) diff --git a/h2integrate/converters/ammonia/simple_ammonia_model.py b/h2integrate/converters/ammonia/simple_ammonia_model.py index 527e2333b..79e8e2adc 100644 --- a/h2integrate/converters/ammonia/simple_ammonia_model.py +++ b/h2integrate/converters/ammonia/simple_ammonia_model.py @@ -34,6 +34,7 @@ class SimpleAmmoniaPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/co2/marine/direct_ocean_capture.py b/h2integrate/converters/co2/marine/direct_ocean_capture.py index 0702aab32..7f72eae12 100644 --- a/h2integrate/converters/co2/marine/direct_ocean_capture.py +++ b/h2integrate/converters/co2/marine/direct_ocean_capture.py @@ -80,6 +80,7 @@ class DOCPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/co2/marine/ocean_alkalinity_enhancement.py b/h2integrate/converters/co2/marine/ocean_alkalinity_enhancement.py index 96995c8f5..6089c0658 100644 --- a/h2integrate/converters/co2/marine/ocean_alkalinity_enhancement.py +++ b/h2integrate/converters/co2/marine/ocean_alkalinity_enhancement.py @@ -73,6 +73,7 @@ class OAEPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hopp/hopp_wrapper.py b/h2integrate/converters/hopp/hopp_wrapper.py index b4fd4c33e..d801acc7e 100644 --- a/h2integrate/converters/hopp/hopp_wrapper.py +++ b/h2integrate/converters/hopp/hopp_wrapper.py @@ -33,6 +33,7 @@ class HOPPComponent(PerformanceModelBaseClass, CacheBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index c0934a013..3c3221947 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -9,6 +9,7 @@ class ElectrolyzerPerformanceBaseClass(ResizeablePerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py b/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py index fc3c24fea..11b44189a 100644 --- a/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py +++ b/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py @@ -46,6 +46,8 @@ class GeoH2SubsurfacePerformanceConfig(BaseConfig): class GeoH2SubsurfacePerformanceBaseClass(PerformanceModelBaseClass): + _control_classifier = "curtailable" + """OpenMDAO component for modeling the performance of the well subsurface for geologic hydrogen. diff --git a/h2integrate/converters/hydrogen/geologic/h2_well_surface_baseclass.py b/h2integrate/converters/hydrogen/geologic/h2_well_surface_baseclass.py index e9107249c..84edafcc8 100644 --- a/h2integrate/converters/hydrogen/geologic/h2_well_surface_baseclass.py +++ b/h2integrate/converters/hydrogen/geologic/h2_well_surface_baseclass.py @@ -28,6 +28,8 @@ class GeoH2SurfacePerformanceConfig(BaseConfig): class GeoH2SurfacePerformanceBaseClass(PerformanceModelBaseClass): + _control_classifier = "dispatchable" + """OpenMDAO component for modeling the performance of the wellhead surface processing for geologic hydrogen. diff --git a/h2integrate/converters/hydrogen/h2_fuel_cell.py b/h2integrate/converters/hydrogen/h2_fuel_cell.py index c0fe905f1..36d2c1a76 100644 --- a/h2integrate/converters/hydrogen/h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/h2_fuel_cell.py @@ -42,6 +42,7 @@ class LinearH2FuelCellPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hydrogen/steam_methane_reformer.py b/h2integrate/converters/hydrogen/steam_methane_reformer.py index d82d585c8..b469cbd8a 100644 --- a/h2integrate/converters/hydrogen/steam_methane_reformer.py +++ b/h2integrate/converters/hydrogen/steam_methane_reformer.py @@ -48,6 +48,7 @@ class SteamMethaneReformerPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/iron/humbert_ewin_perf.py b/h2integrate/converters/iron/humbert_ewin_perf.py index 1fc65f46d..0d87433ee 100644 --- a/h2integrate/converters/iron/humbert_ewin_perf.py +++ b/h2integrate/converters/iron/humbert_ewin_perf.py @@ -79,6 +79,7 @@ class HumbertEwinPerformanceComponent(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): self.commodity = "sponge_iron" diff --git a/h2integrate/converters/iron/iron_dri_base.py b/h2integrate/converters/iron/iron_dri_base.py index 3b4e9efba..b9ac1348b 100644 --- a/h2integrate/converters/iron/iron_dri_base.py +++ b/h2integrate/converters/iron/iron_dri_base.py @@ -34,6 +34,7 @@ class IronReductionPlantBasePerformanceComponent(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/iron/martin_mine_perf_model.py b/h2integrate/converters/iron/martin_mine_perf_model.py index 8c77d0777..b5084de4a 100644 --- a/h2integrate/converters/iron/martin_mine_perf_model.py +++ b/h2integrate/converters/iron/martin_mine_perf_model.py @@ -35,6 +35,7 @@ class MartinIronMinePerformanceComponent(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/methanol/methanol_baseclass.py b/h2integrate/converters/methanol/methanol_baseclass.py index 1d918303d..b860c99de 100644 --- a/h2integrate/converters/methanol/methanol_baseclass.py +++ b/h2integrate/converters/methanol/methanol_baseclass.py @@ -38,6 +38,7 @@ class MethanolPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/natural_gas/dummy_gas_components.py b/h2integrate/converters/natural_gas/dummy_gas_components.py index 96525ff5f..f35537b74 100644 --- a/h2integrate/converters/natural_gas/dummy_gas_components.py +++ b/h2integrate/converters/natural_gas/dummy_gas_components.py @@ -65,6 +65,7 @@ class SimpleGasProducerPerformance(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() @@ -148,6 +149,7 @@ class SimpleGasConsumerPerformance(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/nitrogen/simple_ASU.py b/h2integrate/converters/nitrogen/simple_ASU.py index 12ef88b48..da4762517 100644 --- a/h2integrate/converters/nitrogen/simple_ASU.py +++ b/h2integrate/converters/nitrogen/simple_ASU.py @@ -69,6 +69,7 @@ class SimpleASUPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/nuclear/nuclear_plant.py b/h2integrate/converters/nuclear/nuclear_plant.py index fc9a7e3f1..d8a86ec29 100644 --- a/h2integrate/converters/nuclear/nuclear_plant.py +++ b/h2integrate/converters/nuclear/nuclear_plant.py @@ -37,6 +37,7 @@ class QuinnNuclearPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py index ff9eb0461..073171d52 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py @@ -143,6 +143,7 @@ class CMUElectricArcFurnaceDRIPerformanceComponent(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py index 00dfa74d6..492babb34 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py @@ -105,6 +105,7 @@ class CMUElectricArcFurnaceScrapOnlyPerformanceComponent(PerformanceModelBaseCla 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/steel/steel_baseclass.py b/h2integrate/converters/steel/steel_baseclass.py index 24eb57f5c..121ac3087 100644 --- a/h2integrate/converters/steel/steel_baseclass.py +++ b/h2integrate/converters/steel/steel_baseclass.py @@ -6,6 +6,7 @@ class SteelPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/steel/steel_eaf_base.py b/h2integrate/converters/steel/steel_eaf_base.py index a73c3863e..8fdd9e131 100644 --- a/h2integrate/converters/steel/steel_eaf_base.py +++ b/h2integrate/converters/steel/steel_eaf_base.py @@ -34,6 +34,7 @@ class ElectricArcFurnacePlantBasePerformanceComponent(PerformanceModelBaseClass) 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/water/desal/desalination_baseclass.py b/h2integrate/converters/water/desal/desalination_baseclass.py index fcabf728e..6b87e7c70 100644 --- a/h2integrate/converters/water/desal/desalination_baseclass.py +++ b/h2integrate/converters/water/desal/desalination_baseclass.py @@ -6,6 +6,7 @@ class DesalinationPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "dispatchable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/water_power/hydro_plant_run_of_river.py b/h2integrate/converters/water_power/hydro_plant_run_of_river.py index c00575901..108269067 100644 --- a/h2integrate/converters/water_power/hydro_plant_run_of_river.py +++ b/h2integrate/converters/water_power/hydro_plant_run_of_river.py @@ -40,6 +40,7 @@ class RunOfRiverHydroPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/water_power/tidal_pysam.py b/h2integrate/converters/water_power/tidal_pysam.py index f0e961175..6d65d8fc2 100644 --- a/h2integrate/converters/water_power/tidal_pysam.py +++ b/h2integrate/converters/water_power/tidal_pysam.py @@ -124,6 +124,7 @@ class PySAMTidalPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/converters/wind/wind_plant_ard.py b/h2integrate/converters/wind/wind_plant_ard.py index fedb9ab33..408fc4890 100644 --- a/h2integrate/converters/wind/wind_plant_ard.py +++ b/h2integrate/converters/wind/wind_plant_ard.py @@ -38,6 +38,7 @@ class WindArdPerformanceCompatibilityComponent(PerformanceModelBaseClass): """ _time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model + _control_classifier = "curtailable" def initialize(self): super().initialize() diff --git a/h2integrate/demand/demand_base.py b/h2integrate/demand/demand_base.py index 9417bdf83..1052471e4 100644 --- a/h2integrate/demand/demand_base.py +++ b/h2integrate/demand/demand_base.py @@ -44,6 +44,7 @@ class DemandComponentBase(PerformanceModelBaseClass): """ _time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model + _control_classifier = "dispatchable" def setup(self): """Define inputs and outputs for demand component. From a56a57fc7874b09d5f5679bbfbe35b1cc351fcd9 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 11:13:50 -0600 Subject: [PATCH 053/132] updated baseclass methods and demand following controller --- .../system_level/demand_following_control.py | 40 +++-- .../system_level/system_level_control_base.py | 148 +++++++++++------- 2 files changed, 123 insertions(+), 65 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 209a05312..09b7cb65d 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -21,13 +21,33 @@ def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() # 1. Curtailable techs: full production - demand = self._subtract_curtailable(inputs, outputs, demand) + for curtailable_tech in self.curtailable_techs: + commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) + # check that this tech produces the commodity demanded + if self.commodity in commodity_from_tech: + # if the commodity produced from a tech is the demanded commodity + # then subtract the curtailable production from the demand + demand = self._subtract_curtailable( + curtailable_tech, demand, self.commodity, inputs, outputs + ) # 2. Storage dispatch - demand = self._dispatch_storage(inputs, outputs, demand) + # number of storage components that produce the demanded commodity + n_storage = len( + [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + ) + for storage_tech in self.storage_techs: + commodity_from_tech = self._get_commodity_for_tech(storage_tech) + if self.commodity in commodity_from_tech: + demand = self._dispatch_storage( + storage_tech, demand / n_storage, self.commodity, inputs, outputs + ) # 3. Dispatchable techs: equal share of remaining demand remaining = np.maximum(demand, 0.0) + + # calculate the number of dispatchable technologies that + # produce the demanded commodity n_dispatchable = len( [ s @@ -35,16 +55,12 @@ def compute(self, inputs, outputs): if self.commodity in self._get_commodity_for_tech(s) ] ) - - # calculate the number of dispatchable technologies that - # produce the demanded commodity - if n_dispatchable > 0: - share = remaining / n_dispatchable - for set_point_name, commodity in zip( - self.dispatchable_set_point_names, self.dispatchable_commodity_names - ): - if commodity == self.commodity: - outputs[set_point_name] = share + for dispatchable_tech in self.dispatchable_techs: + commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) + if self.commodity in commodity_from_tech: + outputs[f"{dispatchable_tech}_{self.commodity}_set_point"] = ( + remaining / n_dispatchable + ) # Check for nans or inf if not all(np.isfinite(c).all() for k, c in outputs.items()): diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 83d34bcb7..185b661b0 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -302,65 +302,107 @@ def _setup_tech_category(self, category, tech_list): setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) - def _subtract_curtailable(self, inputs, outputs, demand): + def _subtract_curtailable(self, curtailable_tech, remaining_demand, commodity, inputs, outputs): """Apply curtailable techs: set_point = rated, subtract output from demand. Returns the updated demand array. """ - for in_name, set_point_name, rated_name, commodity in zip( - self.curtailable_input_names, - self.curtailable_set_point_names, - self.curtailable_rated_names, - self.curtailable_commodity_names, - ): - # Output the set-point as the rated production of that technology - outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) - if commodity == self.commodity: - demand -= inputs[in_name] - - return demand - - def _dispatch_storage(self, inputs, outputs, demand): - """Dispatch storage techs proportionally and subtract actual output from demand. - - Positive set_point = discharge, negative = charge. - Returns the updated demand array. - """ - # calculate the number of storage technologies that - # produce the demanded commodity - n_storage = len( - [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] - ) - if n_storage > 0: - # split the demand across the storage technologies - storage_share = demand / n_storage - for set_point_name, commodity in zip( - self.storage_set_point_names, self.storage_commodity_names - ): - if commodity == self.commodity: - if f"_{commodity}_demand" in set_point_name: - # storage tech has a controller, output combined demand (always positive) - # demand should be what is input to storage + storage_share - storage_tech_name = set_point_name.split(f"_{commodity}_demand")[0] - upstream_techs = self.get_upstream_techs_for_commodity( - storage_tech_name, commodity - ) - commodity_into_storage = np.zeros(self.n_timesteps) - for tech_name in upstream_techs: - commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] - outputs[set_point_name] = commodity_into_storage + storage_share - else: - # storage tech does not have a controller, - # output set point (charge/discharge) command - # charge when remaining demand is negative - # discharge when remaining demand is positive - outputs[set_point_name] = storage_share + if curtailable_tech not in self.curtailable_techs: + return - for tech_name, in_name in zip(self.storage_techs, self.storage_input_names): - if self.commodity in self._get_commodity_for_tech(tech_name): - demand -= inputs[in_name] + if f"{curtailable_tech}_rated_{commodity}_production" not in inputs: + return + + # Output the set-point as the rated production of that technology + outputs[f"{curtailable_tech}_{commodity}_set_point"] = inputs[ + f"{curtailable_tech}_rated_{commodity}_production" + ] * np.ones(self.n_timesteps) + remaining_demand -= inputs[f"{curtailable_tech}_{commodity}_out"] + + return remaining_demand + # for in_name, set_point_name, rated_name, commodity in zip( + # self.curtailable_input_names, + # self.curtailable_set_point_names, + # self.curtailable_rated_names, + # self.curtailable_commodity_names, + # ): + # # Output the set-point as the rated production of that technology + # outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) + # if commodity == self.commodity: + # demand -= inputs[in_name] + + # return demand + + def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, outputs): + if storage_tech not in self.storage_techs: + return - return demand + if f"{storage_tech}_{commodity}_out" not in inputs: + return + + if self.storage_techs_to_control.get(storage_tech, False): + # storage tech has a controller, output combined demand (always positive) + # demand should be what is input to storage + remaining_demand + # get the technologies upstream of the storage that output that commodity + upstream_techs = self.get_upstream_techs_for_commodity(storage_tech, commodity) + commodity_into_storage = np.zeros(self.n_timesteps) + for tech_name in upstream_techs: + commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] + + outputs[f"{storage_tech}_{commodity}_demand"] = ( + commodity_into_storage + remaining_demand + ) + remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] + return remaining_demand + + if f"{storage_tech}_{commodity}_set_point" in outputs: + # storage tech does not have a controller, output set point (charge/discharge) command + # charge when remaining demand is negative, discharge when remaining demand is positive + outputs[f"{storage_tech}_{commodity}_set_point"] = remaining_demand + remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] + return remaining_demand + + # def _dispatch_storage(self, inputs, outputs, demand): + # """Dispatch storage techs proportionally and subtract actual output from demand. + + # Positive set_point = discharge, negative = charge. + # Returns the updated demand array. + # """ + # # calculate the number of storage technologies that + # # produce the demanded commodity + # n_storage = len( + # [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + # ) + # if n_storage > 0: + # # split the demand across the storage technologies + # storage_share = demand / n_storage + # for set_point_name, commodity in zip( + # self.storage_set_point_names, self.storage_commodity_names + # ): + # if commodity == self.commodity: + # if f"_{commodity}_demand" in set_point_name: + # # storage tech has a controller, output combined demand (always positive) + # # demand should be what is input to storage + storage_share + # storage_tech_name = set_point_name.split(f"_{commodity}_demand")[0] + # upstream_techs = self.get_upstream_techs_for_commodity( + # storage_tech_name, commodity + # ) + # commodity_into_storage = np.zeros(self.n_timesteps) + # for tech_name in upstream_techs: + # commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] + # outputs[set_point_name] = commodity_into_storage + storage_share + # else: + # # storage tech does not have a controller, + # # output set point (charge/discharge) command + # # charge when remaining demand is negative + # # discharge when remaining demand is positive + # outputs[set_point_name] = storage_share + + # for tech_name, in_name in zip(self.storage_techs, self.storage_input_names): + # if self.commodity in self._get_commodity_for_tech(tech_name): + # demand -= inputs[in_name] + + # return demand def _get_commodity_for_tech(self, tech_name): """Get a list of the commodities produced for a technology. From 0f5e5e722f7ab401d8bb45c4b7c6eece4defe234 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 11:18:14 -0600 Subject: [PATCH 054/132] updated cost control strategies and cleaned up baseclass --- .../system_level/cost_minimization_control.py | 21 +++++++- .../profit_maximization_control.py | 21 +++++++- .../system_level/system_level_control_base.py | 54 ------------------- 3 files changed, 38 insertions(+), 58 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 3ba2d5366..96bc458b4 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -40,10 +40,27 @@ def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() # 1. Curtailable techs: full production - demand = self._subtract_curtailable(inputs, outputs, demand) + for curtailable_tech in self.curtailable_techs: + commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) + # check that this tech produces the commodity demanded + if self.commodity in commodity_from_tech: + # if the commodity produced from a tech is the demanded commodity + # then subtract the curtailable production from the demand + demand = self._subtract_curtailable( + curtailable_tech, demand, self.commodity, inputs, outputs + ) # 2. Storage dispatch - demand = self._dispatch_storage(inputs, outputs, demand) + # number of storage components that produce the demanded commodity + n_storage = len( + [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + ) + for storage_tech in self.storage_techs: + commodity_from_tech = self._get_commodity_for_tech(storage_tech) + if self.commodity in commodity_from_tech: + demand = self._dispatch_storage( + storage_tech, demand / n_storage, self.commodity, inputs, outputs + ) # 3. Merit-order dispatch: cheapest dispatchable first remaining = np.maximum(demand, 0.0) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index eb9077856..ef178ad0d 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -97,10 +97,27 @@ def compute(self, inputs, outputs): sell_price = inputs["commodity_sell_price"] # shape (n_timesteps,) # 1. Curtailable techs: full production (always profitable) - demand = self._subtract_curtailable(inputs, outputs, demand) + for curtailable_tech in self.curtailable_techs: + commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) + # check that this tech produces the commodity demanded + if self.commodity in commodity_from_tech: + # if the commodity produced from a tech is the demanded commodity + # then subtract the curtailable production from the demand + demand = self._subtract_curtailable( + curtailable_tech, demand, self.commodity, inputs, outputs + ) # 2. Storage dispatch - demand = self._dispatch_storage(inputs, outputs, demand) + # number of storage components that produce the demanded commodity + n_storage = len( + [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + ) + for storage_tech in self.storage_techs: + commodity_from_tech = self._get_commodity_for_tech(storage_tech) + if self.commodity in commodity_from_tech: + demand = self._dispatch_storage( + storage_tech, demand / n_storage, self.commodity, inputs, outputs + ) # 3. Profit-driven merit-order dispatch remaining = np.maximum(demand, 0.0) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 185b661b0..663f136a4 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -320,18 +320,6 @@ def _subtract_curtailable(self, curtailable_tech, remaining_demand, commodity, i remaining_demand -= inputs[f"{curtailable_tech}_{commodity}_out"] return remaining_demand - # for in_name, set_point_name, rated_name, commodity in zip( - # self.curtailable_input_names, - # self.curtailable_set_point_names, - # self.curtailable_rated_names, - # self.curtailable_commodity_names, - # ): - # # Output the set-point as the rated production of that technology - # outputs[set_point_name] = inputs[rated_name] * np.ones(self.n_timesteps) - # if commodity == self.commodity: - # demand -= inputs[in_name] - - # return demand def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, outputs): if storage_tech not in self.storage_techs: @@ -362,48 +350,6 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand - # def _dispatch_storage(self, inputs, outputs, demand): - # """Dispatch storage techs proportionally and subtract actual output from demand. - - # Positive set_point = discharge, negative = charge. - # Returns the updated demand array. - # """ - # # calculate the number of storage technologies that - # # produce the demanded commodity - # n_storage = len( - # [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] - # ) - # if n_storage > 0: - # # split the demand across the storage technologies - # storage_share = demand / n_storage - # for set_point_name, commodity in zip( - # self.storage_set_point_names, self.storage_commodity_names - # ): - # if commodity == self.commodity: - # if f"_{commodity}_demand" in set_point_name: - # # storage tech has a controller, output combined demand (always positive) - # # demand should be what is input to storage + storage_share - # storage_tech_name = set_point_name.split(f"_{commodity}_demand")[0] - # upstream_techs = self.get_upstream_techs_for_commodity( - # storage_tech_name, commodity - # ) - # commodity_into_storage = np.zeros(self.n_timesteps) - # for tech_name in upstream_techs: - # commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] - # outputs[set_point_name] = commodity_into_storage + storage_share - # else: - # # storage tech does not have a controller, - # # output set point (charge/discharge) command - # # charge when remaining demand is negative - # # discharge when remaining demand is positive - # outputs[set_point_name] = storage_share - - # for tech_name, in_name in zip(self.storage_techs, self.storage_input_names): - # if self.commodity in self._get_commodity_for_tech(tech_name): - # demand -= inputs[in_name] - - # return demand - def _get_commodity_for_tech(self, tech_name): """Get a list of the commodities produced for a technology. From e8b0319ce9319f5af8c5fec29fad7666ba557288 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 11:46:36 -0600 Subject: [PATCH 055/132] updated find_converter_tech method --- .../system_level/system_level_control_base.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 663f136a4..8e25454f1 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -1,3 +1,6 @@ +import operator +import functools + import numpy as np import networkx as nx import openmdao.api as om @@ -423,7 +426,7 @@ def find_converter_techs(self): downstream_of_previous_converter = [ n for i, n in enumerate(self.technology_graph.__iter__()) - if i > idx_upstream_converter + if i > min(idx_upstream_converter) ] all_upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( set(self.input_techs) @@ -438,19 +441,22 @@ def find_converter_techs(self): upstream_commodities = [ self._get_commodity_for_tech(t) for t in connected_upstream_techs ] + upstream_commodities = functools.reduce(operator.iadd, upstream_commodities, []) # symmetric difference # commodities that are not in both input_output_commodity = set(upstream_commodities) ^ set(tech_output_commodity) if len(input_output_commodity) > 1: - input_commodity = list( + input_commodities = list( input_output_commodity.intersection(set(upstream_commodities)) ) - output_commodity = list( + output_commodities = list( input_output_commodity.intersection(set(tech_output_commodity)) ) - # formatted as (input commodity, tech_name, output comodity) - converter_techs.add((input_commodity, tech, output_commodity)) + for input_commodity in input_commodities: + for output_commodity in output_commodities: + # formatted as (input commodity, tech_name, output comodity) + converter_techs.add((input_commodity, tech, output_commodity)) upstream_converter = tech return converter_techs From 8fd6a7662925e41c36706a456e62af8f3952abb8 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 11:53:16 -0600 Subject: [PATCH 056/132] started adding logic for multi-commods --- .../system_level/demand_following_control.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 09b7cb65d..0672194da 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -20,6 +20,9 @@ class DemandFollowingControl(SystemLevelControlBase): def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() + if self.multi_commodity_system: + self.find_converter_techs() + # 1. Curtailable techs: full production for curtailable_tech in self.curtailable_techs: commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) From 2432793e1aeefc9326f77dc7cac41b562849e9d6 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 12:21:33 -0600 Subject: [PATCH 057/132] connected feedstocks --- .../system_level/system_level_control_base.py | 53 +++++++++++++++++++ h2integrate/core/h2integrate_model.py | 13 ++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 83d34bcb7..149a3fe2a 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -51,6 +51,9 @@ def setup(self): self.storage_techs = [ k for k, v in slc_config["tech_control_classifiers"].items() if v == "storage" ] + self.feedstock_comps = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "feedstock" + ] self.input_techs = set( self.curtailable_techs + self.dispatchable_techs + self.storage_techs @@ -78,6 +81,7 @@ def setup(self): self._setup_tech_category("curtailable", self.curtailable_techs) self._setup_tech_category("dispatchable", self.dispatchable_techs) self._setup_tech_category("storage", self.storage_techs) + self._setup_feedstock_category(self.feedstock_comps) def _setup_commodity_for_given_units( self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=1.0 @@ -302,6 +306,55 @@ def _setup_tech_category(self, category, tech_list): setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) + def _setup_feedstock_category(self, feedstock_list): + """Iterate over the feedstocks and add inputs for the available feedstock + + Args: + feedstock_list (list[str]): name of feedstock techs + """ + for tech_name in feedstock_list: + tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] + for commodity in tech_commodities: + in_name = f"{tech_name}_{commodity}_out" + + if commodity in self.commodities_to_units: + # Units are already known explicitly + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodities_to_units[commodity], + desc=f"{commodity} output from {tech_name}", + ) + elif commodity in self.commodities_to_ref_var: + # Units are inferred from a previously-registered reference variable + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=None, + copy_units=self.commodities_to_ref_var[commodity], + desc=f"{commodity} output from {tech_name}", + ) + else: + # Units are unknown; try to discover them from the connection + meta_data = self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=None, + units_by_conn=True, + desc=f"{commodity} output from {tech_name}", + ) + if meta_data["units"] is None: + # Still unknown: register in_name as the reference + # variable so later techs with this commodity can + # copy its units. + self.commodities_to_ref_var[commodity] = in_name + else: + # Connection provided units — record them for future use + self.commodities_to_units[commodity] = meta_data["units"] + def _subtract_curtailable(self, inputs, outputs, demand): """Apply curtailable techs: set_point = rated, subtract output from demand. diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 8bf0082c1..a43f6e40b 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -558,7 +558,7 @@ def _classify_slc_technologies(self): storage_tech_to_control[tech] = True # Remove feedstocks and connectors - control_classifiers_to_connect = ["curtailable", "dispatchable", "storage"] + control_classifiers_to_connect = ["curtailable", "dispatchable", "storage", "feedstock"] tech_to_commodities = { (e[0], e[-1]) for e in sources_to_commodities @@ -640,6 +640,16 @@ def add_system_level_controller(self, slc_config): # Curtailable, dispatchable, and storage techs: read output and write set_point for tech_to_commodity in slc_config["tech_to_commodity"]: tech_name, commodity = tech_to_commodity + if slc_config["tech_control_classifiers"][tech_name] == "feedstock": + # Only connect the feedstock output to the SLC + self.plant.connect( + f"{tech_name}_source.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) + continue + + # For all other techs, connect the tech output and rated production + # to the SLC self.plant.connect( f"{tech_name}.{commodity}_out", f"system_level_controller.{tech_name}_{commodity}_out", @@ -650,6 +660,7 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) + # Connect the SLC to the controllable tech input if slc_config["storage_techs_to_control"].get(tech_name, False): # storage has its own controller # provide demand to storage controller, From ae3b8d127af4a54c8b46af56724d400fc05e6554 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 12:39:30 -0600 Subject: [PATCH 058/132] moved logic from compute to method in demand following --- .../system_level/demand_following_control.py | 84 ++++++++++++++----- .../system_level/system_level_control_base.py | 2 +- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 0672194da..b8afe9270 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -17,33 +17,30 @@ class DemandFollowingControl(SystemLevelControlBase): consider costs. """ - def compute(self, inputs, outputs): - demand = inputs[self.demand_input_name].copy() - - if self.multi_commodity_system: - self.find_converter_techs() + def run_control_for_commodity_subset(self, inputs, outputs, commodity, commodity_demand): + demand = commodity_demand.copy() # 1. Curtailable techs: full production for curtailable_tech in self.curtailable_techs: commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) # check that this tech produces the commodity demanded - if self.commodity in commodity_from_tech: + if commodity in commodity_from_tech: # if the commodity produced from a tech is the demanded commodity # then subtract the curtailable production from the demand demand = self._subtract_curtailable( - curtailable_tech, demand, self.commodity, inputs, outputs + curtailable_tech, demand, commodity, inputs, outputs ) # 2. Storage dispatch # number of storage components that produce the demanded commodity n_storage = len( - [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + [s for s in self.storage_techs if commodity in self._get_commodity_for_tech(s)] ) for storage_tech in self.storage_techs: commodity_from_tech = self._get_commodity_for_tech(storage_tech) - if self.commodity in commodity_from_tech: + if commodity in commodity_from_tech: demand = self._dispatch_storage( - storage_tech, demand / n_storage, self.commodity, inputs, outputs + storage_tech, demand / n_storage, commodity, inputs, outputs ) # 3. Dispatchable techs: equal share of remaining demand @@ -52,18 +49,67 @@ def compute(self, inputs, outputs): # calculate the number of dispatchable technologies that # produce the demanded commodity n_dispatchable = len( - [ - s - for s in self.dispatchable_techs - if self.commodity in self._get_commodity_for_tech(s) - ] + [s for s in self.dispatchable_techs if commodity in self._get_commodity_for_tech(s)] ) for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) - if self.commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{self.commodity}_set_point"] = ( - remaining / n_dispatchable - ) + if commodity in commodity_from_tech: + outputs[f"{dispatchable_tech}_{commodity}_set_point"] = remaining / n_dispatchable + + return outputs + + def compute(self, inputs, outputs): + if self.multi_commodity_system: + self.find_converter_techs() + outputs = self.run_control_for_commodity_subset( + inputs, outputs, self.commodity, inputs[self.demand_input_name].copy() + ) + + else: + demand = inputs[self.demand_input_name].copy() + outputs = self.run_control_for_commodity_subset(inputs, outputs, self.commodity, demand) + + # # 1. Curtailable techs: full production + # for curtailable_tech in self.curtailable_techs: + # commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) + # # check that this tech produces the commodity demanded + # if self.commodity in commodity_from_tech: + # # if the commodity produced from a tech is the demanded commodity + # # then subtract the curtailable production from the demand + # demand = self._subtract_curtailable( + # curtailable_tech, demand, self.commodity, inputs, outputs + # ) + + # # 2. Storage dispatch + # # number of storage components that produce the demanded commodity + # n_storage = len( + # [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] + # ) + # for storage_tech in self.storage_techs: + # commodity_from_tech = self._get_commodity_for_tech(storage_tech) + # if self.commodity in commodity_from_tech: + # demand = self._dispatch_storage( + # storage_tech, demand / n_storage, self.commodity, inputs, outputs + # ) + + # # 3. Dispatchable techs: equal share of remaining demand + # remaining = np.maximum(demand, 0.0) + + # # calculate the number of dispatchable technologies that + # # produce the demanded commodity + # n_dispatchable = len( + # [ + # s + # for s in self.dispatchable_techs + # if self.commodity in self._get_commodity_for_tech(s) + # ] + # ) + # for dispatchable_tech in self.dispatchable_techs: + # commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) + # if self.commodity in commodity_from_tech: + # outputs[f"{dispatchable_tech}_{self.commodity}_set_point"] = ( + # remaining / n_dispatchable + # ) # Check for nans or inf if not all(np.isfinite(c).all() for k, c in outputs.items()): diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 8e25454f1..37fd54d3b 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -392,7 +392,7 @@ def get_upstream_techs_for_commodity(self, tech_name: str, commodity: str): return list(upstream_techs) def find_converter_techs(self): - """Get the name of the technology that transforms a commodity + """Get the name of the technology that transforms a commodity. Returns: set(tuple): set of converter technologies formatted as From 0f7d6b9ea2a6c9b5ea8d4662ce06e552bd6b6a5e Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 12:50:00 -0600 Subject: [PATCH 059/132] updated find_converter_techs and get_upstream_techs_for_commodity --- .../system_level/system_level_control_base.py | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 1f39ddc7c..988f8a021 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -658,9 +658,11 @@ def _feedstock_marginal_cost(self, inputs, marginal_cost_data): return np.full(self.n_timesteps, marginal_cost_scalar) - def get_upstream_techs_for_commodity(self, tech_name: str, commodity: str): + def get_upstream_techs_for_commodity( + self, tech_name: str, commodity: str, include_feedstock_sources=True + ): """Get the name of technologies that are upstream - of `tech_name` and that output `commodity` + of `tech_name` and that output `commodity`. Args: tech_name (str): name of technology @@ -669,6 +671,11 @@ def get_upstream_techs_for_commodity(self, tech_name: str, commodity: str): Returns: list[str]: list of technologies upstream of the tech_name that produce a given commodity """ + if include_feedstock_sources: + input_techs = self.input_techs | set(self.feedstock_comps) + else: + input_techs = self.input_techs.copy() + # figure out where the upstream commodity is coming from upstream_components = nx.ancestors(self.technology_graph, tech_name) # iterates through a list of 3 length tuples (source, dest, commodity) @@ -678,18 +685,21 @@ def get_upstream_techs_for_commodity(self, tech_name: str, commodity: str): if s[0] in upstream_components and s[2] == commodity ] # get the technologies that are available to the controller - upstream_techs = set(upstream_components_shared_commodity).intersection( - set(self.input_techs) - ) + upstream_techs = set(upstream_components_shared_commodity).intersection(set(input_techs)) return list(upstream_techs) - def find_converter_techs(self): + def find_converter_techs(self, include_feedstock_sources=True): """Get the name of the technology that transforms a commodity. + Does not include feedstocks. Returns: set(tuple): set of converter technologies formatted as (input_commodity, converter tech name, output_commodity) """ + if include_feedstock_sources: + input_techs = self.input_techs | set(self.feedstock_comps) + else: + input_techs = self.input_techs.copy() if not self.multi_commodity_system: return @@ -697,17 +707,16 @@ def find_converter_techs(self): edges = list(self.technology_graph.edges(data="commodity")) upstream_converter = None - # for tech in self.input_techs: for edge in edges: tech, dest_tech, cmod = edge - if tech in self.input_techs: + if tech in input_techs: tech_output_commodity = self._get_commodity_for_tech(tech) # NOTE: unsure how this would work for systems with tiered converters # aka - maybe have to eliminate a converter once we've discovered it if upstream_converter is None: upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( - set(self.input_techs) + set(input_techs) ) else: idx_upstream_converter = [ @@ -721,7 +730,7 @@ def find_converter_techs(self): if i > min(idx_upstream_converter) ] all_upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( - set(self.input_techs) + set(input_techs) ) upstream_techs = all_upstream_techs.intersection( set(downstream_of_previous_converter) From be846a0e5612362a655d221a3df73546fbfeb1ba Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 13:28:48 -0600 Subject: [PATCH 060/132] bugfix --- h2integrate/core/h2integrate_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 002ec15f4..f2e3d1c44 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -590,7 +590,6 @@ def add_system_level_controller(self, slc_config): 4. Creates connections between the controller and each technology 5. For cost/profit strategies, connects marginal cost inputs """ - slc_config = self.plant_config["system_level_control"] # 1. Select controller class based on strategy strategy_name = self.plant_config["system_level_control"].get("control_strategy") From 1f2e5cc419bec3713f5417b4a0b8c10d6221be69 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 7 May 2026 15:20:36 -0500 Subject: [PATCH 061/132] Ard control classifier --- h2integrate/converters/wind/wind_plant_ard.py | 1 + 1 file changed, 1 insertion(+) diff --git a/h2integrate/converters/wind/wind_plant_ard.py b/h2integrate/converters/wind/wind_plant_ard.py index 408fc4890..779f72988 100644 --- a/h2integrate/converters/wind/wind_plant_ard.py +++ b/h2integrate/converters/wind/wind_plant_ard.py @@ -149,6 +149,7 @@ class ArdWindPlantModel(om.Group): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model + _control_classifier = "curtailable" def initialize(self): self.options.declare("driver_config", types=dict) From 8f77755fed8cc7918cb3310e8209801e1834e56a Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 7 May 2026 14:28:15 -0600 Subject: [PATCH 062/132] Updating for changes to slc_config --- h2integrate/core/h2integrate_model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 002ec15f4..69aad11fe 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -590,10 +590,10 @@ def add_system_level_controller(self, slc_config): 4. Creates connections between the controller and each technology 5. For cost/profit strategies, connects marginal cost inputs """ - slc_config = self.plant_config["system_level_control"] + plant_slc_config = self.plant_config["system_level_control"] # 1. Select controller class based on strategy - strategy_name = self.plant_config["system_level_control"].get("control_strategy") + strategy_name = plant_slc_config.get("control_strategy") slc_cls = self.supported_models.get(strategy_name) if slc_cls is None: raise ValueError( @@ -610,7 +610,7 @@ def add_system_level_controller(self, slc_config): self.plant.add_subsystem("system_level_controller", slc_comp) # 2. Configure the nonlinear solver - solver_config = SLCSolverOptionsConfig.from_dict(slc_config.get("solver_options", {})) + solver_config = SLCSolverOptionsConfig.from_dict(plant_slc_config.get("solver_options", {})) solver_cls = solver_config.return_nonlinear_solver() solver = solver_cls() solver_options = solver_config.get_solver_options() @@ -660,7 +660,7 @@ def add_system_level_controller(self, slc_config): # 4. For cost-aware strategies, connect cost inputs based on cost_per_tech if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): - cost_per_tech = slc_config.get("cost_per_tech", {}) + cost_per_tech = plant_slc_config.get("cost_per_tech", {}) for tech_name, _ in slc_config["tech_to_commodity"]: if self.tech_control_classifiers[tech_name] == "dispatchable": cost_spec = cost_per_tech.get(tech_name, 0.0) From 883c0b9fd6321756e46e12284b42d65105ab36d2 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 7 May 2026 15:44:32 -0500 Subject: [PATCH 063/132] ard. --- h2integrate/converters/wind/wind_plant_ard.py | 4 ++++ h2integrate/core/h2integrate_model.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/h2integrate/converters/wind/wind_plant_ard.py b/h2integrate/converters/wind/wind_plant_ard.py index 779f72988..811e083f2 100644 --- a/h2integrate/converters/wind/wind_plant_ard.py +++ b/h2integrate/converters/wind/wind_plant_ard.py @@ -156,6 +156,10 @@ def initialize(self): self.options.declare("plant_config", types=dict) self.options.declare("tech_config", types=dict) + self.commodity = "electricity" + self.commodity_rate_units = "kW" + self.commodity_amount_units = "kW*h" + if set_up_ard_model is None: msg = ( "Please install `ard-nrel` or `h2integrate[ard]` to use the" diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index f2e3d1c44..2b5a0f89c 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -1952,7 +1952,7 @@ def _check_tech_connections(self): if group is None: continue - io_params.update(group.get_io_metadata().keys()) + io_params.update([key.split(".")[-1] for key in group.get_io_metadata().keys()]) tech_io[tech_name] = io_params From b6b14151f82d1010825c8f79ec129021fe9ae889 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 7 May 2026 16:43:36 -0500 Subject: [PATCH 064/132] test --- h2integrate/postprocess/test/test_sql_timeseries_to_csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index a5b04bb6e..d345474c8 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -60,7 +60,7 @@ def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath) res = save_case_timeseries_as_csv(run_example_02_sql_fpath, save_to_file=True) with subtests.test("Check number of columns"): - assert len(res.columns.to_list()) == 51 + assert len(res.columns.to_list()) == 57 with subtests.test("Check number of rows"): assert len(res) == 8760 From f46e7c84d5d169901295e6128450c61b0e91e6b7 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 16:46:38 -0600 Subject: [PATCH 065/132] updated _find_feedstock_techs to use self.feedstock_comps --- .../system_level/system_level_control_base.py | 17 +++-- .../system_level/test/test_slc_controllers.py | 68 ++++++------------- 2 files changed, 30 insertions(+), 55 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 988f8a021..6c9fdb287 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -606,20 +606,19 @@ def _find_feedstock_techs(self, tech_name): Returns: list[str]: names of upstream feedstock technologies. """ - tech_config = self.options["tech_config"] - technologies = tech_config.get("technologies", {}) interconnections = self.options["plant_config"].get("technology_interconnections", []) # Upstream tech names for this dispatchable tech + # NOTE: could getting upstream_techs be replaced with the two lines below + # comds = self._get_commodity_for_tech(tech_name) + # upstream_techs = list( + # set([self.get_upstream_techs_for_commodity(tech_name, c) for c in comds]) + # ) upstream_techs = [conn[0] for conn in interconnections if conn[1] == tech_name] - feedstock_names = [] - for upstream in upstream_techs: - tech_def = technologies.get(upstream, {}) - perf_model = tech_def.get("performance_model", {}).get("model", "") - cost_model = tech_def.get("cost_model", {}).get("model", "") - if "Feedstock" in perf_model or "Feedstock" in cost_model: - feedstock_names.append(upstream) + feedstock_names = [ + upstream for upstream in upstream_techs if upstream in self.feedstock_comps + ] return feedstock_names diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index fc41d3727..a908e4c19 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -22,13 +22,16 @@ def _make_plant_config( curtailable=None, dispatchable=None, storage=None, + feedstock=None, sell_price=0.06, cost_per_tech=None, technology_interconnections=None, ): """Build a minimal plant_config dict for controller tests.""" - all_techs = (curtailable or []) + (dispatchable or []) + (storage or []) + all_techs = (curtailable or []) + (dispatchable or []) + (storage or []) + (feedstock or []) + tech_to_commodity = {(t, "electricity") for t in all_techs} + config = { "plant": {"simulation": {"n_timesteps": n_timesteps, "dt": 3600}, "plant_life": 30}, "system_level_control": { @@ -39,6 +42,7 @@ def _make_plant_config( "curtailable_techs": curtailable or [], "dispatchable_techs": dispatchable or [], "storage_techs": storage or [], + "feedstock_techs": feedstock or [], "tech_to_commodity": tech_to_commodity, "commodity_sell_price": sell_price, "cost_per_tech": cost_per_tech or {}, @@ -56,7 +60,8 @@ def _make_slc_config(plant_config): curtailable = slc.get("curtailable_techs", []) dispatchable = slc.get("dispatchable_techs", []) storage = slc.get("storage_techs", []) - all_techs = curtailable + dispatchable + storage + feedstock = slc.get("feedstock_techs", []) + all_techs = curtailable + dispatchable + storage + feedstock # Build technology graph tech_graph = nx.DiGraph() @@ -79,6 +84,8 @@ def _make_slc_config(plant_config): classifiers[t] = "dispatchable" for t in storage: classifiers[t] = "storage" + for t in feedstock: + classifiers[t] = "feedstock" return { "demand_commodity": slc["demand_commodity"], @@ -91,7 +98,7 @@ def _make_slc_config(plant_config): } -def _build_problem(slc_cls, plant_config, tech_config=None): +def _build_problem(slc_cls, plant_config): """Create and setup an OpenMDAO Problem with the given controller.""" slc_config = _make_slc_config(plant_config) prob = om.Problem() @@ -100,7 +107,7 @@ def _build_problem(slc_cls, plant_config, tech_config=None): slc_cls( driver_config={}, plant_config=plant_config, - tech_config=tech_config or {}, + tech_config={}, slc_config=slc_config, ), ) @@ -482,6 +489,7 @@ def test_feedstock_single(self): """feedstock mode: single upstream feedstock drives marginal cost.""" pc = _make_plant_config( dispatchable=["ng_plant"], + feedstock=["ng_feed"], demand=50000, sell_price=0.10, cost_per_tech={"ng_plant": "feedstock"}, @@ -489,15 +497,8 @@ def test_feedstock_single(self): ["ng_feed", "ng_plant", "natural_gas", "pipe"], ], ) - tech_config = { - "technologies": { - "ng_feed": { - "performance_model": {"model": "FeedstockPerformanceModel"}, - "cost_model": {"model": "FeedstockCostModel"}, - }, - } - } - prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config) + + prob = _build_problem(CostMinimizationControl, pc) prob.set_val("slc.ng_plant_rated_electricity_production", 100000) # Feedstock VarOpEx: $1M/yr; production: 100 MW * 4 h = 400 MWh prob.set_val("slc.ng_feed_VarOpEx", np.full(30, 1_000_000.0)) @@ -513,6 +514,7 @@ def test_feedstock_multiple(self): """feedstock mode: multiple upstream feedstocks are summed.""" pc = _make_plant_config( dispatchable=["plant"], + feedstock=["feed_a", "feed_b"], demand=50000, sell_price=0.10, cost_per_tech={"plant": "feedstock"}, @@ -522,22 +524,8 @@ def test_feedstock_multiple(self): ["other_tech", "plant", "something", "cable"], ], ) - tech_config = { - "technologies": { - "feed_a": { - "performance_model": {"model": "FeedstockPerformanceModel"}, - "cost_model": {"model": "FeedstockCostModel"}, - }, - "feed_b": { - "performance_model": {"model": "FeedstockPerformanceModel"}, - "cost_model": {"model": "FeedstockCostModel"}, - }, - "other_tech": { - "performance_model": {"model": "SomePerformanceModel"}, - }, - } - } - prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config) + + prob = _build_problem(CostMinimizationControl, pc) prob.set_val("slc.plant_rated_electricity_production", 100000) # Two feedstocks: $500k and $300k → total $800k/yr prob.set_val("slc.feed_a_VarOpEx", np.full(30, 500_000.0)) @@ -554,6 +542,7 @@ def test_feedstock_profit_max_unprofitable(self): """feedstock mode in profit max: unprofitable when feedstock costs exceed sell price.""" pc = _make_plant_config( dispatchable=["ng_plant"], + feedstock=["ng_feed"], demand=50000, sell_price=0.01, # very low sell price cost_per_tech={"ng_plant": "feedstock"}, @@ -561,15 +550,8 @@ def test_feedstock_profit_max_unprofitable(self): ["ng_feed", "ng_plant", "natural_gas", "pipe"], ], ) - tech_config = { - "technologies": { - "ng_feed": { - "performance_model": {"model": "FeedstockPerformanceModel"}, - "cost_model": {"model": "FeedstockCostModel"}, - }, - } - } - prob = _build_problem(ProfitMaximizationControl, pc, tech_config=tech_config) + + prob = _build_problem(ProfitMaximizationControl, pc) prob.set_val("slc.ng_plant_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.01) # Very expensive feedstock: $100M/yr → high marginal cost @@ -591,12 +573,6 @@ def test_feedstock_no_feedstock_raises(self): ["some_tech", "ng_plant", "electricity", "cable"], ], ) - tech_config = { - "technologies": { - "some_tech": { - "performance_model": {"model": "SomePerformanceModel"}, - }, - } - } + with pytest.raises(ValueError, match="at least one feedstock"): - _build_problem(CostMinimizationControl, pc, tech_config=tech_config) + _build_problem(CostMinimizationControl, pc) From b34bb916cac96b72fd04e48afdcb55624bcaec9d Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 7 May 2026 16:49:43 -0600 Subject: [PATCH 066/132] updated some doc strings in slc baseclass --- .../system_level/system_level_control_base.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 6c9fdb287..b953a965a 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -597,8 +597,7 @@ def _find_feedstock_techs(self, tech_name): """Find feedstock technologies connected upstream of tech_name. Scans ``technology_interconnections`` for connections whose - destination is tech_name and whose source uses - ``FeedstockPerformanceModel`` or ``FeedstockCostModel``. + destination is tech_name and whose source is a feedstock. Args: tech_name (str): the dispatchable technology name. @@ -666,6 +665,8 @@ def get_upstream_techs_for_commodity( Args: tech_name (str): name of technology commodity (str): commodity name + include_feedstock_sources (bool, optional): If True, include techs + that have an input commodity from a feedstock. Defaults to True. Returns: list[str]: list of technologies upstream of the tech_name that produce a given commodity @@ -689,7 +690,10 @@ def get_upstream_techs_for_commodity( def find_converter_techs(self, include_feedstock_sources=True): """Get the name of the technology that transforms a commodity. - Does not include feedstocks. + + Args: + include_feedstock_sources (bool, optional): If True, include techs + that have an input commodity from a feedstock. Defaults to True. Returns: set(tuple): set of converter technologies formatted as From 4fb89906e2c305e806e9c1c100d6d30ce7485504 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Fri, 8 May 2026 11:20:30 -0500 Subject: [PATCH 067/132] docs wip --- .../control_classifier.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/control/system_level_control/control_classifier.md diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md new file mode 100644 index 000000000..8797ab81b --- /dev/null +++ b/docs/control/system_level_control/control_classifier.md @@ -0,0 +1,50 @@ +# System Level Control Technology Performance Classifiers + +To enable a generic system level control framework we need to classify each technology based on how the model, that is included in H2I, can operate within the system. + +```{note} +While in real life there are a lot of controllable parameters allowing for ramping production up or down for a particular technology (e.g., turbine yaw). The particular model in H2I might not be capable of simulating a modulated response based on an input signal. +``` + +We have identified three key classifiers that are able to represent the different behaviors that we can expect from the model. Each performance model includes a parameter setting the classifier `_control_classifier`. + +Classifier | Meaning | Example Techs +-- | -- | -- +curtailable | Produces based on resource or input commodity; can only be reduced | wind, solar, nuclear +dispatchable | Can modulate consumption/production within bounds | grid, NG turbine +storage | Can modulate consumption/production within bounds while tracking SOC; does not produce/consume energy | battery, h2 storage, any storage + +To add a classifier for a particular model it would look something like this in the class: +```{python} +_control_classifier = "curtailable" +``` + +## Curtailable +A curtailable performance model represents anything that can have the output reduced based on a give set point from the system level controller. This classifier and the inputs and outputs are included in the figure below. A good example of this is the PVWatts PySAM solar plant in H2I, the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the tracking software, but we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. + +```{figure} figures/curtailable.png +:width: 70% +:align: center +``` + +### Apply curtailment based on set_point +Within the `compute()` method in the performance model you can apply the curtailment using the `apply_curtailment()` method. +``` +self.apply_curtailment(outputs) +``` +which, applies curtailment to `{commodity}_out` based on `{commodity}_set_point`. There is then `uncurtailed_{commodity}_out` and `{commodity}_out` as outputs from the performance model. + +## Dispatchable +A dispatchable performance model represents anything that can receive a set point. Any model that has the "dispatchable" control classifier tag is able to receive a set point and change it's behavior based on that set point. There aren't additional special methods to handle this because it's internal to each performance model. + +```{figure} figures/dispatchable.png +:width: 70% +:align: center +``` + +## Storage +Storage is a unique control classifier because it assumes that within the model that energy isn't created or destroyed (minus some efficiency losses). While it's technically "dispatchable" in that it can receive and change its performance based on a set point it's handling within H2I is unique because it's attached to storage performance models, which is handled differently than converter performance models. + +The storage performance models that have the "storage" control classifier additionally require a storage-level controller in addition to the overarching system level controller. See the image below for reference. The storage-level controller takes in the system level-controller set points and outputs charge (negative) and discharge (positive) commands (storage-level set points) to the storage performance model. + +ADD IMAGE - wait until [PR # 731](https://github.com/NatLabRockies/H2Integrate/pull/731) comes in. From 31711d41504833d28a5a6e467e986c91331b3c80 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 10:57:48 -0600 Subject: [PATCH 068/132] Minor refactor to demand following control --- .../system_level/demand_following_control.py | 67 +++---------------- .../system_level/system_level_control_base.py | 2 +- 2 files changed, 9 insertions(+), 60 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index b8afe9270..0269bde9e 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -43,8 +43,8 @@ def run_control_for_commodity_subset(self, inputs, outputs, commodity, commodity storage_tech, demand / n_storage, commodity, inputs, outputs ) - # 3. Dispatchable techs: equal share of remaining demand - remaining = np.maximum(demand, 0.0) + # 3. Dispatchable techs + remaining_demand = np.maximum(demand, 0.0) # calculate the number of dispatchable technologies that # produce the demanded commodity @@ -54,67 +54,16 @@ def run_control_for_commodity_subset(self, inputs, outputs, commodity, commodity for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) if commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{commodity}_set_point"] = remaining / n_dispatchable + outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( + remaining_demand / n_dispatchable + ) return outputs def compute(self, inputs, outputs): if self.multi_commodity_system: self.find_converter_techs() - outputs = self.run_control_for_commodity_subset( - inputs, outputs, self.commodity, inputs[self.demand_input_name].copy() - ) - - else: - demand = inputs[self.demand_input_name].copy() - outputs = self.run_control_for_commodity_subset(inputs, outputs, self.commodity, demand) - - # # 1. Curtailable techs: full production - # for curtailable_tech in self.curtailable_techs: - # commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) - # # check that this tech produces the commodity demanded - # if self.commodity in commodity_from_tech: - # # if the commodity produced from a tech is the demanded commodity - # # then subtract the curtailable production from the demand - # demand = self._subtract_curtailable( - # curtailable_tech, demand, self.commodity, inputs, outputs - # ) - - # # 2. Storage dispatch - # # number of storage components that produce the demanded commodity - # n_storage = len( - # [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] - # ) - # for storage_tech in self.storage_techs: - # commodity_from_tech = self._get_commodity_for_tech(storage_tech) - # if self.commodity in commodity_from_tech: - # demand = self._dispatch_storage( - # storage_tech, demand / n_storage, self.commodity, inputs, outputs - # ) - # # 3. Dispatchable techs: equal share of remaining demand - # remaining = np.maximum(demand, 0.0) - - # # calculate the number of dispatchable technologies that - # # produce the demanded commodity - # n_dispatchable = len( - # [ - # s - # for s in self.dispatchable_techs - # if self.commodity in self._get_commodity_for_tech(s) - # ] - # ) - # for dispatchable_tech in self.dispatchable_techs: - # commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) - # if self.commodity in commodity_from_tech: - # outputs[f"{dispatchable_tech}_{self.commodity}_set_point"] = ( - # remaining / n_dispatchable - # ) - - # Check for nans or inf - if not all(np.isfinite(c).all() for k, c in outputs.items()): - bad_outputs = [k for k, c in outputs.items() if not np.isfinite(c).all()] - raise ValueError(f"These outputs contain non-finite values: {bad_outputs}") - if not all(np.isfinite(c).all() for k, c in inputs.items()): - bad_inputs = [k for k, c in inputs.items() if not np.isfinite(c).all()] - raise ValueError(f"These inputs contain non-finite values: {bad_inputs}") + outputs = self.run_control_for_commodity_subset( + inputs, outputs, self.commodity, inputs[self.demand_input_name].copy() + ) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index b953a965a..d162e0778 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -759,7 +759,7 @@ def find_converter_techs(self, include_feedstock_sources=True): for input_commodity in input_commodities: for output_commodity in output_commodities: - # formatted as (input commodity, tech_name, output comodity) + # formatted as (input commodity, tech_name, output commodity) converter_techs.add((input_commodity, tech, output_commodity)) upstream_converter = tech From 9bae204ad76c4621fe1aac773e8316fd311f4f7d Mon Sep 17 00:00:00 2001 From: kbrunik Date: Fri, 8 May 2026 12:10:36 -0500 Subject: [PATCH 069/132] docs --- docs/_static/class_hierarchy.html | 4 ++-- docs/_toc.yml | 11 ++++++++--- docs/control/storage_level_control.md | 3 +++ .../system_level_control/control_classifier.md | 15 ++++++++++++--- .../system_level_control/system_level_control.md | 10 ++++++++++ 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 docs/control/storage_level_control.md create mode 100644 docs/control/system_level_control/system_level_control.md diff --git a/docs/_static/class_hierarchy.html b/docs/_static/class_hierarchy.html index fea629882..7149a5c30 100644 --- a/docs/_static/class_hierarchy.html +++ b/docs/_static/class_hierarchy.html @@ -380,8 +380,8 @@

// parsing and collecting nodes and edges from the python - nodes = new vis.DataSet([{"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FeedstockCostModel", "label": "FeedstockCostModel", "shape": "ellipse", "size": 18.0, "title": "FeedstockCostModel\ncore/feedstocks.py\n[Core / General]", "x": -79.5125603737886, "y": 584.9567473090942}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteBaseComponent", "label": "SiteBaseComponent", "shape": "ellipse", "size": 18.72972972972973, "title": "SiteBaseComponent\ncore/sites.py\n[Core / General]", "x": -51.99787538017026, "y": 668.8874099443384}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteLocationComponent", "label": "SiteLocationComponent", "shape": "ellipse", "size": 18.0, "title": "SiteLocationComponent\ncore/sites.py\n[Core / General]", "x": -137.54209445136647, "y": 722.897904528822}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PerformanceModelBaseClass", "label": "PerformanceModelBaseClass", "shape": "ellipse", "size": 40.62162162162162, "title": "PerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -243.0155271316636, "y": 685.2630296209401}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CostModelBaseClass", "label": "CostModelBaseClass", "shape": "ellipse", "size": 45.0, "title": "CostModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -288.0485916668164, "y": 575.9204299065049}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResizeablePerformanceModelBaseClass", "label": "ResizeablePerformanceModelBaseClass", "shape": "ellipse", "size": 19.45945945945946, "title": "ResizeablePerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -237.4418960911029, "y": 464.62515055513364}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CacheBaseClass", "label": "CacheBaseClass", "shape": "ellipse", "size": 19.45945945945946, "title": "CacheBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -119.33772505659815, "y": 423.5780806776881}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericConverterCostModel", "label": "GenericConverterCostModel", "shape": "dot", "size": 18.0, "title": "GenericConverterCostModel\nconverters/generic_converter_cost.py\n[Converter / Other]", "x": 428.09388111524015, "y": 469.0988894808179}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMSolarPlantPerformanceModel", "label": "PYSAMSolarPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMSolarPlantPerformanceModel\nconverters/solar/solar_pysam.py\n[Converter / Solar]", "x": 455.6085661088585, "y": 553.0295521160621}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBUtilityPVCostModel", "label": "ATBUtilityPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBUtilityPVCostModel\nconverters/solar/atb_utility_pv_cost.py\n[Converter / Solar]", "x": 370.0643470376623, "y": 607.0400467005456}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBResComPVCostModel", "label": "ATBResComPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBResComPVCostModel\nconverters/solar/atb_res_com_pv_cost.py\n[Converter / Solar]", "x": 264.59091435736514, "y": 569.4051717926637}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarPerformanceBaseClass", "label": "SolarPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SolarPerformanceBaseClass\nconverters/solar/solar_baseclass.py\n[Converter / Solar]", "x": 219.55784982221238, "y": 460.06257207822847}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerPerformanceBaseClass", "label": "ElectrolyzerPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "ElectrolyzerPerformanceBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 270.16454539792585, "y": 348.7672927268573}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerCostBaseClass", "label": "ElectrolyzerCostBaseClass", "shape": "dot", "size": 20.18918918918919, "title": "ElectrolyzerCostBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 388.2687164324306, "y": 307.72022284941175}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SingliticoCostModel", "label": "SingliticoCostModel", "shape": "dot", "size": 18.0, "title": "SingliticoCostModel\nconverters/hydrogen/singlitico_cost_model.py\n[Converter / Hydrogen]", "x": 501.4805766605487, "y": 365.4133442102892}, {"borderWidth": 1, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WOMBATElectrolyzerModel", "label": "WOMBATElectrolyzerModel", "shape": "dot", "size": 18.0, "title": "WOMBATElectrolyzerModel\nconverters/hydrogen/wombat_model.py\n[Converter / Hydrogen]", "x": 538.9625776291001, "y": 488.44605748599986}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinearH2FuelCellPerformanceModel", "label": "LinearH2FuelCellPerformanceModel", "shape": "dot", "size": 18.0, "title": "LinearH2FuelCellPerformanceModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 475.93189116793957, "y": 601.9588898891661}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "H2FuelCellCostModel", "label": "H2FuelCellCostModel", "shape": "dot", "size": 18.0, "title": "H2FuelCellCostModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 349.5705117805884, "y": 635.8507248662497}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerPerformanceModel", "label": "SteamMethaneReformerPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerPerformanceModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 236.61361523178945, "y": 568.2423536759715}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerCostModel", "label": "SteamMethaneReformerCostModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerCostModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 206.39396475153276, "y": 439.409697663304}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "BasicElectrolyzerCostModel", "label": "BasicElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "BasicElectrolyzerCostModel\nconverters/hydrogen/basic_cost_model.py\n[Converter / Hydrogen]", "x": 278.165573095184, "y": 327.54056326717114}, {"borderWidth": 2.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ECOElectrolyzerPerformanceModel", "label": "ECOElectrolyzerPerformanceModel", "shape": "dot", "size": 18.72972972972973, "title": "ECOElectrolyzerPerformanceModel\nconverters/hydrogen/pem_electrolyzer.py\n[Converter / Hydrogen]", "x": 408.929515746538, "y": 301.0719911584519}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CustomElectrolyzerCostModel", "label": "CustomElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "CustomElectrolyzerCostModel\nconverters/hydrogen/custom_electrolyzer_cost_model.py\n[Converter / Hydrogen]", "x": 519.3422437620703, "y": 376.741275969993}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostModel", "label": "GeoH2SubsurfaceCostModel", "shape": "dot", "size": 18.0, "title": "GeoH2SubsurfaceCostModel\nconverters/hydrogen/geologic/mathur_modified.py\n[Converter / Hydrogen]", "x": 541.9933368656093, "y": 509.0547616483423}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfacePerformanceBaseClass", "label": "GeoH2SubsurfacePerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "GeoH2SubsurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 462.61867180963463, "y": 617.7338834509918}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostBaseClass", "label": "GeoH2SubsurfaceCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SubsurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 329.04975630639217, "y": 636.513453478361}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfacePerformanceModel", "label": "AspenGeoH2SurfacePerformanceModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfacePerformanceModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 222.32576716621537, "y": 553.5863417347226}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfaceCostModel", "label": "AspenGeoH2SurfaceCostModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfaceCostModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 207.46113153897124, "y": 419.00371238109653}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGeoH2PerformanceModel", "label": "NaturalGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGeoH2PerformanceModel\nconverters/hydrogen/geologic/simple_natural_geoh2.py\n[Converter / Hydrogen]", "x": 293.81016729091453, "y": 314.4201619012048}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StimulatedGeoH2PerformanceModel", "label": "StimulatedGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "StimulatedGeoH2PerformanceModel\nconverters/hydrogen/geologic/templeton_serpentinization.py\n[Converter / Hydrogen]", "x": 429.1980303433203, "y": 303.5048975398027}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfacePerformanceBaseClass", "label": "GeoH2SurfacePerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 531.4807512394786, "y": 393.1585470237545}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfaceCostBaseClass", "label": "GeoH2SurfaceCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 538.4198729733245, "y": 529.1652694271473}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisPerformanceModel", "label": "ReverseOsmosisPerformanceModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisPerformanceModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 445.5710237882473, "y": 629.0047614736493}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisCostModel", "label": "ReverseOsmosisCostModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisCostModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 309.11651798504033, "y": 631.947653855694}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationPerformanceBaseClass", "label": "DesalinationPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "DesalinationPerformanceBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 211.84908461781183, "y": 536.0083507662598}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationCostBaseClass", "label": "DesalinationCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "DesalinationCostBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 212.91655044595416, "y": 399.26617741803875}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearPerformanceModel", "label": "QuinnNuclearPerformanceModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearPerformanceModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 311.84419223616084, "y": 304.68898638961775}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearCostModel", "label": "QuinnNuclearCostModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearCostModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 448.7220200189815, "y": 309.77552217810415}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceCostModel", "label": "CMUElectricArcFurnaceCostModel", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceCostModel\nconverters/steel/cmu_eaf_cost.py\n[Converter / Steel]", "x": 540.4994435124524, "y": 411.5906925910052}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantCostComponent", "label": "HydrogenEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 531.3901362621964, "y": 548.4583323631547}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantCostComponent", "label": "NaturalGasEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 426.78782378431725, "y": 637.3337381981482}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantPerformanceComponent", "label": "HydrogenEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 290.0713774101109, "y": 624.2026575560053}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantPerformanceComponent", "label": "NaturalGasEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 204.19394571089566, "y": 516.9137611171568}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "label": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_scrap.py\n[Converter / Steel]", "x": 221.34134343018306, "y": 380.48561129518464}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBasePerformanceComponent", "label": "ElectricArcFurnacePlantBasePerformanceComponent", "shape": "dot", "size": 19.45945945945946, "title": "ElectricArcFurnacePlantBasePerformanceComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 331.21568985008844, "y": 297.6965237937115}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBaseCostComponent", "label": "ElectricArcFurnacePlantBaseCostComponent", "shape": "dot", "size": 19.45945945945946, "title": "ElectricArcFurnacePlantBaseCostComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 467.2216800346311, "y": 318.8505150630724}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceDRIPerformanceComponent", "label": "CMUElectricArcFurnaceDRIPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceDRIPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_dri.py\n[Converter / Steel]", "x": 546.8371236174256, "y": 431.20832772949075}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceBaseClass", "label": "SteelPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SteelPerformanceBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 521.6903751911968, "y": 566.6610637668477}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostBaseClass", "label": "SteelCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SteelCostBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 406.952112243024, "y": 643.0222537742708}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceModel", "label": "SteelPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteelPerformanceModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 272.18129178907674, "y": 613.9005699916162}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostAndFinancialModel", "label": "SteelCostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "SteelCostAndFinancialModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 199.15055717864382, "y": 496.88602197643854}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUPerformanceModel", "label": "SimpleASUPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleASUPerformanceModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 232.2254768075065, "y": 362.9235822800501}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUCostModel", "label": "SimpleASUCostModel", "shape": "dot", "size": 18.0, "title": "SimpleASUCostModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 351.4109262191128, "y": 293.29530750309686}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBWindPlantCostModel", "label": "ATBWindPlantCostModel", "shape": "dot", "size": 18.0, "title": "ATBWindPlantCostModel\nconverters/wind/atb_wind_cost.py\n[Converter / Wind]", "x": 484.44055215455836, "y": 330.297978929092}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMWindPlantPerformanceModel", "label": "PYSAMWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMWindPlantPerformanceModel\nconverters/wind/wind_pysam.py\n[Converter / Wind]", "x": 550.5984027605526, "y": 451.5476939728353}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindPerformanceBaseClass", "label": "WindPerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "WindPerformanceBaseClass\nconverters/wind/wind_plant_baseclass.py\n[Converter / Wind]", "x": 509.69716559653716, "y": 583.5219955261796}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlorisWindPlantPerformanceModel", "label": "FlorisWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "FlorisWindPlantPerformanceModel\nconverters/wind/floris.py\n[Converter / Wind]", "x": 386.4910795111691, "y": 646.1453801885751}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdPerformanceCompatibilityComponent", "label": "WindArdPerformanceCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdPerformanceCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 255.69275934662096, "y": 601.3783905588575}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdCostCompatibilityComponent", "label": "WindArdCostCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdCostCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 196.66404742738186, "y": 476.325072910983}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantPerformanceModel", "label": "SMRMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantPerformanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 245.26041830184303, "y": 346.82157500140227}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantCostModel", "label": "SMRMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantCostModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 372.0506131909644, "y": 291.4439725755037}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantFinanceModel", "label": "SMRMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantFinanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 500.1422507144458, "y": 343.82986093378406}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolPerformanceBaseClass", "label": "MethanolPerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolPerformanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 551.8160292273673, "y": 472.2454066683052}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolCostBaseClass", "label": "MethanolCostBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolCostBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 495.6839168464708, "y": 598.8099536341376}, {"borderWidth": 5.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolFinanceBaseClass", "label": "MethanolFinanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolFinanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 365.7556658010815, "y": 646.7308814798549}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantPerformanceModel", "label": "CO2HMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantPerformanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 240.8316118946296, "y": 586.8992069729802}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantCostModel", "label": "CO2HMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantCostModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 196.70889860494393, "y": 455.57195413603677}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantFinanceModel", "label": "CO2HMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantFinanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 260.1901653677206, "y": 332.3999371200461}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantCostComponent", "label": "HydrogenIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 392.80172635379284, "y": 292.1171568185306}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantCostComponent", "label": "NaturalGasIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 514.1120611197007, "y": 359.1947982547017}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantPerformanceComponent", "label": "HydrogenIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 550.5168235029448, "y": 492.97505700886006}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantPerformanceComponent", "label": "NaturalGasIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 479.8992121579394, "y": 612.3160092753269}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertEwinPerformanceComponent", "label": "HumbertEwinPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HumbertEwinPerformanceComponent\nconverters/iron/humbert_ewin_perf.py\n[Converter / Iron]", "x": 345.0667047898959, "y": 644.8082942814825}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMineCostComponent", "label": "MartinIronMineCostComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMineCostComponent\nconverters/iron/martin_mine_cost_model.py\n[Converter / Iron]", "x": 227.80083824635747, "y": 570.7102438066149}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronTransportCostComponent", "label": "IronTransportCostComponent", "shape": "dot", "size": 18.0, "title": "IronTransportCostComponent\nconverters/iron/iron_transport.py\n[Converter / Iron]", "x": 199.25186993001995, "y": 434.94269396402495}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBasePerformanceComponent", "label": "IronReductionPlantBasePerformanceComponent", "shape": "dot", "size": 19.45945945945946, "title": "IronReductionPlantBasePerformanceComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 276.76776483357787, "y": 319.8555634030555}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBaseCostComponent", "label": "IronReductionPlantBaseCostComponent", "shape": "dot", "size": 19.45945945945946, "title": "IronReductionPlantBaseCostComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 413.3524790181906, "y": 295.27713454003253}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMinePerformanceComponent", "label": "MartinIronMinePerformanceComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMinePerformanceComponent\nconverters/iron/martin_mine_perf_model.py\n[Converter / Iron]", "x": 526.1593352437131, "y": 376.14527848915895}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertStinnEwinCostComponent", "label": "HumbertStinnEwinCostComponent", "shape": "dot", "size": 18.0, "title": "HumbertStinnEwinCostComponent\nconverters/iron/humbert_stinn_ewin_cost.py\n[Converter / Iron]", "x": 546.743615781497, "y": 513.4286945748072}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HOPPComponent", "label": "HOPPComponent", "shape": "dot", "size": 18.0, "title": "HOPPComponent\nconverters/hopp/hopp_wrapper.py\n[Converter / HOPP]", "x": 462.5917542911312, "y": 623.8559111338152}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMTidalPerformanceModel", "label": "PySAMTidalPerformanceModel", "shape": "dot", "size": 18.0, "title": "PySAMTidalPerformanceModel\nconverters/water_power/tidal_pysam.py\n[Converter / Water Power]", "x": 324.72859310432364, "y": 640.4260460063381}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMMarineCostModel", "label": "PySAMMarineCostModel", "shape": "dot", "size": 18.0, "title": "PySAMMarineCostModel\nconverters/water_power/pysam_marine_cost.py\n[Converter / Water Power]", "x": 216.77814592164026, "y": 553.0618685876668}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroPerformanceModel", "label": "RunOfRiverHydroPerformanceModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroPerformanceModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 204.23854510804242, "y": 414.73832160687783}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroCostModel", "label": "RunOfRiverHydroCostModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroCostModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 294.740834296002, "y": 309.3594743780847}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaPerformanceModel", "label": "SimpleAmmoniaPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaPerformanceModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 433.40509869823285, "y": 300.86319031224053}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaCostModel", "label": "SimpleAmmoniaCostModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaCostModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 536.1198784691253, "y": 394.42665374762043}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopPerformanceModel", "label": "AmmoniaSynLoopPerformanceModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopPerformanceModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 540.5636645511591, "y": 533.3117528946093}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopCostModel", "label": "AmmoniaSynLoopCostModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopCostModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 444.01862690077985, "y": 633.2724247412674}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCPerformanceModel", "label": "DOCPerformanceModel", "shape": "dot", "size": 18.0, "title": "DOCPerformanceModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 305.03269414802736, "y": 633.6581275003193}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCCostModel", "label": "DOCCostModel", "shape": "dot", "size": 18.0, "title": "DOCCostModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 207.91368001519578, "y": 534.2137056268189}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAEPerformanceModel", "label": "OAEPerformanceModel", "shape": "dot", "size": 18.0, "title": "OAEPerformanceModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 211.58805712431138, "y": 395.2469621597975}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostModel", "label": "OAECostModel", "shape": "dot", "size": 18.0, "title": "OAECostModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 313.84715753363025, "y": 301.0546018388401}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostAndFinancialModel", "label": "OAECostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "OAECostAndFinancialModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 452.67476445714954, "y": 308.7874754191507}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridPerformanceModel", "label": "GridPerformanceModel", "shape": "dot", "size": 18.0, "title": "GridPerformanceModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 543.8580906910796, "y": 413.7741089596238}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridCostModel", "label": "GridCostModel", "shape": "dot", "size": 18.0, "title": "GridCostModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 532.0718732102009, "y": 552.342805603834}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasPerformanceModel", "label": "NaturalGasPerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGasPerformanceModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 424.4472139785939, "y": 640.4373943201894}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasCostModel", "label": "NaturalGasCostModel", "shape": "dot", "size": 18.0, "title": "NaturalGasCostModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 286.2569295976094, "y": 624.6065418587294}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerPerformance", "label": "SimpleGasProducerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 201.3280452712436, "y": 514.4356470449293}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerPerformance", "label": "SimpleGasConsumerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 221.19128243913522, "y": 376.74290673623443}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerCost", "label": "SimpleGasProducerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 333.8144210804685, "y": 295.05389888426953}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerCost", "label": "SimpleGasConsumerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 470.89095415961566, "y": 318.9337463910879}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceModel", "label": "StoragePerformanceModel", "shape": "diamond", "size": 18.0, "title": "StoragePerformanceModel\nstorage/storage_performance_model.py\n[Storage / General]", "x": 428.09388111524004, "y": -469.09888948081795}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceBase", "label": "StoragePerformanceBase", "shape": "diamond", "size": 20.18918918918919, "title": "StoragePerformanceBase\nstorage/storage_baseclass.py\n[Storage / General]", "x": 455.6085661088584, "y": -385.16822684557377}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageAutoSizingModel", "label": "StorageAutoSizingModel", "shape": "diamond", "size": 18.0, "title": "StorageAutoSizingModel\nstorage/simple_storage_auto_sizing.py\n[Storage / General]", "x": 370.0643470376622, "y": -331.15773226109025}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericStorageCostModel", "label": "GenericStorageCostModel", "shape": "diamond", "size": 18.0, "title": "GenericStorageCostModel\nstorage/generic_storage_cost.py\n[Storage / General]", "x": 264.590914357365, "y": -368.7926071689721}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MCHTOLStorageCostModel", "label": "MCHTOLStorageCostModel", "shape": "diamond", "size": 18.0, "title": "MCHTOLStorageCostModel\nstorage/hydrogen/mch_storage.py\n[Storage / General]", "x": 219.55784982221226, "y": -478.13520688340736}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenStorageBaseCostModel", "label": "HydrogenStorageBaseCostModel", "shape": "diamond", "size": 20.91891891891892, "title": "HydrogenStorageBaseCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 270.16454539792574, "y": -589.4304862347785}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinedRockCavernStorageCostModel", "label": "LinedRockCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "LinedRockCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 388.2687164324305, "y": -630.4775561122241}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SaltCavernStorageCostModel", "label": "SaltCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "SaltCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 501.4805766605486, "y": -572.7844347513467}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PipeStorageCostModel", "label": "PipeStorageCostModel", "shape": "diamond", "size": 18.0, "title": "PipeStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 538.9625776291, "y": -449.75172147563603}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CompressedGasStorageCostModel", "label": "CompressedGasStorageCostModel", "shape": "diamond", "size": 18.0, "title": "CompressedGasStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 475.93189116793945, "y": -336.23888907246976}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMBatteryPerformanceModel", "label": "PySAMBatteryPerformanceModel", "shape": "diamond", "size": 18.0, "title": "PySAMBatteryPerformanceModel\nstorage/battery/pysam_battery.py\n[Storage / General]", "x": 349.5705117805883, "y": -302.34705409538617}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBBatteryCostModel", "label": "ATBBatteryCostModel", "shape": "diamond", "size": 18.0, "title": "ATBBatteryCostModel\nstorage/battery/atb_battery_cost.py\n[Storage / General]", "x": 236.61361523178934, "y": -369.9554252856643}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastLCO", "label": "ProFastLCO", "shape": "star", "size": 18.0, "title": "ProFastLCO\nfinances/profast_lco.py\n[Finance / General]", "x": -486.58132074145146, "y": 260.3302434705349}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastBase", "label": "ProFastBase", "shape": "star", "size": 19.45945945945946, "title": "ProFastBase\nfinances/profast_base.py\n[Finance / General]", "x": -459.0666357478331, "y": 344.2609061057791}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastNPV", "label": "ProFastNPV", "shape": "star", "size": 18.0, "title": "ProFastNPV\nfinances/profast_npv.py\n[Finance / General]", "x": -544.6108548190293, "y": 398.2714006902626}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResourceBaseAPIModel", "label": "ResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "ResourceBaseAPIModel\nresource/resource_base.py\n[Resource / General]", "x": -79.51256037378874, "y": -584.9567473090942}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianSolarAPI", "label": "MeteosatPrimeMeridianSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -51.9978753801704, "y": -501.02608467385005}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianTMYSolarAPI", "label": "MeteosatPrimeMeridianTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianTMYSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -137.5420944513666, "y": -447.0155900893665}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarResourceBaseAPIModel", "label": "SolarResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "SolarResourceBaseAPIModel\nresource/solar/solar_resource_base.py\n[Resource / General]", "x": -243.01552713166376, "y": -484.6504649972484}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalSolarResource", "label": "OpenMeteoHistoricalSolarResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalSolarResource\nresource/solar/openmeteo_solar.py\n[Resource / General]", "x": -288.0485916668165, "y": -593.9930647116836}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari7SolarAPI", "label": "Himawari7SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari7SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -237.44189609110305, "y": -705.2883440630549}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari8SolarAPI", "label": "Himawari8SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari8SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -119.33772505659829, "y": -746.3354139405003}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HimawariTMYSolarAPI", "label": "HimawariTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "HimawariTMYSolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -6.125864828480175, "y": -688.6422925796229}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NLRDeveloperAPISolarResourceBase", "label": "NLRDeveloperAPISolarResourceBase", "shape": "triangle", "size": 24.56756756756757, "title": "NLRDeveloperAPISolarResourceBase\nresource/solar/nlr_developer_api_base.py\n[Resource / General]", "x": 31.356136140071186, "y": -565.6095793039123}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESAggregatedSolarAPI", "label": "GOESAggregatedSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESAggregatedSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -31.67455032108934, "y": -452.096746900746}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESConusSolarAPI", "label": "GOESConusSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESConusSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -158.0359297084405, "y": -418.2049119236624}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESFullDiscSolarAPI", "label": "GOESFullDiscSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESFullDiscSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -270.99282625723947, "y": -485.8132831139406}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESTMYSolarAPI", "label": "GOESTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESTMYSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -301.2124767374961, "y": -614.6459391266081}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalWindResource", "label": "OpenMeteoHistoricalWindResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalWindResource\nresource/wind/openmeteo_wind.py\n[Resource / General]", "x": -229.44086839384488, "y": -726.515073522741}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindResourceBaseAPIModel", "label": "WindResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "WindResourceBaseAPIModel\nresource/wind/wind_resource_base.py\n[Resource / General]", "x": -98.67692574249088, "y": -752.9836456314601}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WTKNLRDeveloperAPIWindResource", "label": "WTKNLRDeveloperAPIWindResource", "shape": "triangle", "size": 18.0, "title": "WTKNLRDeveloperAPIWindResource\nresource/wind/nlr_developer_wtk_api.py\n[Resource / General]", "x": 11.735802273041458, "y": -677.3143608199191}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericDemandComponent", "label": "GenericDemandComponent", "shape": "dot", "size": 18.0, "title": "GenericDemandComponent\ndemand/generic_demand.py\n[Other / Other]", "x": -486.58132074145146, "y": -260.3302434705348}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandComponentBase", "label": "DemandComponentBase", "shape": "dot", "size": 19.45945945945946, "title": "DemandComponentBase\ndemand/demand_base.py\n[Other / Other]", "x": -459.0666357478331, "y": -176.39958083529064}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlexibleDemandComponent", "label": "FlexibleDemandComponent", "shape": "dot", "size": 18.0, "title": "FlexibleDemandComponent\ndemand/flexible_demand.py\n[Other / Other]", "x": -544.6108548190293, "y": -122.38908625080711}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoStorageControllerBaseClass", "label": "PyomoStorageControllerBaseClass", "shape": "diamond", "size": 19.45945945945946, "title": "PyomoStorageControllerBaseClass\ncontrol/control_strategies/pyomo_storage_controller_baseclass.py\n[Storage / General]", "x": 206.39396475153265, "y": -498.78808129833186}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageOpenLoopControlBase", "label": "StorageOpenLoopControlBase", "shape": "diamond", "size": 20.18918918918919, "title": "StorageOpenLoopControlBase\ncontrol/control_strategies/storage/openloop_storage_control_base.py\n[Storage / General]", "x": 278.1655730951839, "y": -610.6572156944648}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandOpenLoopStorageController", "label": "DemandOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "DemandOpenLoopStorageController\ncontrol/control_strategies/storage/demand_openloop_storage_controller.py\n[Storage / General]", "x": 408.9295157465379, "y": -637.1257878031839}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HeuristicLoadFollowingStorageController", "label": "HeuristicLoadFollowingStorageController", "shape": "diamond", "size": 18.0, "title": "HeuristicLoadFollowingStorageController\ncontrol/control_strategies/storage/heuristic_pyomo_controller.py\n[Storage / General]", "x": 519.3422437620702, "y": -561.4565029916428}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OptimizedDispatchStorageController", "label": "OptimizedDispatchStorageController", "shape": "diamond", "size": 18.0, "title": "OptimizedDispatchStorageController\ncontrol/control_strategies/storage/optimized_pyomo_controller.py\n[Storage / General]", "x": 541.9933368656092, "y": -429.1430173132935}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleStorageOpenLoopController", "label": "SimpleStorageOpenLoopController", "shape": "diamond", "size": 18.0, "title": "SimpleStorageOpenLoopController\ncontrol/control_strategies/storage/simple_openloop_controller.py\n[Storage / General]", "x": 462.6186718096345, "y": -320.4638955106441}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PeakLoadManagementHeuristicOpenLoopStorageController", "label": "PeakLoadManagementHeuristicOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "PeakLoadManagementHeuristicOpenLoopStorageController\ncontrol/control_strategies/storage/plm_openloop_storage_controller.py\n[Storage / General]", "x": 329.04975630639206, "y": -301.68432548327485}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleBaseClass", "label": "PyomoRuleBaseClass", "shape": "hexagon", "size": 19.45945945945946, "title": "PyomoRuleBaseClass\ncontrol/control_rules/pyomo_rule_baseclass.py\n[Control / General]", "x": 654.0, "y": 0.0}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoDispatchGenericConverter", "label": "PyomoDispatchGenericConverter", "shape": "dot", "size": 18.0, "title": "PyomoDispatchGenericConverter\ncontrol/control_rules/converters/generic_converter.py\n[Converter / Other]", "x": 549.2687648311249, "y": 433.9130181048081}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleStorageBaseclass", "label": "PyomoRuleStorageBaseclass", "shape": "diamond", "size": 18.0, "title": "PyomoRuleStorageBaseclass\ncontrol/control_rules/storage/pyomo_storage_rule_baseclass.py\n[Storage / General]", "x": 222.32576716621526, "y": -384.6114372269132}]); - edges = new vis.DataSet([{"arrows": "to", "from": "SiteBaseComponent", "to": "SiteLocationComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ResizeablePerformanceModelBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SolarPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "LinearH2FuelCellPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteamMethaneReformerPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SubsurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DesalinationPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "QuinnNuclearPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ElectricArcFurnacePlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceDRIPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteelPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleASUPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindArdPerformanceCompatibilityComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MethanolPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HumbertEwinPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "IronReductionPlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MartinIronMinePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "PySAMTidalPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "RunOfRiverHydroPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleAmmoniaPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DOCPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "OAEPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GridPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "NaturalGasPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasProducerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasConsumerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "StoragePerformanceBase"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DemandComponentBase"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "FeedstockCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericConverterCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBUtilityPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBResComPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectrolyzerCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "H2FuelCellCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteamMethaneReformerCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SubsurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DesalinationCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "QuinnNuclearCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "CMUElectricArcFurnaceCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectricArcFurnacePlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteelCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleASUCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBWindPlantCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "WindArdCostCompatibilityComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MethanolCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MartinIronMineCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronTransportCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronReductionPlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HumbertStinnEwinCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "PySAMMarineCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "RunOfRiverHydroCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleAmmoniaCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "AmmoniaSynLoopCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DOCCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostAndFinancialModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GridCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "NaturalGasCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasProducerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasConsumerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MCHTOLStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HydrogenStorageBaseCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBBatteryCostModel"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "ElectrolyzerPerformanceBaseClass"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "AmmoniaSynLoopPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "SolarPerformanceBaseClass", "to": "PYSAMSolarPlantPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerPerformanceBaseClass", "to": "ECOElectrolyzerPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "SingliticoCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "BasicElectrolyzerCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "CustomElectrolyzerCostModel"}, {"arrows": "to", "from": "ECOElectrolyzerPerformanceModel", "to": "WOMBATElectrolyzerModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "NaturalGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "StimulatedGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfaceCostBaseClass", "to": "GeoH2SubsurfaceCostModel"}, {"arrows": "to", "from": "GeoH2SurfacePerformanceBaseClass", "to": "AspenGeoH2SurfacePerformanceModel"}, {"arrows": "to", "from": "GeoH2SurfaceCostBaseClass", "to": "AspenGeoH2SurfaceCostModel"}, {"arrows": "to", "from": "DesalinationPerformanceBaseClass", "to": "ReverseOsmosisPerformanceModel"}, {"arrows": "to", "from": "DesalinationCostBaseClass", "to": "ReverseOsmosisCostModel"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "HydrogenEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "NaturalGasEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "HydrogenEAFPlantCostComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "NaturalGasEAFPlantCostComponent"}, {"arrows": "to", "from": "SteelPerformanceBaseClass", "to": "SteelPerformanceModel"}, {"arrows": "to", "from": "SteelCostBaseClass", "to": "SteelCostAndFinancialModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "PYSAMWindPlantPerformanceModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "SMRMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "CO2HMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "SMRMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "CO2HMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "SMRMethanolPlantFinanceModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "CO2HMethanolPlantFinanceModel"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "HydrogenIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "NaturalGasIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "HydrogenIronReductionPlantCostComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "NaturalGasIronReductionPlantCostComponent"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StoragePerformanceModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StorageAutoSizingModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "PySAMBatteryPerformanceModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "LinedRockCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "SaltCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "PipeStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "CompressedGasStorageCostModel"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastLCO"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastNPV"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "SolarResourceBaseAPIModel"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "WindResourceBaseAPIModel"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "OpenMeteoHistoricalSolarResource"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "NLRDeveloperAPISolarResourceBase"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari7SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari8SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "HimawariTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESAggregatedSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESConusSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESFullDiscSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESTMYSolarAPI"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "OpenMeteoHistoricalWindResource"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "WTKNLRDeveloperAPIWindResource"}, {"arrows": "to", "from": "DemandComponentBase", "to": "GenericDemandComponent"}, {"arrows": "to", "from": "DemandComponentBase", "to": "FlexibleDemandComponent"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "HeuristicLoadFollowingStorageController"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "OptimizedDispatchStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "DemandOpenLoopStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "SimpleStorageOpenLoopController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "PeakLoadManagementHeuristicOpenLoopStorageController"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoDispatchGenericConverter"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoRuleStorageBaseclass"}]); + nodes = new vis.DataSet([{"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FeedstockCostModel", "label": "FeedstockCostModel", "shape": "ellipse", "size": 18.0, "title": "FeedstockCostModel\ncore/feedstocks.py\n[Core / General]", "x": -79.5125603737886, "y": 584.9567473090942}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteBaseComponent", "label": "SiteBaseComponent", "shape": "ellipse", "size": 18.72972972972973, "title": "SiteBaseComponent\ncore/sites.py\n[Core / General]", "x": -51.99787538017026, "y": 668.8874099443384}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteLocationComponent", "label": "SiteLocationComponent", "shape": "ellipse", "size": 18.0, "title": "SiteLocationComponent\ncore/sites.py\n[Core / General]", "x": -137.54209445136647, "y": 722.897904528822}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PerformanceModelBaseClass", "label": "PerformanceModelBaseClass", "shape": "ellipse", "size": 40.62162162162162, "title": "PerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -243.0155271316636, "y": 685.2630296209401}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CostModelBaseClass", "label": "CostModelBaseClass", "shape": "ellipse", "size": 45.0, "title": "CostModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -288.0485916668164, "y": 575.9204299065049}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResizeablePerformanceModelBaseClass", "label": "ResizeablePerformanceModelBaseClass", "shape": "ellipse", "size": 19.45945945945946, "title": "ResizeablePerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -237.4418960911029, "y": 464.62515055513364}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CacheBaseClass", "label": "CacheBaseClass", "shape": "ellipse", "size": 19.45945945945946, "title": "CacheBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -119.33772505659815, "y": 423.5780806776881}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericConverterCostModel", "label": "GenericConverterCostModel", "shape": "dot", "size": 18.0, "title": "GenericConverterCostModel\nconverters/generic_converter_cost.py\n[Converter / Other]", "x": 428.09388111524015, "y": 469.0988894808179}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMSolarPlantPerformanceModel", "label": "PYSAMSolarPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMSolarPlantPerformanceModel\nconverters/solar/solar_pysam.py\n[Converter / Solar]", "x": 455.6085661088585, "y": 553.0295521160621}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBUtilityPVCostModel", "label": "ATBUtilityPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBUtilityPVCostModel\nconverters/solar/atb_utility_pv_cost.py\n[Converter / Solar]", "x": 370.0643470376623, "y": 607.0400467005456}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBResComPVCostModel", "label": "ATBResComPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBResComPVCostModel\nconverters/solar/atb_res_com_pv_cost.py\n[Converter / Solar]", "x": 264.59091435736514, "y": 569.4051717926637}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarPerformanceBaseClass", "label": "SolarPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SolarPerformanceBaseClass\nconverters/solar/solar_baseclass.py\n[Converter / Solar]", "x": 219.55784982221238, "y": 460.06257207822847}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerPerformanceBaseClass", "label": "ElectrolyzerPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "ElectrolyzerPerformanceBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 270.16454539792585, "y": 348.7672927268573}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerCostBaseClass", "label": "ElectrolyzerCostBaseClass", "shape": "dot", "size": 20.18918918918919, "title": "ElectrolyzerCostBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 388.2687164324306, "y": 307.72022284941175}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SingliticoCostModel", "label": "SingliticoCostModel", "shape": "dot", "size": 18.0, "title": "SingliticoCostModel\nconverters/hydrogen/singlitico_cost_model.py\n[Converter / Hydrogen]", "x": 501.4805766605487, "y": 365.4133442102892}, {"borderWidth": 1, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WOMBATElectrolyzerModel", "label": "WOMBATElectrolyzerModel", "shape": "dot", "size": 18.0, "title": "WOMBATElectrolyzerModel\nconverters/hydrogen/wombat_model.py\n[Converter / Hydrogen]", "x": 538.9625776291001, "y": 488.44605748599986}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinearH2FuelCellPerformanceModel", "label": "LinearH2FuelCellPerformanceModel", "shape": "dot", "size": 18.0, "title": "LinearH2FuelCellPerformanceModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 475.93189116793957, "y": 601.9588898891661}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "H2FuelCellCostModel", "label": "H2FuelCellCostModel", "shape": "dot", "size": 18.0, "title": "H2FuelCellCostModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 349.5705117805884, "y": 635.8507248662497}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerPerformanceModel", "label": "SteamMethaneReformerPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerPerformanceModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 236.61361523178945, "y": 568.2423536759715}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerCostModel", "label": "SteamMethaneReformerCostModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerCostModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 206.39396475153276, "y": 439.409697663304}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "BasicElectrolyzerCostModel", "label": "BasicElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "BasicElectrolyzerCostModel\nconverters/hydrogen/basic_cost_model.py\n[Converter / Hydrogen]", "x": 278.165573095184, "y": 327.54056326717114}, {"borderWidth": 2.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ECOElectrolyzerPerformanceModel", "label": "ECOElectrolyzerPerformanceModel", "shape": "dot", "size": 18.72972972972973, "title": "ECOElectrolyzerPerformanceModel\nconverters/hydrogen/pem_electrolyzer.py\n[Converter / Hydrogen]", "x": 408.929515746538, "y": 301.0719911584519}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CustomElectrolyzerCostModel", "label": "CustomElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "CustomElectrolyzerCostModel\nconverters/hydrogen/custom_electrolyzer_cost_model.py\n[Converter / Hydrogen]", "x": 519.3422437620703, "y": 376.741275969993}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostModel", "label": "GeoH2SubsurfaceCostModel", "shape": "dot", "size": 18.0, "title": "GeoH2SubsurfaceCostModel\nconverters/hydrogen/geologic/mathur_modified.py\n[Converter / Hydrogen]", "x": 541.9933368656093, "y": 509.0547616483423}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfacePerformanceBaseClass", "label": "GeoH2SubsurfacePerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "GeoH2SubsurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 462.61867180963463, "y": 617.7338834509918}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostBaseClass", "label": "GeoH2SubsurfaceCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SubsurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 329.04975630639217, "y": 636.513453478361}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfacePerformanceModel", "label": "AspenGeoH2SurfacePerformanceModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfacePerformanceModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 222.32576716621537, "y": 553.5863417347226}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfaceCostModel", "label": "AspenGeoH2SurfaceCostModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfaceCostModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 207.46113153897124, "y": 419.00371238109653}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGeoH2PerformanceModel", "label": "NaturalGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGeoH2PerformanceModel\nconverters/hydrogen/geologic/simple_natural_geoh2.py\n[Converter / Hydrogen]", "x": 293.81016729091453, "y": 314.4201619012048}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StimulatedGeoH2PerformanceModel", "label": "StimulatedGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "StimulatedGeoH2PerformanceModel\nconverters/hydrogen/geologic/templeton_serpentinization.py\n[Converter / Hydrogen]", "x": 429.1980303433203, "y": 303.5048975398027}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfacePerformanceBaseClass", "label": "GeoH2SurfacePerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 531.4807512394786, "y": 393.1585470237545}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfaceCostBaseClass", "label": "GeoH2SurfaceCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "GeoH2SurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 538.4198729733245, "y": 529.1652694271473}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisPerformanceModel", "label": "ReverseOsmosisPerformanceModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisPerformanceModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 445.5710237882473, "y": 629.0047614736493}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisCostModel", "label": "ReverseOsmosisCostModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisCostModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 309.11651798504033, "y": 631.947653855694}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationPerformanceBaseClass", "label": "DesalinationPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "DesalinationPerformanceBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 211.84908461781183, "y": 536.0083507662598}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationCostBaseClass", "label": "DesalinationCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "DesalinationCostBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 212.91655044595416, "y": 399.26617741803875}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearPerformanceModel", "label": "QuinnNuclearPerformanceModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearPerformanceModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 311.84419223616084, "y": 304.68898638961775}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearCostModel", "label": "QuinnNuclearCostModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearCostModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 448.7220200189815, "y": 309.77552217810415}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceCostModel", "label": "CMUElectricArcFurnaceCostModel", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceCostModel\nconverters/steel/cmu_eaf_cost.py\n[Converter / Steel]", "x": 540.4994435124524, "y": 411.5906925910052}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantCostComponent", "label": "HydrogenEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 531.3901362621964, "y": 548.4583323631547}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantCostComponent", "label": "NaturalGasEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 426.78782378431725, "y": 637.3337381981482}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantPerformanceComponent", "label": "HydrogenEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 290.0713774101109, "y": 624.2026575560053}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantPerformanceComponent", "label": "NaturalGasEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 204.19394571089566, "y": 516.9137611171568}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "label": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_scrap.py\n[Converter / Steel]", "x": 221.34134343018306, "y": 380.48561129518464}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBasePerformanceComponent", "label": "ElectricArcFurnacePlantBasePerformanceComponent", "shape": "dot", "size": 19.45945945945946, "title": "ElectricArcFurnacePlantBasePerformanceComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 331.21568985008844, "y": 297.6965237937115}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBaseCostComponent", "label": "ElectricArcFurnacePlantBaseCostComponent", "shape": "dot", "size": 19.45945945945946, "title": "ElectricArcFurnacePlantBaseCostComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 467.2216800346311, "y": 318.8505150630724}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceDRIPerformanceComponent", "label": "CMUElectricArcFurnaceDRIPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceDRIPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_dri.py\n[Converter / Steel]", "x": 546.8371236174256, "y": 431.20832772949075}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceBaseClass", "label": "SteelPerformanceBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SteelPerformanceBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 521.6903751911968, "y": 566.6610637668477}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostBaseClass", "label": "SteelCostBaseClass", "shape": "dot", "size": 18.72972972972973, "title": "SteelCostBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 406.952112243024, "y": 643.0222537742708}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceModel", "label": "SteelPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteelPerformanceModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 272.18129178907674, "y": 613.9005699916162}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostAndFinancialModel", "label": "SteelCostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "SteelCostAndFinancialModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 199.15055717864382, "y": 496.88602197643854}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUPerformanceModel", "label": "SimpleASUPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleASUPerformanceModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 232.2254768075065, "y": 362.9235822800501}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUCostModel", "label": "SimpleASUCostModel", "shape": "dot", "size": 18.0, "title": "SimpleASUCostModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 351.4109262191128, "y": 293.29530750309686}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBWindPlantCostModel", "label": "ATBWindPlantCostModel", "shape": "dot", "size": 18.0, "title": "ATBWindPlantCostModel\nconverters/wind/atb_wind_cost.py\n[Converter / Wind]", "x": 484.44055215455836, "y": 330.297978929092}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMWindPlantPerformanceModel", "label": "PYSAMWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMWindPlantPerformanceModel\nconverters/wind/wind_pysam.py\n[Converter / Wind]", "x": 550.5984027605526, "y": 451.5476939728353}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindPerformanceBaseClass", "label": "WindPerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "WindPerformanceBaseClass\nconverters/wind/wind_plant_baseclass.py\n[Converter / Wind]", "x": 509.69716559653716, "y": 583.5219955261796}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlorisWindPlantPerformanceModel", "label": "FlorisWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "FlorisWindPlantPerformanceModel\nconverters/wind/floris.py\n[Converter / Wind]", "x": 386.4910795111691, "y": 646.1453801885751}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdPerformanceCompatibilityComponent", "label": "WindArdPerformanceCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdPerformanceCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 255.69275934662096, "y": 601.3783905588575}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdCostCompatibilityComponent", "label": "WindArdCostCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdCostCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 196.66404742738186, "y": 476.325072910983}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantPerformanceModel", "label": "SMRMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantPerformanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 245.26041830184303, "y": 346.82157500140227}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantCostModel", "label": "SMRMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantCostModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 372.0506131909644, "y": 291.4439725755037}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantFinanceModel", "label": "SMRMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantFinanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 500.1422507144458, "y": 343.82986093378406}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolPerformanceBaseClass", "label": "MethanolPerformanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolPerformanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 551.8160292273673, "y": 472.2454066683052}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolCostBaseClass", "label": "MethanolCostBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolCostBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 495.6839168464708, "y": 598.8099536341376}, {"borderWidth": 5.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolFinanceBaseClass", "label": "MethanolFinanceBaseClass", "shape": "dot", "size": 19.45945945945946, "title": "MethanolFinanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 365.7556658010815, "y": 646.7308814798549}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantPerformanceModel", "label": "CO2HMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantPerformanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 240.8316118946296, "y": 586.8992069729802}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantCostModel", "label": "CO2HMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantCostModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 196.70889860494393, "y": 455.57195413603677}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantFinanceModel", "label": "CO2HMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantFinanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 260.1901653677206, "y": 332.3999371200461}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantCostComponent", "label": "HydrogenIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 392.80172635379284, "y": 292.1171568185306}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantCostComponent", "label": "NaturalGasIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 514.1120611197007, "y": 359.1947982547017}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantPerformanceComponent", "label": "HydrogenIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 550.5168235029448, "y": 492.97505700886006}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantPerformanceComponent", "label": "NaturalGasIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 479.8992121579394, "y": 612.3160092753269}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertEwinPerformanceComponent", "label": "HumbertEwinPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HumbertEwinPerformanceComponent\nconverters/iron/humbert_ewin_perf.py\n[Converter / Iron]", "x": 345.0667047898959, "y": 644.8082942814825}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMineCostComponent", "label": "MartinIronMineCostComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMineCostComponent\nconverters/iron/martin_mine_cost_model.py\n[Converter / Iron]", "x": 227.80083824635747, "y": 570.7102438066149}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronTransportCostComponent", "label": "IronTransportCostComponent", "shape": "dot", "size": 18.0, "title": "IronTransportCostComponent\nconverters/iron/iron_transport.py\n[Converter / Iron]", "x": 199.25186993001995, "y": 434.94269396402495}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBasePerformanceComponent", "label": "IronReductionPlantBasePerformanceComponent", "shape": "dot", "size": 19.45945945945946, "title": "IronReductionPlantBasePerformanceComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 276.76776483357787, "y": 319.8555634030555}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBaseCostComponent", "label": "IronReductionPlantBaseCostComponent", "shape": "dot", "size": 19.45945945945946, "title": "IronReductionPlantBaseCostComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 413.3524790181906, "y": 295.27713454003253}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMinePerformanceComponent", "label": "MartinIronMinePerformanceComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMinePerformanceComponent\nconverters/iron/martin_mine_perf_model.py\n[Converter / Iron]", "x": 526.1593352437131, "y": 376.14527848915895}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertStinnEwinCostComponent", "label": "HumbertStinnEwinCostComponent", "shape": "dot", "size": 18.0, "title": "HumbertStinnEwinCostComponent\nconverters/iron/humbert_stinn_ewin_cost.py\n[Converter / Iron]", "x": 546.743615781497, "y": 513.4286945748072}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HOPPComponent", "label": "HOPPComponent", "shape": "dot", "size": 18.0, "title": "HOPPComponent\nconverters/hopp/hopp_wrapper.py\n[Converter / HOPP]", "x": 462.5917542911312, "y": 623.8559111338152}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMTidalPerformanceModel", "label": "PySAMTidalPerformanceModel", "shape": "dot", "size": 18.0, "title": "PySAMTidalPerformanceModel\nconverters/water_power/tidal_pysam.py\n[Converter / Water Power]", "x": 324.72859310432364, "y": 640.4260460063381}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMMarineCostModel", "label": "PySAMMarineCostModel", "shape": "dot", "size": 18.0, "title": "PySAMMarineCostModel\nconverters/water_power/pysam_marine_cost.py\n[Converter / Water Power]", "x": 216.77814592164026, "y": 553.0618685876668}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroPerformanceModel", "label": "RunOfRiverHydroPerformanceModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroPerformanceModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 204.23854510804242, "y": 414.73832160687783}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroCostModel", "label": "RunOfRiverHydroCostModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroCostModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 294.740834296002, "y": 309.3594743780847}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaPerformanceModel", "label": "SimpleAmmoniaPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaPerformanceModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 433.40509869823285, "y": 300.86319031224053}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaCostModel", "label": "SimpleAmmoniaCostModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaCostModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 536.1198784691253, "y": 394.42665374762043}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopPerformanceModel", "label": "AmmoniaSynLoopPerformanceModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopPerformanceModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 540.5636645511591, "y": 533.3117528946093}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopCostModel", "label": "AmmoniaSynLoopCostModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopCostModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 444.01862690077985, "y": 633.2724247412674}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCPerformanceModel", "label": "DOCPerformanceModel", "shape": "dot", "size": 18.0, "title": "DOCPerformanceModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 305.03269414802736, "y": 633.6581275003193}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCCostModel", "label": "DOCCostModel", "shape": "dot", "size": 18.0, "title": "DOCCostModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 207.91368001519578, "y": 534.2137056268189}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAEPerformanceModel", "label": "OAEPerformanceModel", "shape": "dot", "size": 18.0, "title": "OAEPerformanceModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 211.58805712431138, "y": 395.2469621597975}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostModel", "label": "OAECostModel", "shape": "dot", "size": 18.0, "title": "OAECostModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 313.84715753363025, "y": 301.0546018388401}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostAndFinancialModel", "label": "OAECostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "OAECostAndFinancialModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 452.67476445714954, "y": 308.7874754191507}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridPerformanceModel", "label": "GridPerformanceModel", "shape": "dot", "size": 18.0, "title": "GridPerformanceModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 543.8580906910796, "y": 413.7741089596238}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridCostModel", "label": "GridCostModel", "shape": "dot", "size": 18.0, "title": "GridCostModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 532.0718732102009, "y": 552.342805603834}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasPerformanceModel", "label": "NaturalGasPerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGasPerformanceModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 424.4472139785939, "y": 640.4373943201894}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasCostModel", "label": "NaturalGasCostModel", "shape": "dot", "size": 18.0, "title": "NaturalGasCostModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 286.2569295976094, "y": 624.6065418587294}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerPerformance", "label": "SimpleGasProducerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 201.3280452712436, "y": 514.4356470449293}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerPerformance", "label": "SimpleGasConsumerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 221.19128243913522, "y": 376.74290673623443}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerCost", "label": "SimpleGasProducerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 333.8144210804685, "y": 295.05389888426953}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerCost", "label": "SimpleGasConsumerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 470.89095415961566, "y": 318.9337463910879}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceModel", "label": "StoragePerformanceModel", "shape": "diamond", "size": 18.0, "title": "StoragePerformanceModel\nstorage/storage_performance_model.py\n[Storage / General]", "x": 428.09388111524004, "y": -469.09888948081795}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceBase", "label": "StoragePerformanceBase", "shape": "diamond", "size": 20.18918918918919, "title": "StoragePerformanceBase\nstorage/storage_baseclass.py\n[Storage / General]", "x": 455.6085661088584, "y": -385.16822684557377}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageAutoSizingModel", "label": "StorageAutoSizingModel", "shape": "diamond", "size": 18.0, "title": "StorageAutoSizingModel\nstorage/simple_storage_auto_sizing.py\n[Storage / General]", "x": 370.0643470376622, "y": -331.15773226109025}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericStorageCostModel", "label": "GenericStorageCostModel", "shape": "diamond", "size": 18.0, "title": "GenericStorageCostModel\nstorage/generic_storage_cost.py\n[Storage / General]", "x": 264.590914357365, "y": -368.7926071689721}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MCHTOLStorageCostModel", "label": "MCHTOLStorageCostModel", "shape": "diamond", "size": 18.0, "title": "MCHTOLStorageCostModel\nstorage/hydrogen/mch_storage.py\n[Storage / General]", "x": 219.55784982221226, "y": -478.13520688340736}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenStorageBaseCostModel", "label": "HydrogenStorageBaseCostModel", "shape": "diamond", "size": 20.91891891891892, "title": "HydrogenStorageBaseCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 270.16454539792574, "y": -589.4304862347785}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinedRockCavernStorageCostModel", "label": "LinedRockCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "LinedRockCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 388.2687164324305, "y": -630.4775561122241}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SaltCavernStorageCostModel", "label": "SaltCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "SaltCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 501.4805766605486, "y": -572.7844347513467}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PipeStorageCostModel", "label": "PipeStorageCostModel", "shape": "diamond", "size": 18.0, "title": "PipeStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 538.9625776291, "y": -449.75172147563603}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CompressedGasStorageCostModel", "label": "CompressedGasStorageCostModel", "shape": "diamond", "size": 18.0, "title": "CompressedGasStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 475.93189116793945, "y": -336.23888907246976}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMBatteryPerformanceModel", "label": "PySAMBatteryPerformanceModel", "shape": "diamond", "size": 18.0, "title": "PySAMBatteryPerformanceModel\nstorage/battery/pysam_battery.py\n[Storage / General]", "x": 349.5705117805883, "y": -302.34705409538617}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBBatteryCostModel", "label": "ATBBatteryCostModel", "shape": "diamond", "size": 18.0, "title": "ATBBatteryCostModel\nstorage/battery/atb_battery_cost.py\n[Storage / General]", "x": 236.61361523178934, "y": -369.9554252856643}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastLCO", "label": "ProFastLCO", "shape": "star", "size": 18.0, "title": "ProFastLCO\nfinances/profast_lco.py\n[Finance / General]", "x": -486.58132074145146, "y": 260.3302434705349}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastBase", "label": "ProFastBase", "shape": "star", "size": 19.45945945945946, "title": "ProFastBase\nfinances/profast_base.py\n[Finance / General]", "x": -459.0666357478331, "y": 344.2609061057791}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastNPV", "label": "ProFastNPV", "shape": "star", "size": 18.0, "title": "ProFastNPV\nfinances/profast_npv.py\n[Finance / General]", "x": -544.6108548190293, "y": 398.2714006902626}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResourceBaseAPIModel", "label": "ResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "ResourceBaseAPIModel\nresource/resource_base.py\n[Resource / General]", "x": -79.51256037378874, "y": -584.9567473090942}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianSolarAPI", "label": "MeteosatPrimeMeridianSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -51.9978753801704, "y": -501.02608467385005}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianTMYSolarAPI", "label": "MeteosatPrimeMeridianTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianTMYSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -137.5420944513666, "y": -447.0155900893665}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarResourceBaseAPIModel", "label": "SolarResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "SolarResourceBaseAPIModel\nresource/solar/solar_resource_base.py\n[Resource / General]", "x": -243.01552713166376, "y": -484.6504649972484}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalSolarResource", "label": "OpenMeteoHistoricalSolarResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalSolarResource\nresource/solar/openmeteo_solar.py\n[Resource / General]", "x": -288.0485916668165, "y": -593.9930647116836}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari7SolarAPI", "label": "Himawari7SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari7SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -237.44189609110305, "y": -705.2883440630549}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari8SolarAPI", "label": "Himawari8SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari8SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -119.33772505659829, "y": -746.3354139405003}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HimawariTMYSolarAPI", "label": "HimawariTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "HimawariTMYSolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -6.125864828480175, "y": -688.6422925796229}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NLRDeveloperAPISolarResourceBase", "label": "NLRDeveloperAPISolarResourceBase", "shape": "triangle", "size": 24.56756756756757, "title": "NLRDeveloperAPISolarResourceBase\nresource/solar/nlr_developer_api_base.py\n[Resource / General]", "x": 31.356136140071186, "y": -565.6095793039123}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESAggregatedSolarAPI", "label": "GOESAggregatedSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESAggregatedSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -31.67455032108934, "y": -452.096746900746}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESConusSolarAPI", "label": "GOESConusSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESConusSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -158.0359297084405, "y": -418.2049119236624}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESFullDiscSolarAPI", "label": "GOESFullDiscSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESFullDiscSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -270.99282625723947, "y": -485.8132831139406}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESTMYSolarAPI", "label": "GOESTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESTMYSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -301.2124767374961, "y": -614.6459391266081}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalWindResource", "label": "OpenMeteoHistoricalWindResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalWindResource\nresource/wind/openmeteo_wind.py\n[Resource / General]", "x": -229.44086839384488, "y": -726.515073522741}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindResourceBaseAPIModel", "label": "WindResourceBaseAPIModel", "shape": "triangle", "size": 19.45945945945946, "title": "WindResourceBaseAPIModel\nresource/wind/wind_resource_base.py\n[Resource / General]", "x": -98.67692574249088, "y": -752.9836456314601}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WTKNLRDeveloperAPIWindResource", "label": "WTKNLRDeveloperAPIWindResource", "shape": "triangle", "size": 18.0, "title": "WTKNLRDeveloperAPIWindResource\nresource/wind/nlr_developer_wtk_api.py\n[Resource / General]", "x": 11.735802273041458, "y": -677.3143608199191}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericDemandComponent", "label": "GenericDemandComponent", "shape": "dot", "size": 18.0, "title": "GenericDemandComponent\ndemand/generic_demand.py\n[Other / Other]", "x": -486.58132074145146, "y": -260.3302434705348}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandComponentBase", "label": "DemandComponentBase", "shape": "dot", "size": 19.45945945945946, "title": "DemandComponentBase\ndemand/demand_base.py\n[Other / Other]", "x": -459.0666357478331, "y": -176.39958083529064}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlexibleDemandComponent", "label": "FlexibleDemandComponent", "shape": "dot", "size": 18.0, "title": "FlexibleDemandComponent\ndemand/flexible_demand.py\n[Other / Other]", "x": -544.6108548190293, "y": -122.38908625080711}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoStorageControllerBaseClass", "label": "PyomoStorageControllerBaseClass", "shape": "diamond", "size": 20.18918918918919, "title": "PyomoStorageControllerBaseClass\ncontrol/control_strategies/pyomo_storage_controller_baseclass.py\n[Storage / General]", "x": 206.39396475153265, "y": -498.78808129833186}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SystemLevelControlBase", "label": "SystemLevelControlBase", "shape": "hexagon", "size": 20.18918918918919, "title": "SystemLevelControlBase\ncontrol/control_strategies/system_level/system_level_control_base.py\n[Control / General]", "x": 654.0, "y": 0.0}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProfitMaximizationControl", "label": "ProfitMaximizationControl", "shape": "hexagon", "size": 18.0, "title": "ProfitMaximizationControl\ncontrol/control_strategies/system_level/profit_maximization_control.py\n[Control / General]", "x": 681.5146849936184, "y": 83.93066263524416}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandFollowingControl", "label": "DemandFollowingControl", "shape": "hexagon", "size": 18.0, "title": "DemandFollowingControl\ncontrol/control_strategies/system_level/demand_following_control.py\n[Control / General]", "x": 595.9704659224221, "y": 137.9411572197277}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CostMinimizationControl", "label": "CostMinimizationControl", "shape": "hexagon", "size": 18.0, "title": "CostMinimizationControl\ncontrol/control_strategies/system_level/cost_minimization_control.py\n[Control / General]", "x": 490.497033242125, "y": 100.30628231184586}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PeakLoadManagementOptimizedStorageController", "label": "PeakLoadManagementOptimizedStorageController", "shape": "diamond", "size": 18.0, "title": "PeakLoadManagementOptimizedStorageController\ncontrol/control_strategies/storage/plm_optimized_storage_controller.py\n[Storage / General]", "x": 278.1655730951839, "y": -610.6572156944648}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageOpenLoopControlBase", "label": "StorageOpenLoopControlBase", "shape": "diamond", "size": 20.18918918918919, "title": "StorageOpenLoopControlBase\ncontrol/control_strategies/storage/openloop_storage_control_base.py\n[Storage / General]", "x": 408.9295157465379, "y": -637.1257878031839}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandOpenLoopStorageController", "label": "DemandOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "DemandOpenLoopStorageController\ncontrol/control_strategies/storage/demand_openloop_storage_controller.py\n[Storage / General]", "x": 519.3422437620702, "y": -561.4565029916428}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HeuristicLoadFollowingStorageController", "label": "HeuristicLoadFollowingStorageController", "shape": "diamond", "size": 18.0, "title": "HeuristicLoadFollowingStorageController\ncontrol/control_strategies/storage/heuristic_pyomo_controller.py\n[Storage / General]", "x": 541.9933368656092, "y": -429.1430173132935}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OptimizedDispatchStorageController", "label": "OptimizedDispatchStorageController", "shape": "diamond", "size": 18.0, "title": "OptimizedDispatchStorageController\ncontrol/control_strategies/storage/optimized_pyomo_controller.py\n[Storage / General]", "x": 462.6186718096345, "y": -320.4638955106441}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleStorageOpenLoopController", "label": "SimpleStorageOpenLoopController", "shape": "diamond", "size": 18.0, "title": "SimpleStorageOpenLoopController\ncontrol/control_strategies/storage/simple_openloop_controller.py\n[Storage / General]", "x": 329.04975630639206, "y": -301.68432548327485}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PeakLoadManagementHeuristicOpenLoopStorageController", "label": "PeakLoadManagementHeuristicOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "PeakLoadManagementHeuristicOpenLoopStorageController\ncontrol/control_strategies/storage/plm_openloop_storage_controller.py\n[Storage / General]", "x": 222.32576716621526, "y": -384.6114372269132}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleBaseClass", "label": "PyomoRuleBaseClass", "shape": "hexagon", "size": 19.45945945945946, "title": "PyomoRuleBaseClass\ncontrol/control_rules/pyomo_rule_baseclass.py\n[Control / General]", "x": 445.4639687069722, "y": -9.036317402589397}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoDispatchGenericConverter", "label": "PyomoDispatchGenericConverter", "shape": "dot", "size": 18.0, "title": "PyomoDispatchGenericConverter\ncontrol/control_rules/converters/generic_converter.py\n[Converter / Other]", "x": 549.2687648311249, "y": 433.9130181048081}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleStorageBaseclass", "label": "PyomoRuleStorageBaseclass", "shape": "diamond", "size": 18.0, "title": "PyomoRuleStorageBaseclass\ncontrol/control_rules/storage/pyomo_storage_rule_baseclass.py\n[Storage / General]", "x": 207.46113153897113, "y": -519.1940665805394}]); + edges = new vis.DataSet([{"arrows": "to", "from": "SiteBaseComponent", "to": "SiteLocationComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ResizeablePerformanceModelBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SolarPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "LinearH2FuelCellPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteamMethaneReformerPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SubsurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DesalinationPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "QuinnNuclearPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ElectricArcFurnacePlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceDRIPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteelPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleASUPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindArdPerformanceCompatibilityComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MethanolPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HumbertEwinPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "IronReductionPlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MartinIronMinePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "PySAMTidalPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "RunOfRiverHydroPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleAmmoniaPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DOCPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "OAEPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GridPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "NaturalGasPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasProducerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasConsumerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "StoragePerformanceBase"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DemandComponentBase"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "FeedstockCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericConverterCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBUtilityPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBResComPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectrolyzerCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "H2FuelCellCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteamMethaneReformerCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SubsurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DesalinationCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "QuinnNuclearCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "CMUElectricArcFurnaceCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectricArcFurnacePlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteelCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleASUCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBWindPlantCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "WindArdCostCompatibilityComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MethanolCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MartinIronMineCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronTransportCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronReductionPlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HumbertStinnEwinCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "PySAMMarineCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "RunOfRiverHydroCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleAmmoniaCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "AmmoniaSynLoopCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DOCCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostAndFinancialModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GridCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "NaturalGasCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasProducerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasConsumerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MCHTOLStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HydrogenStorageBaseCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBBatteryCostModel"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "ElectrolyzerPerformanceBaseClass"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "AmmoniaSynLoopPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "SolarPerformanceBaseClass", "to": "PYSAMSolarPlantPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerPerformanceBaseClass", "to": "ECOElectrolyzerPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "SingliticoCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "BasicElectrolyzerCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "CustomElectrolyzerCostModel"}, {"arrows": "to", "from": "ECOElectrolyzerPerformanceModel", "to": "WOMBATElectrolyzerModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "NaturalGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "StimulatedGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfaceCostBaseClass", "to": "GeoH2SubsurfaceCostModel"}, {"arrows": "to", "from": "GeoH2SurfacePerformanceBaseClass", "to": "AspenGeoH2SurfacePerformanceModel"}, {"arrows": "to", "from": "GeoH2SurfaceCostBaseClass", "to": "AspenGeoH2SurfaceCostModel"}, {"arrows": "to", "from": "DesalinationPerformanceBaseClass", "to": "ReverseOsmosisPerformanceModel"}, {"arrows": "to", "from": "DesalinationCostBaseClass", "to": "ReverseOsmosisCostModel"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "HydrogenEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "NaturalGasEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "HydrogenEAFPlantCostComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "NaturalGasEAFPlantCostComponent"}, {"arrows": "to", "from": "SteelPerformanceBaseClass", "to": "SteelPerformanceModel"}, {"arrows": "to", "from": "SteelCostBaseClass", "to": "SteelCostAndFinancialModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "PYSAMWindPlantPerformanceModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "SMRMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "CO2HMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "SMRMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "CO2HMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "SMRMethanolPlantFinanceModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "CO2HMethanolPlantFinanceModel"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "HydrogenIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "NaturalGasIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "HydrogenIronReductionPlantCostComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "NaturalGasIronReductionPlantCostComponent"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StoragePerformanceModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StorageAutoSizingModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "PySAMBatteryPerformanceModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "LinedRockCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "SaltCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "PipeStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "CompressedGasStorageCostModel"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastLCO"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastNPV"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "SolarResourceBaseAPIModel"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "WindResourceBaseAPIModel"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "OpenMeteoHistoricalSolarResource"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "NLRDeveloperAPISolarResourceBase"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari7SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari8SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "HimawariTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESAggregatedSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESConusSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESFullDiscSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESTMYSolarAPI"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "OpenMeteoHistoricalWindResource"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "WTKNLRDeveloperAPIWindResource"}, {"arrows": "to", "from": "DemandComponentBase", "to": "GenericDemandComponent"}, {"arrows": "to", "from": "DemandComponentBase", "to": "FlexibleDemandComponent"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "PeakLoadManagementOptimizedStorageController"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "HeuristicLoadFollowingStorageController"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "OptimizedDispatchStorageController"}, {"arrows": "to", "from": "SystemLevelControlBase", "to": "ProfitMaximizationControl"}, {"arrows": "to", "from": "SystemLevelControlBase", "to": "DemandFollowingControl"}, {"arrows": "to", "from": "SystemLevelControlBase", "to": "CostMinimizationControl"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "DemandOpenLoopStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "SimpleStorageOpenLoopController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "PeakLoadManagementHeuristicOpenLoopStorageController"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoDispatchGenericConverter"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoRuleStorageBaseclass"}]); nodeColors = {}; allNodes = nodes.get({ returnType: "Object" }); diff --git a/docs/_toc.yml b/docs/_toc.yml index f09d2dc31..1f4fa339a 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -71,9 +71,14 @@ parts: - caption: Control chapters: - file: control/control_overview - - file: control/open-loop_controllers - - file: control/pyomo_controllers - - file: control/controller_demonstrations + - file: control/system_level_control/system_level_control + sections: + - file: control/system_level_control/control_classifier + - file: control/storage_level_control + sections: + - file: control/open-loop_controllers + - file: control/pyomo_controllers + - file: control/controller_demonstrations - caption: Demand chapters: - file: demand/demand_components diff --git a/docs/control/storage_level_control.md b/docs/control/storage_level_control.md new file mode 100644 index 000000000..30544f0a3 --- /dev/null +++ b/docs/control/storage_level_control.md @@ -0,0 +1,3 @@ +# Storage-Level Control + +ADD diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index 8797ab81b..c5586b54c 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -43,8 +43,17 @@ A dispatchable performance model represents anything that can receive a set poin ``` ## Storage -Storage is a unique control classifier because it assumes that within the model that energy isn't created or destroyed (minus some efficiency losses). While it's technically "dispatchable" in that it can receive and change its performance based on a set point it's handling within H2I is unique because it's attached to storage performance models, which is handled differently than converter performance models. +Storage is a unique control classifier because it assumes that within the model that energy isn't created or destroyed (minus some efficiency losses). While it's technically "dispatchable" in that it can receive and change its performance based on a set point it's handling within H2I is unique because it's attached to storage performance models, which is handled differently than converter performance models. A converter model only has positive (or zero) `{commodity}_out`, whereas a storage model can have positive or negative `{commodity}_out`. -The storage performance models that have the "storage" control classifier additionally require a storage-level controller in addition to the overarching system level controller. See the image below for reference. The storage-level controller takes in the system level-controller set points and outputs charge (negative) and discharge (positive) commands (storage-level set points) to the storage performance model. +There are two types of cases for the storage control classifier: +1. **with a storage controller** +When the storage performance model is controlled with a storage-level controller (open-loop or feedback controlled), the system-level controller outputs combined demand, that is always positive to the storage-level controller. The demand is `{commodity}_in` from the technologies upstream of the storage that output the same commodity to the storage performance model and the `remaining_demand`. -ADD IMAGE - wait until [PR # 731](https://github.com/NatLabRockies/H2Integrate/pull/731) comes in. +2. **without a storage controller** +The system-level controller outputs set points to the storage performance model which can be considered charge (negative) and discharge (positive) commands (storage-level set points) to the storage performance model, directly. + + +```{figure} figures/storage.png +:width: 85% +:align: center +``` diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md new file mode 100644 index 000000000..249e01f67 --- /dev/null +++ b/docs/control/system_level_control/system_level_control.md @@ -0,0 +1,10 @@ +# System-Level Control + +System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller, which can work with other technology level controllers. + +```{figure} figures/storage.png +:width: 70% +:align: center +``` + +At a very basic level the SLC receives a demand. Based on that demand From b04ece225d9bce40eefc32fc5875deb0cec3f300 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Fri, 8 May 2026 12:12:09 -0500 Subject: [PATCH 070/132] docs --- docs/control/system_level_control/system_level_control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 249e01f67..a3bca1143 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -2,7 +2,7 @@ System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller, which can work with other technology level controllers. -```{figure} figures/storage.png +```{figure} figures/slc_basic.png :width: 70% :align: center ``` From 66e11533084c48b4713610dec180b62afefdb851 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 11:25:25 -0600 Subject: [PATCH 071/132] Additional refactoring of demand following control --- .../system_level/demand_following_control.py | 15 +++------------ .../system_level/system_level_control_base.py | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 0269bde9e..00e081ee8 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -17,8 +17,9 @@ class DemandFollowingControl(SystemLevelControlBase): consider costs. """ - def run_control_for_commodity_subset(self, inputs, outputs, commodity, commodity_demand): - demand = commodity_demand.copy() + def compute(self, inputs, outputs): + commodity = self.commodity + demand = inputs[self.demand_input_name].copy() # 1. Curtailable techs: full production for curtailable_tech in self.curtailable_techs: @@ -57,13 +58,3 @@ def run_control_for_commodity_subset(self, inputs, outputs, commodity, commodity outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( remaining_demand / n_dispatchable ) - - return outputs - - def compute(self, inputs, outputs): - if self.multi_commodity_system: - self.find_converter_techs() - - outputs = self.run_control_for_commodity_subset( - inputs, outputs, self.commodity, inputs[self.demand_input_name].copy() - ) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index d162e0778..0e8e0abe1 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -70,7 +70,7 @@ def setup(self): self.curtailable_techs + self.dispatchable_techs + self.storage_techs ) - # Input: demand profile (default value from config) + # Input: demand profile self.demand_input_name = f"{self.commodity}_demand" self.add_input( self.demand_input_name, From ebb9abb7220f8ea7ab0674afb0100c95c930c18e Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 11:34:14 -0600 Subject: [PATCH 072/132] Refactoring some SLC base methods --- .../system_level/demand_following_control.py | 2 +- .../system_level/system_level_control_base.py | 146 +++++++----------- h2integrate/core/h2integrate_model.py | 4 +- 3 files changed, 62 insertions(+), 90 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 00e081ee8..0e885e1a4 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -21,7 +21,7 @@ def compute(self, inputs, outputs): commodity = self.commodity demand = inputs[self.demand_input_name].copy() - # 1. Curtailable techs: full production + # 1. Curtailable techs: operate at full production for curtailable_tech in self.curtailable_techs: commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) # check that this tech produces the commodity demanded diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 0e8e0abe1..7d649f668 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -94,121 +94,93 @@ def setup(self): self._setup_tech_category("storage", self.storage_techs) self._setup_feedstock_category(self.feedstock_comps) - def _setup_commodity_for_given_units( - self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=1.0 + def _setup_commodity( + self, + tech_name, + commodity, + commodity_units=None, + commodity_reference_var=None, + add_in_name=True, + initial_set_point=1.0, ): - """Adds inputs and outputs for a commodity when the units are known. - The inputs and outputs that are added have the below naming convention: + """Register OpenMDAO inputs and outputs for a single (tech, commodity) pair. - - ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name - - ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production - capacity of tech_name - - ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name + This method handles unit specification in two mutually exclusive ways: - Args: - tech_name (str): name of technology - commodity (str): commodity of the technology described by `tech_name` - commodity_units (str): units of commodity - add_in_name (bool, optional): If True, add the input for the in_name variable. - Defaults to True. - initial_set_point (float, optional): Add as the initial value for the - set_point variable. Defaults to 1.0. - Returns: - tuple(str, str, str): tuple of in_name, set_point_name, and rated_name - """ - in_name = f"{tech_name}_{commodity}_out" - rated_name = f"{tech_name}_rated_{commodity}_production" + 1. **Explicit units** - pass ``commodity_units`` (e.g. ``"kW"``). + Each variable is created with ``units=commodity_units``. + 2. **Copied units** - pass ``commodity_reference_var`` (the name of an + already-registered input whose units should be reused). + Each variable is created with ``units=None, copy_units=commodity_reference_var``. - if self.storage_techs_to_control.get(tech_name, False): - # tech_name is storage and does have an attached controller - set_point_name = f"{tech_name}_{commodity}_demand" - else: - # if tech_name is not in storage_techs_to_control - # or storage tech does not have an attached controller - set_point_name = f"{tech_name}_{commodity}_set_point" + Exactly one of ``commodity_units`` or ``commodity_reference_var`` must be + provided. - if add_in_name: - self.add_input( - in_name, - val=0.0, - shape=self.n_timesteps, - units=commodity_units, - desc=f"{commodity} output from {tech_name}", - ) - self.add_input( - rated_name, - val=0.0, - units=commodity_units, - desc=f"Rated {commodity} production for {tech_name}", - ) - self.add_output( - set_point_name, - val=initial_set_point, - shape=self.n_timesteps, - units=commodity_units, - desc=f"Set point for {tech_name} {commodity} curtailment", - ) - - return in_name, set_point_name, rated_name - - def _setup_commodity_for_copy_units( - self, tech_name, commodity, commodity_reference_var, add_in_name=True, initial_set_point=1.0 - ): - """Adds inputs and outputs for a commodity where the units are based on a reference - input variable. The inputs and outputs that are added have the below - naming convention: + The following OpenMDAO variables are created: - - ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name - - ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production - capacity of tech_name - - ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name + - Input ``"{tech_name}_{commodity}_out"`` - commodity produced by the tech + (only if ``add_in_name=True``). + - Input ``"{tech_name}_rated_{commodity}_production"`` - rated production + capacity of the tech. + - Output ``"{tech_name}_{commodity}_set_point"`` (or + ``"{tech_name}_{commodity}_demand"`` for storage techs with an attached + controller) - control set-point sent to the tech. Args: - tech_name (str): name of technology - commodity (str): commodity of the technology described by `tech_name` - commodity_reference_var (str): name of input to copy units from - add_in_name (bool, optional): If True, add the input for the in_name variable. - Defaults to True. - initial_set_point (float, optional): Add as the initial value for the - set_point variable. Defaults to 1.0. + tech_name (str): Name of the technology. + commodity (str): Commodity produced by ``tech_name``. + commodity_units (str | None): Explicit unit string for the commodity. + Mutually exclusive with ``commodity_reference_var``. + commodity_reference_var (str | None): Name of an existing input + variable whose units should be copied. Mutually exclusive with + ``commodity_units``. + add_in_name (bool, optional): If True, register the + ``"{tech_name}_{commodity}_out"`` input. Defaults to True. + initial_set_point (float, optional): Initial value for the + set-point output. Defaults to 1.0. Returns: - tuple(str, str, str): tuple of in_name, set_point_name, and rated_name + tuple[str, str, str]: ``(in_name, set_point_name, rated_name)`` """ + # --- Determine unit kwargs for add_input / add_output --------- + # Either explicit units or copy_units from a reference variable. + if commodity_units is not None: + unit_kwargs = {"units": commodity_units} + else: + unit_kwargs = {"units": None, "copy_units": commodity_reference_var} + + # --- Build variable names ------------------------------------- in_name = f"{tech_name}_{commodity}_out" rated_name = f"{tech_name}_rated_{commodity}_production" + # Storage techs with an attached controller receive a "demand" + # output instead of a "set_point" output. if self.storage_techs_to_control.get(tech_name, False): - # tech_name is storage and does have an attached controller set_point_name = f"{tech_name}_{commodity}_demand" else: - # if tech_name is not in storage_techs_to_control - # or storage tech does not have an attached controller set_point_name = f"{tech_name}_{commodity}_set_point" + # --- Register inputs and output ------------------------------- if add_in_name: self.add_input( in_name, val=0.0, shape=self.n_timesteps, - units=None, - copy_units=commodity_reference_var, desc=f"{commodity} output from {tech_name}", + **unit_kwargs, ) self.add_input( rated_name, val=0.0, - units=None, - copy_units=commodity_reference_var, desc=f"Rated {commodity} production for {tech_name}", + **unit_kwargs, ) self.add_output( set_point_name, val=initial_set_point, shape=self.n_timesteps, - units=None, - copy_units=commodity_reference_var, desc=f"Set point for {tech_name} {commodity} curtailment", + **unit_kwargs, ) return in_name, set_point_name, rated_name @@ -256,19 +228,19 @@ def _setup_tech_category(self, category, tech_list): for commodity in tech_commodities: if commodity in self.commodities_to_units: # Units are already known explicitly - in_name, set_point_name, rated_name = self._setup_commodity_for_given_units( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, - self.commodities_to_units[commodity], + commodity_units=self.commodities_to_units[commodity], add_in_name=True, initial_set_point=initial_set_point, ) elif commodity in self.commodities_to_ref_var: # Units are inferred from a previously-registered reference variable - in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, - self.commodities_to_ref_var[commodity], + commodity_reference_var=self.commodities_to_ref_var[commodity], add_in_name=True, initial_set_point=initial_set_point, ) @@ -288,20 +260,20 @@ def _setup_tech_category(self, category, tech_list): # variable so later techs with this commodity can # copy its units. self.commodities_to_ref_var[commodity] = in_name - in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, - self.commodities_to_ref_var[commodity], + commodity_reference_var=self.commodities_to_ref_var[commodity], add_in_name=False, initial_set_point=initial_set_point, ) else: # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - in_name, set_point_name, rated_name = self._setup_commodity_for_given_units( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, - self.commodities_to_units[commodity], + commodity_units=self.commodities_to_units[commodity], add_in_name=False, initial_set_point=initial_set_point, ) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index d83df0674..69afe1177 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -562,7 +562,7 @@ def _classify_slc_technologies(self): # Remove feedstocks and connectors control_classifiers_to_connect = ["curtailable", "dispatchable", "storage", "feedstock"] - tech_to_commodities = { + tech_to_commodity = { (e[0], e[-1]) for e in sources_to_commodities if self.tech_control_classifiers[e[0]] in control_classifiers_to_connect @@ -572,7 +572,7 @@ def _classify_slc_technologies(self): slc_config["demand_tech"] = demand_tech slc_config["demand_commodity"] = demand_commodity slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units - slc_config["tech_to_commodity"] = tech_to_commodities + slc_config["tech_to_commodity"] = tech_to_commodity slc_config["storage_techs_to_control"] = storage_tech_to_control slc_config["technology_graph"] = self.technology_graph From b427be854694c04b6d8534a0191ac426cfad94f0 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 12:05:31 -0600 Subject: [PATCH 073/132] Added complex profit max example to test --- .../system_level/test/test_slc_examples.py | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 4e23a67d6..ccdf5dc37 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -123,3 +123,90 @@ def test_slc_battery_with_controller(subtests, temp_copy_of_example): ) == 0.10902004 ) + + +@pytest.mark.unit +@pytest.mark.parametrize( + "example_folder,resource_example_folder", + [("35_system_level_control/complex_profit_max", None)], +) +def test_slc_complex_profit_max(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + model = H2IntegrateModel(example_folder / "complex_profit_max.yaml") + + n_timesteps = 8760 + hours_of_day = np.tile(np.arange(24), 365) + day_of_year = np.repeat(np.arange(365), 24) + + # Non-constant demand: base 50 MW, daytime bump to ~80 MW, summer cooling peak + base_demand = 50_000 # kW + daytime_bump = np.where((hours_of_day >= 7) & (hours_of_day < 21), 30_000, 0) + seasonal_demand = 1.0 + 0.4 * np.sin(2 * np.pi * (day_of_year - 172) / 365) + demand_profile = (base_demand + daytime_bump) * seasonal_demand + + # ERCOT-like wholesale sell price ($/kWh) with diurnal shape + sell_price = np.zeros(n_timesteps) + for h in range(n_timesteps): + hour = hours_of_day[h] + day = day_of_year[h // 24] if h // 24 < 365 else day_of_year[-1] + season = 1.0 + 0.35 * np.sin(2 * np.pi * (day - 172) / 365) + + if hour < 6: + price = 0.025 + elif hour < 10: + price = 0.025 + (hour - 6) * 0.008 + elif hour < 15: + price = 0.035 + elif hour < 20: + price = 0.035 + (hour - 15) * 0.018 + else: + price = 0.125 - (hour - 20) * 0.025 + + sell_price[h] = price * season + + # Summer evening price spikes + for h in range(n_timesteps): + day = day_of_year[h // 24] if h // 24 < 365 else day_of_year[-1] + hour = hours_of_day[h] + if 150 <= day <= 250 and 17 <= hour <= 20 and day % 5 == 0: + sell_price[h] = max(sell_price[h], 0.20) + + # Grid buy price: wholesale + retail markup + grid_buy_price = sell_price + 0.02 + + model.setup() + + model.prob.set_val( + "plant.electrical_load_demand.electricity_demand", + demand_profile, + ) + model.prob.set_val( + "plant.system_level_controller.commodity_sell_price", + sell_price, + units="USD/(kW*h)", + ) + model.prob.set_val( + "plant.grid_buy.electricity_buy_price", + grid_buy_price, + units="USD/(kW*h)", + ) + + model.run() + + wind_out = model.prob.get_val("wind.electricity_out") + solar_out = model.prob.get_val("solar.electricity_out") + ng_out = model.prob.get_val("natural_gas_plant.electricity_out", units="kW") + grid_out = model.prob.get_val("grid_buy.electricity_out") + + with subtests.test("wind farm generates power"): + assert wind_out.sum() > 0 + + with subtests.test("solar farm generates power"): + assert solar_out.sum() > 0 + + with subtests.test("natural gas dispatched"): + assert ng_out.sum() > 0 + + with subtests.test("grid used when needed"): + assert grid_out.sum() > 0 From 59b16766307f89c8ceefa9893ae270e701356c12 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Fri, 8 May 2026 12:07:59 -0600 Subject: [PATCH 074/132] updated location of cost_per_tech --- .../battery_with_controller/plant_config.yaml | 7 ++++--- .../complex_profit_max/plant_config.yaml | 13 +++++++------ .../profit_maximization/plant_config.yaml | 10 ++++------ .../yes_hydrogen/plant_config.yaml | 7 ++++--- .../system_level/cost_minimization_control.py | 2 +- .../system_level/profit_maximization_control.py | 3 ++- .../system_level/system_level_control_base.py | 10 +++++++--- h2integrate/core/h2integrate_model.py | 2 +- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/examples/35_system_level_control/battery_with_controller/plant_config.yaml b/examples/35_system_level_control/battery_with_controller/plant_config.yaml index d3c242b7b..a2967e397 100644 --- a/examples/35_system_level_control/battery_with_controller/plant_config.yaml +++ b/examples/35_system_level_control/battery_with_controller/plant_config.yaml @@ -36,9 +36,10 @@ plant: dt: 3600 system_level_control: control_strategy: DemandFollowingControl - solver_name: gauss_seidel - max_iter: 20 - convergence_tolerance: 1.0e-6 + solver_options: + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 finance_parameters: finance_groups: profast_lco: diff --git a/examples/35_system_level_control/complex_profit_max/plant_config.yaml b/examples/35_system_level_control/complex_profit_max/plant_config.yaml index b9379f090..9270b35a2 100644 --- a/examples/35_system_level_control/complex_profit_max/plant_config.yaml +++ b/examples/35_system_level_control/complex_profit_max/plant_config.yaml @@ -42,9 +42,10 @@ system_level_control: control_strategy: ProfitMaximizationControl control_parameters: commodity_sell_price: 0.06 # $/kWh default; overridden in run script - cost_per_tech: - natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx - grid_buy: buy_price # use electricity_buy_price from cost config - solver_name: gauss_seidel - max_iter: 30 - convergence_tolerance: 1.0e-6 + cost_per_tech: + natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx + grid_buy: buy_price # use electricity_buy_price from cost config + solver_options: + solver_name: gauss_seidel + max_iter: 30 + convergence_tolerance: 1.0e-6 diff --git a/examples/35_system_level_control/profit_maximization/plant_config.yaml b/examples/35_system_level_control/profit_maximization/plant_config.yaml index 46f0fb769..fff67f46d 100644 --- a/examples/35_system_level_control/profit_maximization/plant_config.yaml +++ b/examples/35_system_level_control/profit_maximization/plant_config.yaml @@ -25,15 +25,13 @@ plant: dt: 3600 system_level_control: control_strategy: ProfitMaximizationControl + control_parameters: + commodity_sell_price: profast_npv # name of finance group whose commodity_sell_price to use + cost_per_tech: + natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx solver_options: solver_name: gauss_seidel max_iter: 20 - cost_per_tech: - natural_gas_plant: feedstock # use upstream feedstock (ng_feedstock) VarOpEx - control_parameters: - commodity_sell_price: profast_npv # name of finance group whose commodity_sell_price to use - solver_name: gauss_seidel - max_iter: 20 finance_parameters: finance_groups: profast_npv: diff --git a/examples/35_system_level_control/yes_hydrogen/plant_config.yaml b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml index 14e1878ec..ce6872101 100644 --- a/examples/35_system_level_control/yes_hydrogen/plant_config.yaml +++ b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml @@ -43,9 +43,10 @@ plant: dt: 3600 system_level_control: control_strategy: DemandFollowingControl - solver_name: gauss_seidel - max_iter: 20 - convergence_tolerance: 1.0e-6 + solver_options: + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 # finance_parameters: # finance_groups: # profast_lco: diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index e2ea815c1..948589b25 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -16,7 +16,7 @@ class CostMinimizationControl(SystemLevelControlBase): each up to its rated capacity, until remaining demand is met. Marginal costs are configured via ``cost_per_tech`` in the - ``system_level_control`` section of ``plant_config``. Each + ``system_level_control["control_parameters"]`` section of ``plant_config``. Each dispatchable technology's entry can be: - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 4c80f3b52..ed4e04315 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -10,6 +10,7 @@ @define(kw_only=True) class ProfitMaximizationControlConfig(BaseConfig): commodity_sell_price: float = field(default=0.0) + cost_per_tech: dict = field(default={}) class ProfitMaximizationControl(SystemLevelControlBase): @@ -32,7 +33,7 @@ class ProfitMaximizationControl(SystemLevelControlBase): whose ``model_inputs.commodity_sell_price`` will be used. Marginal costs are configured via ``cost_per_tech`` in the - ``system_level_control`` section of ``plant_config``. Each + ``system_level_control["control_parameters"]`` section of ``plant_config``. Each dispatchable technology's entry can be: - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index b953a965a..b80d3a489 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -438,7 +438,7 @@ def _setup_marginal_costs(self): (e.g., ``CostMinimizationControl``, ``ProfitMaximizationControl``). Reads ``cost_per_tech`` from - ``plant_config["system_level_control"]`` and creates appropriate + ``plant_config["system_level_control"]["control_parameters"]`` and creates appropriate OpenMDAO inputs for each dispatchable technology: - Numeric value (e.g. ``0.05``): used directly as a constant @@ -459,8 +459,12 @@ def _setup_marginal_costs(self): divides by the tech's total production. Handles the common single-feedstock case as well as multiple feedstock streams. """ - slc_config = self.options["plant_config"]["system_level_control"] - self.cost_per_tech = slc_config.get("cost_per_tech", {}) + + self.cost_per_tech = ( + self.options["plant_config"]["system_level_control"] + .get("control_parameters", {}) + .get("cost_per_tech", {}) + ) self.dt_hours = self.options["plant_config"]["plant"]["simulation"]["dt"] / 3600 hours_simulated = self.dt_hours * self.n_timesteps self.fraction_of_year_simulated = hours_simulated / 8760 diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 26cdeb595..7fdf556db 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -660,7 +660,7 @@ def add_system_level_controller(self, slc_config): # 4. For cost-aware strategies, connect cost inputs based on cost_per_tech if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): - cost_per_tech = plant_slc_config.get("cost_per_tech", {}) + cost_per_tech = plant_slc_config.get("control_parameters", {}).get("cost_per_tech", {}) for tech_name, _ in slc_config["tech_to_commodity"]: if self.tech_control_classifiers[tech_name] == "dispatchable": cost_spec = cost_per_tech.get(tech_name, 0.0) From 3a20fcf65a43687cf263ed35ed75e33e4c4081ee Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 12:12:50 -0600 Subject: [PATCH 075/132] update SLC add method --- .../system_level/system_level_control_base.py | 23 ++-- h2integrate/core/h2integrate_model.py | 128 ++++++++++++++---- 2 files changed, 115 insertions(+), 36 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 7d649f668..373b6cb4f 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -53,18 +53,17 @@ def setup(self): self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] - self.curtailable_techs = [ - k for k, v in slc_config["tech_control_classifiers"].items() if v == "curtailable" - ] - self.dispatchable_techs = [ - k for k, v in slc_config["tech_control_classifiers"].items() if v == "dispatchable" - ] - self.storage_techs = [ - k for k, v in slc_config["tech_control_classifiers"].items() if v == "storage" - ] - self.feedstock_comps = [ - k for k, v in slc_config["tech_control_classifiers"].items() if v == "feedstock" - ] + # Partition technologies by control classifier in a single pass + classifiers = slc_config["tech_control_classifiers"] + techs_by_category = {"curtailable": [], "dispatchable": [], "storage": [], "feedstock": []} + for tech, category in classifiers.items(): + if category in techs_by_category: + techs_by_category[category].append(tech) + + self.curtailable_techs = techs_by_category["curtailable"] + self.dispatchable_techs = techs_by_category["dispatchable"] + self.storage_techs = techs_by_category["storage"] + self.feedstock_comps = techs_by_category["feedstock"] self.input_techs = set( self.curtailable_techs + self.dispatchable_techs + self.storage_techs diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 69afe1177..818eb728e 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -581,18 +581,92 @@ def _classify_slc_technologies(self): return slc_config def add_system_level_controller(self, slc_config): - """Add the DemandFollowingControl component and configure the plant solver. - - This method: - 1. Selects the appropriate controller class based on ``control_strategy`` - 2. Adds it as a subsystem to the plant group - 3. Configures the nonlinear solver on the plant group - 4. Creates connections between the controller and each technology - 5. For cost/profit strategies, connects marginal cost inputs + """Add a system-level controller component and connect it within the plant. + + Instantiates the controller specified by ``control_strategy`` in the plant configuration, + adds it as an OpenMDAO subsystem named ``"system_level_controller"``, configures + solvers on the plant group to resolve the feedback loop, and creates all + necessary OpenMDAO connections between the controller and the technology models it + dispatches. + + The method executes in five sequential steps: + + 1. **Select and instantiate the controller** - Looks up the class from + ``supported_models`` using the ``control_strategy`` string (e.g. + ``"DemandFollowingControl"``, ``"ProfitMaximizationControl"``). Raises ``ValueError`` + if the strategy name is not found. The instantiated component is added to + ``self.plant`` as ``"system_level_controller"``. + + 2. **Configure the plant-level nonlinear solver** - Because the controller creates a + feedback loop (controller outputs become technology inputs, whose outputs feed back to + the controller), a nonlinear solver is required. Solver type and options are read from + ``plant_config["system_level_control"]["solver_options"]`` via + ``SLCSolverOptionsConfig``. A ``DirectSolver`` is set as the linear solver and + is largely inconsequential as we're not propagating derivatives at this time. + + 3. **Connect technology outputs to controller inputs** - For each ``(tech_name, + commodity)`` pair in ``slc_config["tech_to_commodity"]``: + + - **Feedstock techs**: Only the commodity output + (``{tech_name}_source.{commodity}_out``) is connected to the controller. Feedstocks + have no set-point or rated-production connection. + - **Curtailable / dispatchable / storage techs**: Both the commodity output + (``{tech_name}.{commodity}_out``) and rated production + (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. + The controller's set-point output is connected back to the tech: + + - If the storage tech has its own sub-controller + (``storage_techs_to_control[tech_name] == True``), the controller outputs a + *demand* signal (``{tech_name}_{commodity}_demand``) that the storage + sub-controller consumes. + - Otherwise, the controller outputs a *set_point* signal + (``{tech_name}_{commodity}_set_point``) directly to the performance model. + + 4. **Connect marginal-cost inputs for cost-aware strategies** - Only executed when + ``control_strategy`` is ``"CostMinimizationControl"`` or + ``"ProfitMaximizationControl"``. Additional cost-aware control strategies + would need to be added here. For each dispatchable tech, the ``cost_per_tech`` + specification determines which cost signal is connected: + + - ``"VarOpEx"``: connects the tech's own ``VarOpEx`` output. + - ``"feedstock"``: scans ``technology_interconnections`` for upstream feedstock + technologies and connects each feedstock's ``VarOpEx`` output. + - ``"buy_price"``: no connection needed; the controller reads a default value from the + tech config that can be overridden at runtime via ``prob.set_val()``. + - Numeric scalar: no connection needed; the value is used directly as a constant + marginal cost. + + 5. **Connect the demand profile** - Connects the demand technology's output + (``{demand_tech}.{demand_commodity}_demand_out``) to the controller's demand input + (``system_level_controller.{demand_commodity}_demand``). + + Args: + slc_config (dict): Pre-computed dictionary produced by + ``_classify_slc_technologies()``. Expected keys: + + - ``"demand_tech"`` (str): Name of the demand technology. + - ``"demand_commodity"`` (str): Commodity the demand consumes. + - ``"tech_to_commodity"`` (set[tuple[str, str]]): Set of ``(tech_name, + commodity)`` pairs for all controlled techs. + - ``"tech_control_classifiers"`` (dict[str, str]): Mapping of tech name to + classifier (``"curtailable"``, ``"dispatchable"``, ``"storage"``, + ``"feedstock"``). + - ``"storage_techs_to_control"`` (dict[str, bool]): Whether each storage tech + has its own sub-controller. + - ``"technology_graph"`` (nx.DiGraph): Directed graph of technology + interconnections. + + Raises: + ValueError: If ``control_strategy`` is not found in ``self.supported_models``. + + Side Effects: + - Adds ``"system_level_controller"`` subsystem to ``self.plant``. + - Sets ``self.plant.nonlinear_solver`` and ``self.plant.linear_solver``. + - Creates OpenMDAO connections within ``self.plant``. """ plant_slc_config = self.plant_config["system_level_control"] - # 1. Select controller class based on strategy + # --- Step 1: Select and instantiate the controller class ---------- strategy_name = plant_slc_config.get("control_strategy") slc_cls = self.supported_models.get(strategy_name) if slc_cls is None: @@ -609,7 +683,9 @@ def add_system_level_controller(self, slc_config): ) self.plant.add_subsystem("system_level_controller", slc_comp) - # 2. Configure the nonlinear solver + # --- Step 2: Configure the nonlinear solver on the plant group ---- + # The feedback loop (controller <-> technologies) requires an + # iterative nonlinear solver to converge. solver_config = SLCSolverOptionsConfig.from_dict(plant_slc_config.get("solver_options", {})) solver_cls = solver_config.return_nonlinear_solver() solver = solver_cls() @@ -618,21 +694,22 @@ def add_system_level_controller(self, slc_config): solver.options[k] = v self.plant.nonlinear_solver = solver self.plant.linear_solver = om.DirectSolver() - # 3. Connect the controller's inputs/outputs to technology models - # Curtailable, dispatchable, and storage techs: read output and write set_point + # --- Step 3: Connect technology outputs/inputs to the controller -- for tech_to_commodity in slc_config["tech_to_commodity"]: tech_name, commodity = tech_to_commodity + if slc_config["tech_control_classifiers"][tech_name] == "feedstock": - # Only connect the feedstock output to the SLC + # Feedstocks only provide their commodity output to the + # controller; they receive no set-point back. self.plant.connect( f"{tech_name}_source.{commodity}_out", f"system_level_controller.{tech_name}_{commodity}_out", ) continue - # For all other techs, connect the tech output and rated production - # to the SLC + # Curtailable, dispatchable, and storage techs: connect their + # commodity output and rated production as controller inputs. self.plant.connect( f"{tech_name}.{commodity}_out", f"system_level_controller.{tech_name}_{commodity}_out", @@ -643,34 +720,37 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) - # Connect the SLC to the controllable tech input + # Connect the controller's output back to the technology. if slc_config["storage_techs_to_control"].get(tech_name, False): - # storage has its own controller - # provide demand to storage controller, - # storage controller will provide set-point to performance model + # Storage tech with its own sub-controller: provide a demand + # signal that the sub-controller translates into + # charge/discharge commands. self.plant.connect( f"system_level_controller.{tech_name}_{commodity}_demand", f"{tech_name}.{commodity}_demand", ) else: + # All other techs (or storage without a sub-controller): + # provide a set-point directly to the performance model. self.plant.connect( f"system_level_controller.{tech_name}_{commodity}_set_point", f"{tech_name}.{commodity}_set_point", ) - # 4. For cost-aware strategies, connect cost inputs based on cost_per_tech + # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): cost_per_tech = plant_slc_config.get("cost_per_tech", {}) for tech_name, _ in slc_config["tech_to_commodity"]: if self.tech_control_classifiers[tech_name] == "dispatchable": cost_spec = cost_per_tech.get(tech_name, 0.0) if cost_spec == "VarOpEx": + # Tech's own variable operating expenditure self.plant.connect( f"{tech_name}.VarOpEx", f"system_level_controller.{tech_name}_VarOpEx", ) elif cost_spec == "feedstock": - # Connect VarOpEx from each upstream feedstock + # Sum VarOpEx from all upstream feedstock technologies interconnections = self.plant_config.get("technology_interconnections", []) technologies = self.technology_config.get("technologies", {}) for conn in interconnections: @@ -685,10 +765,10 @@ def add_system_level_controller(self, slc_config): f"{upstream}.VarOpEx", f"system_level_controller.{upstream}_VarOpEx", ) - # buy_price: defaults from tech config, overridable via set_val - # scalar: no connection needed + # "buy_price": default from tech config, overridable via set_val + # numeric scalar: used directly, no connection needed - # Connect demand profile from the demand component to the controller + # --- Step 5: Connect the demand profile to the controller --------- demand_tech = slc_config["demand_tech"] demand_commodity = slc_config["demand_commodity"] self.plant.connect( From 503c6066a8ce8656903b16f757ee9bfffd021b92 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 12:13:00 -0600 Subject: [PATCH 076/132] update SLC add method --- .../system_level/system_level_control_base.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 373b6cb4f..7d649f668 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -53,17 +53,18 @@ def setup(self): self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] - # Partition technologies by control classifier in a single pass - classifiers = slc_config["tech_control_classifiers"] - techs_by_category = {"curtailable": [], "dispatchable": [], "storage": [], "feedstock": []} - for tech, category in classifiers.items(): - if category in techs_by_category: - techs_by_category[category].append(tech) - - self.curtailable_techs = techs_by_category["curtailable"] - self.dispatchable_techs = techs_by_category["dispatchable"] - self.storage_techs = techs_by_category["storage"] - self.feedstock_comps = techs_by_category["feedstock"] + self.curtailable_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "curtailable" + ] + self.dispatchable_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "dispatchable" + ] + self.storage_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "storage" + ] + self.feedstock_comps = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "feedstock" + ] self.input_techs = set( self.curtailable_techs + self.dispatchable_techs + self.storage_techs From 4deb91dc4d5773449737c9d406d41c6ca8a1d69f Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 12:24:37 -0600 Subject: [PATCH 077/132] Refactoring some SLC base methods --- .../system_level/system_level_control_base.py | 190 +++++++++--------- 1 file changed, 91 insertions(+), 99 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 7d649f668..fe404af0a 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -1,6 +1,3 @@ -import operator -import functools - import numpy as np import networkx as nx import openmdao.api as om @@ -566,32 +563,20 @@ def _varopex_marginal_cost(self, inputs, tech_name): return np.full(self.n_timesteps, marginal_cost_scalar) def _find_feedstock_techs(self, tech_name): - """Find feedstock technologies connected upstream of tech_name. + """Find feedstock technologies upstream of ``tech_name`` at any depth. - Scans ``technology_interconnections`` for connections whose - destination is tech_name and whose source is a feedstock. + Uses graph ancestors rather than direct interconnections so that + feedstocks behind intermediate components (e.g. combiners) are found. Args: - tech_name (str): the dispatchable technology name. + tech_name (str): The dispatchable technology name. Returns: - list[str]: names of upstream feedstock technologies. + list[str]: Names of upstream feedstock technologies. """ - interconnections = self.options["plant_config"].get("technology_interconnections", []) - - # Upstream tech names for this dispatchable tech - # NOTE: could getting upstream_techs be replaced with the two lines below - # comds = self._get_commodity_for_tech(tech_name) - # upstream_techs = list( - # set([self.get_upstream_techs_for_commodity(tech_name, c) for c in comds]) - # ) - upstream_techs = [conn[0] for conn in interconnections if conn[1] == tech_name] - - feedstock_names = [ - upstream for upstream in upstream_techs if upstream in self.feedstock_comps - ] - - return feedstock_names + # All ancestors at any depth, filtered to feedstocks + ancestors = nx.ancestors(self.technology_graph, tech_name) + return [tech for tech in ancestors if tech in self.feedstock_comps] def _feedstock_marginal_cost(self, inputs, marginal_cost_data): """Compute marginal cost from upstream feedstock VarOpEx values. @@ -631,108 +616,115 @@ def _feedstock_marginal_cost(self, inputs, marginal_cost_data): def get_upstream_techs_for_commodity( self, tech_name: str, commodity: str, include_feedstock_sources=True ): - """Get the name of technologies that are upstream - of `tech_name` and that output `commodity`. + """Find controlled technologies upstream of ``tech_name`` that output ``commodity``. + + Walks the technology graph backwards from ``tech_name``, finds all ancestor + nodes that have an outgoing edge carrying ``commodity``, then filters to only + those managed by the controller. Args: - tech_name (str): name of technology - commodity (str): commodity name - include_feedstock_sources (bool, optional): If True, include techs - that have an input commodity from a feedstock. Defaults to True. + tech_name (str): Technology whose upstream suppliers are sought. + commodity (str): Commodity of interest (e.g. ``"electricity"``). + include_feedstock_sources (bool, optional): If True, feedstock techs are + included in the set of controller-managed technologies. Defaults to True. Returns: - list[str]: list of technologies upstream of the tech_name that produce a given commodity + list[str]: Controller-managed technologies upstream of ``tech_name`` + that produce ``commodity``. """ + # Build the set of techs the controller can see if include_feedstock_sources: input_techs = self.input_techs | set(self.feedstock_comps) else: input_techs = self.input_techs.copy() - # figure out where the upstream commodity is coming from - upstream_components = nx.ancestors(self.technology_graph, tech_name) - # iterates through a list of 3 length tuples (source, dest, commodity) - upstream_components_shared_commodity = [ - s[0] - for s in list(self.technology_graph.edges(data="commodity")) - if s[0] in upstream_components and s[2] == commodity - ] - # get the technologies that are available to the controller - upstream_techs = set(upstream_components_shared_commodity).intersection(set(input_techs)) - return list(upstream_techs) + # All graph ancestors of tech_name (any depth) + ancestors = nx.ancestors(self.technology_graph, tech_name) + + # Keep only ancestors that have an outgoing edge carrying the target commodity. + # Edges are (source, dest, commodity) tuples + ancestors_with_commodity = { + src + for src, _, comm in self.technology_graph.edges(data="commodity") + if src in ancestors and comm == commodity + } + + # Intersect with controller-managed techs + return list(ancestors_with_commodity & input_techs) def find_converter_techs(self, include_feedstock_sources=True): - """Get the name of the technology that transforms a commodity. + """Identify technologies that transform one commodity into another. + + A "converter" is a tech whose output commodities differ from the commodities + produced by its upstream ancestors (e.g. an electrolyzer: electricity → hydrogen). Args: - include_feedstock_sources (bool, optional): If True, include techs - that have an input commodity from a feedstock. Defaults to True. + include_feedstock_sources (bool, optional): If True, include feedstock techs + in the set of candidate technologies. Defaults to True. Returns: - set(tuple): set of converter technologies formatted as - (input_commodity, converter tech name, output_commodity) + set[tuple[str, str, str]]: Set of ``(input_commodity, tech_name, output_commodity)`` + tuples for each detected conversion. Returns ``None`` for single-commodity systems. """ if include_feedstock_sources: input_techs = self.input_techs | set(self.feedstock_comps) else: input_techs = self.input_techs.copy() + + # Single-commodity systems have no special handling by definition if not self.multi_commodity_system: return converter_techs = set() - + node_order = list(self.technology_graph.nodes()) edges = list(self.technology_graph.edges(data="commodity")) - upstream_converter = None - for edge in edges: - tech, dest_tech, cmod = edge - if tech in input_techs: - tech_output_commodity = self._get_commodity_for_tech(tech) - - # NOTE: unsure how this would work for systems with tiered converters - # aka - maybe have to eliminate a converter once we've discovered it - if upstream_converter is None: - upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( - set(input_techs) - ) - else: - idx_upstream_converter = [ - i - for i, n in enumerate(self.technology_graph.__iter__()) - if n == upstream_converter - ] - downstream_of_previous_converter = [ - n - for i, n in enumerate(self.technology_graph.__iter__()) - if i > min(idx_upstream_converter) - ] - all_upstream_techs = nx.ancestors(self.technology_graph, tech).intersection( - set(input_techs) - ) - upstream_techs = all_upstream_techs.intersection( - set(downstream_of_previous_converter) - ) - connected_upstream_techs = [ - t for t in upstream_techs if nx.has_path(self.technology_graph, t, tech) - ] - upstream_commodities = [ - self._get_commodity_for_tech(t) for t in connected_upstream_techs - ] - upstream_commodities = functools.reduce(operator.iadd, upstream_commodities, []) - # symmetric difference - # commodities that are not in both - input_output_commodity = set(upstream_commodities) ^ set(tech_output_commodity) - if len(input_output_commodity) > 1: - input_commodities = list( - input_output_commodity.intersection(set(upstream_commodities)) - ) - output_commodities = list( - input_output_commodity.intersection(set(tech_output_commodity)) - ) - - for input_commodity in input_commodities: - for output_commodity in output_commodities: - # formatted as (input commodity, tech_name, output commodity) - converter_techs.add((input_commodity, tech, output_commodity)) - upstream_converter = tech + # Track the most recently discovered converter so we can scope + # upstream searches for chained converters (A→B→C where B and C + # both convert). Without this, C would see A's commodity as upstream + # input even though B already consumed it. + last_converter = None + + for source_tech, _, _ in edges: + if source_tech not in input_techs: + continue + + # Get the commodities produced by this tech (the "output" side of the conversion) + output_commodities = set(self._get_commodity_for_tech(source_tech)) + + # Find controlled ancestors of this tech + all_ancestors = nx.ancestors(self.technology_graph, source_tech) & input_techs + + if last_converter is not None: + # Only consider ancestors that appear after the last converter + # in topological order, preventing double-counting across + # chained converters. + converter_idx = node_order.index(last_converter) + nodes_after_converter = set(node_order[converter_idx + 1 :]) + ancestors = all_ancestors & nodes_after_converter + else: + ancestors = all_ancestors + + # Keep only ancestors actually connected (reachable) to this tech + connected_ancestors = [ + t for t in ancestors if nx.has_path(self.technology_graph, t, source_tech) + ] + + # Gather all commodities produced by connected ancestors + input_commodities = set() + for ancestor in connected_ancestors: + input_commodities.update(self._get_commodity_for_tech(ancestor)) + + # A converter has commodities that appear only on one side: + # upstream-only commodities are consumed, output-only are produced. + consumed = input_commodities - output_commodities + produced = output_commodities - input_commodities + + # If both sides have unique commodities, this tech is a converter + if consumed and produced: + for in_comm in consumed: + for out_comm in produced: + converter_techs.add((in_comm, source_tech, out_comm)) + last_converter = source_tech return converter_techs From 2b7fed56e51b41697fe94f8dc65943c2598efa28 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 8 May 2026 12:39:50 -0600 Subject: [PATCH 078/132] Expanding SLC docstrings --- .../system_level/demand_following_control.py | 23 +++++++++---- .../system_level/solver_options.py | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 0e885e1a4..815b95099 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -8,13 +8,24 @@ class DemandFollowingControl(SystemLevelControlBase): """Demand-following system-level controller. - Dispatch priority: - 1. Curtailable techs run at rated capacity (zero marginal cost). - 2. Storage absorbs surplus / provides deficit (set_point = net demand). - 3. Remaining demand is split equally across dispatchable techs. + Dispatches technologies to meet a time-varying demand profile without + considering costs. The demand is satisfied in a fixed three-step priority + order, and each step's shortfall or surplus is passed to the next: - This strategy always attempts to meet demand exactly; it does not - consider costs. + 1. **Curtailable techs** run at their full rated capacity. Their total + output is subtracted from the demand, which may drive the residual + demand negative (surplus). + + 2. **Storage techs** receive the residual demand (which may be positive + or negative). When demand is positive the storage is commanded to + discharge; when negative it is commanded to charge. If multiple + storage techs produce the demanded commodity, the residual demand is + split **evenly** across them (each receives ``demand / n_storage``). + + 3. **Dispatchable techs** cover any remaining positive demand after + storage. The remaining demand (floored at zero) is split **evenly** + across all dispatchable techs that produce the demanded commodity + (each receives ``remaining_demand / n_dispatchable``). """ def compute(self, inputs, outputs): diff --git a/h2integrate/control/control_strategies/system_level/solver_options.py b/h2integrate/control/control_strategies/system_level/solver_options.py index 58817b36b..e3b5186c8 100644 --- a/h2integrate/control/control_strategies/system_level/solver_options.py +++ b/h2integrate/control/control_strategies/system_level/solver_options.py @@ -9,6 +9,25 @@ @define(kw_only=True) class SLCSolverOptionsConfig(BaseConfig): + """Configuration for the nonlinear solver used by the system-level controller. + + Controls which OpenMDAO nonlinear solver is applied to the plant group and + how it converges. The ``convergence_tolerance`` sets both ``atol`` and ``rtol`` + by default; either can be overridden individually. + + Attributes: + solver_name: Solver type. One of ``"gauss_seidel"``, ``"newton"``, or + ``"block_jacobi"``. + max_iter: Maximum number of nonlinear iterations. + atol: Absolute convergence tolerance. Defaults to ``convergence_tolerance``. + rtol: Relative convergence tolerance. Defaults to ``convergence_tolerance``. + convergence_tolerance: Convenience value used to set both ``atol`` and ``rtol`` + when they are not specified individually. + iprint: Solver print level (0 = silent, 2 = verbose). + solver_option_kwargs: Additional keyword arguments passed directly to the + solver's ``options`` dict. + """ + solver_name: str = field( default="gauss_seidel", validator=contains(["gauss_seidel", "newton", "block_jacobi"]) ) @@ -19,6 +38,7 @@ class SLCSolverOptionsConfig(BaseConfig): iprint: int = field(default=2) solver_option_kwargs: dict = field(default={}) + # Maps user-facing solver names to OpenMDAO solver classes solver_map: ClassVar = { "gauss_seidel": om.NonlinearBlockGS, "newton": om.NewtonSolver, @@ -26,13 +46,23 @@ class SLCSolverOptionsConfig(BaseConfig): } def __attrs_post_init__(self): + # Default atol/rtol to the shared convergence_tolerance if not set if self.atol is None: self.atol = self.convergence_tolerance if self.rtol is None: self.rtol = self.convergence_tolerance def get_solver_options(self): + """Build the options dict to apply to the nonlinear solver. + + Merges config attributes with any extra ``solver_option_kwargs`` and + renames ``max_iter`` to ``maxiter`` (the OpenMDAO option name). + + Returns: + dict: Keyword arguments suitable for ``solver.options[k] = v``. + """ d = self.as_dict() + # These attrs configure *which* solver or are handled separately non_solver_option_attrs = [ "solver_name", "solver_map", @@ -41,10 +71,12 @@ def get_solver_options(self): "max_iter", ] solver_options = {k: v for k, v in d.items() if k not in non_solver_option_attrs} + # Merge extra kwargs and translate max_iter → maxiter for OpenMDAO solver_options_full = ( solver_options | self.solver_option_kwargs | {"maxiter": self.max_iter} ) return solver_options_full def return_nonlinear_solver(self): + """Return the OpenMDAO nonlinear solver class for ``solver_name``.""" return self.solver_map[self.solver_name] From da11a526bf2ddd6b65386b9e0c0ae989993af129 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Fri, 8 May 2026 12:57:34 -0600 Subject: [PATCH 079/132] refactored test_slc_controllers --- .../system_level/test/test_slc_controllers.py | 597 +++++++++++------- 1 file changed, 371 insertions(+), 226 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index a908e4c19..895341142 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -16,107 +16,127 @@ ) -def _make_plant_config( - n_timesteps=4, - demand=50000, - curtailable=None, - dispatchable=None, - storage=None, - feedstock=None, - sell_price=0.06, - cost_per_tech=None, - technology_interconnections=None, +def _build_plant_config( + technology_interconnections, n_timesteps=4, sell_price=0.06, cost_per_tech=None ): - """Build a minimal plant_config dict for controller tests.""" - all_techs = (curtailable or []) + (dispatchable or []) + (storage or []) + (feedstock or []) - - tech_to_commodity = {(t, "electricity") for t in all_techs} - - config = { + if cost_per_tech is None: + return { + "plant": {"simulation": {"n_timesteps": n_timesteps, "dt": 3600}, "plant_life": 30}, + "system_level_control": {"control_parameters": {"commodity_sell_price": sell_price}}, + "technology_interconnections": technology_interconnections, + } + return { "plant": {"simulation": {"n_timesteps": n_timesteps, "dt": 3600}, "plant_life": 30}, "system_level_control": { - "demand_commodity": "electricity", - "demand_commodity_rate_units": "kW", - "demand_tech": "demand", - "demand_profile": demand, - "curtailable_techs": curtailable or [], - "dispatchable_techs": dispatchable or [], - "storage_techs": storage or [], - "feedstock_techs": feedstock or [], - "tech_to_commodity": tech_to_commodity, - "commodity_sell_price": sell_price, - "cost_per_tech": cost_per_tech or {}, - "control_parameters": {"commodity_sell_price": sell_price}, + "control_parameters": { + "commodity_sell_price": sell_price, + "cost_per_tech": cost_per_tech, + } }, + "technology_interconnections": technology_interconnections, } - if technology_interconnections is not None: - config["technology_interconnections"] = technology_interconnections - return config - - -def _make_slc_config(plant_config): - """Build a minimal slc_config dict from a plant_config for controller tests.""" - slc = plant_config["system_level_control"] - curtailable = slc.get("curtailable_techs", []) - dispatchable = slc.get("dispatchable_techs", []) - storage = slc.get("storage_techs", []) - feedstock = slc.get("feedstock_techs", []) - all_techs = curtailable + dispatchable + storage + feedstock - - # Build technology graph - tech_graph = nx.DiGraph() - for t in all_techs: - tech_graph.add_node(t) - tech_graph.add_node(slc["demand_tech"]) - for t in all_techs: - tech_graph.add_edge(t, slc["demand_tech"], commodity=slc["demand_commodity"]) - for conn in plant_config.get("technology_interconnections", []): - if len(conn) >= 4: - tech_graph.add_edge(conn[0], conn[1], commodity=conn[2]) + + +def _build_technology_graph(technology_interconnections): + technology_graph = nx.DiGraph() + for connection in technology_interconnections: + source = connection[0] + destination = connection[1] + if len(connection) == 4: + technology_graph.add_edge(source, destination, commodity=connection[2]) else: - tech_graph.add_edge(conn[0], conn[1]) - - # Build tech_control_classifiers - classifiers = {} - for t in curtailable: - classifiers[t] = "curtailable" - for t in dispatchable: - classifiers[t] = "dispatchable" - for t in storage: - classifiers[t] = "storage" - for t in feedstock: - classifiers[t] = "feedstock" + technology_graph.add_edge(source, destination) + return technology_graph - return { - "demand_commodity": slc["demand_commodity"], - "demand_commodity_rate_units": slc.get("demand_commodity_rate_units"), - "demand_tech": slc["demand_tech"], - "tech_to_commodity": slc["tech_to_commodity"], - "storage_techs_to_control": {}, - "technology_graph": tech_graph, - "tech_control_classifiers": classifiers, + +def _build_tech_control_classifiers( + curtailable=None, dispatchable=None, storage=None, feedstock=None +): + tech_control_classifiers = {k: "curtailable" for k in (curtailable or [])} + tech_control_classifiers |= {k: "dispatchable" for k in (dispatchable or [])} + tech_control_classifiers |= {k: "storage" for k in (storage or [])} + tech_control_classifiers |= {k: "feedstock" for k in (feedstock or [])} + return tech_control_classifiers + + +def _build_slc_config( + technology_graph, + tech_control_classifiers: dict, + demand_tech: str = "demand", + demand_commodity: str = "electricity", + demand_commodity_rate_units: str = "kW", + storage_techs_with_control: list = [], +): + sources_to_commodities = { + (e[0], e[-1]) for e in technology_graph.edges(data="commodity") if e[-1] is not None } + tech_to_commodities = { + (e[0], e[-1]) for e in sources_to_commodities if e[0] in tech_control_classifiers + } + + storage_techs = [k for k, v in tech_control_classifiers.items() if v == "storage"] + storage_techs_to_control = { + k: True if k in storage_techs_with_control else False for k in storage_techs + } + + slc_config = { + "demand_commodity": demand_commodity, + "demand_commodity_rate_units": demand_commodity_rate_units, + "demand_tech": demand_tech, + "tech_to_commodity": tech_to_commodities, + "storage_techs_to_control": storage_techs_to_control, + "technology_graph": technology_graph, + "tech_control_classifiers": tech_control_classifiers, + } + return slc_config -def _build_problem(slc_cls, plant_config): + +def _build_problem(slc_cls, plant_config, slc_config, demand=50000, tech_config={}): """Create and setup an OpenMDAO Problem with the given controller.""" - slc_config = _make_slc_config(plant_config) prob = om.Problem() + + feedstock_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "feedstock" + ] + feedstock_subsystem_names = [] + for fi, feedstock_tech in enumerate(feedstock_techs): + feedstock_commodity = [ + e[-1] for e in slc_config["tech_to_commodity"] if e[0] == feedstock_tech + ] + feedstock_comp = prob.model.add_subsystem(f"IVC{fi}", om.Group()) + feedstock_comp.add_subsystem( + "feedstock", + om.IndepVarComp( + name=f"{feedstock_tech}_{feedstock_commodity[0]}_out", + val=np.full(plant_config["plant"]["simulation"]["n_timesteps"], 1e9), + units="MMBtu/h", + ), + ) + + feedstock_subsystem_names.append( + f"IVC{fi}.feedstock.{feedstock_tech}_{feedstock_commodity[0]}_out" + ) + prob.model.add_subsystem( "slc", slc_cls( driver_config={}, plant_config=plant_config, - tech_config={}, + tech_config=tech_config, slc_config=slc_config, ), ) + + for feedstock_name in feedstock_subsystem_names: + connection_destination = feedstock_name.split(".")[-1] + prob.model.connect(feedstock_name, f"slc.{connection_destination}") + prob.setup() # Set demand profile from config - slc_cfg = plant_config["system_level_control"] - demand_name = f"slc.{slc_cfg['demand_commodity']}_demand" - prob.set_val(demand_name, slc_cfg["demand_profile"]) + demand_name = f"slc.{slc_config['demand_commodity']}_demand" + prob.set_val(demand_name, demand) return prob @@ -129,31 +149,48 @@ class TestSystemLevelControlBase: """Tests for the abstract base class setup logic.""" def test_base_creates_curtailable_io(self): - pc = _make_plant_config(curtailable=["wind"]) + tech_connections = [["wind", "demand", "electricity", "cable"]] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(curtailable=["wind"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) # Use DemandFollowingControl since base is abstract - prob = _build_problem(DemandFollowingControl, pc) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) # _var_rel2meta uses relative names (no "slc." prefix) assert "wind_electricity_out" in prob.model.slc._var_rel2meta assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_dispatchable_io(self): - pc = _make_plant_config(dispatchable=["ng"]) - prob = _build_problem(DemandFollowingControl, pc) + tech_connections = [["ng", "demand", "electricity", "cable"]] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) assert "ng_electricity_out" in prob.model.slc._var_rel2meta assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_storage_io(self): - pc = _make_plant_config(storage=["battery"]) - prob = _build_problem(DemandFollowingControl, pc) + tech_connections = [["battery", "demand", "electricity", "cable"]] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(storage=["battery"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + assert "battery_electricity_out" in prob.model.slc._var_rel2meta assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_demand_input(self): - pc = _make_plant_config() - prob = _build_problem(DemandFollowingControl, pc) + plant_config = _build_plant_config([]) + tech_graph = _build_technology_graph([]) + tech_control_classifiers = _build_tech_control_classifiers() + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + assert "electricity_demand" in prob.model.slc._var_rel2meta def test_backward_compat_alias(self): @@ -169,8 +206,17 @@ class TestDemandFollowingControl: """Tests for the demand-following (equal-share) controller.""" def test_equal_share_two_dispatchable(self): - pc = _make_plant_config(dispatchable=["ng1", "ng2"]) - prob = _build_problem(DemandFollowingControl, pc) + tech_connections = [ + ["ng1", "combiner", "electricity", "cable"], + ["ng2", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng1", "ng2"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + prob.set_val("slc.ng1_rated_electricity_production", 80000) prob.set_val("slc.ng2_rated_electricity_production", 40000) prob.run_model() @@ -181,8 +227,19 @@ def test_equal_share_two_dispatchable(self): np.testing.assert_allclose(sp2, 25000) def test_curtailable_reduces_demand(self): - pc = _make_plant_config(curtailable=["wind"], dispatchable=["ng"]) - prob = _build_problem(DemandFollowingControl, pc) + tech_connections = [ + ["wind", "combiner", "electricity", "cable"], + ["ng", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + curtailable=["wind"], dispatchable=["ng"] + ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + prob.set_val("slc.wind_electricity_out", [30000, 60000, 50000, 10000]) prob.set_val("slc.wind_rated_electricity_production", 120000) prob.set_val("slc.ng_rated_electricity_production", 100000) @@ -194,8 +251,21 @@ def test_curtailable_reduces_demand(self): np.testing.assert_allclose(ng_sp, expected) def test_storage_absorbs_surplus(self): - pc = _make_plant_config(curtailable=["wind"], storage=["battery"], dispatchable=["ng"]) - prob = _build_problem(DemandFollowingControl, pc) + tech_connections = [ + ["wind", "battery", "electricity", "cable"], + ["wind", "combiner", "electricity", "cable"], + ["battery", "combiner", "electricity", "cable"], + ["ng", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config(tech_connections) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + curtailable=["wind"], storage=["battery"], dispatchable=["ng"] + ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + prob.set_val("slc.wind_electricity_out", [70000, 30000, 50000, 50000]) prob.set_val("slc.wind_rated_electricity_production", 120000) prob.set_val("slc.battery_electricity_out", [0, 0, 0, 0]) @@ -210,8 +280,12 @@ def test_storage_absorbs_surplus(self): def test_no_techs_runs(self): """Controller with no techs should still run without error.""" - pc = _make_plant_config() - prob = _build_problem(DemandFollowingControl, pc) + plant_config = _build_plant_config([]) + tech_graph = _build_technology_graph([]) + tech_control_classifiers = _build_tech_control_classifiers() + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(DemandFollowingControl, plant_config, slc_config) + prob.run_model() # should not raise @@ -223,12 +297,21 @@ class TestCostMinimizationControl: """Tests for the merit-order cost-minimization controller.""" def test_cheapest_dispatched_first(self): - pc = _make_plant_config( - dispatchable=["cheap", "expensive"], - demand=50000, - cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + tech_connections = [ + ["cheap", "combiner", "electricity", "cable"], + ["expensive", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, cost_per_tech={"cheap": 0.03, "expensive": 0.08} + ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["cheap", "expensive"] ) - prob = _build_problem(CostMinimizationControl, pc) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.cheap_rated_electricity_production", 80000) prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() @@ -240,12 +323,21 @@ def test_cheapest_dispatched_first(self): np.testing.assert_allclose(expensive_sp, 0) def test_overflow_to_expensive(self): - pc = _make_plant_config( - dispatchable=["cheap", "expensive"], - demand=50000, - cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + tech_connections = [ + ["cheap", "combiner", "electricity", "cable"], + ["expensive", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, cost_per_tech={"cheap": 0.03, "expensive": 0.08} ) - prob = _build_problem(CostMinimizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["cheap", "expensive"] + ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.cheap_rated_electricity_production", 30000) prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() @@ -257,13 +349,19 @@ def test_overflow_to_expensive(self): np.testing.assert_allclose(expensive_sp, 20000) def test_with_curtailable_reduces_dispatch(self): - pc = _make_plant_config( - curtailable=["wind"], - dispatchable=["ng"], - demand=50000, - cost_per_tech={"ng": 0.05}, + tech_connections = [ + ["wind", "combiner", "electricity", "cable"], + ["ng", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config(tech_connections, cost_per_tech={"ng": 0.05}) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + curtailable=["wind"], dispatchable=["ng"] ) - prob = _build_problem(CostMinimizationControl, pc) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.wind_electricity_out", [40000, 40000, 40000, 40000]) prob.set_val("slc.wind_rated_electricity_production", 120000) prob.set_val("slc.ng_rated_electricity_production", 100000) @@ -282,13 +380,21 @@ class TestProfitMaximizationControl: """Tests for the profit-maximization controller.""" def test_unprofitable_tech_not_dispatched(self): - pc = _make_plant_config( - dispatchable=["cheap", "expensive"], - demand=50000, - sell_price=0.06, - cost_per_tech={"cheap": 0.03, "expensive": 0.08}, + tech_connections = [ + ["cheap", "combiner", "electricity", "cable"], + ["expensive", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.06, cost_per_tech={"cheap": 0.03, "expensive": 0.08} ) - prob = _build_problem(ProfitMaximizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["cheap", "expensive"] + ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.cheap_rated_electricity_production", 30000) prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.set_val("slc.commodity_sell_price", 0.06) @@ -302,13 +408,19 @@ def test_unprofitable_tech_not_dispatched(self): np.testing.assert_allclose(expensive_sp, 0) def test_all_profitable(self): - pc = _make_plant_config( - dispatchable=["a", "b"], - demand=50000, - sell_price=0.10, - cost_per_tech={"a": 0.03, "b": 0.05}, + tech_connections = [ + ["a", "combiner", "electricity", "cable"], + ["b", "combiner", "electricity", "cable"], + ["combiner", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"a": 0.03, "b": 0.05} ) - prob = _build_problem(ProfitMaximizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["a", "b"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.a_rated_electricity_production", 80000) prob.set_val("slc.b_rated_electricity_production", 40000) prob.set_val("slc.commodity_sell_price", 0.10) @@ -321,13 +433,17 @@ def test_all_profitable(self): np.testing.assert_allclose(b_sp, 0) def test_none_profitable(self): - pc = _make_plant_config( - dispatchable=["ng"], - demand=50000, - sell_price=0.01, - cost_per_tech={"ng": 0.05}, + tech_connections = [ + ["ng", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.01, cost_per_tech={"ng": 0.05} ) - prob = _build_problem(ProfitMaximizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.ng_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.01) prob.run_model() @@ -337,13 +453,17 @@ def test_none_profitable(self): np.testing.assert_allclose(ng_sp, 0) def test_sell_price_from_config(self): - pc = _make_plant_config( - dispatchable=["ng"], - demand=50000, - sell_price=0.10, - cost_per_tech={"ng": 0.03}, + tech_connections = [ + ["ng", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"ng": 0.03} ) - prob = _build_problem(ProfitMaximizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.ng_rated_electricity_production", 100000) # Don't set sell_price explicitly — should use config default 0.10 prob.run_model() @@ -353,13 +473,17 @@ def test_sell_price_from_config(self): np.testing.assert_allclose(ng_sp, 50000) def test_time_varying_sell_price(self): - pc = _make_plant_config( - dispatchable=["ng"], - demand=50000, - sell_price=0.06, - cost_per_tech={"ng": 0.05}, + tech_connections = [ + ["ng", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.06, cost_per_tech={"ng": 0.05} ) - prob = _build_problem(ProfitMaximizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.ng_rated_electricity_production", 100000) # Sell price varies: 2 profitable hours, 2 unprofitable prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) @@ -371,13 +495,6 @@ def test_time_varying_sell_price(self): def test_buy_price_scalar(self): """buy_price mode with a scalar buy price from tech config.""" - pc = _make_plant_config( - dispatchable=["grid"], - demand=50000, - sell_price=0.10, - cost_per_tech={"grid": "buy_price"}, - ) - # Add tech config with buy price tech_config = { "technologies": { "grid": { @@ -387,17 +504,24 @@ def test_buy_price_scalar(self): } } } - prob = om.Problem() - prob.model.add_subsystem( - "slc", - ProfitMaximizationControl( - driver_config={}, - plant_config=pc, - tech_config=tech_config, - slc_config=_make_slc_config(pc), - ), + + tech_connections = [ + ["grid", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"grid": "buy_price"} + ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["grid"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem( + ProfitMaximizationControl, + plant_config, + slc_config, + demand=50000, + tech_config=tech_config, ) - prob.setup() + prob.set_val("slc.electricity_demand", 50000) prob.set_val("slc.grid_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.10) @@ -409,12 +533,7 @@ def test_buy_price_scalar(self): def test_buy_price_time_varying(self): """buy_price mode with time-varying prices (override via set_val).""" - pc = _make_plant_config( - dispatchable=["grid"], - demand=50000, - sell_price=0.06, - cost_per_tech={"grid": "buy_price"}, - ) + tech_config = { "technologies": { "grid": { @@ -424,17 +543,23 @@ def test_buy_price_time_varying(self): } } } - prob = om.Problem() - prob.model.add_subsystem( - "slc", - ProfitMaximizationControl( - driver_config={}, - plant_config=pc, - tech_config=tech_config, - slc_config=_make_slc_config(pc), - ), + tech_connections = [ + ["grid", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.06, cost_per_tech={"grid": "buy_price"} ) - prob.setup() + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["grid"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem( + ProfitMaximizationControl, + plant_config, + slc_config, + demand=50000, + tech_config=tech_config, + ) + prob.set_val("slc.electricity_demand", 50000) prob.set_val("slc.grid_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.06) @@ -447,13 +572,17 @@ def test_buy_price_time_varying(self): def test_varopex_mode(self): """VarOpEx mode computes marginal cost from VarOpEx / production.""" - pc = _make_plant_config( - dispatchable=["gen"], - demand=50000, - sell_price=0.10, - cost_per_tech={"gen": "VarOpEx"}, + tech_connections = [ + ["gen", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"gen": "VarOpEx"} ) - prob = _build_problem(CostMinimizationControl, pc) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["gen"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.gen_rated_electricity_production", 100000) # Set VarOpEx ($/year, shape=plant_life=30) and production prob.set_val("slc.gen_VarOpEx", np.full(30, 500000.0)) @@ -470,13 +599,16 @@ def test_varopex_mode(self): def test_cost_per_tech_default_zero(self): """Techs not listed in cost_per_tech default to zero marginal cost.""" - pc = _make_plant_config( - dispatchable=["ng"], - demand=50000, - sell_price=0.10, - cost_per_tech={}, # Empty: ng defaults to 0.0 - ) - prob = _build_problem(ProfitMaximizationControl, pc) + + tech_connections = [ + ["ng", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config(tech_connections, sell_price=0.10, cost_per_tech={}) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) + prob.set_val("slc.ng_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() @@ -487,18 +619,21 @@ def test_cost_per_tech_default_zero(self): def test_feedstock_single(self): """feedstock mode: single upstream feedstock drives marginal cost.""" - pc = _make_plant_config( - dispatchable=["ng_plant"], - feedstock=["ng_feed"], - demand=50000, - sell_price=0.10, - cost_per_tech={"ng_plant": "feedstock"}, - technology_interconnections=[ - ["ng_feed", "ng_plant", "natural_gas", "pipe"], - ], + + tech_connections = [ + ["ng_feed", "ng_plant", "natural_gas", "pipe"], + ["ng_plant", "demand", "electricity", "cable"], + ] + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"ng_plant": "feedstock"} + ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["ng_plant"], feedstock=["ng_feed"] ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) - prob = _build_problem(CostMinimizationControl, pc) prob.set_val("slc.ng_plant_rated_electricity_production", 100000) # Feedstock VarOpEx: $1M/yr; production: 100 MW * 4 h = 400 MWh prob.set_val("slc.ng_feed_VarOpEx", np.full(30, 1_000_000.0)) @@ -512,20 +647,23 @@ def test_feedstock_single(self): def test_feedstock_multiple(self): """feedstock mode: multiple upstream feedstocks are summed.""" - pc = _make_plant_config( - dispatchable=["plant"], - feedstock=["feed_a", "feed_b"], - demand=50000, - sell_price=0.10, - cost_per_tech={"plant": "feedstock"}, - technology_interconnections=[ - ["feed_a", "plant", "gas_a", "pipe"], - ["feed_b", "plant", "gas_b", "pipe"], - ["other_tech", "plant", "something", "cable"], - ], + tech_connections = [ + ["feed_a", "plant", "gas_a", "pipe"], + ["feed_b", "plant", "gas_b", "pipe"], + ["other_tech", "plant", "something", "cable"], + ["plant", "demand", "electricity", "cable"], + ] + + plant_config = _build_plant_config( + tech_connections, sell_price=0.10, cost_per_tech={"plant": "feedstock"} ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["plant"], feedstock=["feed_a", "feed_b"] + ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) - prob = _build_problem(CostMinimizationControl, pc) prob.set_val("slc.plant_rated_electricity_production", 100000) # Two feedstocks: $500k and $300k → total $800k/yr prob.set_val("slc.feed_a_VarOpEx", np.full(30, 500_000.0)) @@ -540,18 +678,22 @@ def test_feedstock_multiple(self): def test_feedstock_profit_max_unprofitable(self): """feedstock mode in profit max: unprofitable when feedstock costs exceed sell price.""" - pc = _make_plant_config( - dispatchable=["ng_plant"], - feedstock=["ng_feed"], - demand=50000, - sell_price=0.01, # very low sell price - cost_per_tech={"ng_plant": "feedstock"}, - technology_interconnections=[ - ["ng_feed", "ng_plant", "natural_gas", "pipe"], - ], + + tech_connections = [ + ["ng_feed", "ng_plant", "natural_gas", "pipe"], + ["ng_plant", "demand", "electricity", "cable"], + ] + # use a very low sell price + plant_config = _build_plant_config( + tech_connections, sell_price=0.01, cost_per_tech={"ng_plant": "feedstock"} + ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers( + dispatchable=["ng_plant"], feedstock=["ng_feed"] ) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) + prob = _build_problem(ProfitMaximizationControl, plant_config, slc_config, demand=50000) - prob = _build_problem(ProfitMaximizationControl, pc) prob.set_val("slc.ng_plant_rated_electricity_production", 100000) prob.set_val("slc.commodity_sell_price", 0.01) # Very expensive feedstock: $100M/yr → high marginal cost @@ -565,14 +707,17 @@ def test_feedstock_profit_max_unprofitable(self): def test_feedstock_no_feedstock_raises(self): """feedstock mode raises ValueError when no feedstock is found upstream.""" - pc = _make_plant_config( - dispatchable=["ng_plant"], - demand=50000, - cost_per_tech={"ng_plant": "feedstock"}, - technology_interconnections=[ - ["some_tech", "ng_plant", "electricity", "cable"], - ], + + tech_connections = [ + ["some_tech", "ng_plant", "electricity", "cable"], + ] + + plant_config = _build_plant_config( + tech_connections, sell_price=0.01, cost_per_tech={"ng_plant": "feedstock"} ) + tech_graph = _build_technology_graph(tech_connections) + tech_control_classifiers = _build_tech_control_classifiers(dispatchable=["ng_plant"]) + slc_config = _build_slc_config(tech_graph, tech_control_classifiers) with pytest.raises(ValueError, match="at least one feedstock"): - _build_problem(CostMinimizationControl, pc) + _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) From 6eeac7194b52341eb63ca7486c0a22b2a8ce454b Mon Sep 17 00:00:00 2001 From: kbrunik Date: Sun, 10 May 2026 08:09:53 -0500 Subject: [PATCH 080/132] docs update --- docs/_toc.yml | 7 ++- docs/control/storage_level_control.md | 3 -- .../system_level_control/slc_cost_min.md | 2 + .../slc_demand_following.md | 2 + .../system_level_control/slc_profit_max.md | 2 + .../system_level_control.md | 47 +++++++++++++++++- .../system_level_control_base.md | 2 + .../controller_demonstrations.md | 4 +- .../figures/Pyomo_dispatch_figure.png | Bin .../figures/example_peak_load_dispatch.png | Bin .../figures/plm_optimized_dispatch.png | Bin .../open-loop_controllers.md | 2 +- .../pyomo_controllers.md | 4 +- .../technology_control_overview.md} | 4 +- 14 files changed, 65 insertions(+), 14 deletions(-) delete mode 100644 docs/control/storage_level_control.md create mode 100644 docs/control/system_level_control/slc_cost_min.md create mode 100644 docs/control/system_level_control/slc_demand_following.md create mode 100644 docs/control/system_level_control/slc_profit_max.md create mode 100644 docs/control/system_level_control/system_level_control_base.md rename docs/control/{ => technology_level_control}/controller_demonstrations.md (94%) rename docs/control/{ => technology_level_control}/figures/Pyomo_dispatch_figure.png (100%) rename docs/control/{ => technology_level_control}/figures/example_peak_load_dispatch.png (100%) rename docs/control/{ => technology_level_control}/figures/plm_optimized_dispatch.png (100%) rename docs/control/{ => technology_level_control}/open-loop_controllers.md (99%) rename docs/control/{ => technology_level_control}/pyomo_controllers.md (94%) rename docs/control/{control_overview.md => technology_level_control/technology_control_overview.md} (71%) diff --git a/docs/_toc.yml b/docs/_toc.yml index 1f4fa339a..e1255eaca 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -70,11 +70,14 @@ parts: - file: resource/tidal_resource - caption: Control chapters: - - file: control/control_overview - file: control/system_level_control/system_level_control sections: + - file: control/system_level_control/system_level_control_base - file: control/system_level_control/control_classifier - - file: control/storage_level_control + - file: control/system_level_control/slc_demand_following + - file: control/system_level_control/slc_cost_min + - file: control/system_level_control/slc_profit_max + - file: control/technology_level_control/technology_control_overview sections: - file: control/open-loop_controllers - file: control/pyomo_controllers diff --git a/docs/control/storage_level_control.md b/docs/control/storage_level_control.md deleted file mode 100644 index 30544f0a3..000000000 --- a/docs/control/storage_level_control.md +++ /dev/null @@ -1,3 +0,0 @@ -# Storage-Level Control - -ADD diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md new file mode 100644 index 000000000..f24570590 --- /dev/null +++ b/docs/control/system_level_control/slc_cost_min.md @@ -0,0 +1,2 @@ +(slc-cost-min)= +# Cost Minimization System Level Controller diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md new file mode 100644 index 000000000..72a05dcf4 --- /dev/null +++ b/docs/control/system_level_control/slc_demand_following.md @@ -0,0 +1,2 @@ +(slc-demand-following)= +# Demand Following System Level Controller diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md new file mode 100644 index 000000000..42ac80f14 --- /dev/null +++ b/docs/control/system_level_control/slc_profit_max.md @@ -0,0 +1,2 @@ +(slc-profit-max)= +# Profit Maximization System Level Controller diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index a3bca1143..5ebbd3838 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -1,10 +1,53 @@ # System-Level Control -System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller, which can work with other technology level controllers. +System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller meaning that it can work to coordinate the entire system and can work with other technology level controllers. + +The most basic SLC is shown in the figured below, where the SLC receives a demand. Based on that demand it will output set points for `{commodity}_out` to the individual technology blocks included within the system. Each technology based on it's controller classification will respond to the set point. From each technology block there is `{commodity}_out` (potentially changed by the set point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the set points in attempts to meet the demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. ```{figure} figures/slc_basic.png :width: 70% :align: center ``` -At a very basic level the SLC receives a demand. Based on that demand +The SLC control strategy and solver options are set within `plant_config.yaml` under the `"system_level_control"` section. + +```{yaml} +system_level_control: + control_strategy: DemandFollowingControl + solver_options: + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 +``` + +To set the demand for the SLC that is configured in the `tech_config.yaml` using a demand block/component. For example: + +```{yaml} +electrical_load_demand: +performance_model: + model: GenericDemandComponent +model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 30000 +``` + +## Control Strategies +There are several simple control strategies already implemented in the SLC paradigm. While fairly simplistic, they are meant to illustrate how information can be passed from different blocks/components (converters, storage, feedstocks, demand, etc.) and models (performance, cost, finance) to use within the SLC. + +The current control strategies are: +1. [Demand Following](#slc-demand-following) +2. [Cost Minimization](#slc-cost-min) +3. [Profit Maximization](#slc-profit-max) + +```{note} +The strategies currently implemented are experimental and will likely require further development for specific analyses. +``` + +All control strategies inherit `SystemLevelControlBase`, which is a base class that has common setup logic shared by all system-level control strategies. + +See additional information, which is more developer focused, about the [`SystemLevelControlBase`](#slc-base). + +## Solver Options +The system attempts to converge the system using a solver. The solver is defined in `solver_options`. diff --git a/docs/control/system_level_control/system_level_control_base.md b/docs/control/system_level_control/system_level_control_base.md new file mode 100644 index 000000000..003ee07ad --- /dev/null +++ b/docs/control/system_level_control/system_level_control_base.md @@ -0,0 +1,2 @@ +(slc-base)= +# System Level Control Base Class diff --git a/docs/control/controller_demonstrations.md b/docs/control/technology_level_control/controller_demonstrations.md similarity index 94% rename from docs/control/controller_demonstrations.md rename to docs/control/technology_level_control/controller_demonstrations.md index 825ca8675..e6e42af58 100644 --- a/docs/control/controller_demonstrations.md +++ b/docs/control/technology_level_control/controller_demonstrations.md @@ -28,7 +28,7 @@ The following example is an expanded form of `examples/14_wind_hydrogen_dispatch Here, we're highlighting the dispatch controller setup from `examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml`. Please note some sections are removed simply to highlight the controller sections -```{literalinclude} ../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml +```{literalinclude} ../../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml :language: yaml :lineno-start: 52 :linenos: true @@ -37,7 +37,7 @@ Here, we're highlighting the dispatch controller setup from We also include a demand technology to calculate how much demand is met, how much commodity is unused to meet the demand, and how much demand is remaining: -```{literalinclude} ../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml +```{literalinclude} ../../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml :language: yaml :lineno-start: 79 :linenos: true diff --git a/docs/control/figures/Pyomo_dispatch_figure.png b/docs/control/technology_level_control/figures/Pyomo_dispatch_figure.png similarity index 100% rename from docs/control/figures/Pyomo_dispatch_figure.png rename to docs/control/technology_level_control/figures/Pyomo_dispatch_figure.png diff --git a/docs/control/figures/example_peak_load_dispatch.png b/docs/control/technology_level_control/figures/example_peak_load_dispatch.png similarity index 100% rename from docs/control/figures/example_peak_load_dispatch.png rename to docs/control/technology_level_control/figures/example_peak_load_dispatch.png diff --git a/docs/control/figures/plm_optimized_dispatch.png b/docs/control/technology_level_control/figures/plm_optimized_dispatch.png similarity index 100% rename from docs/control/figures/plm_optimized_dispatch.png rename to docs/control/technology_level_control/figures/plm_optimized_dispatch.png diff --git a/docs/control/open-loop_controllers.md b/docs/control/technology_level_control/open-loop_controllers.md similarity index 99% rename from docs/control/open-loop_controllers.md rename to docs/control/technology_level_control/open-loop_controllers.md index cc601a137..60b7f378d 100644 --- a/docs/control/open-loop_controllers.md +++ b/docs/control/technology_level_control/open-loop_controllers.md @@ -49,7 +49,7 @@ from pathlib import Path from IPython.display import HTML, display # Change to an example directory -os.chdir("../../examples/14_wind_hydrogen_dispatch/") +os.chdir("../../../examples/14_wind_hydrogen_dispatch/") # Build and set up the model h2i_model = H2IntegrateModel("inputs/h2i_wind_to_h2_storage.yaml") diff --git a/docs/control/pyomo_controllers.md b/docs/control/technology_level_control/pyomo_controllers.md similarity index 94% rename from docs/control/pyomo_controllers.md rename to docs/control/technology_level_control/pyomo_controllers.md index 09f93e5af..19ebfc9f4 100644 --- a/docs/control/pyomo_controllers.md +++ b/docs/control/technology_level_control/pyomo_controllers.md @@ -33,7 +33,7 @@ from pathlib import Path from IPython.display import HTML, display # Change to an example directory -os.chdir("../../examples/18_pyomo_heuristic_dispatch/") +os.chdir("../../../examples/18_pyomo_heuristic_dispatch/") # Build and set up the model h2i_model = H2IntegrateModel("pyomo_heuristic_dispatch.yaml") @@ -75,7 +75,7 @@ For an example of how to use the heuristic Pyomo control framework with the `Heu ## Optimized Load Following Controller The optimized dispatch method is specified by setting the storage control to `OptimizedDispatchStorageController`. Unlike the heuristic method, the optimized dispatch method does not use `dispatch_rule_set` as an input in the `tech_config`. The `OptimizedDispatchStorageController` method maximizes the load met while minimizing the cost of the system (operating cost) over each specified time window. -The optimized dispatch using Pyomo is implemented differently than the heuristic dispatch in order to be able to properly aggregate the individual Pyomo technology models into a cohesive Pyomo plant model for the optimization solver. Practically, this means that the Pyomo elements of the dispatch (including the individual technology models and the plant model) are not exposed to the main H2I code flow, and do not appear in the N2 diagram. The figure below shows a flow diagram of how the dispatch is implemented. The green blocks below represent what is represented in the N2 diagram of the system. The dispatch routine is currently self-contained within the storage technology of the system, though it includes solving an aggregated plant model in the optimization +The optimized dispatch using Pyomo is implemented differently than the heuristic dispatch in order to be able to properly aggregate the individual Pyomo technology models into a cohesive Pyomo plant model for the optimization solver. The Pyomo plant model is from the perspective of the storage technology and is meant to track inflows of commodities and other parameters that might impact the dispatch of the storage from upstream technologies. Practically, this means that the Pyomo elements of the dispatch (including the individual technology models and the plant model) are not exposed to the main H2I code flow, and do not appear in the N2 diagram. The figure below shows a flow diagram of how the dispatch is implemented. The green blocks below represent what is represented in the N2 diagram of the system. The dispatch routine is currently self-contained within the storage technology of the system, though it includes solving an aggregated plant model in the optimization ```{note} Only the PySAM battery performance model can call Pyomo dispatch at this time. ``` diff --git a/docs/control/control_overview.md b/docs/control/technology_level_control/technology_control_overview.md similarity index 71% rename from docs/control/control_overview.md rename to docs/control/technology_level_control/technology_control_overview.md index 1b18fd85b..d0016acea 100644 --- a/docs/control/control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,6 +1,6 @@ -# Control Overview +# Technology-Level Control -There are two different systematic approaches, or frameworks, in H2Integrate for control: [open-loop](#open-loop-control) and [pyomo](#pyomo-control). These two frameworks are useful in different situations and have different impacts on the system and control strategies that can be implemented. Both control frameworks are focused on technology-level dispatching. The open-loop framework has logic that is applicable to both storage technologies and converter technologies and the pyomo framework is currently applicable to storage technologies. However, we plan to extend them to work more generally as system controllers. Although the controllers are not operating at the system-level for now, they behave somewhat like system controllers in that they may curtail/discard commodity amounts exceeding the needs of the storage technology and the specified demand. However, any unused commodity may be connected to another down-stream component to avoid actual curtailment. +There are two different systematic approaches, or frameworks, in H2Integrate for technology-level control: [open-loop](#open-loop-control) and [pyomo](#pyomo-control). These two frameworks are useful in different situations and have different impacts on the system and control strategies that can be implemented. Both control frameworks are focused on technology-level dispatching. The open-loop framework has logic that is applicable to both storage technologies and converter technologies **IS THIS STILL TRUE?** and the pyomo framework is currently applicable to storage technologies. The technology-level storage controllers may curtail/discard commodity amounts exceeding the needs of the storage technology and the specified demand. However, any unused commodity may be connected to another down-stream component to avoid actual curtailment. (open-loop-control-framework)= ## Open-loop control framework From 9beec63e822965015ba7835e1a08c8f873ffd05f Mon Sep 17 00:00:00 2001 From: kbrunik Date: Mon, 11 May 2026 14:38:12 -0500 Subject: [PATCH 081/132] more docs --- docs/_toc.yml | 14 ++++++++------ .../system_level_control/control_classifier.md | 4 ++++ docs/control/system_level_control/controllers.md | 15 +++++++++++++++ .../system_level_control/system_level_control.md | 4 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 docs/control/system_level_control/controllers.md diff --git a/docs/_toc.yml b/docs/_toc.yml index e1255eaca..f7ac1f722 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -74,14 +74,16 @@ parts: sections: - file: control/system_level_control/system_level_control_base - file: control/system_level_control/control_classifier - - file: control/system_level_control/slc_demand_following - - file: control/system_level_control/slc_cost_min - - file: control/system_level_control/slc_profit_max + - file: control/system_level_control/controllers + sections: + - file: control/system_level_control/slc_demand_following + - file: control/system_level_control/slc_cost_min + - file: control/system_level_control/slc_profit_max - file: control/technology_level_control/technology_control_overview sections: - - file: control/open-loop_controllers - - file: control/pyomo_controllers - - file: control/controller_demonstrations + - file: control/technology_level_control/open-loop_controllers + - file: control/technology_level_control/pyomo_controllers + - file: control/technology_level_control/controller_demonstrations - caption: Demand chapters: - file: demand/demand_components diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index c5586b54c..246961029 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -13,6 +13,7 @@ Classifier | Meaning | Example Techs curtailable | Produces based on resource or input commodity; can only be reduced | wind, solar, nuclear dispatchable | Can modulate consumption/production within bounds | grid, NG turbine storage | Can modulate consumption/production within bounds while tracking SOC; does not produce/consume energy | battery, h2 storage, any storage +feedstock | Can't be controlled but system knows how much is available | NG from a pipe To add a classifier for a particular model it would look something like this in the class: ```{python} @@ -57,3 +58,6 @@ The system-level controller outputs set points to the storage performance model :width: 85% :align: center ``` + +## Feedstock +Another category of control classifiers are feedstocks. The unique thing about feedstocks is that they are considered outside of the controllable system within H2I. While they can't be controlled it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. diff --git a/docs/control/system_level_control/controllers.md b/docs/control/system_level_control/controllers.md new file mode 100644 index 000000000..c0b91b9e5 --- /dev/null +++ b/docs/control/system_level_control/controllers.md @@ -0,0 +1,15 @@ +# Control Strategies +There are several simple control strategies already implemented in the SLC paradigm. While fairly simplistic, they are meant to illustrate how information can be passed from different blocks/components (converters, storage, feedstocks, demand, etc.) and models (performance, cost, finance) to use within the SLC. + +The current control strategies are: +1. [Demand Following](#slc-demand-following) +2. [Cost Minimization](#slc-cost-min) +3. [Profit Maximization](#slc-profit-max) + +```{note} +The strategies currently implemented are experimental and will likely require further development for specific analyses. +``` + +All control strategies inherit `SystemLevelControlBase`, which is a base class that has common setup logic shared by all system-level control strategies. + +See additional information, which is more developer focused, about the [`SystemLevelControlBase`](#slc-base). diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 5ebbd3838..9e8f89b4f 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -11,7 +11,7 @@ The most basic SLC is shown in the figured below, where the SLC receives a deman The SLC control strategy and solver options are set within `plant_config.yaml` under the `"system_level_control"` section. -```{yaml} +```yaml system_level_control: control_strategy: DemandFollowingControl solver_options: @@ -22,7 +22,7 @@ system_level_control: To set the demand for the SLC that is configured in the `tech_config.yaml` using a demand block/component. For example: -```{yaml} +```yaml electrical_load_demand: performance_model: model: GenericDemandComponent From f76330235083065d5075fd42009711a42d5f1498 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 14:54:42 -0600 Subject: [PATCH 082/132] updated no_battery example --- .../no_battery/plant_config.yaml | 14 +++++++------- .../no_battery/tech_config.yaml | 7 ------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/examples/35_system_level_control/no_battery/plant_config.yaml b/examples/35_system_level_control/no_battery/plant_config.yaml index c5eca242c..010794a6e 100644 --- a/examples/35_system_level_control/no_battery/plant_config.yaml +++ b/examples/35_system_level_control/no_battery/plant_config.yaml @@ -14,14 +14,14 @@ sites: # with the reverse definition. # this will naturally grow as we mature the interconnected tech technology_interconnections: - - [wind, combiner, electricity, cable] # source_tech, dest_tech, transport_item, transport_type = connection - - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect NG feedstock to NG plant + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] + # combine the electricity and natural gas production + - [wind, combiner, electricity, cable] + - [natural_gas_plant, combiner, electricity, cable] + # subtract the combined electricity production from the demand - [combiner, electrical_load_demand, electricity, cable] - # subtract wind from demand - - [combiner, fin_combiner, electricity, cable] - - [natural_gas_plant, fin_combiner, electricity, cable] resource_to_tech_connections: # connect the wind resource to the wind technology - [site.wind_resource, wind, wind_resource_data] @@ -86,7 +86,7 @@ finance_parameters: finance_subgroups: renewables: commodity: electricity - commodity_stream: combiner + commodity_stream: wind finance_groups: [profast_lco, profast_npv] technologies: [wind] natural_gas: @@ -96,7 +96,7 @@ finance_parameters: technologies: [natural_gas_plant, ng_feedstock] electricity: commodity: electricity - commodity_stream: fin_combiner + commodity_stream: combiner finance_groups: [profast_lco] technologies: [wind, natural_gas_plant, ng_feedstock] cost_adjustment_parameters: diff --git a/examples/35_system_level_control/no_battery/tech_config.yaml b/examples/35_system_level_control/no_battery/tech_config.yaml index 10c0959c6..fa4881fbd 100644 --- a/examples/35_system_level_control/no_battery/tech_config.yaml +++ b/examples/35_system_level_control/no_battery/tech_config.yaml @@ -77,10 +77,3 @@ technologies: performance_parameters: commodity: electricity commodity_rate_units: kW - fin_combiner: - performance_model: - model: GenericCombinerPerformanceModel - model_inputs: - performance_parameters: - commodity: electricity - commodity_rate_units: kW From 12f0b1115603af5efc98ba928883f1031148c10a Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 14:59:46 -0600 Subject: [PATCH 083/132] cleaned up other slc examples --- .../battery_with_controller/plant_config.yaml | 16 ++++++++-------- .../battery_with_controller/tech_config.yaml | 2 +- .../yes_battery/plant_config.yaml | 14 +++++++------- .../yes_battery/tech_config.yaml | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/35_system_level_control/battery_with_controller/plant_config.yaml b/examples/35_system_level_control/battery_with_controller/plant_config.yaml index a2967e397..24e0aeb39 100644 --- a/examples/35_system_level_control/battery_with_controller/plant_config.yaml +++ b/examples/35_system_level_control/battery_with_controller/plant_config.yaml @@ -14,18 +14,18 @@ sites: # with the reverse definition. # this will naturally grow as we mature the interconnected tech technology_interconnections: - - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect NG feedstock to NG plant - - [wind, battery, electricity, cable] + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # wind output available for battery charging (electricity_in) - - [wind, fin_combiner, electricity, cable] + - [wind, battery, electricity, cable] # wind to combined output - - [battery, fin_combiner, electricity, cable] - # battery net output to combined output - - [natural_gas_plant, fin_combiner, electricity, cable] + - [wind, combiner, electricity, cable] + # battery output to combined output + - [battery, combiner, electricity, cable] # NG to combined output - - [fin_combiner, electrical_load_demand, electricity, cable] + - [natural_gas_plant, combiner, electricity, cable] # combined supply to demand + - [combiner, electrical_load_demand, electricity, cable] resource_to_tech_connections: # connect the wind resource to the wind technology - [site.wind_resource, wind, wind_resource_data] @@ -100,7 +100,7 @@ finance_parameters: technologies: [natural_gas_plant, ng_feedstock] electricity: commodity: electricity - commodity_stream: fin_combiner + commodity_stream: combiner finance_groups: [profast_lco] technologies: [wind, battery, natural_gas_plant, ng_feedstock] cost_adjustment_parameters: diff --git a/examples/35_system_level_control/battery_with_controller/tech_config.yaml b/examples/35_system_level_control/battery_with_controller/tech_config.yaml index 21075c502..20d6e1f8a 100644 --- a/examples/35_system_level_control/battery_with_controller/tech_config.yaml +++ b/examples/35_system_level_control/battery_with_controller/tech_config.yaml @@ -97,7 +97,7 @@ technologies: capacity_capex: 310 # $/kWh charge_capex: 311 # $/kW opex_fraction: 0.025 - fin_combiner: + combiner: performance_model: model: GenericCombinerPerformanceModel model_inputs: diff --git a/examples/35_system_level_control/yes_battery/plant_config.yaml b/examples/35_system_level_control/yes_battery/plant_config.yaml index a2967e397..d53a525ca 100644 --- a/examples/35_system_level_control/yes_battery/plant_config.yaml +++ b/examples/35_system_level_control/yes_battery/plant_config.yaml @@ -14,18 +14,18 @@ sites: # with the reverse definition. # this will naturally grow as we mature the interconnected tech technology_interconnections: - - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect NG feedstock to NG plant - - [wind, battery, electricity, cable] + - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # wind output available for battery charging (electricity_in) - - [wind, fin_combiner, electricity, cable] + - [wind, battery, electricity, cable] # wind to combined output - - [battery, fin_combiner, electricity, cable] + - [wind, combiner, electricity, cable] # battery net output to combined output - - [natural_gas_plant, fin_combiner, electricity, cable] + - [battery, combiner, electricity, cable] # NG to combined output - - [fin_combiner, electrical_load_demand, electricity, cable] + - [natural_gas_plant, combiner, electricity, cable] # combined supply to demand + - [combiner, electrical_load_demand, electricity, cable] resource_to_tech_connections: # connect the wind resource to the wind technology - [site.wind_resource, wind, wind_resource_data] @@ -100,7 +100,7 @@ finance_parameters: technologies: [natural_gas_plant, ng_feedstock] electricity: commodity: electricity - commodity_stream: fin_combiner + commodity_stream: combiner finance_groups: [profast_lco] technologies: [wind, battery, natural_gas_plant, ng_feedstock] cost_adjustment_parameters: diff --git a/examples/35_system_level_control/yes_battery/tech_config.yaml b/examples/35_system_level_control/yes_battery/tech_config.yaml index acda181e3..258e95da2 100644 --- a/examples/35_system_level_control/yes_battery/tech_config.yaml +++ b/examples/35_system_level_control/yes_battery/tech_config.yaml @@ -92,7 +92,7 @@ technologies: capacity_capex: 310 # $/kWh charge_capex: 311 # $/kW opex_fraction: 0.025 - fin_combiner: + combiner: performance_model: model: GenericCombinerPerformanceModel model_inputs: From 6af23971a2f39122f57a99eaa8bfeb4ff7a1d91f Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 15:02:18 -0600 Subject: [PATCH 084/132] removed SLC baseconfig since its unused --- .../system_level/system_level_control_base.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 20ffe56b7..1c7ba6dc5 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -1,14 +1,6 @@ import numpy as np import networkx as nx import openmdao.api as om -from attrs import field, define - -from h2integrate.core.utilities import BaseConfig - - -@define(kw_only=True) -class SystemLevelControlBaseConfig(BaseConfig): - demand_tech: str | None = field(default=None) class SystemLevelControlBase(om.ExplicitComponent): From dee192513703158421f8ced3d3a3759cff2ca7b4 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 15:32:47 -0600 Subject: [PATCH 085/132] updated docstring in baseclass --- .../system_level/system_level_control_base.py | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 1c7ba6dc5..e7e5ad05f 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -8,19 +8,27 @@ class SystemLevelControlBase(om.ExplicitComponent): Provides common setup logic shared by all system-level control strategies: demand input, curtailable/dispatchable/storage technology I/O creation, - and technology classification reading from ``plant_config``. + and technology classification reading from ``plant_config`` and ``slc_config`` Subclasses must implement ``compute()`` with their dispatch strategy. - Configuration is read from ``plant_config["system_level_control"]``, + Information passed to the controller from H2IntegrateModel is input in the ``slc_config``, which must contain: - - ``commodity``: the commodity being controlled (e.g. "electricity") - - ``commodity_units``: units string (or None) + - ``demand_commodity``: the commodity being controlled (e.g. "electricity") + - ``demand_commodity_rate_units``: units string (or None) of the demand commodity - ``demand_tech``: name of the demand technology - - ``curtailable_techs``: list of curtailable technology names - - ``dispatchable_techs``: list of dispatchable technology names - - ``storage_techs``: list of storage technology names + - ``storage_techs_to_control``: dictionary with keys of the technology names. The value is True + if the technology is classified as "storage" and has an attached controller. + Otherwise the value is False. + - ``technology_graph``: directional graph object representation of the + technology_interconnections found in the ``plant_config`` + - ``tech_to_commodity``: set of tuples formatted as (tech_name, tech_output_commodity) + - ``tech_control_classifiers``: dictionary of technologies with keys as the technology names the + value as the corresponding control classifier + + Controller-specific configuration parameters may be read from + ``plant_config["system_level_control"]["control_parameters"]`` """ def initialize(self): From 37be44e12114ed578917c1538a105e95cf20d079 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Mon, 11 May 2026 16:41:10 -0500 Subject: [PATCH 086/132] docs added --- .../control_classifier.md | 4 +- .../system_level_control/slc_cost_min.md | 2 + .../slc_demand_following.md | 6 +++ .../system_level_control/slc_profit_max.md | 2 + .../system_level_control.md | 2 +- .../system_level_control_base.md | 37 +++++++++++++++++++ 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index 246961029..51047c007 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -6,14 +6,14 @@ To enable a generic system level control framework we need to classify each tech While in real life there are a lot of controllable parameters allowing for ramping production up or down for a particular technology (e.g., turbine yaw). The particular model in H2I might not be capable of simulating a modulated response based on an input signal. ``` -We have identified three key classifiers that are able to represent the different behaviors that we can expect from the model. Each performance model includes a parameter setting the classifier `_control_classifier`. +We have identified four key classifiers that are able to represent the different behaviors that we can expect from the models. Each performance model includes a parameter setting the classifier `_control_classifier`. Classifier | Meaning | Example Techs -- | -- | -- curtailable | Produces based on resource or input commodity; can only be reduced | wind, solar, nuclear dispatchable | Can modulate consumption/production within bounds | grid, NG turbine storage | Can modulate consumption/production within bounds while tracking SOC; does not produce/consume energy | battery, h2 storage, any storage -feedstock | Can't be controlled but system knows how much is available | NG from a pipe +feedstock | Can't be controlled but system knows how much is available | NG or water from feedstock To add a classifier for a particular model it would look something like this in the class: ```{python} diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md index f24570590..1212a39ef 100644 --- a/docs/control/system_level_control/slc_cost_min.md +++ b/docs/control/system_level_control/slc_cost_min.md @@ -1,2 +1,4 @@ (slc-cost-min)= # Cost Minimization System Level Controller + +## Limitations diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 72a05dcf4..969d170c1 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -1,2 +1,8 @@ (slc-demand-following)= # Demand Following System Level Controller + +## Inputs and Outputs + +## Heterogenous Systems + +## Limitations diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md index 42ac80f14..e8659f8c5 100644 --- a/docs/control/system_level_control/slc_profit_max.md +++ b/docs/control/system_level_control/slc_profit_max.md @@ -1,2 +1,4 @@ (slc-profit-max)= # Profit Maximization System Level Controller + +## Limitations diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 9e8f89b4f..9c2b61509 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -45,7 +45,7 @@ The current control strategies are: The strategies currently implemented are experimental and will likely require further development for specific analyses. ``` -All control strategies inherit `SystemLevelControlBase`, which is a base class that has common setup logic shared by all system-level control strategies. +All control strategies inherit [`SystemLevelControlBase`](#slc-base), which is a base class that has common setup logic shared by all system-level control strategies. See additional information, which is more developer focused, about the [`SystemLevelControlBase`](#slc-base). diff --git a/docs/control/system_level_control/system_level_control_base.md b/docs/control/system_level_control/system_level_control_base.md index 003ee07ad..ad2acf592 100644 --- a/docs/control/system_level_control/system_level_control_base.md +++ b/docs/control/system_level_control/system_level_control_base.md @@ -1,2 +1,39 @@ (slc-base)= # System Level Control Base Class + +The system-level control base class provides a common framework that all controllers (advanced control strategies) can use to configure required inputs and outputs for both the controllers and the components they control or track. This generalization is necessary to implement system-level control in H2I. If the technologies and controllers in a given system were fully specified, this base class would not be needed. + +The base class also abstracts logic that may be shared across different controller types. It includes methods that could be useful, but not all methods will be relevant to every controller you implement. + +There are several methods that are already used in the simple controllers that inherit these system. + +Setup I/O for SLC controllers. +- `initialize()` +- `setup()` +- `_setup_commodity()` +- `_setup_tech_category()` +- `_setup_feedstock_category()` +- `find_converter_techs()` + - Note: this currently is not implemented but will be used for heterogeneous commodity systems. + +Functions for controlling components based on assigned control classifier. +- `_subtract_curtailable()` +- `_dispatch_storage()` +- `get_upstream_techs_for_commodity()` + +Helper functions for cost-aware controllers. +- `_setup_marginal_costs()` +- `_compute_marginal_costs()` +- `_buy_price_marginal_cost()` +- `_varopex_marginal_cost()` +- `_find_feedstock_techs()` +- `_feedstock_marginal_cost()` + +## Base Class and Methods + +```{eval-rst} +.. autoclass:: h2integrate.control.control_strategies.system_level.system_level_control_base.SystemLevelControlBase + :members: + :undoc-members: + :show-inheritance: +``` From 416dc5dc9598d220f6b76b47ba2cb019ec805762 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 16:42:22 -0600 Subject: [PATCH 087/132] minor update to demand following and updated profast to handle zero cf --- .../yes_hydrogen/plant_config.yaml | 96 +++++++++---------- .../system_level/demand_following_control.py | 19 ++-- .../system_level/test/test_slc_examples.py | 8 ++ h2integrate/finances/profast_lco.py | 13 +++ 4 files changed, 82 insertions(+), 54 deletions(-) diff --git a/examples/35_system_level_control/yes_hydrogen/plant_config.yaml b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml index ce6872101..9244ce3fb 100644 --- a/examples/35_system_level_control/yes_hydrogen/plant_config.yaml +++ b/examples/35_system_level_control/yes_hydrogen/plant_config.yaml @@ -47,51 +47,51 @@ system_level_control: solver_name: gauss_seidel max_iter: 20 convergence_tolerance: 1.0e-6 -# finance_parameters: -# finance_groups: -# profast_lco: -# 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.] -# finance_subgroups: -# # renewables: -# # commodity: electricity -# # commodity_stream: wind -# # finance_groups: [profast_lco] -# # technologies: [wind] -# # natural_gas: -# # commodity: electricity -# # commodity_stream: natural_gas_plant -# # finance_groups: [profast_lco] -# # technologies: [natural_gas_plant, ng_feedstock] -# electricity: -# commodity: electricity -# commodity_stream: elec_combiner -# finance_groups: [profast_lco] -# technologies: [wind, battery, natural_gas_plant, ng_feedstock] -# # hydrogen: -# # commodity: hydrogen -# # commodity_stream: h2_combiner -# # finance_groups: [profast_lco] -# # technologies: [wind, battery, natural_gas_plant, ng_feedstock, electrolyzer, h2_storage] -# cost_adjustment_parameters: -# cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year -# target_dollar_year: 2022 +finance_parameters: + finance_groups: + profast_lco: + 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.] + finance_subgroups: + renewables: + commodity: electricity + commodity_stream: wind + finance_groups: [profast_lco] + technologies: [wind] + natural_gas: + commodity: electricity + commodity_stream: natural_gas_plant + finance_groups: [profast_lco] + technologies: [natural_gas_plant, ng_feedstock] + electricity: + commodity: electricity + commodity_stream: elec_combiner + finance_groups: [profast_lco] + technologies: [wind, battery, natural_gas_plant, ng_feedstock] + hydrogen: + commodity: hydrogen + commodity_stream: h2_combiner + finance_groups: [profast_lco] + technologies: [wind, battery, natural_gas_plant, ng_feedstock, electrolyzer, h2_storage] + cost_adjustment_parameters: + cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year + target_dollar_year: 2022 diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 815b95099..7821f8d84 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -36,12 +36,19 @@ def compute(self, inputs, outputs): for curtailable_tech in self.curtailable_techs: commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) # check that this tech produces the commodity demanded - if commodity in commodity_from_tech: - # if the commodity produced from a tech is the demanded commodity - # then subtract the curtailable production from the demand - demand = self._subtract_curtailable( - curtailable_tech, demand, commodity, inputs, outputs - ) + for tech_commodity in commodity_from_tech: + if tech_commodity == commodity: + # if the commodity produced from a tech is the demanded commodity + # then subtract the curtailable production from the demand + demand = self._subtract_curtailable( + curtailable_tech, demand, commodity, inputs, outputs + ) + else: + if f"{curtailable_tech}_rated_{tech_commodity}_production" in inputs: + # set the set-point as the rated production + outputs[f"{curtailable_tech}_{tech_commodity}_set_point"] = inputs[ + f"{curtailable_tech}_rated_{tech_commodity}_production" + ] * np.ones(self.n_timesteps) # 2. Storage dispatch # number of storage components that produce the demanded commodity diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index ccdf5dc37..c85352ef5 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -98,6 +98,14 @@ def test_slc_yes_hydrogen(subtests, temp_copy_of_example): with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 + with subtests.test("LCOH"): + assert ( + pytest.approx( + model.prob.get_val("finance_subgroup_hydrogen.LCOH", units="USD/kg"), rel=1e-6 + ) + == 14.878096642042243 + ) + @pytest.mark.unit @pytest.mark.parametrize( diff --git a/h2integrate/finances/profast_lco.py b/h2integrate/finances/profast_lco.py index 566b393d3..ab353ffe3 100644 --- a/h2integrate/finances/profast_lco.py +++ b/h2integrate/finances/profast_lco.py @@ -1,3 +1,4 @@ +import warnings from pathlib import Path import numpy as np @@ -106,6 +107,18 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """ pf = self.populate_profast(inputs) + if "system_level_control" in self.options["plant_config"] and np.all( + inputs["capacity_factor"] == 0.0 + ): + outputs[self.LCO_str] = 1e12 + msg = ( + f"Commodity stream for finance group has a zero capacity factor. " + "If you recieve this warning multiple times, there may be a problem " + "with your setup. ProFAST is not being run on this iteration and the " + f"{self.LCO_str} is being set to default value of 1e12 ({self.price_units})" + ) + warnings.warn(msg, UserWarning) + return # simulate ProFAST sol, summary, price_breakdown = run_profast(pf) From 7deabecbad33a44225f8054ac96b02d4c1964611 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Mon, 11 May 2026 16:43:13 -0600 Subject: [PATCH 088/132] added start of demand following docs --- .../slc_demand_following.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 72a05dcf4..01d0e5b3c 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -1,2 +1,33 @@ (slc-demand-following)= # Demand Following System Level Controller + +The demand following controller, `DemandFollowingControl`, aims to fully meet the demand and does not have any inputs related to cost. + +## Inputs + +The inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: + +- `f"{tech_name}_{tech_output_commodity}_out"` +- `f"{tech_name}_rated_{tech_output_commodity}_production"` + +The inputs for technologies classified as `feedstock` are: +- `f"{tech_name}_{commodity}_out"` + +## Outputs +The outputs for technologies classified as `curtailable`, `dispatchable`, or `storage` and *without a storage controller* are: +- `f"{tech_name}_{tech_output_commodity}_set_point"` + +The outputs for technologies classified as `storage` that *have a storage controller* are: +- `f"{tech_name}_{tech_output_commodity}_demand"` + +## Heterogenous Systems + + +## Limitations + + +## General Logic + +First, control logic is as follows: +- For every technology classified as "curtailable", set the set-point as the rated commodity production of that technology. Subtract the commodity produced by the technology from the overall demand profile +- The remaining demand profile will be negative when the curtailable technologies produce more commodity than demanded and positive when the curtailable technologies produce less commodity than demanded. The remaining demand profile is divided by the number of storage technologies in the system to get the set point for each storage technology. This set point is negative to command the storage to charge, and positive to command the storage to discharge. From b6003fe8946c871b29f1b37a0428fc87ba6918c7 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Mon, 11 May 2026 22:48:44 -0600 Subject: [PATCH 089/132] Adding to SLC docs --- .../system_level_control/slc_cost_min.md | 68 ++++++++++ .../slc_demand_following.md | 61 ++++++++- .../system_level_control/slc_profit_max.md | 117 ++++++++++++++++++ 3 files changed, 245 insertions(+), 1 deletion(-) diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md index 1212a39ef..40e304523 100644 --- a/docs/control/system_level_control/slc_cost_min.md +++ b/docs/control/system_level_control/slc_cost_min.md @@ -1,4 +1,72 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.18.1 +kernelspec: + display_name: Python 3.11.13 ('h2i_env') + language: python + name: python3 +--- + (slc-cost-min)= # Cost Minimization System Level Controller +The cost minimization controller, `CostMinimizationControl`, meets demand at minimum variable cost using merit-order dispatch. +Unlike the {ref}`demand following controller `, which splits demand evenly across dispatchable technologies, this controller dispatches the cheapest technologies first. + +## Dispatch Logic + +The controller follows a three-step dispatch process: + +1. **Curtailable technologies** run at their full rated capacity (assumed zero marginal cost). Their output is subtracted from the demand. +2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging). Residual demand is split evenly across storage technologies producing the demanded commodity. +3. **Dispatchable technologies** are dispatched by cheapest marginal cost first, each up to its rated capacity, until the remaining demand is met. + +## Marginal Cost Configuration + +Marginal costs are specified per dispatchable technology in the `cost_per_tech` dictionary under `system_level_control.control_parameters` in the plant config. Each entry can be: + +| Value | Description | +| --- | --- | +| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_unit*h)` | +| `"buy_price"` | Uses the technology's configured purchase price | +| `"VarOpEx"` | Derives marginal cost from the technology's variable operating expenditure divided by total production | +| `"feedstock"` | Sums upstream feedstock `VarOpEx` values and divides by the technology's total production | + +```{note} +The dispatch order is determined by sorting dispatchable technologies by their **mean** marginal cost across all timesteps (cheapest first). +``` + +### Example Configuration + +```yaml +system_level_control: + control_strategy: CostMinimizationControl + control_parameters: + cost_per_tech: + natural_gas_plant: feedstock +``` + +## Inputs and Outputs + +In addition to the standard inputs inherited from `SystemLevelControlBase`, the cost minimization controller adds marginal cost inputs based on the `cost_per_tech` configuration (see above). + +The base inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: + +- `f"{tech_name}_{tech_output_commodity}_out"` +- `f"{tech_name}_rated_{tech_output_commodity}_production"` + +The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: +- `f"{tech_name}_{tech_output_commodity}_set_point"` + +The outputs for `storage` technologies *with* a storage controller are: +- `f"{tech_name}_{tech_output_commodity}_demand"` + ## Limitations + +- Greedy dispatch: The merit-order approach is greedy - it does not look ahead across timesteps to optimize total cost over the simulation horizon. +- Even splitting across storage: Residual demand is split evenly across storage technologies regardless of capacity or state of charge. +- Demand is always met: Unlike the {ref}`profit maximization controller `, this controller always attempts to meet demand regardless of cost. diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index acca39b00..1e58a9e49 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -1,8 +1,59 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.18.1 +kernelspec: + display_name: Python 3.11.13 ('h2i_env') + language: python + name: python3 +--- + (slc-demand-following)= # Demand Following System Level Controller The demand following controller, `DemandFollowingControl`, aims to fully meet the demand and does not have any inputs related to cost. +The N2 diagram below shows an example system using the demand following controller with wind, natural gas, and battery storage technologies. + +```{code-cell} ipython3 +:tags: [remove-input] + +from h2integrate.core.h2integrate_model import H2IntegrateModel +import openmdao.api as om +import os + +import html +from pathlib import Path +from IPython.display import HTML, display + +os.chdir("../../../examples/35_system_level_control/battery_with_controller/") + +h2i_model = H2IntegrateModel("wind_ng_demand.yaml") +h2i_model.setup() + +om.n2( + h2i_model.prob, + outfile="h2i_n2.html", + display_in_notebook=False, + show_browser=False, +) + +n2_html = "h2i_n2.html" +n2_srcdoc = html.escape(Path(n2_html).read_text(encoding="utf-8")) +display( + HTML( + f'
' + f'' + '
' + ) +) +``` + ## Inputs and Outputs The inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: @@ -20,11 +71,19 @@ The outputs for technologies classified as `curtailable`, `dispatchable`, or `st The outputs for technologies classified as `storage` that *have a storage controller* are: - `f"{tech_name}_{tech_output_commodity}_demand"` -## Heterogenous Systems +## Systems with Heterogeneous Commodities + +The `DemandFollowingControl` controller can be used in hybrid systems where technologies produce different commodities. +For example, in a system where an electrolyzer produces hydrogen and the demand commodity is hydrogen, the controller can set the electricity-generating technologies' set-points to meet the hydrogen demand. +This framework provides a starting point for hybrid energy system control but is intended to be extended with more sophisticated strategies for complex multi-commodity systems. ## Limitations +- No cost awareness: The controller dispatches technologies purely to meet demand without considering operational costs, commodity prices, or economic optimization. +- Even splitting across storage: When multiple storage technologies produce the demanded commodity, the residual demand is divided evenly among them (`demand / n_storage`), regardless of differences in capacity, state of charge, or efficiency. +- Even splitting across dispatchable technologies: Similarly, any remaining demand after storage dispatch is split evenly across all dispatchable technologies (`remaining_demand / n_dispatchable`), without accounting for marginal costs or capacity constraints. +- Fixed priority order: The dispatch order (curtailable → storage → dispatchable) is fixed in the current implementation. ## General Logic diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md index e8659f8c5..c31b77aa4 100644 --- a/docs/control/system_level_control/slc_profit_max.md +++ b/docs/control/system_level_control/slc_profit_max.md @@ -1,4 +1,121 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.18.1 +kernelspec: + display_name: Python 3.11.13 ('h2i_env') + language: python + name: python3 +--- + (slc-profit-max)= # Profit Maximization System Level Controller +The profit maximization controller, `ProfitMaximizationControl`, dispatches technologies only when the revenue from selling the commodity exceeds the marginal cost of production. This means demand may go **unmet** if dispatch is unprofitable. + +The N2 diagram below shows an example system using the profit maximization controller with wind, natural gas, and battery storage technologies. + +```{code-cell} ipython3 +:tags: [remove-input] + +from h2integrate.core.h2integrate_model import H2IntegrateModel +import openmdao.api as om +import os + +import html +from pathlib import Path +from IPython.display import HTML, display + +os.chdir("../../../examples/35_system_level_control/profit_maximization/") + +h2i_model = H2IntegrateModel("wind_ng_demand.yaml") +h2i_model.setup() + +om.n2( + h2i_model.prob, + outfile="h2i_n2.html", + display_in_notebook=False, + show_browser=False, +) + +n2_html = "h2i_n2.html" +n2_srcdoc = html.escape(Path(n2_html).read_text(encoding="utf-8")) +display( + HTML( + f'
' + f'' + '
' + ) +) +``` + +## Dispatch Logic + +The controller follows a three-step dispatch process: + +1. **Curtailable technologies** run at full rated capacity - they are always profitable to produce (zero marginal cost). +2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging), split evenly across storage technologies producing the demanded commodity. +3. **Dispatchable technologies** are dispatched in merit order (cheapest first), but **only at timesteps where their marginal cost is below the sell price**. At each timestep, the dispatch is the minimum of the remaining demand and the rated capacity, gated by the profitability check. + +```{note} +This is the key difference from the {ref}`cost minimization controller `: unprofitable dispatch is skipped entirely, so demand may go unmet. +``` + +## Commodity Sell Price + +The sell price can be configured in two ways in `system_level_control.control_parameters`: + +| Value | Description | +| --- | --- | +| Numeric (e.g. `0.06`) | Constant sell price in `$/(commodity_unit*h)` | +| String (e.g. `"profast_npv"`) | Name of a finance group in `finance_parameters.finance_groups` whose `model_inputs.commodity_sell_price` will be used | + +## Marginal Cost Configuration + +Marginal costs are configured identically to the {ref}`cost minimization controller ` via `cost_per_tech`. Each dispatchable technology's entry can be: + +| Value | Description | +| --- | --- | +| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_unit*h)` | +| `"buy_price"` | Uses the technology's configured purchase price | +| `"VarOpEx"` | Derives cost from VarOpEx / total production | +| `"feedstock"` | Sums upstream feedstock VarOpEx / total production | + +### Example Configuration + +```yaml +system_level_control: + control_strategy: ProfitMaximizationControl + control_parameters: + commodity_sell_price: profast_npv # look up from finance group + cost_per_tech: + natural_gas_plant: feedstock # use upstream feedstock VarOpEx +``` + +## Inputs and Outputs + +In addition to the standard inputs inherited from `SystemLevelControlBase`, this controller adds: + +- `commodity_sell_price` - the sell price per unit of the demanded commodity, shape `(n_timesteps,)` +- Marginal cost inputs per dispatchable technology based on `cost_per_tech` configuration + +The base inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: + +- `f"{tech_name}_{tech_output_commodity}_out"` +- `f"{tech_name}_rated_{tech_output_commodity}_production"` + +The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: +- `f"{tech_name}_{tech_output_commodity}_set_point"` + +The outputs for `storage` technologies *with* a storage controller are: +- `f"{tech_name}_{tech_output_commodity}_demand"` + ## Limitations + +- Demand may go unmet: If no dispatchable technology is profitable at a given timestep, the remaining demand is not served. +- Even splitting across storage: Residual demand is split evenly across storage technologies regardless of capacity or state of charge. From 2b4f83503216c7ae1840dec168f48a0bbbe9d63a Mon Sep 17 00:00:00 2001 From: kbrunik Date: Tue, 12 May 2026 08:58:10 -0500 Subject: [PATCH 090/132] small doc mods --- docs/_toc.yml | 2 +- .../system_level_control/controllers.md | 4 +-- .../slc_demand_following.md | 27 ++++++++++++++----- .../system_level_control.md | 18 ++++++------- .../system_level_control_base.md | 2 +- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/docs/_toc.yml b/docs/_toc.yml index f7ac1f722..aa8d2794a 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -77,8 +77,8 @@ parts: - file: control/system_level_control/controllers sections: - file: control/system_level_control/slc_demand_following - - file: control/system_level_control/slc_cost_min - file: control/system_level_control/slc_profit_max + - file: control/system_level_control/slc_cost_min - file: control/technology_level_control/technology_control_overview sections: - file: control/technology_level_control/open-loop_controllers diff --git a/docs/control/system_level_control/controllers.md b/docs/control/system_level_control/controllers.md index c0b91b9e5..fed919828 100644 --- a/docs/control/system_level_control/controllers.md +++ b/docs/control/system_level_control/controllers.md @@ -3,8 +3,8 @@ There are several simple control strategies already implemented in the SLC parad The current control strategies are: 1. [Demand Following](#slc-demand-following) -2. [Cost Minimization](#slc-cost-min) -3. [Profit Maximization](#slc-profit-max) +2. [Profit Maximization](#slc-profit-max) +3. [Cost Minimization](#slc-cost-min) ```{note} The strategies currently implemented are experimental and will likely require further development for specific analyses. diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 1e58a9e49..391026a1b 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -53,6 +53,27 @@ display( ) ) ``` +## Dispatch Logic + +The he demand is satisfied in a fixed three-step priority order, and each step's shortfall or surplus is passed to the next: + +1. **Curtailable techs** run at their full rated capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). + +2. **Storage techs** receive the residual demand (which may be positive or negative). When demand is positive the storage is commanded to discharge; when negative it is commanded to charge. If multiple storage techs produce the demanded commodity, the residual demand is +split **evenly** across them (each receives ``demand / n_storage``). + +3. **Dispatchable techs** cover any remaining positive demand after storage. The remaining demand (floored at zero) is split **evenly** across all dispatchable techs that produce the demanded commodity (each receives ``remaining_demand / n_dispatchable``). + +### Example Configuration + +```yaml +system_level_control: + control_strategy: DemandFollowingControl + solver_options: # solver options for resolving feedback + solver_name: gauss_seidel + max_iter: 20 + convergence_tolerance: 1.0e-6 +``` ## Inputs and Outputs @@ -84,9 +105,3 @@ This framework provides a starting point for hybrid energy system control but is - Even splitting across storage: When multiple storage technologies produce the demanded commodity, the residual demand is divided evenly among them (`demand / n_storage`), regardless of differences in capacity, state of charge, or efficiency. - Even splitting across dispatchable technologies: Similarly, any remaining demand after storage dispatch is split evenly across all dispatchable technologies (`remaining_demand / n_dispatchable`), without accounting for marginal costs or capacity constraints. - Fixed priority order: The dispatch order (curtailable → storage → dispatchable) is fixed in the current implementation. - -## General Logic - -First, control logic is as follows: -- For every technology classified as "curtailable", set the set-point as the rated commodity production of that technology. Subtract the commodity produced by the technology from the overall demand profile -- The remaining demand profile will be negative when the curtailable technologies produce more commodity than demanded and positive when the curtailable technologies produce less commodity than demanded. The remaining demand profile is divided by the number of storage technologies in the system to get the set point for each storage technology. This set point is negative to command the storage to charge, and positive to command the storage to discharge. diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 9c2b61509..8f4b2e40f 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -24,13 +24,13 @@ To set the demand for the SLC that is configured in the `tech_config.yaml` using ```yaml electrical_load_demand: -performance_model: - model: GenericDemandComponent -model_inputs: - performance_parameters: - commodity: electricity - commodity_rate_units: kW - demand_profile: 30000 + performance_model: + model: GenericDemandComponent + model_inputs: + performance_parameters: + commodity: electricity + commodity_rate_units: kW + demand_profile: 30000 ``` ## Control Strategies @@ -38,8 +38,8 @@ There are several simple control strategies already implemented in the SLC parad The current control strategies are: 1. [Demand Following](#slc-demand-following) -2. [Cost Minimization](#slc-cost-min) -3. [Profit Maximization](#slc-profit-max) +2. [Profit Maximization](#slc-profit-max) +3. [Cost Minimization](#slc-cost-min) ```{note} The strategies currently implemented are experimental and will likely require further development for specific analyses. diff --git a/docs/control/system_level_control/system_level_control_base.md b/docs/control/system_level_control/system_level_control_base.md index ad2acf592..bee202706 100644 --- a/docs/control/system_level_control/system_level_control_base.md +++ b/docs/control/system_level_control/system_level_control_base.md @@ -14,7 +14,7 @@ Setup I/O for SLC controllers. - `_setup_tech_category()` - `_setup_feedstock_category()` - `find_converter_techs()` - - Note: this currently is not implemented but will be used for heterogeneous commodity systems. + - Note: this method is currently is not used but will be used for heterogeneous commodity systems. Functions for controlling components based on assigned control classifier. - `_subtract_curtailable()` From e8cf31f92359dc488b1f19e396fbffb2e4e50c8d Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 12 May 2026 09:31:42 -0600 Subject: [PATCH 091/132] minor update to doc page --- docs/control/system_level_control/slc_demand_following.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 391026a1b..9f68aed6b 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -27,9 +27,10 @@ import os import html from pathlib import Path +from h2integrate import EXAMPLE_DIR from IPython.display import HTML, display -os.chdir("../../../examples/35_system_level_control/battery_with_controller/") +os.chdir("EXAMPLE_DIR/35_system_level_control/battery_with_controller/") h2i_model = H2IntegrateModel("wind_ng_demand.yaml") h2i_model.setup() @@ -55,7 +56,7 @@ display( ``` ## Dispatch Logic -The he demand is satisfied in a fixed three-step priority order, and each step's shortfall or surplus is passed to the next: +The demand is satisfied in a fixed three-step priority order, and each step's shortfall or surplus is passed to the next: 1. **Curtailable techs** run at their full rated capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). From 0263a589843fdb48c719ee1dc67d0993be2bad83 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 12 May 2026 13:12:06 -0600 Subject: [PATCH 092/132] minor clarification in doc --- docs/control/system_level_control/slc_demand_following.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 9f68aed6b..8fea76611 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -96,7 +96,7 @@ The outputs for technologies classified as `storage` that *have a storage contro ## Systems with Heterogeneous Commodities The `DemandFollowingControl` controller can be used in hybrid systems where technologies produce different commodities. -For example, in a system where an electrolyzer produces hydrogen and the demand commodity is hydrogen, the controller can set the electricity-generating technologies' set-points to meet the hydrogen demand. +For example, in a system where an electrolyzer produces hydrogen and the demand commodity is hydrogen, the controller can set the electricity-generating *curtailable* technologies' set-points to meet the hydrogen demand. This framework provides a starting point for hybrid energy system control but is intended to be extended with more sophisticated strategies for complex multi-commodity systems. From 85c867954a92cdec199adb43d87cdab8b32a1091 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 13 May 2026 09:36:43 -0600 Subject: [PATCH 093/132] Reconfiguring the connection for varopex --- h2integrate/core/h2integrate_model.py | 51 ++++++++++++++++----------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index b48f4368e..3fc6e88ad 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -472,14 +472,22 @@ def create_plant_model(self): self.plant = self.model.add_subsystem("plant", plant_group, promotes=["*"]) def _classify_slc_technologies(self): - """Classify technologies for system-level control and store in plant_config. + """Classify technologies for system-level control. Uses ``self.tech_control_classifiers`` (populated by ``create_technology_models()``) to partition technologies into curtailable, dispatchable, and storage lists. Also identifies the single demand technology and its commodity. - Results are written into ``self.plant_config["system_level_control"]`` so - they are available to the ``DemandFollowingControl`` component at setup time. + Returns: + dict: Classification dictionary (``slc_config``) with keys: + + - ``"demand_tech"`` (str) + - ``"demand_commodity"`` (str) + - ``"demand_commodity_rate_units"`` (str | None) + - ``"tech_to_commodity"`` (set[tuple[str, str]]) + - ``"storage_techs_to_control"`` (dict[str, bool]) + - ``"technology_graph"`` (nx.DiGraph) + - ``"tech_control_classifiers"`` (dict[str, str]) """ slc_config = {} technologies = self.technology_config.get("technologies", {}) @@ -629,8 +637,11 @@ def add_system_level_controller(self, slc_config): specification determines which cost signal is connected: - ``"VarOpEx"``: connects the tech's own ``VarOpEx`` output. - - ``"feedstock"``: scans ``technology_interconnections`` for upstream feedstock - technologies and connects each feedstock's ``VarOpEx`` output. + - ``"feedstock"``: uses graph traversal (``nx.ancestors``) on the + ``technology_graph`` to find all upstream feedstock technologies + at any depth and connects each feedstock's ``VarOpEx`` output. + This is consistent with the ``_find_feedstock_techs`` method + used by the controller component internally. - ``"buy_price"``: no connection needed; the controller reads a default value from the tech config that can be overridden at runtime via ``prob.set_val()``. - Numeric scalar: no connection needed; the value is used directly as a constant @@ -740,6 +751,7 @@ def add_system_level_controller(self, slc_config): # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): cost_per_tech = plant_slc_config.get("control_parameters", {}).get("cost_per_tech", {}) + technology_graph = slc_config["technology_graph"] for tech_name, _ in slc_config["tech_to_commodity"]: if self.tech_control_classifiers[tech_name] == "dispatchable": cost_spec = cost_per_tech.get(tech_name, 0.0) @@ -750,21 +762,20 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_VarOpEx", ) elif cost_spec == "feedstock": - # Sum VarOpEx from all upstream feedstock technologies - interconnections = self.plant_config.get("technology_interconnections", []) - technologies = self.technology_config.get("technologies", {}) - for conn in interconnections: - if conn[1] != tech_name: - continue - upstream = conn[0] - tech_def = technologies.get(upstream, {}) - perf_model = tech_def.get("performance_model", {}).get("model", "") - cost_model = tech_def.get("cost_model", {}).get("model", "") - if "Feedstock" in perf_model or "Feedstock" in cost_model: - self.plant.connect( - f"{upstream}.VarOpEx", - f"system_level_controller.{upstream}_VarOpEx", - ) + # Find all upstream feedstock technologies using + # graph traversal (matches _find_feedstock_techs + # in the SLC component). + ancestors = nx.ancestors(technology_graph, tech_name) + feedstock_names = [ + t + for t in ancestors + if self.tech_control_classifiers.get(t) == "feedstock" + ] + for feedstock_name in feedstock_names: + self.plant.connect( + f"{feedstock_name}.VarOpEx", + f"system_level_controller.{feedstock_name}_VarOpEx", + ) # "buy_price": default from tech config, overridable via set_val # numeric scalar: used directly, no connection needed From ecf4273c38dd5cf7f6cce26be47178783a5244e8 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 14 May 2026 13:49:38 -0600 Subject: [PATCH 094/132] Shifting to five control classifiers --- .../control_classifier.md | 29 +++-- .../system_level/cost_minimization_control.py | 30 +++-- .../system_level/demand_following_control.py | 41 ++++--- .../profit_maximization_control.py | 30 +++-- .../system_level/system_level_control_base.py | 114 +++++++++++++++--- .../system_level/test/test_slc_controllers.py | 19 +-- h2integrate/converters/hopp/hopp_wrapper.py | 2 +- .../hydrogen/electrolyzer_baseclass.py | 10 ++ .../geologic/h2_well_subsurface_baseclass.py | 2 +- .../converters/hydrogen/pem_electrolyzer.py | 9 +- .../converters/nuclear/nuclear_plant.py | 2 +- .../converters/solar/solar_baseclass.py | 2 +- .../water_power/hydro_plant_run_of_river.py | 2 +- .../converters/water_power/tidal_pysam.py | 2 +- h2integrate/converters/wind/wind_plant_ard.py | 4 +- .../converters/wind/wind_plant_baseclass.py | 2 +- h2integrate/core/h2integrate_model.py | 28 ++++- h2integrate/core/model_baseclasses.py | 10 +- 18 files changed, 240 insertions(+), 98 deletions(-) diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index 51047c007..9b8cc5038 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -4,24 +4,30 @@ To enable a generic system level control framework we need to classify each tech ```{note} While in real life there are a lot of controllable parameters allowing for ramping production up or down for a particular technology (e.g., turbine yaw). The particular model in H2I might not be capable of simulating a modulated response based on an input signal. +These classifications are for how the models in H2I are implemented, **not** how the actual physical subsystem might operate. +This is a useful and necessary distinction that delineates different model capabilities clearly. ``` -We have identified four key classifiers that are able to represent the different behaviors that we can expect from the models. Each performance model includes a parameter setting the classifier `_control_classifier`. +We have identified five key classifiers that are able to represent the different behaviors that we can expect from the models. Each performance model includes a parameter setting the classifier `_control_classifier`. Classifier | Meaning | Example Techs -- | -- | -- -curtailable | Produces based on resource or input commodity; can only be reduced | wind, solar, nuclear -dispatchable | Can modulate consumption/production within bounds | grid, NG turbine -storage | Can modulate consumption/production within bounds while tracking SOC; does not produce/consume energy | battery, h2 storage, any storage -feedstock | Can't be controlled but system knows how much is available | NG or water from feedstock +fixed | Always produces commodity and cannot be controlled or reduced; does not receive a set-point | classical nuclear +flexible | Produces based on resource; can only reduce (curtail) | wind, solar +dispatchable | Can modulate consumption/production within bounds; receives a commodity set-point | grid, electrolyzer, NG turbine +storage | Can modulate consumption/production within bounds while tracking SOC | battery, h2 storage, any storage +feedstock | Are not directly controlled, but useful for SLC to know about to make dispatch decisions | feedstocks To add a classifier for a particular model it would look something like this in the class: ```{python} -_control_classifier = "curtailable" +_control_classifier = "flexible" ``` -## Curtailable -A curtailable performance model represents anything that can have the output reduced based on a give set point from the system level controller. This classifier and the inputs and outputs are included in the figure below. A good example of this is the PVWatts PySAM solar plant in H2I, the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the tracking software, but we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. +## Fixed +A fixed performance model represents anything that always produces at its rated capacity and cannot be controlled or reduced by the system level controller. The SLC reads the output from a fixed technology and subtracts it from the demand, but does not send a set-point back to the technology. A good example of this is a classical nuclear plant model — it produces a constant output that the rest of the system must accommodate. + +## Flexible +A flexible performance model represents anything that can have the output reduced based on a given set point from the system level controller. A good example of this is the PVWatts PySAM solar plant in H2I, the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the tracking software, but we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. ```{figure} figures/curtailable.png :width: 70% @@ -61,3 +67,10 @@ The system-level controller outputs set points to the storage performance model ## Feedstock Another category of control classifiers are feedstocks. The unique thing about feedstocks is that they are considered outside of the controllable system within H2I. While they can't be controlled it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. + +## SLC Dispatch Order +The system level controllers dispatch technologies in the following order: +1. **Fixed** — subtract their production from demand +2. **Flexible** — run at full capacity, subtract from demand +3. **Storage** — absorb surplus or provide deficit +4. **Dispatchable** — cover remaining demand diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 948589b25..d9208a0c7 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -10,9 +10,10 @@ class CostMinimizationControl(SystemLevelControlBase): Meets demand at minimum variable cost using merit-order dispatch: - 1. Curtailable techs run at rated capacity (assuming zero marginal cost). - 2. Storage absorbs surplus / provides deficit. - 3. Dispatchable techs are dispatched in ascending marginal-cost order, + 1. Fixed techs always produce (cannot be controlled). + 2. Flexible techs run at rated capacity (assuming zero marginal cost). + 3. Storage absorbs surplus / provides deficit. + 4. Dispatchable techs are dispatched in ascending marginal-cost order, each up to its rated capacity, until remaining demand is met. Marginal costs are configured via ``cost_per_tech`` in the @@ -33,18 +34,21 @@ def setup(self): def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() - # 1. Curtailable techs: full production - for curtailable_tech in self.curtailable_techs: - commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) - # check that this tech produces the commodity demanded + # 1. Fixed techs: always produce, subtract from demand + for fixed_tech in self.fixed_techs: + commodity_from_tech = self._get_commodity_for_tech(fixed_tech) if self.commodity in commodity_from_tech: - # if the commodity produced from a tech is the demanded commodity - # then subtract the curtailable production from the demand - demand = self._subtract_curtailable( - curtailable_tech, demand, self.commodity, inputs, outputs + demand = self._subtract_fixed(fixed_tech, demand, self.commodity, inputs) + + # 2. Flexible techs: full production + for flexible_tech in self.flexible_techs: + commodity_from_tech = self._get_commodity_for_tech(flexible_tech) + if self.commodity in commodity_from_tech: + demand = self._subtract_flexible( + flexible_tech, demand, self.commodity, inputs, outputs ) - # 2. Storage dispatch + # 3. Storage dispatch # number of storage components that produce the demanded commodity n_storage = len( [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] @@ -56,7 +60,7 @@ def compute(self, inputs, outputs): storage_tech, demand / n_storage, self.commodity, inputs, outputs ) - # 3. Merit-order dispatch: cheapest dispatchable first + # 4. Merit-order dispatch: cheapest dispatchable first remaining = np.maximum(demand, 0.0) marginal_costs = self._compute_marginal_costs(inputs) diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 7821f8d84..eb2427f00 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -9,20 +9,23 @@ class DemandFollowingControl(SystemLevelControlBase): """Demand-following system-level controller. Dispatches technologies to meet a time-varying demand profile without - considering costs. The demand is satisfied in a fixed three-step priority + considering costs. The demand is satisfied in a fixed four-step priority order, and each step's shortfall or surplus is passed to the next: - 1. **Curtailable techs** run at their full rated capacity. Their total + 1. **Fixed techs** always produce at their rated capacity and cannot be + controlled. Their total output is subtracted from the demand. + + 2. **Flexible techs** run at their full rated capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). - 2. **Storage techs** receive the residual demand (which may be positive + 3. **Storage techs** receive the residual demand (which may be positive or negative). When demand is positive the storage is commanded to discharge; when negative it is commanded to charge. If multiple storage techs produce the demanded commodity, the residual demand is split **evenly** across them (each receives ``demand / n_storage``). - 3. **Dispatchable techs** cover any remaining positive demand after + 4. **Dispatchable techs** cover any remaining positive demand after storage. The remaining demand (floored at zero) is split **evenly** across all dispatchable techs that produce the demanded commodity (each receives ``remaining_demand / n_dispatchable``). @@ -32,25 +35,29 @@ def compute(self, inputs, outputs): commodity = self.commodity demand = inputs[self.demand_input_name].copy() - # 1. Curtailable techs: operate at full production - for curtailable_tech in self.curtailable_techs: - commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) - # check that this tech produces the commodity demanded + # 1. Fixed techs: always produce, subtract from demand + for fixed_tech in self.fixed_techs: + commodity_from_tech = self._get_commodity_for_tech(fixed_tech) + for tech_commodity in commodity_from_tech: + if tech_commodity == commodity: + demand = self._subtract_fixed(fixed_tech, demand, commodity, inputs) + + # 2. Flexible techs: operate at full production + for flexible_tech in self.flexible_techs: + commodity_from_tech = self._get_commodity_for_tech(flexible_tech) for tech_commodity in commodity_from_tech: if tech_commodity == commodity: - # if the commodity produced from a tech is the demanded commodity - # then subtract the curtailable production from the demand - demand = self._subtract_curtailable( - curtailable_tech, demand, commodity, inputs, outputs + demand = self._subtract_flexible( + flexible_tech, demand, commodity, inputs, outputs ) else: - if f"{curtailable_tech}_rated_{tech_commodity}_production" in inputs: + if f"{flexible_tech}_rated_{tech_commodity}_production" in inputs: # set the set-point as the rated production - outputs[f"{curtailable_tech}_{tech_commodity}_set_point"] = inputs[ - f"{curtailable_tech}_rated_{tech_commodity}_production" + outputs[f"{flexible_tech}_{tech_commodity}_set_point"] = inputs[ + f"{flexible_tech}_rated_{tech_commodity}_production" ] * np.ones(self.n_timesteps) - # 2. Storage dispatch + # 3. Storage dispatch # number of storage components that produce the demanded commodity n_storage = len( [s for s in self.storage_techs if commodity in self._get_commodity_for_tech(s)] @@ -62,7 +69,7 @@ def compute(self, inputs, outputs): storage_tech, demand / n_storage, commodity, inputs, outputs ) - # 3. Dispatchable techs + # 4. Dispatchable techs remaining_demand = np.maximum(demand, 0.0) # calculate the number of dispatchable technologies that diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index ed4e04315..1fd8868a1 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -19,10 +19,11 @@ class ProfitMaximizationControl(SystemLevelControlBase): Dispatches technologies only when the commodity sell price exceeds the marginal cost of production: - 1. Curtailable techs run at rated capacity (zero marginal cost, + 1. Fixed techs always produce (cannot be controlled). + 2. Flexible techs run at rated capacity (zero marginal cost, always profitable to produce). - 2. Storage absorbs surplus / provides deficit. - 3. Dispatchable techs are dispatched in merit order (cheapest first), + 3. Storage absorbs surplus / provides deficit. + 4. Dispatchable techs are dispatched in merit order (cheapest first), but **only if** their marginal cost is below the sell price. Demand may go unmet if dispatch is unprofitable. @@ -93,18 +94,21 @@ def compute(self, inputs, outputs): demand = inputs[self.demand_input_name].copy() sell_price = inputs["commodity_sell_price"] # shape (n_timesteps,) - # 1. Curtailable techs: full production (always profitable) - for curtailable_tech in self.curtailable_techs: - commodity_from_tech = self._get_commodity_for_tech(curtailable_tech) - # check that this tech produces the commodity demanded + # 1. Fixed techs: always produce, subtract from demand + for fixed_tech in self.fixed_techs: + commodity_from_tech = self._get_commodity_for_tech(fixed_tech) if self.commodity in commodity_from_tech: - # if the commodity produced from a tech is the demanded commodity - # then subtract the curtailable production from the demand - demand = self._subtract_curtailable( - curtailable_tech, demand, self.commodity, inputs, outputs + demand = self._subtract_fixed(fixed_tech, demand, self.commodity, inputs) + + # 2. Flexible techs: full production (always profitable) + for flexible_tech in self.flexible_techs: + commodity_from_tech = self._get_commodity_for_tech(flexible_tech) + if self.commodity in commodity_from_tech: + demand = self._subtract_flexible( + flexible_tech, demand, self.commodity, inputs, outputs ) - # 2. Storage dispatch + # 3. Storage dispatch # number of storage components that produce the demanded commodity n_storage = len( [s for s in self.storage_techs if self.commodity in self._get_commodity_for_tech(s)] @@ -116,7 +120,7 @@ def compute(self, inputs, outputs): storage_tech, demand / n_storage, self.commodity, inputs, outputs ) - # 3. Profit-driven merit-order dispatch + # 4. Profit-driven merit-order dispatch remaining = np.maximum(demand, 0.0) marginal_costs = self._compute_marginal_costs(inputs) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index e7e5ad05f..8cd0ee195 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -7,7 +7,7 @@ class SystemLevelControlBase(om.ExplicitComponent): """Base class for system-level controllers. Provides common setup logic shared by all system-level control strategies: - demand input, curtailable/dispatchable/storage technology I/O creation, + demand input, fixed/flexible/dispatchable/storage technology I/O creation, and technology classification reading from ``plant_config`` and ``slc_config`` Subclasses must implement ``compute()`` with their dispatch strategy. @@ -50,8 +50,11 @@ def setup(self): self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] - self.curtailable_techs = [ - k for k, v in slc_config["tech_control_classifiers"].items() if v == "curtailable" + self.fixed_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "fixed" + ] + self.flexible_techs = [ + k for k, v in slc_config["tech_control_classifiers"].items() if v == "flexible" ] self.dispatchable_techs = [ k for k, v in slc_config["tech_control_classifiers"].items() if v == "dispatchable" @@ -64,7 +67,7 @@ def setup(self): ] self.input_techs = set( - self.curtailable_techs + self.dispatchable_techs + self.storage_techs + self.fixed_techs + self.flexible_techs + self.dispatchable_techs + self.storage_techs ) # Input: demand profile @@ -86,7 +89,8 @@ def setup(self): self.commodities_to_units = {self.commodity: self.commodity_units} self.commodities_to_ref_var = {} - self._setup_tech_category("curtailable", self.curtailable_techs) + self._setup_fixed_category(self.fixed_techs) + self._setup_tech_category("flexible", self.flexible_techs) self._setup_tech_category("dispatchable", self.dispatchable_techs) self._setup_tech_category("storage", self.storage_techs) self._setup_feedstock_category(self.feedstock_comps) @@ -185,7 +189,7 @@ def _setup_commodity( def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. - This single method handles curtailable, dispatchable, and storage + This single method handles flexible, dispatchable, and storage technologies. The logic is identical for all three categories — iterate over each technology's commodities and register the appropriate inputs (production output, rated capacity) and output @@ -203,13 +207,13 @@ def _setup_tech_category(self, category, tech_list): ``self.{category}_commodity_names`` These lists are consumed by ``compute()`` and the helper methods - ``_subtract_curtailable`` and ``_dispatch_storage``. + ``_subtract_flexible`` and ``_dispatch_storage``. Args: - category (str): One of ``"curtailable"``, ``"dispatchable"``, + category (str): One of ``"flexible"``, ``"dispatchable"``, or ``"storage"``. Used to name the attribute lists. tech_list (list[str]): Technology names belonging to this category - (e.g. ``self.curtailable_techs``). + (e.g. ``self.flexible_techs``). """ initial_set_point = 1.0 @@ -286,6 +290,67 @@ def _setup_tech_category(self, category, tech_list): setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) + def _setup_fixed_category(self, fixed_list): + """Create OpenMDAO input variables for fixed technologies. + + Fixed technologies always produce at their rated capacity and do not + receive a set-point from the controller. Only commodity output inputs + are registered so the controller can read their production and subtract + it from demand. + + After this method returns, two lists are stored on ``self``: + + ``self.fixed_input_names`` + ``self.fixed_commodity_names`` + + Args: + fixed_list (list[str]): Technology names classified as ``"fixed"``. + """ + input_names = [] + commodity_names = [] + + for tech_name in fixed_list: + tech_commodities = [e[1] for e in self.techs_to_commodities if e[0] == tech_name] + for commodity in tech_commodities: + in_name = f"{tech_name}_{commodity}_out" + + if commodity in self.commodities_to_units: + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=self.commodities_to_units[commodity], + desc=f"{commodity} output from {tech_name}", + ) + elif commodity in self.commodities_to_ref_var: + self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=None, + copy_units=self.commodities_to_ref_var[commodity], + desc=f"{commodity} output from {tech_name}", + ) + else: + meta_data = self.add_input( + in_name, + val=0.0, + shape=self.n_timesteps, + units=None, + units_by_conn=True, + desc=f"{commodity} output from {tech_name}", + ) + if meta_data["units"] is None: + self.commodities_to_ref_var[commodity] = in_name + else: + self.commodities_to_units[commodity] = meta_data["units"] + + input_names.append(in_name) + commodity_names.append(commodity) + + self.fixed_input_names = input_names + self.fixed_commodity_names = commodity_names + def _setup_feedstock_category(self, feedstock_list): """Iterate over the feedstocks and add inputs for the available feedstock @@ -335,22 +400,39 @@ def _setup_feedstock_category(self, feedstock_list): # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - def _subtract_curtailable(self, curtailable_tech, remaining_demand, commodity, inputs, outputs): - """Apply curtailable techs: set_point = rated, subtract output from demand. + def _subtract_fixed(self, fixed_tech, remaining_demand, commodity, inputs): + """Apply fixed techs: subtract their output from demand. + + Fixed techs always produce and do not receive a set-point. + + Returns the updated demand array. + """ + if fixed_tech not in self.fixed_techs: + return remaining_demand + + in_name = f"{fixed_tech}_{commodity}_out" + if in_name not in inputs: + return remaining_demand + + remaining_demand -= inputs[in_name] + return remaining_demand + + def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, outputs): + """Apply flexible techs: set_point = rated, subtract output from demand. Returns the updated demand array. """ - if curtailable_tech not in self.curtailable_techs: + if flexible_tech not in self.flexible_techs: return - if f"{curtailable_tech}_rated_{commodity}_production" not in inputs: + if f"{flexible_tech}_rated_{commodity}_production" not in inputs: return # Output the set-point as the rated production of that technology - outputs[f"{curtailable_tech}_{commodity}_set_point"] = inputs[ - f"{curtailable_tech}_rated_{commodity}_production" + outputs[f"{flexible_tech}_{commodity}_set_point"] = inputs[ + f"{flexible_tech}_rated_{commodity}_production" ] * np.ones(self.n_timesteps) - remaining_demand -= inputs[f"{curtailable_tech}_{commodity}_out"] + remaining_demand -= inputs[f"{flexible_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index 895341142..91cd39e9d 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -50,9 +50,10 @@ def _build_technology_graph(technology_interconnections): def _build_tech_control_classifiers( - curtailable=None, dispatchable=None, storage=None, feedstock=None + fixed=None, flexible=None, dispatchable=None, storage=None, feedstock=None ): - tech_control_classifiers = {k: "curtailable" for k in (curtailable or [])} + tech_control_classifiers = {k: "fixed" for k in (fixed or [])} + tech_control_classifiers |= {k: "flexible" for k in (flexible or [])} tech_control_classifiers |= {k: "dispatchable" for k in (dispatchable or [])} tech_control_classifiers |= {k: "storage" for k in (storage or [])} tech_control_classifiers |= {k: "feedstock" for k in (feedstock or [])} @@ -148,11 +149,11 @@ def _build_problem(slc_cls, plant_config, slc_config, demand=50000, tech_config= class TestSystemLevelControlBase: """Tests for the abstract base class setup logic.""" - def test_base_creates_curtailable_io(self): + def test_base_creates_flexible_io(self): tech_connections = [["wind", "demand", "electricity", "cable"]] plant_config = _build_plant_config(tech_connections) tech_graph = _build_technology_graph(tech_connections) - tech_control_classifiers = _build_tech_control_classifiers(curtailable=["wind"]) + tech_control_classifiers = _build_tech_control_classifiers(flexible=["wind"]) slc_config = _build_slc_config(tech_graph, tech_control_classifiers) # Use DemandFollowingControl since base is abstract prob = _build_problem(DemandFollowingControl, plant_config, slc_config) @@ -226,7 +227,7 @@ def test_equal_share_two_dispatchable(self): np.testing.assert_allclose(sp1, 25000) np.testing.assert_allclose(sp2, 25000) - def test_curtailable_reduces_demand(self): + def test_flexible_reduces_demand(self): tech_connections = [ ["wind", "combiner", "electricity", "cable"], ["ng", "combiner", "electricity", "cable"], @@ -235,7 +236,7 @@ def test_curtailable_reduces_demand(self): plant_config = _build_plant_config(tech_connections) tech_graph = _build_technology_graph(tech_connections) tech_control_classifiers = _build_tech_control_classifiers( - curtailable=["wind"], dispatchable=["ng"] + flexible=["wind"], dispatchable=["ng"] ) slc_config = _build_slc_config(tech_graph, tech_control_classifiers) prob = _build_problem(DemandFollowingControl, plant_config, slc_config) @@ -261,7 +262,7 @@ def test_storage_absorbs_surplus(self): plant_config = _build_plant_config(tech_connections) tech_graph = _build_technology_graph(tech_connections) tech_control_classifiers = _build_tech_control_classifiers( - curtailable=["wind"], storage=["battery"], dispatchable=["ng"] + flexible=["wind"], storage=["battery"], dispatchable=["ng"] ) slc_config = _build_slc_config(tech_graph, tech_control_classifiers) prob = _build_problem(DemandFollowingControl, plant_config, slc_config) @@ -348,7 +349,7 @@ def test_overflow_to_expensive(self): np.testing.assert_allclose(cheap_sp, 30000) np.testing.assert_allclose(expensive_sp, 20000) - def test_with_curtailable_reduces_dispatch(self): + def test_with_flexible_reduces_dispatch(self): tech_connections = [ ["wind", "combiner", "electricity", "cable"], ["ng", "combiner", "electricity", "cable"], @@ -357,7 +358,7 @@ def test_with_curtailable_reduces_dispatch(self): plant_config = _build_plant_config(tech_connections, cost_per_tech={"ng": 0.05}) tech_graph = _build_technology_graph(tech_connections) tech_control_classifiers = _build_tech_control_classifiers( - curtailable=["wind"], dispatchable=["ng"] + flexible=["wind"], dispatchable=["ng"] ) slc_config = _build_slc_config(tech_graph, tech_control_classifiers) prob = _build_problem(CostMinimizationControl, plant_config, slc_config, demand=50000) diff --git a/h2integrate/converters/hopp/hopp_wrapper.py b/h2integrate/converters/hopp/hopp_wrapper.py index d801acc7e..994ae6cfc 100644 --- a/h2integrate/converters/hopp/hopp_wrapper.py +++ b/h2integrate/converters/hopp/hopp_wrapper.py @@ -33,7 +33,7 @@ class HOPPComponent(PerformanceModelBaseClass, CacheBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index 3c3221947..94a5a50a2 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -23,6 +23,16 @@ def setup(self): # Define inputs for electricity self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") + # Dispatchable models receive a set_point from the system-level controller + if "system_level_control" in self.options["plant_config"]: + self.add_input( + f"{self.commodity}_set_point", + val=0.0, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Set point for {self.commodity} production from SLC", + ) + def compute(self, inputs, outputs): """ Computation for the OM component. diff --git a/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py b/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py index 11b44189a..adaf61d9c 100644 --- a/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py +++ b/h2integrate/converters/hydrogen/geologic/h2_well_subsurface_baseclass.py @@ -46,7 +46,7 @@ class GeoH2SubsurfacePerformanceConfig(BaseConfig): class GeoH2SubsurfacePerformanceBaseClass(PerformanceModelBaseClass): - _control_classifier = "curtailable" + _control_classifier = "dispatchable" """OpenMDAO component for modeling the performance of the well subsurface for geologic hydrogen. diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 39e2069ef..0c5aada06 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -63,7 +63,7 @@ class ECOElectrolyzerPerformanceModel(ElectrolyzerPerformanceBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "dispatchable" def setup(self): self.config = ECOElectrolyzerPerformanceModelConfig.from_dict( @@ -223,5 +223,8 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): "Annual O2 Production [kg/year]" ] - # Apply curtailment based on set_point - self.apply_curtailment(outputs) + # Apply set_point from system-level controller if present + if "system_level_control" in self.options["plant_config"]: + set_point = inputs[f"{self.commodity}_set_point"] + commodity_out_key = f"{self.commodity}_out" + outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], set_point) diff --git a/h2integrate/converters/nuclear/nuclear_plant.py b/h2integrate/converters/nuclear/nuclear_plant.py index d8a86ec29..836d9ce52 100644 --- a/h2integrate/converters/nuclear/nuclear_plant.py +++ b/h2integrate/converters/nuclear/nuclear_plant.py @@ -37,7 +37,7 @@ class QuinnNuclearPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "dispatchable" + _control_classifier = "fixed" def initialize(self): super().initialize() diff --git a/h2integrate/converters/solar/solar_baseclass.py b/h2integrate/converters/solar/solar_baseclass.py index cdb125a8d..dcf01bbc5 100644 --- a/h2integrate/converters/solar/solar_baseclass.py +++ b/h2integrate/converters/solar/solar_baseclass.py @@ -6,7 +6,7 @@ class SolarPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() diff --git a/h2integrate/converters/water_power/hydro_plant_run_of_river.py b/h2integrate/converters/water_power/hydro_plant_run_of_river.py index 108269067..a7034046b 100644 --- a/h2integrate/converters/water_power/hydro_plant_run_of_river.py +++ b/h2integrate/converters/water_power/hydro_plant_run_of_river.py @@ -40,7 +40,7 @@ class RunOfRiverHydroPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() diff --git a/h2integrate/converters/water_power/tidal_pysam.py b/h2integrate/converters/water_power/tidal_pysam.py index 6d65d8fc2..6c245ec8b 100644 --- a/h2integrate/converters/water_power/tidal_pysam.py +++ b/h2integrate/converters/water_power/tidal_pysam.py @@ -124,7 +124,7 @@ class PySAMTidalPerformanceModel(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() diff --git a/h2integrate/converters/wind/wind_plant_ard.py b/h2integrate/converters/wind/wind_plant_ard.py index 811e083f2..929f0b0a9 100644 --- a/h2integrate/converters/wind/wind_plant_ard.py +++ b/h2integrate/converters/wind/wind_plant_ard.py @@ -38,7 +38,7 @@ class WindArdPerformanceCompatibilityComponent(PerformanceModelBaseClass): """ _time_step_bounds = (3600, 3600) # (min, max) time step lengths compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() @@ -149,7 +149,7 @@ class ArdWindPlantModel(om.Group): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): self.options.declare("driver_config", types=dict) diff --git a/h2integrate/converters/wind/wind_plant_baseclass.py b/h2integrate/converters/wind/wind_plant_baseclass.py index b8a90ed6e..08e8907b4 100644 --- a/h2integrate/converters/wind/wind_plant_baseclass.py +++ b/h2integrate/converters/wind/wind_plant_baseclass.py @@ -6,7 +6,7 @@ class WindPerformanceBaseClass(PerformanceModelBaseClass): 3600, 3600, ) # (min, max) time step lengths (in seconds) compatible with this model - _control_classifier = "curtailable" + _control_classifier = "flexible" def initialize(self): super().initialize() diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 3fc6e88ad..9f526ce6e 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -475,7 +475,7 @@ def _classify_slc_technologies(self): """Classify technologies for system-level control. Uses ``self.tech_control_classifiers`` (populated by ``create_technology_models()``) - to partition technologies into curtailable, dispatchable, and storage lists. + to partition technologies into fixed, flexible, dispatchable, and storage lists. Also identifies the single demand technology and its commodity. Returns: @@ -569,7 +569,13 @@ def _classify_slc_technologies(self): storage_tech_to_control[tech] = True # Remove feedstocks and connectors - control_classifiers_to_connect = ["curtailable", "dispatchable", "storage", "feedstock"] + control_classifiers_to_connect = [ + "fixed", + "flexible", + "dispatchable", + "storage", + "feedstock", + ] tech_to_commodity = { (e[0], e[-1]) for e in sources_to_commodities @@ -618,7 +624,10 @@ def add_system_level_controller(self, slc_config): - **Feedstock techs**: Only the commodity output (``{tech_name}_source.{commodity}_out``) is connected to the controller. Feedstocks have no set-point or rated-production connection. - - **Curtailable / dispatchable / storage techs**: Both the commodity output + - **Fixed techs**: Only the commodity output + (``{tech_name}.{commodity}_out``) is connected to the controller. Fixed techs + always produce and receive no set-point or rated-production connection. + - **Flexible / dispatchable / storage techs**: Both the commodity output (``{tech_name}.{commodity}_out``) and rated production (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. The controller's set-point output is connected back to the tech: @@ -660,7 +669,7 @@ def add_system_level_controller(self, slc_config): - ``"tech_to_commodity"`` (set[tuple[str, str]]): Set of ``(tech_name, commodity)`` pairs for all controlled techs. - ``"tech_control_classifiers"`` (dict[str, str]): Mapping of tech name to - classifier (``"curtailable"``, ``"dispatchable"``, ``"storage"``, + classifier (``"fixed"``, ``"flexible"``, ``"dispatchable"``, ``"storage"``, ``"feedstock"``). - ``"storage_techs_to_control"`` (dict[str, bool]): Whether each storage tech has its own sub-controller. @@ -719,7 +728,16 @@ def add_system_level_controller(self, slc_config): ) continue - # Curtailable, dispatchable, and storage techs: connect their + if slc_config["tech_control_classifiers"][tech_name] == "fixed": + # Fixed techs only provide their commodity output to the + # controller; they always produce and receive no set-point. + self.plant.connect( + f"{tech_name}.{commodity}_out", + f"system_level_controller.{tech_name}_{commodity}_out", + ) + continue + + # Flexible, dispatchable, and storage techs: connect their # commodity output and rated production as controller inputs. self.plant.connect( f"{tech_name}.{commodity}_out", diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index baa43e5f2..ac2f34dfc 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -99,8 +99,8 @@ def setup(self): # operational life of the technology if the technology cannot be replaced self.add_output("operational_life", val=self.plant_life, units="yr") - # Curtailable models get additional I/O for set_point-based curtailment - if getattr(self, "_control_classifier", None) == "curtailable": + # Flexible models get additional I/O for set_point-based curtailment + if getattr(self, "_control_classifier", None) == "flexible": self.add_input( f"{self.commodity}_set_point", val=1.0, @@ -122,12 +122,12 @@ def apply_curtailment(self, outputs): Copies the current ``{commodity}_out`` into ``uncurtailed_{commodity}_out``, then clips ``{commodity}_out`` to ``min(uncurtailed, set_point)`` element-wise. - Only operates when the model has ``_control_classifier == "curtailable"``. - Should be called at the end of each curtailable model's ``compute()`` method + Only operates when the model has ``_control_classifier == "flexible"``. + Should be called at the end of each flexible model's ``compute()`` method after the raw production has been written to ``outputs[f"{commodity}_out"]``. """ if "system_level_control" in self.options["plant_config"]: - if getattr(self, "_control_classifier", None) != "curtailable": + if getattr(self, "_control_classifier", None) != "flexible": return commodity_out_key = f"{self.commodity}_out" From 4fbd901e18b26527dd1bc3f1eb4de8a30a6ea89a Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 14 May 2026 14:04:19 -0600 Subject: [PATCH 095/132] small doc change --- docs/control/system_level_control/control_classifier.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index 9b8cc5038..a08b77b8e 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -10,7 +10,7 @@ This is a useful and necessary distinction that delineates different model capab We have identified five key classifiers that are able to represent the different behaviors that we can expect from the models. Each performance model includes a parameter setting the classifier `_control_classifier`. -Classifier | Meaning | Example Techs +Classifier | Meaning | Example Technology Models -- | -- | -- fixed | Always produces commodity and cannot be controlled or reduced; does not receive a set-point | classical nuclear flexible | Produces based on resource; can only reduce (curtail) | wind, solar @@ -67,10 +67,3 @@ The system-level controller outputs set points to the storage performance model ## Feedstock Another category of control classifiers are feedstocks. The unique thing about feedstocks is that they are considered outside of the controllable system within H2I. While they can't be controlled it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. - -## SLC Dispatch Order -The system level controllers dispatch technologies in the following order: -1. **Fixed** — subtract their production from demand -2. **Flexible** — run at full capacity, subtract from demand -3. **Storage** — absorb surplus or provide deficit -4. **Dispatchable** — cover remaining demand From 4deb083a03bd911e42a1a4463ef4edd534204ce2 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Thu, 14 May 2026 16:43:20 -0600 Subject: [PATCH 096/132] connected storage duration --- .../system_level/system_level_control_base.py | 5 +++++ h2integrate/core/h2integrate_model.py | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 8cd0ee195..6622f8199 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -279,6 +279,11 @@ def _setup_tech_category(self, category, tech_list): initial_set_point=initial_set_point, ) + if category == "storage": + self.add_input( + f"{tech_name}_{commodity}_storage_duration", val=0.0, shape=1, units="h" + ) + commodity_names.append(commodity) input_names.append(in_name) set_point_names.append(set_point_name) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 9f526ce6e..38795f983 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -749,6 +749,13 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_rated_{commodity}_production", ) + # Storage tech: connect the storage duration as a controller input + if slc_config["tech_control_classifiers"][tech_name] == "storage": + self.plant.connect( + f"{tech_name}.storage_duration", + f"system_level_controller.{tech_name}_{commodity}_storage_duration", + ) + # Connect the controller's output back to the technology. if slc_config["storage_techs_to_control"].get(tech_name, False): # Storage tech with its own sub-controller: provide a demand From 8c968a465509245a882f42e7b9e1abcaa6910b8d Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Tue, 19 May 2026 16:21:32 -0600 Subject: [PATCH 097/132] added more subtests to test_slc_examples for the two single-commodity demand following examples --- .../system_level/test/test_slc_examples.py | 108 ++++++++++++++++-- 1 file changed, 96 insertions(+), 12 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index c85352ef5..0d81f137f 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -15,10 +15,52 @@ def test_slc_no_battery(subtests, temp_copy_of_example): model.run() - wind_out = model.prob.get_val("wind.electricity_out") + with subtests.test("Wind set point == rated"): + assert np.all( + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + == model.prob.get_val("wind.rated_electricity_production", units="kW") + ) - with subtests.test("wind farm generates power"): - assert wind_out.sum() > 0 + with subtests.test("Natural gas plant set point"): + remaining_demand = model.prob.get_val( + "electrical_load_demand.electricity_demand_out", units="kW" + ) - model.prob.get_val("wind.electricity_out", units="kW") + ng_set_point = model.prob.get_val( + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + ) + expected_ng_set_point = np.clip( + remaining_demand, + a_min=0.0, + a_max=model.prob.get_val("natural_gas_plant.rated_electricity_production", units="kW")[ + 0 + ], + ) + assert np.allclose(expected_ng_set_point, ng_set_point, rtol=1e-6, atol=1e-8) + + with subtests.test("Total unmet demand"): + assert ( + pytest.approx(0.0, rel=1e-6, abs=1e-8) + == model.prob.get_val( + "electrical_load_demand.unmet_electricity_demand_out", units="kW" + ).sum() + ) + + with subtests.test("Wind LCOE"): + assert pytest.approx(77.07060204, rel=1e-6) == model.prob.get_val( + "finance_subgroup_renewables.LCOE_profast_lco", units="USD/(MW*h)" + ) + with subtests.test("Natural gas LCOE"): + assert pytest.approx(85.5774049107076, rel=1e-6) == model.prob.get_val( + "finance_subgroup_natural_gas.LCOE", units="USD/(MW*h)" + ) + with subtests.test("Electricity LCOE"): + assert pytest.approx(80.79533451532551, rel=1e-6) == model.prob.get_val( + "finance_subgroup_electricity.LCOE", units="USD/(MW*h)" + ) + with subtests.test("Wind NPV"): + assert pytest.approx(-38.5777102298, rel=1e-6) == model.prob.get_val( + "finance_subgroup_renewables.NPV_electricity__profast_npv", units="MUSD" + ) @pytest.mark.unit @@ -32,18 +74,60 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): model.run() - wind_out = model.prob.get_val("wind.electricity_out") + with subtests.test("Wind set point == rated"): + assert np.all( + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + == model.prob.get_val("wind.rated_electricity_production", units="kW") + ) - with subtests.test("wind farm generates power"): - assert wind_out.sum() > 0 + with subtests.test("Battery set point"): + remaining_demand = model.prob.get_val( + "electrical_load_demand.electricity_demand_out", units="kW" + ) - model.prob.get_val("wind.electricity_out", units="kW") + battery_set_point = model.prob.get_val( + "system_level_controller.battery_electricity_set_point", units="kW" + ) + assert np.allclose(remaining_demand, battery_set_point, rtol=1e-6, atol=1e-8) - with subtests.test("lcoe"): + with subtests.test("Natural gas plant set point"): + remaining_demand = remaining_demand - model.prob.get_val( + "battery.electricity_out", units="kW" + ) + ng_set_point = model.prob.get_val( + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + ) + expected_ng_set_point = np.clip( + remaining_demand, + a_min=0.0, + a_max=model.prob.get_val("natural_gas_plant.rated_electricity_production", units="kW")[ + 0 + ], + ) + assert np.allclose(expected_ng_set_point, ng_set_point, rtol=1e-6, atol=1e-8) + + with subtests.test("Total unmet demand"): assert ( - pytest.approx( - model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), - rel=1e-6, - ) - == 0.10902004 + pytest.approx(0.0, rel=1e-6, abs=1e-8) + == model.prob.get_val( + "electrical_load_demand.unmet_electricity_demand_out", units="kW" + ).sum() + ) + + with subtests.test("Wind LCOE"): + assert pytest.approx(77.07060204, rel=1e-6) == model.prob.get_val( + "finance_subgroup_renewables.LCOE_profast_lco", units="USD/(MW*h)" + ) + with subtests.test("Natural gas LCOE"): + assert pytest.approx(161.0833612618841, rel=1e-6) == model.prob.get_val( + "finance_subgroup_natural_gas.LCOE", units="USD/(MW*h)" + ) + with subtests.test("Electricity LCOE"): + assert pytest.approx(109.02003689718997, rel=1e-6) == model.prob.get_val( + "finance_subgroup_electricity.LCOE", units="USD/(MW*h)" + ) + with subtests.test("Wind NPV"): + assert pytest.approx(-38.5777102298, rel=1e-6) == model.prob.get_val( + "finance_subgroup_renewables.NPV_electricity__profast_npv", units="MUSD" ) From f08382cf24ae723f78401c933b8761b280e5aa9e Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 20 May 2026 09:46:05 -0600 Subject: [PATCH 098/132] Fixing example dir --- docs/control/system_level_control/slc_demand_following.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 8fea76611..95315f191 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -30,7 +30,7 @@ from pathlib import Path from h2integrate import EXAMPLE_DIR from IPython.display import HTML, display -os.chdir("EXAMPLE_DIR/35_system_level_control/battery_with_controller/") +os.chdir(EXAMPLE_DIR / "35_system_level_control/battery_with_controller/") h2i_model = H2IntegrateModel("wind_ng_demand.yaml") h2i_model.setup() From 1d519847a0e6521865e2af747eee70857387a468 Mon Sep 17 00:00:00 2001 From: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Date: Wed, 20 May 2026 10:46:17 -0600 Subject: [PATCH 099/132] fixed failing test --- h2integrate/postprocess/test/test_sql_timeseries_to_csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index 35fd261d8..27903af9f 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -59,7 +59,7 @@ def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath) res = save_case_timeseries_as_csv(run_example_02_sql_fpath, save_to_file=True) with subtests.test("Check number of columns"): - assert len(res.columns.to_list()) == 57 + assert len(res.columns.to_list()) == 55 with subtests.test("Check number of rows"): assert len(res) == 8760 From 784e9374b3c3c9022a77dd0cb061edb75139d53d Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 21 May 2026 10:30:15 -0600 Subject: [PATCH 100/132] Checkpointing progress on all controllers for techs --- h2integrate/converters/grid/test/test_grid.py | 2 +- h2integrate/core/h2integrate_model.py | 67 ++++++++++++++++++- h2integrate/core/supported_models.py | 2 + 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index 7263c9659..4551144ca 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -390,7 +390,7 @@ def test_grid_integration_dt_1800(subtests, tmp_path): h2i.setup() demand = np.full(n_timesteps, demand_kw) - h2i.prob.set_val("grid.electricity_set_point", demand, units="kW") + h2i.prob.set_val("grid.electricity_demand", demand, units="kW") h2i.prob.run_model() expected_out = np.full(n_timesteps, demand_kw) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 67bbb0af2..0a2d42c8c 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -24,6 +24,7 @@ multivariable_streams, is_electricity_producer, ) +from h2integrate.control.control_strategies.passthrough_controller import PassthroughController from h2integrate.control.control_strategies.system_level.solver_options import ( SLCSolverOptionsConfig, ) @@ -757,6 +758,7 @@ def add_system_level_controller(self, slc_config): ) # Connect the controller's output back to the technology. + classifier = slc_config["tech_control_classifiers"][tech_name] if slc_config["storage_techs_to_control"].get(tech_name, False): # Storage tech with its own sub-controller: provide a demand # signal that the sub-controller translates into @@ -765,9 +767,18 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_{commodity}_demand", f"{tech_name}.{commodity}_demand", ) + elif classifier in ("flexible", "dispatchable"): + # Flexible / dispatchable techs always have a controller in + # their tech group (auto-injected PassthroughController if no + # user-defined control_strategy). Route the SLC output to the + # controller's demand input. + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_demand", + ) else: - # All other techs (or storage without a sub-controller): - # provide a set-point directly to the performance model. + # Storage without a sub-controller: provide a set-point + # directly to the performance model. self.plant.connect( f"system_level_controller.{tech_name}_{commodity}_set_point", f"{tech_name}.{commodity}_set_point", @@ -936,6 +947,8 @@ def create_technology_models(self): self.cost_models.append(om_model_object) self.finance_models.append(om_model_object) + self._maybe_add_passthrough_controller(tech_group, comp, individual_tech_config) + continue # Process the models @@ -947,6 +960,7 @@ def create_technology_models(self): "cost_model", ] + perf_om_object = None for model_type in model_types: if model_type in individual_tech_config: om_model_object = self._process_model( @@ -958,6 +972,9 @@ def create_technology_models(self): plural_model_type_name = model_type + "s" getattr(self, plural_model_type_name).append(om_model_object) + if model_type == "performance_model": + perf_om_object = om_model_object + # Collect control classifier for system-level control if model_type == "performance_model" and self.slc: perf_cls = self.supported_models.get(perf_model) @@ -966,6 +983,11 @@ def create_technology_models(self): if classifier is not None: self.tech_control_classifiers[tech_name] = classifier + if perf_om_object is not None: + self._maybe_add_passthrough_controller( + tech_group, perf_om_object, individual_tech_config + ) + # Process the finance models if "finance_model" in individual_tech_config: if "model" in individual_tech_config["finance_model"]: @@ -1038,6 +1060,47 @@ def _check_control_classifier(self, model_name, model_object): msg = f"Model {model_name} is missing a control classifier" raise ValueError(msg) + def _maybe_add_passthrough_controller(self, tech_group, perf_comp, individual_tech_config): + """Automatically add a PassthroughController to a tech group if appropriate. + + A controller is auto-inserted only when: + - the technology has no user-defined ``control_strategy`` in its config, + - the performance model exposes a ``_control_classifier`` of + ``"flexible"`` or ``"dispatchable"``, + - the performance model has set ``commodity`` and ``commodity_rate_units`` + attributes (typically set in its ``initialize()``). + + The controller's ``{commodity}_demand`` input becomes the tech group's + external demand-input promoted at the tech group level, and its + ``{commodity}_set_point`` output is auto-connected (via promotion) to the + performance model's ``{commodity}_set_point`` input if one exists. + """ + if "control_strategy" in individual_tech_config: + return + classifier = getattr(perf_comp, "_control_classifier", None) + if classifier not in ("flexible", "dispatchable"): + return + commodity = getattr(perf_comp, "commodity", None) + commodity_rate_units = getattr(perf_comp, "commodity_rate_units", None) + if commodity is None or commodity_rate_units is None: + return + n_timesteps = int(self.plant_config["plant"]["simulation"]["n_timesteps"]) + controller = PassthroughController( + commodity=commodity, + n_timesteps=n_timesteps, + commodity_rate_units=commodity_rate_units, + ) + om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) + self.control_strategies.append(om_controller) + + # Ensure the controller runs before the performance/cost models that + # consume its set_point output. Subsystem creation order otherwise + # places the controller last in the group's execution order. + existing_order = list(tech_group._static_subsystems_allprocs.keys()) + if "controller" in existing_order: + new_order = ["controller"] + [n for n in existing_order if n != "controller"] + tech_group.set_order(new_order) + def create_finance_model(self): """ Create and configure the finance model(s) for the plant. diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 40d4737dd..563c899be 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -134,6 +134,7 @@ Himawari8SolarAPI, HimawariTMYSolarAPI, ) +from h2integrate.control.control_strategies.passthrough_controller import PassthroughController from h2integrate.converters.hydrogen.geologic.simple_natural_geoh2 import ( NaturalGeoH2PerformanceModel, ) @@ -318,6 +319,7 @@ "PeakLoadManagementOptimizedStorageController": (PeakLoadManagementOptimizedStorageController), "HeuristicLoadFollowingStorageController": HeuristicLoadFollowingStorageController, "OptimizedDispatchStorageController": OptimizedDispatchStorageController, + "PassthroughController": PassthroughController, "GenericDemandComponent": GenericDemandComponent, "FlexibleDemandComponent": FlexibleDemandComponent, # System-level control strategies From 83577e1c32849ff0c9b0b9ee0df042189582dc95 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 22 May 2026 11:21:55 -0600 Subject: [PATCH 101/132] Adding passthrough controller file --- .../passthrough_controller.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 h2integrate/control/control_strategies/passthrough_controller.py diff --git a/h2integrate/control/control_strategies/passthrough_controller.py b/h2integrate/control/control_strategies/passthrough_controller.py new file mode 100644 index 000000000..347ccaae7 --- /dev/null +++ b/h2integrate/control/control_strategies/passthrough_controller.py @@ -0,0 +1,88 @@ +import openmdao.api as om + + +class PassthroughController(om.ExplicitComponent): + """Simple controller that passes a demand signal directly through as a set-point. + + Every technology group is expected to have a controller subsystem. When a + technology does not define its own ``control_strategy``, this passthrough + controller is inserted automatically so that the group exposes a uniform + ``{commodity}_demand`` input and ``{commodity}_set_point`` output interface. + + In a system-level-control (SLC) configuration the SLC output is connected to + ``{commodity}_demand``; this component copies that signal to + ``{commodity}_set_point`` which the performance model consumes. + + When no SLC is present the input defaults to a very large value so that + production is unconstrained, making the component a harmless no-op. + """ + + _time_step_bounds = (0, float("inf")) + + def initialize(self): + self.options.declare("commodity", types=str) + self.options.declare("n_timesteps", types=int) + self.options.declare( + "commodity_rate_units", + types=str, + default=None, + desc="Units for the commodity rate (e.g. 'kW', 'kg/h'). " + "When provided, explicit units are used on the demand input " + "so the variable works even when unconnected (no SLC). " + "The set-point output always uses units_by_conn to inherit " + "units from the connected performance model.", + ) + + def setup(self): + commodity = self.options["commodity"] + n_timesteps = self.options["n_timesteps"] + commodity_rate_units = self.options["commodity_rate_units"] + + # Use explicit units on the input when available so that the + # variable remains valid even when no SLC is connected + # (units_by_conn fails on unconnected variables). + # Default to a large value so that when no SLC is connected the + # downstream performance model behaves as if unconstrained (the perf + # model typically saturates the set-point at its rated capacity). + # We avoid extreme values (e.g. 1e30) here because they pollute the + # NLBGS relative-residual check and cause premature false convergence + # in cyclic system-level control configurations. + default_val = 1.0e9 + + if commodity_rate_units is not None: + self.add_input( + f"{commodity}_demand", + val=default_val, + shape=n_timesteps, + desc=f"Demand signal for {commodity}", + units=commodity_rate_units, + ) + else: + self.add_input( + f"{commodity}_demand", + val=default_val, + shape=n_timesteps, + desc=f"Demand signal for {commodity}", + units_by_conn=True, + ) + + if commodity_rate_units is not None: + self.add_output( + f"{commodity}_set_point", + val=default_val, + shape=n_timesteps, + desc=f"Set point for {commodity} (passthrough of demand)", + units=commodity_rate_units, + ) + else: + self.add_output( + f"{commodity}_set_point", + val=default_val, + shape=n_timesteps, + desc=f"Set point for {commodity} (passthrough of demand)", + units_by_conn=True, + ) + + def compute(self, inputs, outputs): + commodity = self.options["commodity"] + outputs[f"{commodity}_set_point"] = inputs[f"{commodity}_demand"] From 8dbd7bd06707259f74931f8852f63637a03b08b2 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 22 May 2026 11:39:17 -0600 Subject: [PATCH 102/132] Updating tests --- .../system_level/test/test_slc_examples.py | 6 +++--- h2integrate/postprocess/test/test_sql_timeseries_to_csv.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 0d81f137f..230f186a2 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -270,16 +270,16 @@ def test_slc_complex_profit_max(subtests, temp_copy_of_example): model.setup() model.prob.set_val( - "plant.electrical_load_demand.electricity_demand", + "electrical_load_demand.electricity_demand", demand_profile, ) model.prob.set_val( - "plant.system_level_controller.commodity_sell_price", + "system_level_controller.commodity_sell_price", sell_price, units="USD/(kW*h)", ) model.prob.set_val( - "plant.grid_buy.electricity_buy_price", + "grid_buy.electricity_buy_price", grid_buy_price, units="USD/(kW*h)", ) diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index 27903af9f..14a4dbaf3 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -59,7 +59,7 @@ def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath) res = save_case_timeseries_as_csv(run_example_02_sql_fpath, save_to_file=True) with subtests.test("Check number of columns"): - assert len(res.columns.to_list()) == 55 + assert len(res.columns.to_list()) == 61 with subtests.test("Check number of rows"): assert len(res) == 8760 From b2f13c0238fc1d1c97c7e369483a0dc0253953db Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 22 May 2026 11:58:42 -0600 Subject: [PATCH 103/132] Added comments to passthrough controller --- h2integrate/core/h2integrate_model.py | 29 +++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 0a2d42c8c..b7e58b6f3 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -947,7 +947,7 @@ def create_technology_models(self): self.cost_models.append(om_model_object) self.finance_models.append(om_model_object) - self._maybe_add_passthrough_controller(tech_group, comp, individual_tech_config) + self._add_passthrough_controller(tech_group, comp, individual_tech_config) continue @@ -984,7 +984,7 @@ def create_technology_models(self): self.tech_control_classifiers[tech_name] = classifier if perf_om_object is not None: - self._maybe_add_passthrough_controller( + self._add_passthrough_controller( tech_group, perf_om_object, individual_tech_config ) @@ -1060,7 +1060,7 @@ def _check_control_classifier(self, model_name, model_object): msg = f"Model {model_name} is missing a control classifier" raise ValueError(msg) - def _maybe_add_passthrough_controller(self, tech_group, perf_comp, individual_tech_config): + def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_config): """Automatically add a PassthroughController to a tech group if appropriate. A controller is auto-inserted only when: @@ -1075,27 +1075,48 @@ def _maybe_add_passthrough_controller(self, tech_group, perf_comp, individual_te ``{commodity}_set_point`` output is auto-connected (via promotion) to the performance model's ``{commodity}_set_point`` input if one exists. """ + # Skip if the user has already specified a control strategy for this tech; + # their explicit choice takes precedence over the auto-injected passthrough. if "control_strategy" in individual_tech_config: return + + # Only flexible/dispatchable techs accept an externally provided demand + # signal. Fixed, feedstock, connector, and storage techs are handled + # elsewhere (storage uses its own sub-controller; fixed/feedstock have + # no set-point) and must not get a passthrough. classifier = getattr(perf_comp, "_control_classifier", None) if classifier not in ("flexible", "dispatchable"): return + + # The performance model must declare the commodity it produces and the + # units of its set-point so the PassthroughController can size its I/O + # consistently. If either is missing we have nothing to wire up. commodity = getattr(perf_comp, "commodity", None) commodity_rate_units = getattr(perf_comp, "commodity_rate_units", None) if commodity is None or commodity_rate_units is None: return + + # Build the controller sized to the plant's simulation horizon so its + # vector I/O matches the performance model's time-series I/O. n_timesteps = int(self.plant_config["plant"]["simulation"]["n_timesteps"]) controller = PassthroughController( commodity=commodity, n_timesteps=n_timesteps, commodity_rate_units=commodity_rate_units, ) + + # Promote all controller variables so: + # - `{commodity}_demand` becomes the tech group's external input + # (this is what the system-level controller connects to), and + # - `{commodity}_set_point` is auto-connected by name to the + # performance model's matching input via promotion. om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) self.control_strategies.append(om_controller) # Ensure the controller runs before the performance/cost models that # consume its set_point output. Subsystem creation order otherwise - # places the controller last in the group's execution order. + # places the controller last in the group's execution order, which + # would delay the set_point by one solver iteration. existing_order = list(tech_group._static_subsystems_allprocs.keys()) if "controller" in existing_order: new_order = ["controller"] + [n for n in existing_order if n != "controller"] From dfe4cf4b4acdbb0c3e3b5183128635237635823a Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 22 May 2026 12:06:41 -0600 Subject: [PATCH 104/132] Fixing import statements --- h2integrate/core/supported_models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 6bd2d8500..4d6040888 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -182,9 +182,9 @@ def copy(self): "SimpleGasConsumerCost": "converters.natural_gas.dummy_gas_components:SimpleGasConsumerCost", "GasStreamCombinerPerformanceModel": "transporters.gas_stream_combiner:GasStreamCombinerPerformanceModel", # System-level control strategies - "DemandFollowingControl": "control.control_strategies.system_level.demand_following:demand_following_control:DemandFollowingControl", - "CostMinimizationControl": "control.control_strategies.system_level.cost_minimization:cost_minimization_control:CostMinimizationControl", - "ProfitMaximizationControl": "control.control_strategies.system_level.profit_maximization:profit_maximization_control:ProfitMaximizationControl", + "DemandFollowingControl": "control.control_strategies.system_level.demand_following_control:DemandFollowingControl", + "CostMinimizationControl": "control.control_strategies.system_level.cost_minimization_control:CostMinimizationControl", + "ProfitMaximizationControl": "control.control_strategies.system_level.profit_maximization_control:ProfitMaximizationControl", } ) From 270b4d82e889b407644fa8cbb54035e0e6633c28 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Fri, 22 May 2026 15:16:57 -0600 Subject: [PATCH 105/132] Fixing tests and examples --- examples/16_natural_gas/plant_config.yaml | 2 +- examples/23_solar_wind_ng_demand/plant_config.yaml | 2 +- examples/24_solar_battery_grid/plant_config.yaml | 2 +- examples/33_peak_load_management/plant_config.yaml | 2 +- .../control_strategies/passthrough_controller.py | 4 ++-- .../converters/steel/cmu_electric_arc_furnace_dri.py | 12 ++++++------ .../steel/cmu_electric_arc_furnace_scrap.py | 12 ++++++------ 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/16_natural_gas/plant_config.yaml b/examples/16_natural_gas/plant_config.yaml index 5024ff790..aa30629f7 100644 --- a/examples/16_natural_gas/plant_config.yaml +++ b/examples/16_natural_gas/plant_config.yaml @@ -26,7 +26,7 @@ technology_interconnections: # subtract the combined generation from the demand profile - [elec_combiner, electrical_load_demand, electricity, cable] # connect the remaining electricity demand to the NG plant - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] # connect NG feedstock to NG plant - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect natural gas and solar to finance combiner diff --git a/examples/23_solar_wind_ng_demand/plant_config.yaml b/examples/23_solar_wind_ng_demand/plant_config.yaml index 5bf31591d..417448b50 100644 --- a/examples/23_solar_wind_ng_demand/plant_config.yaml +++ b/examples/23_solar_wind_ng_demand/plant_config.yaml @@ -27,7 +27,7 @@ technology_interconnections: # connect NG feedstock to NG plant - [combiner, electrical_load_demand, electricity, cable] # subtract wind and solar from demand - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] # give remaining load demand to natural gas plant - [combiner, fin_combiner, electricity, cable] - [natural_gas_plant, fin_combiner, electricity, cable] diff --git a/examples/24_solar_battery_grid/plant_config.yaml b/examples/24_solar_battery_grid/plant_config.yaml index 3fed5d46d..8c9298c03 100644 --- a/examples/24_solar_battery_grid/plant_config.yaml +++ b/examples/24_solar_battery_grid/plant_config.yaml @@ -27,7 +27,7 @@ technology_interconnections: # subtract variable generation from the demand - [bat_combiner, electrical_load_demand, electricity, cable] # connect remaining demand to grid buying - - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_set_point]] + - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_demand]] # connect surplus generation to grid selling - [electrical_load_demand, grid_sell, [unused_electricity_out, electricity_in]] # combine electricity generated from solar and electricity bought from grid diff --git a/examples/33_peak_load_management/plant_config.yaml b/examples/33_peak_load_management/plant_config.yaml index 93be1cecf..e7bc28ac4 100644 --- a/examples/33_peak_load_management/plant_config.yaml +++ b/examples/33_peak_load_management/plant_config.yaml @@ -12,4 +12,4 @@ technology_interconnections: # include battery charge/discharge in the load - [battery, electrical_load_demand, [electricity_out, electricity_in]] # buy power from the grid to fulfill demand including to accommodate battery operation - - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_set_point]] + - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_demand]] diff --git a/h2integrate/control/control_strategies/passthrough_controller.py b/h2integrate/control/control_strategies/passthrough_controller.py index 347ccaae7..a48aabd17 100644 --- a/h2integrate/control/control_strategies/passthrough_controller.py +++ b/h2integrate/control/control_strategies/passthrough_controller.py @@ -17,7 +17,7 @@ class PassthroughController(om.ExplicitComponent): production is unconstrained, making the component a harmless no-op. """ - _time_step_bounds = (0, float("inf")) + _time_step_bounds = (1, float("inf")) def initialize(self): self.options.declare("commodity", types=str) @@ -45,7 +45,7 @@ def setup(self): # downstream performance model behaves as if unconstrained (the perf # model typically saturates the set-point at its rated capacity). # We avoid extreme values (e.g. 1e30) here because they pollute the - # NLBGS relative-residual check and cause premature false convergence + # solver relative-residual check and cause premature false convergence # in cyclic system-level control configurations. default_val = 1.0e9 diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py index 073171d52..bcdb78223 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py @@ -180,7 +180,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_demand", + "steel_set_point", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -328,19 +328,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_demand = np.where( - inputs["steel_demand"] > system_production, + steel_set_point = np.where( + inputs["steel_set_point"] > system_production, system_production, - inputs["steel_demand"], + inputs["steel_set_point"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_demand"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_demand + steel_from_feedstocks[0] = steel_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py index 492babb34..a6ed8debe 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py @@ -142,7 +142,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_demand", + "steel_set_point", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -260,19 +260,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_demand = np.where( - inputs["steel_demand"] > system_production, + steel_set_point = np.where( + inputs["steel_set_point"] > system_production, system_production, - inputs["steel_demand"], + inputs["steel_set_point"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_demand"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_demand + steel_from_feedstocks[0] = steel_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): From f4b8401f110bb8b07c426d37d66dcdf2583763f5 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Mon, 1 Jun 2026 12:43:11 -0600 Subject: [PATCH 106/132] Partially addressing Jared's PR feedback --- .../system_level_control/slc_cost_min.md | 6 +- .../slc_demand_following.md | 6 +- .../system_level_control/slc_profit_max.md | 8 +- .../system_level/cost_minimization_control.py | 10 +- .../system_level/demand_following_control.py | 8 +- .../profit_maximization_control.py | 8 +- .../system_level/system_level_control_base.py | 100 +++++++++--------- .../system_level/test/test_slc_controllers.py | 52 ++++----- .../system_level/test/test_slc_examples.py | 10 +- h2integrate/core/h2integrate_model.py | 80 +++++++------- 10 files changed, 140 insertions(+), 148 deletions(-) diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md index 40e304523..75284fcc7 100644 --- a/docs/control/system_level_control/slc_cost_min.md +++ b/docs/control/system_level_control/slc_cost_min.md @@ -21,7 +21,7 @@ Unlike the {ref}`demand following controller `, which spli The controller follows a three-step dispatch process: -1. **Curtailable technologies** run at their full rated capacity (assumed zero marginal cost). Their output is subtracted from the demand. +1. **Curtailable technologies** run at their available capacity (assumed zero marginal cost). Their output is subtracted from the demand. 2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging). Residual demand is split evenly across storage technologies producing the demanded commodity. 3. **Dispatchable technologies** are dispatched by cheapest marginal cost first, each up to its rated capacity, until the remaining demand is met. @@ -31,7 +31,7 @@ Marginal costs are specified per dispatchable technology in the `cost_per_tech` | Value | Description | | --- | --- | -| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_unit*h)` | +| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_amount_units)` | | `"buy_price"` | Uses the technology's configured purchase price | | `"VarOpEx"` | Derives marginal cost from the technology's variable operating expenditure divided by total production | | `"feedstock"` | Sums upstream feedstock `VarOpEx` values and divides by the technology's total production | @@ -60,7 +60,7 @@ The base inputs for technologies classified as `curtailable`, `dispatchable`, an - `f"{tech_name}_rated_{tech_output_commodity}_production"` The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: -- `f"{tech_name}_{tech_output_commodity}_set_point"` +- `f"{tech_name}_{tech_output_commodity}_demand"` The outputs for `storage` technologies *with* a storage controller are: - `f"{tech_name}_{tech_output_commodity}_demand"` diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 95315f191..37770ed8a 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -58,9 +58,9 @@ display( The demand is satisfied in a fixed three-step priority order, and each step's shortfall or surplus is passed to the next: -1. **Curtailable techs** run at their full rated capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). +1. **Curtailable techs** run at their available capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). -2. **Storage techs** receive the residual demand (which may be positive or negative). When demand is positive the storage is commanded to discharge; when negative it is commanded to charge. If multiple storage techs produce the demanded commodity, the residual demand is +2. **Storage techs** receive the residual demand (which may be positive or negative). When residual demand is positive the storage is commanded to discharge; when negative it is commanded to charge. If multiple storage techs produce the demanded commodity, the residual demand is split **evenly** across them (each receives ``demand / n_storage``). 3. **Dispatchable techs** cover any remaining positive demand after storage. The remaining demand (floored at zero) is split **evenly** across all dispatchable techs that produce the demanded commodity (each receives ``remaining_demand / n_dispatchable``). @@ -88,7 +88,7 @@ The inputs for technologies classified as `feedstock` are: The outputs for technologies classified as `curtailable`, `dispatchable`, or `storage` and *without a storage controller* are: -- `f"{tech_name}_{tech_output_commodity}_set_point"` +- `f"{tech_name}_{tech_output_commodity}_demand"` The outputs for technologies classified as `storage` that *have a storage controller* are: - `f"{tech_name}_{tech_output_commodity}_demand"` diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md index c31b77aa4..c621c2996 100644 --- a/docs/control/system_level_control/slc_profit_max.md +++ b/docs/control/system_level_control/slc_profit_max.md @@ -58,7 +58,7 @@ display( The controller follows a three-step dispatch process: -1. **Curtailable technologies** run at full rated capacity - they are always profitable to produce (zero marginal cost). +1. **Curtailable technologies** run at available capacity - they are always profitable to produce (zero marginal cost). 2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging), split evenly across storage technologies producing the demanded commodity. 3. **Dispatchable technologies** are dispatched in merit order (cheapest first), but **only at timesteps where their marginal cost is below the sell price**. At each timestep, the dispatch is the minimum of the remaining demand and the rated capacity, gated by the profitability check. @@ -72,7 +72,7 @@ The sell price can be configured in two ways in `system_level_control.control_pa | Value | Description | | --- | --- | -| Numeric (e.g. `0.06`) | Constant sell price in `$/(commodity_unit*h)` | +| Numeric (e.g. `0.06`) | Constant sell price in `$/(commodity_amount_units)` | | String (e.g. `"profast_npv"`) | Name of a finance group in `finance_parameters.finance_groups` whose `model_inputs.commodity_sell_price` will be used | ## Marginal Cost Configuration @@ -81,7 +81,7 @@ Marginal costs are configured identically to the {ref}`cost minimization control | Value | Description | | --- | --- | -| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_unit*h)` | +| Numeric (e.g. `0.05`) | Constant marginal cost in `$/(commodity_amount_units)` | | `"buy_price"` | Uses the technology's configured purchase price | | `"VarOpEx"` | Derives cost from VarOpEx / total production | | `"feedstock"` | Sums upstream feedstock VarOpEx / total production | @@ -110,7 +110,7 @@ The base inputs for technologies classified as `curtailable`, `dispatchable`, an - `f"{tech_name}_rated_{tech_output_commodity}_production"` The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: -- `f"{tech_name}_{tech_output_commodity}_set_point"` +- `f"{tech_name}_{tech_output_commodity}_demand"` The outputs for `storage` technologies *with* a storage controller are: - `f"{tech_name}_{tech_output_commodity}_demand"` diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index d9208a0c7..27818ce65 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -69,16 +69,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable set_points to zero - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable demand outputs to zero + for demand_name in self.dispatchable_demand_names: + outputs[demand_name] = np.zeros(self.n_timesteps) # Dispatch in merit order for idx in dispatch_order: - set_point_name = self.dispatchable_set_point_names[idx] + demand_name = self.dispatchable_demand_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] dispatch = np.minimum(remaining, rated) - outputs[set_point_name] = dispatch + outputs[demand_name] = dispatch remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index eb2427f00..15f1e3cda 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -15,7 +15,7 @@ class DemandFollowingControl(SystemLevelControlBase): 1. **Fixed techs** always produce at their rated capacity and cannot be controlled. Their total output is subtracted from the demand. - 2. **Flexible techs** run at their full rated capacity. Their total + 2. **Flexible techs** run at their available capacity. Their total output is subtracted from the demand, which may drive the residual demand negative (surplus). @@ -52,8 +52,8 @@ def compute(self, inputs, outputs): ) else: if f"{flexible_tech}_rated_{tech_commodity}_production" in inputs: - # set the set-point as the rated production - outputs[f"{flexible_tech}_{tech_commodity}_set_point"] = inputs[ + # set the per-tech demand as the rated production + outputs[f"{flexible_tech}_{tech_commodity}_demand"] = inputs[ f"{flexible_tech}_rated_{tech_commodity}_production" ] * np.ones(self.n_timesteps) @@ -80,6 +80,6 @@ def compute(self, inputs, outputs): for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) if commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( + outputs[f"{dispatchable_tech}_{commodity}_demand"] = ( remaining_demand / n_dispatchable ) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 1fd8868a1..8f6a5079d 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -129,16 +129,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable set_points to zero - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable demand outputs to zero + for demand_name in self.dispatchable_demand_names: + outputs[demand_name] = np.zeros(self.n_timesteps) # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: mc = marginal_costs[idx] # per-timestep array profitable = mc < sell_price # boolean mask per timestep - set_point_name = self.dispatchable_set_point_names[idx] + set_point_name = self.dispatchable_demand_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 6622f8199..aaece4a09 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -12,6 +12,12 @@ class SystemLevelControlBase(om.ExplicitComponent): Subclasses must implement ``compute()`` with their dispatch strategy. + Each technology group is expected to contain a controller (either user-defined or an + auto-injected ``PassthroughController``) that consumes a ``{commodity}_demand`` input and + produces the ``{commodity}_set_point`` actually fed to the performance/cost models. The + system-level controller therefore reasons in terms of *demand* values and emits + ``{tech_name}_{commodity}_demand`` outputs for every controlled technology. + Information passed to the controller from H2IntegrateModel is input in the ``slc_config``, which must contain: @@ -102,7 +108,7 @@ def _setup_commodity( commodity_units=None, commodity_reference_var=None, add_in_name=True, - initial_set_point=1.0, + initial_demand=1.0, ): """Register OpenMDAO inputs and outputs for a single (tech, commodity) pair. @@ -123,9 +129,8 @@ def _setup_commodity( (only if ``add_in_name=True``). - Input ``"{tech_name}_rated_{commodity}_production"`` - rated production capacity of the tech. - - Output ``"{tech_name}_{commodity}_set_point"`` (or - ``"{tech_name}_{commodity}_demand"`` for storage techs with an attached - controller) - control set-point sent to the tech. + - Output ``"{tech_name}_{commodity}_demand"`` - demand signal sent to the + tech's controller (which translates it into a performance-model set-point). Args: tech_name (str): Name of the technology. @@ -137,11 +142,11 @@ def _setup_commodity( ``commodity_units``. add_in_name (bool, optional): If True, register the ``"{tech_name}_{commodity}_out"`` input. Defaults to True. - initial_set_point (float, optional): Initial value for the - set-point output. Defaults to 1.0. + initial_demand (float, optional): Initial value for the + demand output. Defaults to 1.0. Returns: - tuple[str, str, str]: ``(in_name, set_point_name, rated_name)`` + tuple[str, str, str]: ``(in_name, demand_name, rated_name)`` """ # --- Determine unit kwargs for add_input / add_output --------- # Either explicit units or copy_units from a reference variable. @@ -153,13 +158,7 @@ def _setup_commodity( # --- Build variable names ------------------------------------- in_name = f"{tech_name}_{commodity}_out" rated_name = f"{tech_name}_rated_{commodity}_production" - - # Storage techs with an attached controller receive a "demand" - # output instead of a "set_point" output. - if self.storage_techs_to_control.get(tech_name, False): - set_point_name = f"{tech_name}_{commodity}_demand" - else: - set_point_name = f"{tech_name}_{commodity}_set_point" + demand_name = f"{tech_name}_{commodity}_demand" # --- Register inputs and output ------------------------------- if add_in_name: @@ -177,14 +176,14 @@ def _setup_commodity( **unit_kwargs, ) self.add_output( - set_point_name, - val=initial_set_point, + demand_name, + val=initial_demand, shape=self.n_timesteps, - desc=f"Set point for {tech_name} {commodity} curtailment", + desc=f"Demand sent to {tech_name} for {commodity}", **unit_kwargs, ) - return in_name, set_point_name, rated_name + return in_name, demand_name, rated_name def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. @@ -193,16 +192,16 @@ def _setup_tech_category(self, category, tech_list): technologies. The logic is identical for all three categories — iterate over each technology's commodities and register the appropriate inputs (production output, rated capacity) and output - (control set-point). + (per-tech demand). - All initial set-points are ``1.0``; the solver converges from there + All initial demand values are ``1.0``; the solver converges from there using the connected rated-production inputs at run time. After this method returns, four lists are stored on ``self`` under names produced by the *category* prefix: ``self.{category}_input_names`` - ``self.{category}_set_point_names`` + ``self.{category}_demand_names`` ``self.{category}_rated_names`` ``self.{category}_commodity_names`` @@ -215,11 +214,11 @@ def _setup_tech_category(self, category, tech_list): tech_list (list[str]): Technology names belonging to this category (e.g. ``self.flexible_techs``). """ - initial_set_point = 1.0 + initial_demand = 1.0 # --- Initialize the four per-category bookkeeping lists ------- input_names = [] - set_point_names = [] + demand_names = [] rated_names = [] commodity_names = [] @@ -229,21 +228,21 @@ def _setup_tech_category(self, category, tech_list): for commodity in tech_commodities: if commodity in self.commodities_to_units: # Units are already known explicitly - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_units=self.commodities_to_units[commodity], add_in_name=True, - initial_set_point=initial_set_point, + initial_demand=initial_demand, ) elif commodity in self.commodities_to_ref_var: # Units are inferred from a previously-registered reference variable - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], add_in_name=True, - initial_set_point=initial_set_point, + initial_demand=initial_demand, ) else: # Units are unknown; try to discover them from the connection @@ -261,22 +260,22 @@ def _setup_tech_category(self, category, tech_list): # variable so later techs with this commodity can # copy its units. self.commodities_to_ref_var[commodity] = in_name - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], add_in_name=False, - initial_set_point=initial_set_point, + initial_demand=initial_demand, ) else: # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_units=self.commodities_to_units[commodity], add_in_name=False, - initial_set_point=initial_set_point, + initial_demand=initial_demand, ) if category == "storage": @@ -286,12 +285,12 @@ def _setup_tech_category(self, category, tech_list): commodity_names.append(commodity) input_names.append(in_name) - set_point_names.append(set_point_name) + demand_names.append(demand_name) rated_names.append(rated_name) # --- Store lists as self._ attributes ------- setattr(self, f"{category}_input_names", input_names) - setattr(self, f"{category}_set_point_names", set_point_names) + setattr(self, f"{category}_demand_names", demand_names) setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) @@ -423,7 +422,7 @@ def _subtract_fixed(self, fixed_tech, remaining_demand, commodity, inputs): return remaining_demand def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, outputs): - """Apply flexible techs: set_point = rated, subtract output from demand. + """Apply flexible techs: demand = rated, subtract output from demand. Returns the updated demand array. """ @@ -433,8 +432,8 @@ def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, if f"{flexible_tech}_rated_{commodity}_production" not in inputs: return - # Output the set-point as the rated production of that technology - outputs[f"{flexible_tech}_{commodity}_set_point"] = inputs[ + # Set per-tech demand equal to the rated production of that technology + outputs[f"{flexible_tech}_{commodity}_demand"] = inputs[ f"{flexible_tech}_rated_{commodity}_production" ] * np.ones(self.n_timesteps) remaining_demand -= inputs[f"{flexible_tech}_{commodity}_out"] @@ -448,27 +447,28 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if f"{storage_tech}_{commodity}_out" not in inputs: return + demand_name = f"{storage_tech}_{commodity}_demand" + if demand_name not in outputs: + return + if self.storage_techs_to_control.get(storage_tech, False): - # storage tech has a controller, output combined demand (always positive) - # demand should be what is input to storage + remaining_demand - # get the technologies upstream of the storage that output that commodity + # Storage tech has its own sub-controller: emit a combined demand + # signal (always positive) equal to the commodity flowing into + # storage from upstream techs plus any remaining demand. upstream_techs = self.get_upstream_techs_for_commodity(storage_tech, commodity) commodity_into_storage = np.zeros(self.n_timesteps) for tech_name in upstream_techs: commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] - outputs[f"{storage_tech}_{commodity}_demand"] = ( - commodity_into_storage + remaining_demand - ) - remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] - return remaining_demand + outputs[demand_name] = commodity_into_storage + remaining_demand + else: + # Storage without a sub-controller: emit a charge/discharge + # command directly. Charge when remaining demand is negative, + # discharge when positive. + outputs[demand_name] = remaining_demand - if f"{storage_tech}_{commodity}_set_point" in outputs: - # storage tech does not have a controller, output set point (charge/discharge) command - # charge when remaining demand is negative, discharge when remaining demand is positive - outputs[f"{storage_tech}_{commodity}_set_point"] = remaining_demand - remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] - return remaining_demand + remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] + return remaining_demand def _get_commodity_for_tech(self, tech_name): """Get a list of the commodities produced for a technology. diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index 91cd39e9d..2c416f4e0 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -160,7 +160,7 @@ def test_base_creates_flexible_io(self): # _var_rel2meta uses relative names (no "slc." prefix) assert "wind_electricity_out" in prob.model.slc._var_rel2meta assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta + assert "wind_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_dispatchable_io(self): tech_connections = [["ng", "demand", "electricity", "cable"]] @@ -171,7 +171,7 @@ def test_base_creates_dispatchable_io(self): prob = _build_problem(DemandFollowingControl, plant_config, slc_config) assert "ng_electricity_out" in prob.model.slc._var_rel2meta assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta + assert "ng_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_storage_io(self): tech_connections = [["battery", "demand", "electricity", "cable"]] @@ -183,7 +183,7 @@ def test_base_creates_storage_io(self): assert "battery_electricity_out" in prob.model.slc._var_rel2meta assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta + assert "battery_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_demand_input(self): plant_config = _build_plant_config([]) @@ -222,8 +222,8 @@ def test_equal_share_two_dispatchable(self): prob.set_val("slc.ng2_rated_electricity_production", 40000) prob.run_model() - sp1 = prob.get_val("slc.ng1_electricity_set_point") - sp2 = prob.get_val("slc.ng2_electricity_set_point") + sp1 = prob.get_val("slc.ng1_electricity_demand") + sp2 = prob.get_val("slc.ng2_electricity_demand") np.testing.assert_allclose(sp1, 25000) np.testing.assert_allclose(sp2, 25000) @@ -246,7 +246,7 @@ def test_flexible_reduces_demand(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # demand=50k, wind outputs [30k,60k,50k,10k] → remaining = max(0, demand-wind) expected = np.maximum(50000 - np.array([30000, 60000, 50000, 10000]), 0) np.testing.assert_allclose(ng_sp, expected) @@ -274,7 +274,7 @@ def test_storage_absorbs_surplus(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - batt_sp = prob.get_val("slc.battery_electricity_set_point") + batt_sp = prob.get_val("slc.battery_electricity_demand") # demand - wind = [50k-70k, 50k-30k, 0, 0] = [-20k, 20k, 0, 0] expected = np.array([-20000, 20000, 0, 0]) np.testing.assert_allclose(batt_sp, expected) @@ -317,8 +317,8 @@ def test_cheapest_dispatched_first(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap can handle all 50k (rated 80k), so expensive gets 0 np.testing.assert_allclose(cheap_sp, 50000) np.testing.assert_allclose(expensive_sp, 0) @@ -343,8 +343,8 @@ def test_overflow_to_expensive(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap maxes at 30k, expensive picks up remaining 20k np.testing.assert_allclose(cheap_sp, 30000) np.testing.assert_allclose(expensive_sp, 20000) @@ -368,7 +368,7 @@ def test_with_flexible_reduces_dispatch(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # demand 50k - wind 40k = 10k remaining np.testing.assert_allclose(ng_sp, 10000) @@ -401,8 +401,8 @@ def test_unprofitable_tech_not_dispatched(self): prob.set_val("slc.commodity_sell_price", 0.06) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap (0.03 < 0.06) dispatched up to rated 30k # Expensive (0.08 >= 0.06) NOT dispatched, demand unmet np.testing.assert_allclose(cheap_sp, 30000) @@ -427,8 +427,8 @@ def test_all_profitable(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - a_sp = prob.get_val("slc.a_electricity_set_point") - b_sp = prob.get_val("slc.b_electricity_set_point") + a_sp = prob.get_val("slc.a_electricity_demand") + b_sp = prob.get_val("slc.b_electricity_demand") # Both profitable, cheapest first: a gets 50k (rated 80k), b gets 0 np.testing.assert_allclose(a_sp, 50000) np.testing.assert_allclose(b_sp, 0) @@ -449,7 +449,7 @@ def test_none_profitable(self): prob.set_val("slc.commodity_sell_price", 0.01) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # NG cost (0.05) >= sell price (0.01), not dispatched np.testing.assert_allclose(ng_sp, 0) @@ -469,7 +469,7 @@ def test_sell_price_from_config(self): # Don't set sell_price explicitly — should use config default 0.10 prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # Config sell_price=0.10 > marginal 0.03 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -490,7 +490,7 @@ def test_time_varying_sell_price(self): prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # mc=0.05: profitable when sell>0.05 (hours 0,2), not when sell<0.05 (hours 1,3) np.testing.assert_allclose(ng_sp, [50000, 0, 50000, 0]) @@ -528,7 +528,7 @@ def test_buy_price_scalar(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_set_point") + grid_sp = prob.get_val("slc.grid_electricity_demand") # buy_price=0.04 < sell_price=0.10 → dispatched np.testing.assert_allclose(grid_sp, 50000) @@ -568,7 +568,7 @@ def test_buy_price_time_varying(self): prob.set_val("slc.grid_buy_price", [0.03, 0.08, 0.04, 0.09]) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_set_point") + grid_sp = prob.get_val("slc.grid_electricity_demand") np.testing.assert_allclose(grid_sp, [50000, 0, 50000, 0]) def test_varopex_mode(self): @@ -591,7 +591,7 @@ def test_varopex_mode(self): prob.set_val("slc.gen_electricity_out", np.full(4, 100000.0)) prob.run_model() - gen_sp = prob.get_val("slc.gen_electricity_set_point") + gen_sp = prob.get_val("slc.gen_electricity_demand") # VarOpEx=500k $/yr, production=100MW*4h=400MWh over 4h # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 500k / 876k ≈ 0.571 $/MWh ≈ 0.000571 $/kWh @@ -614,7 +614,7 @@ def test_cost_per_tech_default_zero(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # mc=0.0 < sell_price=0.10 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -641,7 +641,7 @@ def test_feedstock_single(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_set_point") + sp = prob.get_val("slc.ng_plant_electricity_demand") # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 1M / 876k ≈ 1.14 $/MWh ≈ 0.00114 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -672,7 +672,7 @@ def test_feedstock_multiple(self): prob.set_val("slc.plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.plant_electricity_set_point") + sp = prob.get_val("slc.plant_electricity_demand") # Total VarOpEx = 800k, annual production = 876,000 MWh # mc ≈ 0.913 $/MWh ≈ 0.000913 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -702,7 +702,7 @@ def test_feedstock_profit_max_unprofitable(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_set_point") + sp = prob.get_val("slc.ng_plant_electricity_demand") # mc = 100M / 876k ≈ 114 $/MWh ≈ 0.114 $/kWh > sell 0.01 → NOT dispatched np.testing.assert_allclose(sp, 0) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 230f186a2..0b341f0d8 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -17,7 +17,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -26,7 +26,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + "system_level_controller.natural_gas_plant_electricity_demand", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, @@ -76,7 +76,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -85,7 +85,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") battery_set_point = model.prob.get_val( - "system_level_controller.battery_electricity_set_point", units="kW" + "system_level_controller.battery_electricity_demand", units="kW" ) assert np.allclose(remaining_demand, battery_set_point, rtol=1e-6, atol=1e-8) @@ -94,7 +94,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "battery.electricity_out", units="kW" ) ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + "system_level_controller.natural_gas_plant_electricity_demand", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 43f8362f7..8567df639 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -628,21 +628,18 @@ def add_system_level_controller(self, slc_config): - **Feedstock techs**: Only the commodity output (``{tech_name}_source.{commodity}_out``) is connected to the controller. Feedstocks - have no set-point or rated-production connection. + have no demand-input connection. - **Fixed techs**: Only the commodity output (``{tech_name}.{commodity}_out``) is connected to the controller. Fixed techs - always produce and receive no set-point or rated-production connection. + always produce and receive no demand-input connection. - **Flexible / dispatchable / storage techs**: Both the commodity output (``{tech_name}.{commodity}_out``) and rated production (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. - The controller's set-point output is connected back to the tech: - - - If the storage tech has its own sub-controller - (``storage_techs_to_control[tech_name] == True``), the controller outputs a - *demand* signal (``{tech_name}_{commodity}_demand``) that the storage - sub-controller consumes. - - Otherwise, the controller outputs a *set_point* signal - (``{tech_name}_{commodity}_set_point``) directly to the performance model. + The controller's per-tech ``{tech_name}_{commodity}_demand`` output is then + connected to the tech group's ``{commodity}_demand`` input. Every controlled + tech group is expected to expose this input — either via a user-defined + ``control_strategy`` or via the auto-injected ``PassthroughController`` — which + converts the demand signal into the appropriate performance-model set-point. 4. **Connect marginal-cost inputs for cost-aware strategies** - Only executed when ``control_strategy`` is ``"CostMinimizationControl"`` or @@ -761,32 +758,14 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_{commodity}_storage_duration", ) - # Connect the controller's output back to the technology. - classifier = slc_config["tech_control_classifiers"][tech_name] - if slc_config["storage_techs_to_control"].get(tech_name, False): - # Storage tech with its own sub-controller: provide a demand - # signal that the sub-controller translates into - # charge/discharge commands. - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_demand", - f"{tech_name}.{commodity}_demand", - ) - elif classifier in ("flexible", "dispatchable"): - # Flexible / dispatchable techs always have a controller in - # their tech group (auto-injected PassthroughController if no - # user-defined control_strategy). Route the SLC output to the - # controller's demand input. - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_demand", - ) - else: - # Storage without a sub-controller: provide a set-point - # directly to the performance model. - self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - f"{tech_name}.{commodity}_set_point", - ) + # Every controlled tech group exposes a ``{commodity}_demand`` + # input (provided by either a user-defined control_strategy or an + # auto-injected PassthroughController). Route the SLC's per-tech + # demand output to that input. + self.plant.connect( + f"system_level_controller.{tech_name}_{commodity}_demand", + f"{tech_name}.{commodity}_demand", + ) # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - if strategy_name in ("CostMinimizationControl", "ProfitMaximizationControl"): @@ -1070,9 +1049,10 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con A controller is auto-inserted only when: - the technology has no user-defined ``control_strategy`` in its config, - the performance model exposes a ``_control_classifier`` of - ``"flexible"`` or ``"dispatchable"``, + ``"flexible"``, ``"dispatchable"``, or ``"storage"``, - the performance model has set ``commodity`` and ``commodity_rate_units`` - attributes (typically set in its ``initialize()``). + attributes (typically set in its ``initialize()``), or those values + can be read from the individual tech config. The controller's ``{commodity}_demand`` input becomes the tech group's external demand-input promoted at the tech group level, and its @@ -1084,19 +1064,31 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con if "control_strategy" in individual_tech_config: return - # Only flexible/dispatchable techs accept an externally provided demand - # signal. Fixed, feedstock, connector, and storage techs are handled - # elsewhere (storage uses its own sub-controller; fixed/feedstock have - # no set-point) and must not get a passthrough. + # Only flexible/dispatchable/storage techs accept an externally + # provided demand signal. Fixed, feedstock, and connector techs are + # handled elsewhere (fixed/feedstock have no demand input) and must + # not get a passthrough. classifier = getattr(perf_comp, "_control_classifier", None) - if classifier not in ("flexible", "dispatchable"): + if classifier not in ("flexible", "dispatchable", "storage"): return # The performance model must declare the commodity it produces and the # units of its set-point so the PassthroughController can size its I/O - # consistently. If either is missing we have nothing to wire up. + # consistently. If they aren't yet set on the component (some models + # only assign these in ``setup()``), fall back to reading them from the + # individual tech config's model_inputs. commodity = getattr(perf_comp, "commodity", None) commodity_rate_units = getattr(perf_comp, "commodity_rate_units", None) + if commodity is None or commodity_rate_units is None: + model_inputs = individual_tech_config.get("model_inputs", {}) + shared = model_inputs.get("shared_parameters", {}) + perf_inputs = model_inputs.get("performance", {}) + if commodity is None: + commodity = perf_inputs.get("commodity", shared.get("commodity")) + if commodity_rate_units is None: + commodity_rate_units = perf_inputs.get( + "commodity_rate_units", shared.get("commodity_rate_units") + ) if commodity is None or commodity_rate_units is None: return From 585c87cf6558fc9374ab38bc81454dd010248fe5 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Mon, 1 Jun 2026 17:10:54 -0600 Subject: [PATCH 107/132] Renaming per PR feedback --- .../technology_control_overview.md | 2 +- .../profit_maximization_control.py | 2 +- .../system_level/system_level_control_base.py | 32 +++++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/control/technology_level_control/technology_control_overview.md b/docs/control/technology_level_control/technology_control_overview.md index d0016acea..4ec6dfc9b 100644 --- a/docs/control/technology_level_control/technology_control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,6 +1,6 @@ # Technology-Level Control -There are two different systematic approaches, or frameworks, in H2Integrate for technology-level control: [open-loop](#open-loop-control) and [pyomo](#pyomo-control). These two frameworks are useful in different situations and have different impacts on the system and control strategies that can be implemented. Both control frameworks are focused on technology-level dispatching. The open-loop framework has logic that is applicable to both storage technologies and converter technologies **IS THIS STILL TRUE?** and the pyomo framework is currently applicable to storage technologies. The technology-level storage controllers may curtail/discard commodity amounts exceeding the needs of the storage technology and the specified demand. However, any unused commodity may be connected to another down-stream component to avoid actual curtailment. +There are two different systematic approaches, or frameworks, in H2Integrate for technology-level control: [open-loop](#open-loop-control) and [pyomo](#pyomo-control). These two frameworks are useful in different situations and have different impacts on the system and control strategies that can be implemented. Both control frameworks are focused on technology-level dispatching. The open-loop framework has logic that is applicable to both storage technologies and converter technologies and the pyomo framework is currently applicable to storage technologies. The technology-level storage controllers may curtail/discard commodity amounts exceeding the needs of the storage technology and the specified demand. However, any unused commodity may be connected to another down-stream component to avoid actual curtailment. (open-loop-control-framework)= ## Open-loop control framework diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 8f6a5079d..39d06e152 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -83,7 +83,7 @@ def setup(self): "commodity_sell_price", val=commodity_sell_price, shape=self.n_timesteps, - units=f"USD/({self.commodity_units}*h)", + units=f"USD/({self.commodity_rate_units}*h)", desc=f"Sell price per unit of {self.commodity}", ) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index aaece4a09..95e772748 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -51,7 +51,7 @@ def setup(self): # Read pre-computed classification from plant_config self.commodity = slc_config["demand_commodity"] - self.commodity_units = slc_config.get("demand_commodity_rate_units", None) + self.commodity_rate_units = slc_config.get("demand_commodity_rate_units", None) self.demand_tech = slc_config["demand_tech"] self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] @@ -82,7 +82,7 @@ def setup(self): self.demand_input_name, val=10.0, shape=self.n_timesteps, - units=self.commodity_units, + units=self.commodity_rate_units, desc=f"Demand profile of {self.commodity}", ) @@ -93,7 +93,7 @@ def setup(self): True if len({e[-1] for e in self.techs_to_commodities}) > 1 else False ) - self.commodities_to_units = {self.commodity: self.commodity_units} + self.commodities_to_units = {self.commodity: self.commodity_rate_units} self.commodities_to_ref_var = {} self._setup_fixed_category(self.fixed_techs) self._setup_tech_category("flexible", self.flexible_techs) @@ -105,7 +105,7 @@ def _setup_commodity( self, tech_name, commodity, - commodity_units=None, + commodity_rate_units=None, commodity_reference_var=None, add_in_name=True, initial_demand=1.0, @@ -114,13 +114,13 @@ def _setup_commodity( This method handles unit specification in two mutually exclusive ways: - 1. **Explicit units** - pass ``commodity_units`` (e.g. ``"kW"``). - Each variable is created with ``units=commodity_units``. + 1. **Explicit units** - pass ``commodity_rate_units`` (e.g. ``"kW"``). + Each variable is created with ``units=commodity_rate_units``. 2. **Copied units** - pass ``commodity_reference_var`` (the name of an already-registered input whose units should be reused). Each variable is created with ``units=None, copy_units=commodity_reference_var``. - Exactly one of ``commodity_units`` or ``commodity_reference_var`` must be + Exactly one of ``commodity_rate_units`` or ``commodity_reference_var`` must be provided. The following OpenMDAO variables are created: @@ -135,11 +135,11 @@ def _setup_commodity( Args: tech_name (str): Name of the technology. commodity (str): Commodity produced by ``tech_name``. - commodity_units (str | None): Explicit unit string for the commodity. + commodity_rate_units (str | None): Explicit unit string for the commodity. Mutually exclusive with ``commodity_reference_var``. commodity_reference_var (str | None): Name of an existing input variable whose units should be copied. Mutually exclusive with - ``commodity_units``. + ``commodity_rate_units``. add_in_name (bool, optional): If True, register the ``"{tech_name}_{commodity}_out"`` input. Defaults to True. initial_demand (float, optional): Initial value for the @@ -150,8 +150,8 @@ def _setup_commodity( """ # --- Determine unit kwargs for add_input / add_output --------- # Either explicit units or copy_units from a reference variable. - if commodity_units is not None: - unit_kwargs = {"units": commodity_units} + if commodity_rate_units is not None: + unit_kwargs = {"units": commodity_rate_units} else: unit_kwargs = {"units": None, "copy_units": commodity_reference_var} @@ -231,7 +231,7 @@ def _setup_tech_category(self, category, tech_list): in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, - commodity_units=self.commodities_to_units[commodity], + commodity_rate_units=self.commodities_to_units[commodity], add_in_name=True, initial_demand=initial_demand, ) @@ -273,7 +273,7 @@ def _setup_tech_category(self, category, tech_list): in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, - commodity_units=self.commodities_to_units[commodity], + commodity_rate_units=self.commodities_to_units[commodity], add_in_name=False, initial_demand=initial_demand, ) @@ -302,6 +302,10 @@ def _setup_fixed_category(self, fixed_list): are registered so the controller can read their production and subtract it from demand. + This method is separate from the more general ``_setup_tech_category`` because the logic + for fixed techs is dramatically simpler + (no demand or rated inputs, only production inputs). + After this method returns, two lists are stored on ``self``: ``self.fixed_input_names`` @@ -552,7 +556,7 @@ def _setup_marginal_costs(self): f"{tech_name}_buy_price", val=default_price, shape=self.n_timesteps, - units=f"USD/({self.commodity_units}*h)", + units=f"USD/({self.commodity_rate_units}*h)", desc=f"Buy price for {tech_name}", ) self.dispatchable_marginal_cost_types.append(("buy_price", tech_name)) From 181445a1ddbe9515051a852dd00822aec599af15 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Mon, 1 Jun 2026 17:24:41 -0600 Subject: [PATCH 108/132] Added notes in the docs that every tech group has a controller --- .../system_level_control/system_level_control.md | 6 +++++- .../technology_control_overview.md | 14 ++++++++++++++ docs/user_guide/how_to_set_up_an_analysis.md | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 8f4b2e40f..66bec95ab 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -2,7 +2,11 @@ System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller meaning that it can work to coordinate the entire system and can work with other technology level controllers. -The most basic SLC is shown in the figured below, where the SLC receives a demand. Based on that demand it will output set points for `{commodity}_out` to the individual technology blocks included within the system. Each technology based on it's controller classification will respond to the set point. From each technology block there is `{commodity}_out` (potentially changed by the set point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the set points in attempts to meet the demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. +The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_demand` signal to each controlled technology. Each technology group contains a controller that converts that demand into the `{commodity}_set_point` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the set-point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the demands in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. + +```{note} +Every technology group has an *implicit passthrough controller* that converts `{commodity}_demand` into `{commodity}_set_point`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the demand → set-point hand-off uniform for every technology, regardless of whether an SLC is present. +``` ```{figure} figures/slc_basic.png :width: 70% diff --git a/docs/control/technology_level_control/technology_control_overview.md b/docs/control/technology_level_control/technology_control_overview.md index 4ec6dfc9b..255be2d54 100644 --- a/docs/control/technology_level_control/technology_control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,5 +1,19 @@ # Technology-Level Control +Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same demand/set-point interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. + +(implicit-passthrough-controller)= +## Implicit passthrough controller + +If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_demand` to `{commodity}_set_point` so that: + +- When an SLC is present, the SLC's per-tech demand is fed straight to the performance model. +- When no SLC is present, the demand input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). + +If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_set_point` output so the rest of the framework can connect to them in a uniform way. + +## Control frameworks + There are two different systematic approaches, or frameworks, in H2Integrate for technology-level control: [open-loop](#open-loop-control) and [pyomo](#pyomo-control). These two frameworks are useful in different situations and have different impacts on the system and control strategies that can be implemented. Both control frameworks are focused on technology-level dispatching. The open-loop framework has logic that is applicable to both storage technologies and converter technologies and the pyomo framework is currently applicable to storage technologies. The technology-level storage controllers may curtail/discard commodity amounts exceeding the needs of the storage technology and the specified demand. However, any unused commodity may be connected to another down-stream component to avoid actual curtailment. (open-loop-control-framework)= diff --git a/docs/user_guide/how_to_set_up_an_analysis.md b/docs/user_guide/how_to_set_up_an_analysis.md index 15c29a418..f75565861 100644 --- a/docs/user_guide/how_to_set_up_an_analysis.md +++ b/docs/user_guide/how_to_set_up_an_analysis.md @@ -94,6 +94,10 @@ Each model has its own set of inputs, which are defined in the source code for t Because there are no default values for the parameters, we suggest you look at an existing example that uses the model you are interested in to see what inputs are required or look at the source code for the model. The different models are defined in the `supported_models.py` file in the `h2integrate` package. +```{note} +Every technology group also contains a controller that converts a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the performance model. If you do not specify a `control_strategy` for a technology, H2Integrate automatically inserts an implicit passthrough controller that simply maps demand to set-point. See the [technology-level control overview](../control/technology_level_control/technology_control_overview.md) for more details. +``` + ## Plant config file The plant config file defines the system configuration, any parameters that might be shared across technologies, and how the technologies are connected together. From 28a0374fbb1d5b699d6bd46656da4aa3431ec108 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 13:12:37 -0600 Subject: [PATCH 109/132] Updating docs based on PR feedback --- .github/workflows/ci.yml | 5 ----- docs/control/system_level_control/slc_cost_min.md | 5 ----- docs/control/system_level_control/slc_demand_following.md | 8 +------- docs/control/system_level_control/slc_profit_max.md | 5 ----- pyproject.toml | 2 +- 5 files changed, 2 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d64a682f..2cc796341 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,5 @@ name: Testing on: - push: - branches: - - main - - develop - - system_level_control pull_request: branches: - main diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md index 75284fcc7..5691faeed 100644 --- a/docs/control/system_level_control/slc_cost_min.md +++ b/docs/control/system_level_control/slc_cost_min.md @@ -58,11 +58,6 @@ The base inputs for technologies classified as `curtailable`, `dispatchable`, an - `f"{tech_name}_{tech_output_commodity}_out"` - `f"{tech_name}_rated_{tech_output_commodity}_production"` - -The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: -- `f"{tech_name}_{tech_output_commodity}_demand"` - -The outputs for `storage` technologies *with* a storage controller are: - `f"{tech_name}_{tech_output_commodity}_demand"` ## Limitations diff --git a/docs/control/system_level_control/slc_demand_following.md b/docs/control/system_level_control/slc_demand_following.md index 37770ed8a..3dbd9b3b6 100644 --- a/docs/control/system_level_control/slc_demand_following.md +++ b/docs/control/system_level_control/slc_demand_following.md @@ -82,17 +82,11 @@ The inputs for technologies classified as `curtailable`, `dispatchable`, and `st - `f"{tech_name}_{tech_output_commodity}_out"` - `f"{tech_name}_rated_{tech_output_commodity}_production"` +- `f"{tech_name}_{tech_output_commodity}_demand"` The inputs for technologies classified as `feedstock` are: - `f"{tech_name}_{commodity}_out"` - -The outputs for technologies classified as `curtailable`, `dispatchable`, or `storage` and *without a storage controller* are: -- `f"{tech_name}_{tech_output_commodity}_demand"` - -The outputs for technologies classified as `storage` that *have a storage controller* are: -- `f"{tech_name}_{tech_output_commodity}_demand"` - ## Systems with Heterogeneous Commodities The `DemandFollowingControl` controller can be used in hybrid systems where technologies produce different commodities. diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md index c621c2996..777475084 100644 --- a/docs/control/system_level_control/slc_profit_max.md +++ b/docs/control/system_level_control/slc_profit_max.md @@ -108,11 +108,6 @@ The base inputs for technologies classified as `curtailable`, `dispatchable`, an - `f"{tech_name}_{tech_output_commodity}_out"` - `f"{tech_name}_rated_{tech_output_commodity}_production"` - -The outputs for `curtailable`, `dispatchable`, or `storage` technologies *without* a storage controller are: -- `f"{tech_name}_{tech_output_commodity}_demand"` - -The outputs for `storage` technologies *with* a storage controller are: - `f"{tech_name}_{tech_output_commodity}_demand"` ## Limitations diff --git a/pyproject.toml b/pyproject.toml index 0237186c8..3346b8887 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ dependencies = [ "matplotlib", "numpy", "numpy-financial", - "openmdao", + "openmdao>=3.44.0", "openmeteo-requests", "pandas>=2.0.3", "ProFAST", From 010800dd58bfbcafcd4c097606947ffa553eb1fb Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 13:19:32 -0600 Subject: [PATCH 110/132] Apply suggestions from code review Co-authored-by: genevievestarke <103534902+genevievestarke@users.noreply.github.com> --- .../system_level_control/control_classifier.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index a08b77b8e..17a09413a 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -1,10 +1,10 @@ # System Level Control Technology Performance Classifiers -To enable a generic system level control framework we need to classify each technology based on how the model, that is included in H2I, can operate within the system. +To enable a generic system level control framework we need to classify each technology based on how the model that is included in H2I can operate within the system. ```{note} -While in real life there are a lot of controllable parameters allowing for ramping production up or down for a particular technology (e.g., turbine yaw). The particular model in H2I might not be capable of simulating a modulated response based on an input signal. -These classifications are for how the models in H2I are implemented, **not** how the actual physical subsystem might operate. +While in real life there are a lot of controllable parameters allowing for ramping production up or down for a particular technology (e.g., wind or solar curtailment), the model of that technology in H2I might not be capable of the same response behavior to input signals. +These classifications are for specific H2I dispatch formulations and are based on how the models in H2I are implemented, **not always** on how the actual physical subsystem might operate. This is a useful and necessary distinction that delineates different model capabilities clearly. ``` @@ -13,10 +13,10 @@ We have identified five key classifiers that are able to represent the different Classifier | Meaning | Example Technology Models -- | -- | -- fixed | Always produces commodity and cannot be controlled or reduced; does not receive a set-point | classical nuclear -flexible | Produces based on resource; can only reduce (curtail) | wind, solar +flexible | Produces based on resource; can only reduce (curtail) from the maximum generation based on available resource | wind, solar dispatchable | Can modulate consumption/production within bounds; receives a commodity set-point | grid, electrolyzer, NG turbine storage | Can modulate consumption/production within bounds while tracking SOC | battery, h2 storage, any storage -feedstock | Are not directly controlled, but useful for SLC to know about to make dispatch decisions | feedstocks +feedstock | Are not directly controlled, but useful for SLC to make dispatch decisions | feedstocks To add a classifier for a particular model it would look something like this in the class: ```{python} @@ -27,7 +27,7 @@ _control_classifier = "flexible" A fixed performance model represents anything that always produces at its rated capacity and cannot be controlled or reduced by the system level controller. The SLC reads the output from a fixed technology and subtracts it from the demand, but does not send a set-point back to the technology. A good example of this is a classical nuclear plant model — it produces a constant output that the rest of the system must accommodate. ## Flexible -A flexible performance model represents anything that can have the output reduced based on a given set point from the system level controller. A good example of this is the PVWatts PySAM solar plant in H2I, the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the tracking software, but we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. +A flexible performance model represents anything that can have the output reduced based on a given set point from the system level controller. A good example of this is the PVWatts PySAM solar plant in H2I; the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the panel tracking software. However, we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. ```{figure} figures/curtailable.png :width: 70% @@ -39,7 +39,7 @@ Within the `compute()` method in the performance model you can apply the curtail ``` self.apply_curtailment(outputs) ``` -which, applies curtailment to `{commodity}_out` based on `{commodity}_set_point`. There is then `uncurtailed_{commodity}_out` and `{commodity}_out` as outputs from the performance model. +which, applies curtailment to `{commodity}_out` based on `{commodity}_set_point`. This adds `uncurtailed_{commodity}_out` and `{commodity}_out` as outputs from the performance model. ## Dispatchable A dispatchable performance model represents anything that can receive a set point. Any model that has the "dispatchable" control classifier tag is able to receive a set point and change it's behavior based on that set point. There aren't additional special methods to handle this because it's internal to each performance model. @@ -50,7 +50,7 @@ A dispatchable performance model represents anything that can receive a set poin ``` ## Storage -Storage is a unique control classifier because it assumes that within the model that energy isn't created or destroyed (minus some efficiency losses). While it's technically "dispatchable" in that it can receive and change its performance based on a set point it's handling within H2I is unique because it's attached to storage performance models, which is handled differently than converter performance models. A converter model only has positive (or zero) `{commodity}_out`, whereas a storage model can have positive or negative `{commodity}_out`. +Storage is a unique control classifier because it assumes that within the model that energy isn't created or destroyed (minus some efficiency losses). While it's technically "dispatchable" in that it can receive and change its performance based on a set point, its handling within H2I is unique because it's attached to storage performance models, which is handled differently than converter performance models. A converter model only has positive (or zero) `{commodity}_out`, whereas a storage model can have positive or negative `{commodity}_out`. There are two types of cases for the storage control classifier: 1. **with a storage controller** @@ -66,4 +66,4 @@ The system-level controller outputs set points to the storage performance model ``` ## Feedstock -Another category of control classifiers are feedstocks. The unique thing about feedstocks is that they are considered outside of the controllable system within H2I. While they can't be controlled it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. +The feedstocks category is unique in that they are considered outside of the controllable system within H2I. While they can't be controlled, it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. From 5c7f447b47ef1197bf3c8c4a5758a6232f1a5f0b Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 13:24:57 -0600 Subject: [PATCH 111/132] Updating adding a new tech doc page based on PR review --- .../adding_a_new_technology.md | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/docs/developer_guide/adding_a_new_technology.md b/docs/developer_guide/adding_a_new_technology.md index 5c22e6d19..73f5d613f 100644 --- a/docs/developer_guide/adding_a_new_technology.md +++ b/docs/developer_guide/adding_a_new_technology.md @@ -11,30 +11,55 @@ We'll start by walking through the process to add a simple solar performance mod 1. **Determine what type of technology you're adding** and if it fits into an existing H2Integrate bucket. In this case, we're adding a solar technology, which has an existing set of baseclasses that we will use. These baseclasses are defined in `h2integrate/converters/solar/solar_baseclass.py`. -They provide the basic structure for a solar technology, including the required inputs and outputs for the models. +They provide the basic structure for a solar technology, including the required class attributes, inputs, and outputs for the models. Here's what that baseclass looks like: ```python -class SolarPerformanceBaseClass(om.ExplicitComponent): +from h2integrate.core.model_baseclasses import PerformanceModelBaseClass + + +class SolarPerformanceBaseClass(PerformanceModelBaseClass): + # (min, max) time step lengths (in seconds) compatible with this model + _time_step_bounds = (3600, 3600) + # System-level control classifier; see the control classifier docs. + _control_classifier = "flexible" def initialize(self): - self.options.declare('plant_config', types=dict) - self.options.declare('tech_config', types=dict) - self.options.declare('driver_config', types=dict) + super().initialize() + # Commodity attributes are required by PerformanceModelBaseClass.setup() + self.commodity = "electricity" + self.commodity_rate_units = "kW" + self.commodity_amount_units = "kW*h" def setup(self): - self.add_output('electricity_out', val=0.0, shape=n_timesteps, units='kW', desc='Power output from SolarPlant') - - def compute(self, inputs, outputs): - """ - Computation for the OM component. + # PerformanceModelBaseClass.setup() registers the standard outputs: + # `{commodity}_out`, `total_{commodity}_produced`, + # `annual_{commodity}_produced`, `rated_{commodity}_production`, + # `replacement_schedule`, `capacity_factor`, `operational_life`. + # When `_control_classifier == "flexible"`, it also registers the + # `{commodity}_set_point` input and `uncurtailed_{commodity}_out` + # output used by `apply_curtailment()`. + super().setup() - For a template class this is not implement and raises an error. - """ + self.add_discrete_input( + "solar_resource_data", + val={}, + desc="Solar resource data dictionary", + ) + def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): raise NotImplementedError("This method should be implemented in a subclass.") ``` +Note that the baseclass inherits from `PerformanceModelBaseClass` (defined in `h2integrate/core/model_baseclasses.py`) rather than `om.ExplicitComponent` directly. This baseclass: + +- Declares the standard `driver_config` / `plant_config` / `tech_config` options. +- Reads `n_timesteps`, `dt`, `plant_life`, and `fraction_of_year_simulated` from `plant_config`. +- Validates that `commodity`, `commodity_rate_units`, and `commodity_amount_units` are set on the subclass and registers all of the standard production outputs from those attributes. +- Adds set-point input and uncurtailed output for `flexible` models, and provides the `apply_curtailment()` helper. + +Every performance model must therefore define three class attributes and three commodity attributes; see the [Required class attributes](#required-class-attributes) section below for details. + 2. **Write the performance model for your technology.** We'll be wrapping a PySAM model for this example. We inherit from the baseclass and implement the `setup` and `compute` methods. @@ -59,16 +84,35 @@ class PYSAMSolarPlantPerformanceComponent(SolarPerformanceBaseClass): solar_resource = SolarResource(lat, lon, year) self.system_model.value("solar_resource_data", solar_resource.data) - def compute(self, inputs, outputs): + def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): self.system_model.execute(0) outputs['electricity_out'] = self.system_model.Outputs.gen + + # Flexible models must apply curtailment from the system-level + # controller's set-point at the end of compute(). This clips + # `{commodity}_out` to `min(uncurtailed, set_point)` and copies the + # raw output into `uncurtailed_{commodity}_out`. It is a no-op when + # no system-level controller is configured. + self.apply_curtailment(outputs) ``` ```{note} The `setup` method is where we initialize the PySAM model and set the solar resource data. We call the baseclass's `setup` method using the `super()` function, then added additional setup steps for the PySAM model. +The `compute` signature is `compute(self, inputs, outputs, discrete_inputs, discrete_outputs)` because performance models may use discrete I/O (e.g. resource data dictionaries). ``` +(required-class-attributes)= +#### Required class attributes + +Every performance model (whether it inherits from a category-specific baseclass like `SolarPerformanceBaseClass` or directly from `PerformanceModelBaseClass`) must define the following class attributes. These are typically set on the category baseclass so that all subclasses inherit them, but they can also be set or overridden on individual model classes. + +- `_control_classifier` (str): How the system-level controller (SLC) should treat this model. One of `"fixed"`, `"flexible"`, `"dispatchable"`, `"storage"`, or `"feedstock"`. The classifier determines whether the SLC sends a set-point to the model and how its output is folded into the dispatch logic. See the {ref}`control classifier docs ` (`docs/control/system_level_control/control_classifier.md`) for details. +- `_time_step_bounds` (tuple[int, int]): `(min, max)` simulation time-step lengths (in seconds) the model can run at. Use `(3600, 3600)` for hourly-only models and a wider range (e.g. `(300, 3600)`) for models that support sub-hourly time steps. The plant simulation `dt` must lie within every model's bounds. +- `commodity` (str), `commodity_rate_units` (str), `commodity_amount_units` (str): set in `initialize()` (or before calling `super().setup()`). These define the commodity produced by the model and the units used for its rate (e.g. `"kW"`, `"kg/h"`) and cumulative amount (e.g. `"kW*h"`, `"kg"`). `PerformanceModelBaseClass.setup()` uses them to register all of the standard outputs and will raise `NotImplementedError` if any are missing. + +For `flexible` models specifically, the baseclass automatically registers the `{commodity}_set_point` input and `uncurtailed_{commodity}_out` output, and the `compute()` method must call `self.apply_curtailment(outputs)` after writing the raw production to `outputs[f"{commodity}_out"]`. For `dispatchable` models the set-point is consumed by the model's own internal logic; no curtailment helper is needed. `fixed` and `feedstock` models do not receive a set-point at all. + 3. **Write the cost model for your technology.** The process for writing a cost model is similar to the performance model, with the required inputs and outputs defined in the technology cost model baseclass. The technology cost model baseclass should inherit the main cost model baseclass (`CostModelBaseClass`) with additional inputs, outputs, and setup added as necessary. The `CostModelBaseClass` has no predefined inputs, but all cost models must output `CapEx`, `OpEx`, and `cost_year`. @@ -151,10 +195,10 @@ class ATBUtilityPVCostModel(CostModelBaseClass): outputs["OpEx"] = opex ``` -4. **Write the control model for your technology.** -For this simplistic case, we will skip the control model because controls models can currently only be added to -storage technologies. The process for writing a control model is similar to the performance model, with the -required inputs and outputs defined in the baseclass. +4. **Write the control model for your technology (optional).** +Every technology group in H2Integrate contains a controller subsystem that converts a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the performance model. If you do not specify a `control_strategy` for your technology, H2Integrate automatically inserts a `PassthroughController` that simply copies demand to set-point, so most new performance models do not need a custom controller. + +You only need to write a control model if you want to override that default — for example, to implement a heuristic or optimized dispatch strategy for a storage technology. The process is similar to the performance model: the controller's required inputs and outputs (`{commodity}_demand` in, `{commodity}_set_point` out) are defined in the relevant control baseclass. See the [technology-level control overview](../control/technology_level_control/technology_control_overview.md) for available frameworks and supported controllers. 5. **Next, add the new technology to the `supported_models.py` file.** This file contains a dictionary of all the available technologies in H2Integrate. @@ -259,7 +303,8 @@ This would require additional logic to first check if the cached object exists a There is an example of this in the `hopp_wrapper.py` file. ### Specifying allowable time step for your model -If you want your model to run with time steps other than 1 hour (3600 s), then you must specify the `_time_step_bounds` as a class attribute in each of your model classes. To run a simulation with a given time step, all models in the plant must be compatible with the desired time step. + +`_time_step_bounds` is a required class attribute (see [Required class attributes](#required-class-attributes)). The default category baseclasses use `(3600, 3600)` (hourly timestep only). If your underlying model supports sub-hourly or multi-hour simulation, set `_time_step_bounds` on your subclass: ```python class ECOElectrolyzerPerformanceModel(ElectrolyzerPerformanceBaseClass): @@ -272,6 +317,8 @@ class ECOElectrolyzerPerformanceModel(ElectrolyzerPerformanceBaseClass): _time_step_bounds = (300, 3600) # (5-min, 1-hour) ``` +To run a simulation with a given time step, every model in the plant must be compatible with the desired `dt` set in `plant_config`. + ### Other cases If you encounter a case that isn't covered here, please discuss it with the H2Integrate dev team for guidance. From d1da302d0b395572d2c9bd4680a4cc10cb32c2fd Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 13:25:40 -0600 Subject: [PATCH 112/132] Merging --- docs/developer_guide/adding_a_new_technology.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/developer_guide/adding_a_new_technology.md b/docs/developer_guide/adding_a_new_technology.md index 73f5d613f..86924c747 100644 --- a/docs/developer_guide/adding_a_new_technology.md +++ b/docs/developer_guide/adding_a_new_technology.md @@ -289,9 +289,6 @@ for tech_name, individual_tech_config in self.technology_config['technologies']. else: tech_group = self.plant.add_subsystem(tech_name, om.Group()) self.tech_names.append(tech_name) - - # Special HOPP handling for short-term - if tech_name in combined_performance_and_cost_model_technologies: ``` There are also situations where the models are still related but can be treated separately. From fa9ef619d901250fd210513ee3b0e812398ab6e8 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 14:31:12 -0600 Subject: [PATCH 113/132] Updated control classifier docs --- .../control_classifier.md | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/docs/control/system_level_control/control_classifier.md b/docs/control/system_level_control/control_classifier.md index 17a09413a..b670b6935 100644 --- a/docs/control/system_level_control/control_classifier.md +++ b/docs/control/system_level_control/control_classifier.md @@ -13,8 +13,8 @@ We have identified five key classifiers that are able to represent the different Classifier | Meaning | Example Technology Models -- | -- | -- fixed | Always produces commodity and cannot be controlled or reduced; does not receive a set-point | classical nuclear -flexible | Produces based on resource; can only reduce (curtail) from the maximum generation based on available resource | wind, solar -dispatchable | Can modulate consumption/production within bounds; receives a commodity set-point | grid, electrolyzer, NG turbine +flexible | Resource-driven; can only be *reduced* (curtailed) below the resource-determined maximum via a set-point | wind, solar +dispatchable | Can modulate production within bounds in response to a set-point | grid, electrolyzer, NG turbine storage | Can modulate consumption/production within bounds while tracking SOC | battery, h2 storage, any storage feedstock | Are not directly controlled, but useful for SLC to make dispatch decisions | feedstocks @@ -23,11 +23,19 @@ To add a classifier for a particular model it would look something like this in _control_classifier = "flexible" ``` +```{note} +**Flexible vs. dispatchable.** Both classifiers receive a `{commodity}_set_point` from the system-level controller, so the distinction is about *what the set-point can do*. A flexible model is a strictly more restricted case of a dispatchable one: the set-point can only *cap* the output below whatever the underlying resource (sun, wind, etc.) makes available. A dispatchable model, by contrast, can be ramped up or down anywhere within its operating bounds in direct response to the set-point. +``` + ## Fixed -A fixed performance model represents anything that always produces at its rated capacity and cannot be controlled or reduced by the system level controller. The SLC reads the output from a fixed technology and subtracts it from the demand, but does not send a set-point back to the technology. A good example of this is a classical nuclear plant model — it produces a constant output that the rest of the system must accommodate. +A fixed performance model represents anything that always produces at its rated capacity and cannot be controlled or reduced by the system level controller. The SLC reads the output from a fixed technology and subtracts it from the demand, but does not send a set-point back to the technology. A good example of this is a classical nuclear plant model: it produces a constant output that the rest of the system must accommodate. ## Flexible -A flexible performance model represents anything that can have the output reduced based on a given set point from the system level controller. A good example of this is the PVWatts PySAM solar plant in H2I; the performance of the system is based on the input solar resource. The solar performance does not change based on, for example, an updated set point to the panel tracking software. However, we could limit the power output from the solar performance model based on a given demand set point. To simplify the implementation of applying this curtailment or reduction based on a set point we added a method, `apply_curtailment()` to the `PerformanceBaseClass`. +A flexible performance model represents anything whose production is determined by an external resource (e.g., wind speed, solar irradiance) and that can only be *reduced* below that resource-determined maximum and never increased above it. The system-level controller sends a `{commodity}_set_point` that acts as an upper bound: when the resource-driven output exceeds the set-point, output is curtailed down to the set-point; otherwise, output is left at the resource-driven value. A good example is the PVWatts PySAM solar plant in H2I; its performance is a function of the input solar resource, and we cannot tell the sun to shine more, but we can curtail the panel output below the available solar production. + +In other words, flexible is a strictly more restricted case of [dispatchable](#dispatchable): a dispatchable model can be ramped both up and down in response to a set-point, while a flexible model can only be ramped down. + +To simplify the implementation of applying this curtailment we added a method, `apply_curtailment()`, to the `PerformanceBaseClass`. ```{figure} figures/curtailable.png :width: 70% @@ -39,10 +47,13 @@ Within the `compute()` method in the performance model you can apply the curtail ``` self.apply_curtailment(outputs) ``` -which, applies curtailment to `{commodity}_out` based on `{commodity}_set_point`. This adds `uncurtailed_{commodity}_out` and `{commodity}_out` as outputs from the performance model. +which applies curtailment to `{commodity}_out` based on `{commodity}_set_point`. This adds `uncurtailed_{commodity}_out` and `{commodity}_out` as outputs from the performance model. +(dispatchable)= ## Dispatchable -A dispatchable performance model represents anything that can receive a set point. Any model that has the "dispatchable" control classifier tag is able to receive a set point and change it's behavior based on that set point. There aren't additional special methods to handle this because it's internal to each performance model. +A dispatchable performance model represents anything that can be ramped both *up and down* within its operating bounds in response to a `{commodity}_set_point` from the system-level controller. Unlike a [flexible](#flexible) model, the set-point for a dispatchable model can request any production level within the model's rated capacity (and minimum load, if applicable), and the model will produce at that level. Examples include a grid connection, an electrolyzer, or a natural-gas turbine. + +There aren't additional special methods to handle this because the set-point response is internal to each performance model. ```{figure} figures/dispatchable.png :width: 70% @@ -66,4 +77,6 @@ The system-level controller outputs set points to the storage performance model ``` ## Feedstock -The feedstocks category is unique in that they are considered outside of the controllable system within H2I. While they can't be controlled, it can be helpful for controllers to know how much feedstock is available within the system, hence their classification. +Feedstocks represent commodity *inputs* to the controllable system: they are consumed by other technologies but their availability is not itself something the controller can adjust. Although feedstocks themselves cannot be dispatched, knowing how much of each feedstock is available is valuable information for more advanced controllers, since feedstock supply can constrain what the controllable technologies are actually able to produce. + +For example, consider an ammonia plant that consumes both hydrogen and nitrogen. If the nitrogen feedstock supply is insufficient to meet the ammonia demand, the ammonia output is capped by the nitrogen availability regardless of how much hydrogen and electricity are produced. A controller that is aware of the nitrogen feedstock can recognize that the ammonia demand cannot be met, and can adjust the set-points for the hydrogen and electricity technologies accordingly (e.g., avoiding over-production of hydrogen that would otherwise go unused). This is why feedstocks are classified separately rather than being ignored by the controller: they are uncontrollable, but they are not irrelevant. From 74cf0770e80d2f9f9ee76c65951e501fc379f8cd Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 3 Jun 2026 14:53:59 -0600 Subject: [PATCH 114/132] Removing now-defunct storage_techs_to_control parameter --- .../system_level/system_level_control_base.py | 28 +++--------- .../system_level/test/test_slc_controllers.py | 7 --- h2integrate/core/h2integrate_model.py | 45 +++++++++---------- 3 files changed, 27 insertions(+), 53 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 95e772748..7c4f7b9f4 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -24,14 +24,11 @@ class SystemLevelControlBase(om.ExplicitComponent): - ``demand_commodity``: the commodity being controlled (e.g. "electricity") - ``demand_commodity_rate_units``: units string (or None) of the demand commodity - ``demand_tech``: name of the demand technology - - ``storage_techs_to_control``: dictionary with keys of the technology names. The value is True - if the technology is classified as "storage" and has an attached controller. - Otherwise the value is False. - ``technology_graph``: directional graph object representation of the technology_interconnections found in the ``plant_config`` - ``tech_to_commodity``: set of tuples formatted as (tech_name, tech_output_commodity) - - ``tech_control_classifiers``: dictionary of technologies with keys as the technology names the - value as the corresponding control classifier + - ``tech_control_classifiers``: dictionary of technologies with key-value pairs of each + technology name and its corresponding control classifier. Controller-specific configuration parameters may be read from ``plant_config["system_level_control"]["control_parameters"]`` @@ -53,7 +50,6 @@ def setup(self): self.commodity = slc_config["demand_commodity"] self.commodity_rate_units = slc_config.get("demand_commodity_rate_units", None) self.demand_tech = slc_config["demand_tech"] - self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] self.fixed_techs = [ @@ -455,21 +451,11 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if demand_name not in outputs: return - if self.storage_techs_to_control.get(storage_tech, False): - # Storage tech has its own sub-controller: emit a combined demand - # signal (always positive) equal to the commodity flowing into - # storage from upstream techs plus any remaining demand. - upstream_techs = self.get_upstream_techs_for_commodity(storage_tech, commodity) - commodity_into_storage = np.zeros(self.n_timesteps) - for tech_name in upstream_techs: - commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] - - outputs[demand_name] = commodity_into_storage + remaining_demand - else: - # Storage without a sub-controller: emit a charge/discharge - # command directly. Charge when remaining demand is negative, - # discharge when positive. - outputs[demand_name] = remaining_demand + # Emit a signed charge/discharge demand signal: charge when remaining + # demand is negative, discharge when positive. The storage tech's + # controller (passthrough by default) forwards this to the performance + # model, which interprets the sign as charge or discharge. + outputs[demand_name] = remaining_demand remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index 2c416f4e0..036e7ee40 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -66,7 +66,6 @@ def _build_slc_config( demand_tech: str = "demand", demand_commodity: str = "electricity", demand_commodity_rate_units: str = "kW", - storage_techs_with_control: list = [], ): sources_to_commodities = { (e[0], e[-1]) for e in technology_graph.edges(data="commodity") if e[-1] is not None @@ -76,17 +75,11 @@ def _build_slc_config( (e[0], e[-1]) for e in sources_to_commodities if e[0] in tech_control_classifiers } - storage_techs = [k for k, v in tech_control_classifiers.items() if v == "storage"] - storage_techs_to_control = { - k: True if k in storage_techs_with_control else False for k in storage_techs - } - slc_config = { "demand_commodity": demand_commodity, "demand_commodity_rate_units": demand_commodity_rate_units, "demand_tech": demand_tech, "tech_to_commodity": tech_to_commodities, - "storage_techs_to_control": storage_techs_to_control, "technology_graph": technology_graph, "tech_control_classifiers": tech_control_classifiers, } diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 8567df639..9575e5855 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -486,13 +486,26 @@ def _classify_slc_technologies(self): Returns: dict: Classification dictionary (``slc_config``) with keys: - - ``"demand_tech"`` (str) - - ``"demand_commodity"`` (str) - - ``"demand_commodity_rate_units"`` (str | None) - - ``"tech_to_commodity"`` (set[tuple[str, str]]) - - ``"storage_techs_to_control"`` (dict[str, bool]) - - ``"technology_graph"`` (nx.DiGraph) - - ``"tech_control_classifiers"`` (dict[str, str]) + - ``"demand_tech"`` (str): Name of the demand technology (the tech whose + performance model is a ``DemandComponent``). + - ``"demand_commodity"`` (str): Commodity the demand technology consumes + (e.g. ``"electricity"``, ``"hydrogen"``). + - ``"demand_commodity_rate_units"`` (str | None): Units string for the + demand commodity rate (e.g. ``"kW"``, ``"kg/h"``), or ``None`` if not + specified in the demand tech config. + - ``"tech_to_commodity"`` (set[tuple[str, str]]): Set of + ``(tech_name, commodity)`` pairs for every technology that the SLC + controls or reads from. Built from outgoing edges of the technology + graph and filtered to fixed, flexible, dispatchable, storage, and + feedstock classifiers. + - ``"technology_graph"`` (nx.DiGraph): Directed graph of technology + interconnections, with edge attribute ``commodity`` indicating the + commodity carried on each edge. Used by cost-aware controllers to + trace upstream feedstocks. + - ``"tech_control_classifiers"`` (dict[str, str]): Mapping of tech name + to its ``_control_classifier`` (one of ``"fixed"``, ``"flexible"``, + ``"dispatchable"``, ``"storage"``, ``"feedstock"``). Determines how + the SLC interacts with each tech. """ slc_config = {} technologies = self.technology_config.get("technologies", {}) @@ -558,21 +571,6 @@ def _classify_slc_technologies(self): if e[-1] is not None } - # Check if storage models have a controller - storage_tech_to_control = {} - for tech, classifier in self.tech_control_classifiers.items(): - if classifier == "storage": - control_model = ( - self.technology_config["technologies"][tech] - .get("control_strategy", {}) - .get("model", None) - ) - if control_model is None: - storage_tech_to_control[tech] = False - else: - # storage model does use a controller - storage_tech_to_control[tech] = True - # Remove feedstocks and connectors control_classifiers_to_connect = [ "fixed", @@ -592,7 +590,6 @@ def _classify_slc_technologies(self): slc_config["demand_commodity"] = demand_commodity slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units slc_config["tech_to_commodity"] = tech_to_commodity - slc_config["storage_techs_to_control"] = storage_tech_to_control slc_config["technology_graph"] = self.technology_graph slc_config["tech_control_classifiers"] = self.tech_control_classifiers @@ -673,8 +670,6 @@ def add_system_level_controller(self, slc_config): - ``"tech_control_classifiers"`` (dict[str, str]): Mapping of tech name to classifier (``"fixed"``, ``"flexible"``, ``"dispatchable"``, ``"storage"``, ``"feedstock"``). - - ``"storage_techs_to_control"`` (dict[str, bool]): Whether each storage tech - has its own sub-controller. - ``"technology_graph"`` (nx.DiGraph): Directed graph of technology interconnections. From 60a9355598ff784a503a5cc7f933599d317666f2 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 4 Jun 2026 12:01:07 -0600 Subject: [PATCH 115/132] Updating SLC plots and docstrings --- .../run_wind_ng_demand.py | 24 ++++++----- .../run_complex_profit_max.py | 40 ++++++++++--------- .../no_battery/run_wind_ng_demand.py | 32 +++++++++------ .../profit_maximization/run_profit_max.py | 24 ++++++----- .../yes_battery/run_wind_ng_demand.py | 24 ++++++----- .../system_level/cost_minimization_control.py | 16 ++++++-- .../profit_maximization_control.py | 22 +++++++--- .../system_level/system_level_control_base.py | 25 ++++++++++-- 8 files changed, 130 insertions(+), 77 deletions(-) diff --git a/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py b/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py index b536e660b..e3eedabbd 100644 --- a/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py +++ b/examples/35_system_level_control/battery_with_controller/run_wind_ng_demand.py @@ -27,23 +27,25 @@ fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True) -# Stacked area: wind + battery discharge + NG = total supply -axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") -axes[0].fill_between( +# Stacked bar chart: wind + battery discharge + NG = total supply +axes[0].bar(hours, wind_out, width=1.0, color="tab:blue", label="Wind", align="edge") +axes[0].bar( hours, - wind_out, - wind_out + batt_discharge, - alpha=0.7, + batt_discharge, + width=1.0, + bottom=wind_out, color="tab:purple", label="Battery Discharge", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - wind_out + batt_discharge, - wind_out + batt_discharge + ng_out, - alpha=0.7, + ng_out, + width=1.0, + bottom=wind_out + batt_discharge, color="tab:orange", label="Natural Gas", + align="edge", ) axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") axes[0].set_ylabel("Power (kW)") @@ -53,7 +55,7 @@ axes[1].plot(hours, batt_soc, color="tab:cyan") axes[1].set_ylabel("Battery SOC (%)") -axes[2].plot(hours, curtailed, color="tab:red") +axes[2].bar(hours, curtailed, width=1.0, color="tab:red", align="edge") axes[2].set_ylabel("Curtailed (kW)") axes[2].set_xlabel("Hour") diff --git a/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py index 1ca78c9d8..bc14cf238 100644 --- a/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py +++ b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py @@ -117,39 +117,43 @@ # --------------------------------------------------------------------------- fig, axes = plt.subplots(5, 1, figsize=(16, 16), sharex=True) -# Panel 1: stacked supply vs demand -axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") -axes[0].fill_between( +# Panel 1: stacked bar supply vs demand +axes[0].bar(hours, wind_out, width=1.0, color="tab:blue", label="Wind", align="edge") +axes[0].bar( hours, - wind_out, - wind_out + solar_out, - alpha=0.7, + solar_out, + width=1.0, + bottom=wind_out, color="gold", label="Solar", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - wind_out + solar_out, - wind_out + solar_out + batt_discharge, - alpha=0.7, + batt_discharge, + width=1.0, + bottom=wind_out + solar_out, color="tab:purple", label="Battery", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - wind_out + solar_out + batt_discharge, - wind_out + solar_out + batt_discharge + ng_out, - alpha=0.7, + ng_out, + width=1.0, + bottom=wind_out + solar_out + batt_discharge, color="tab:orange", label="Natural Gas", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - wind_out + solar_out + batt_discharge + ng_out, - wind_out + solar_out + batt_discharge + ng_out + grid_out, - alpha=0.7, + grid_out, + width=1.0, + bottom=wind_out + solar_out + batt_discharge + ng_out, color="tab:gray", label="Grid Buy", + align="edge", ) axes[0].plot(hours, demand, "k--", linewidth=1.5, label="Demand") axes[0].set_ylabel("Power (kW)") diff --git a/examples/35_system_level_control/no_battery/run_wind_ng_demand.py b/examples/35_system_level_control/no_battery/run_wind_ng_demand.py index f4be3e869..38a7b16c4 100644 --- a/examples/35_system_level_control/no_battery/run_wind_ng_demand.py +++ b/examples/35_system_level_control/no_battery/run_wind_ng_demand.py @@ -23,21 +23,27 @@ ng_out = h2i.prob.get_val("plant.natural_gas_plant.electricity_out", units="kW")[:n_hours] curtailed = h2i.prob.get_val("plant.electrical_load_demand.unused_electricity_out")[:n_hours] -fig, axes = plt.subplots(4, 1, figsize=(12, 10), sharex=True) - -axes[0].plot(hours, demand, color="black") -axes[0].set_ylabel("Demand (kW)") +fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True) + +# Stacked bar chart of supply per hour with demand overlay +axes[0].bar(hours, wind_out, width=1.0, color="tab:blue", label="Wind", align="edge") +axes[0].bar( + hours, + ng_out, + width=1.0, + bottom=wind_out, + color="tab:orange", + label="Natural Gas", + align="edge", +) +axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") +axes[0].set_ylabel("Power (kW)") axes[0].set_title("System-Level Control: First 100 Hours") +axes[0].legend(loc="upper right") -axes[1].plot(hours, wind_out, color="tab:blue") -axes[1].set_ylabel("Wind (kW)") - -axes[2].plot(hours, ng_out, color="tab:orange") -axes[2].set_ylabel("Natural Gas (kW)") - -axes[3].plot(hours, curtailed, color="tab:red") -axes[3].set_ylabel("Curtailed (kW)") -axes[3].set_xlabel("Hour") +axes[1].bar(hours, curtailed, width=1.0, color="tab:red", align="edge") +axes[1].set_ylabel("Curtailed (kW)") +axes[1].set_xlabel("Hour") for ax in axes: ax.grid(True, alpha=0.3) diff --git a/examples/35_system_level_control/profit_maximization/run_profit_max.py b/examples/35_system_level_control/profit_maximization/run_profit_max.py index 2795e3361..1c1b4cbfa 100644 --- a/examples/35_system_level_control/profit_maximization/run_profit_max.py +++ b/examples/35_system_level_control/profit_maximization/run_profit_max.py @@ -36,23 +36,25 @@ # -- Plot -- fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True) -# Panel 1: stacked supply vs demand -axes[0].fill_between(hours, 0, ng_out, alpha=0.7, color="tab:orange", label="Natural Gas") -axes[0].fill_between( +# Panel 1: stacked bar supply vs demand +axes[0].bar(hours, ng_out, width=1.0, color="tab:orange", label="Natural Gas", align="edge") +axes[0].bar( hours, - ng_out, - ng_out + batt_discharge, - alpha=0.7, + batt_discharge, + width=1.0, + bottom=ng_out, color="tab:purple", label="Battery Discharge", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - ng_out + batt_discharge, - ng_out + batt_discharge + wind_out, - alpha=0.7, + wind_out, + width=1.0, + bottom=ng_out + batt_discharge, color="tab:blue", label="Wind", + align="edge", ) axes[0].plot(hours, demand, "k--", linewidth=1.5, label="Demand") axes[0].set_ylabel("Power (kW)") @@ -72,7 +74,7 @@ axes[2].legend(loc="upper right") # Panel 4: curtailed energy -axes[3].plot(hours, curtailed, color="tab:gray") +axes[3].bar(hours, curtailed, width=1.0, color="tab:gray", align="edge") axes[3].set_ylabel("Curtailed (kW)") axes[3].set_xlabel("Hour") axes[3].set_title("Curtailed Electricity") diff --git a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py index b536e660b..e3eedabbd 100644 --- a/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py +++ b/examples/35_system_level_control/yes_battery/run_wind_ng_demand.py @@ -27,23 +27,25 @@ fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True) -# Stacked area: wind + battery discharge + NG = total supply -axes[0].fill_between(hours, 0, wind_out, alpha=0.7, color="tab:blue", label="Wind") -axes[0].fill_between( +# Stacked bar chart: wind + battery discharge + NG = total supply +axes[0].bar(hours, wind_out, width=1.0, color="tab:blue", label="Wind", align="edge") +axes[0].bar( hours, - wind_out, - wind_out + batt_discharge, - alpha=0.7, + batt_discharge, + width=1.0, + bottom=wind_out, color="tab:purple", label="Battery Discharge", + align="edge", ) -axes[0].fill_between( +axes[0].bar( hours, - wind_out + batt_discharge, - wind_out + batt_discharge + ng_out, - alpha=0.7, + ng_out, + width=1.0, + bottom=wind_out + batt_discharge, color="tab:orange", label="Natural Gas", + align="edge", ) axes[0].plot(hours, demand, color="black", linewidth=1.5, linestyle="--", label="Demand") axes[0].set_ylabel("Power (kW)") @@ -53,7 +55,7 @@ axes[1].plot(hours, batt_soc, color="tab:cyan") axes[1].set_ylabel("Battery SOC (%)") -axes[2].plot(hours, curtailed, color="tab:red") +axes[2].bar(hours, curtailed, width=1.0, color="tab:red", align="edge") axes[2].set_ylabel("Curtailed (kW)") axes[2].set_xlabel("Hour") diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 27818ce65..1af7e0eed 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -20,9 +20,19 @@ class CostMinimizationControl(SystemLevelControlBase): ``system_level_control["control_parameters"]`` section of ``plant_config``. Each dispatchable technology's entry can be: - - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) - - ``"buy_price"`` - use the technology's purchase price - - ``"VarOpEx"`` - derive from VarOpEx / total production + - A numeric value (``$/(commodity_rate_unit*h)``, e.g. ``0.05`` for + ``$0.05/kWh``) used directly as a constant marginal cost. + - ``"buy_price"`` - use the technology's own purchase price input + (e.g. ``electricity_buy_price`` for a Grid tech, ``price`` for a + Feedstock tech). The default is read from the tech's cost config + and may be overridden at runtime via ``prob.set_val()``. + - ``"VarOpEx"`` - derive the marginal cost from the technology's own + ``VarOpEx`` output divided by its annualized total production. + - ``"feedstock"`` - sum the ``VarOpEx`` of all feedstock technologies + that are upstream of the dispatchable tech in + ``technology_interconnections`` (using graph ancestors, so feedstocks + behind intermediate components like combiners are included), and + divide by the dispatchable tech's annualized total production. """ def setup(self): diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 39d06e152..9275c0fc4 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -28,18 +28,28 @@ class ProfitMaximizationControl(SystemLevelControlBase): Demand may go unmet if dispatch is unprofitable. Configuration: - ``plant_config["system_level_control"]["commodity_sell_price"]`` - must be set as either a numeric value ($/(commodity_rate_unit*h), - e.g. $/kWh) or the name of a finance group (e.g. ``"profast_npv"``) + ``plant_config["system_level_control"]["control_parameters"]["commodity_sell_price"]`` + must be set as either a numeric value (``$/(commodity_rate_unit*h)``, + e.g. ``$/kWh``) or the name of a finance group (e.g. ``"profast_npv"``) whose ``model_inputs.commodity_sell_price`` will be used. Marginal costs are configured via ``cost_per_tech`` in the ``system_level_control["control_parameters"]`` section of ``plant_config``. Each dispatchable technology's entry can be: - - A numeric value ($/commodity_unit, e.g. 0.05 for $0.05/kWh) - - ``"buy_price"`` — use the technology's purchase price - - ``"VarOpEx"`` — derive from VarOpEx / total production + - A numeric value (``$/(commodity_rate_unit*h)``, e.g. ``0.05`` for + ``$0.05/kWh``) used directly as a constant marginal cost. + - ``"buy_price"`` — use the technology's own purchase price input + (e.g. ``electricity_buy_price`` for a Grid tech, ``price`` for a + Feedstock tech). The default is read from the tech's cost config + and may be overridden at runtime via ``prob.set_val()``. + - ``"VarOpEx"`` — derive the marginal cost from the technology's own + ``VarOpEx`` output divided by its annualized total production. + - ``"feedstock"`` — sum the ``VarOpEx`` of all feedstock technologies + that are upstream of the dispatchable tech in + ``technology_interconnections`` (using graph ancestors, so feedstocks + behind intermediate components like combiners are included), and + divide by the dispatchable tech's annualized total production. """ def _resolve_sell_price(self, config): diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 7c4f7b9f4..8abcdcb6d 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -7,8 +7,9 @@ class SystemLevelControlBase(om.ExplicitComponent): """Base class for system-level controllers. Provides common setup logic shared by all system-level control strategies: - demand input, fixed/flexible/dispatchable/storage technology I/O creation, - and technology classification reading from ``plant_config`` and ``slc_config`` + demand input, fixed/flexible/dispatchable/storage/feedstock technology I/O + creation, and technology classification reading from ``plant_config`` and + ``slc_config``. Subclasses must implement ``compute()`` with their dispatch strategy. @@ -28,10 +29,26 @@ class SystemLevelControlBase(om.ExplicitComponent): technology_interconnections found in the ``plant_config`` - ``tech_to_commodity``: set of tuples formatted as (tech_name, tech_output_commodity) - ``tech_control_classifiers``: dictionary of technologies with key-value pairs of each - technology name and its corresponding control classifier. + technology name and its corresponding control classifier (one of + ``"fixed"``, ``"flexible"``, ``"dispatchable"``, ``"storage"``, or + ``"feedstock"``). Controller-specific configuration parameters may be read from - ``plant_config["system_level_control"]["control_parameters"]`` + ``plant_config["system_level_control"]["control_parameters"]``. + + Cost-aware subclasses (e.g. ``CostMinimizationControl``, + ``ProfitMaximizationControl``) call ``_setup_marginal_costs()`` to register + marginal-cost inputs for each dispatchable technology based on the + ``cost_per_tech`` mapping. Supported values per dispatchable tech are: + + - A numeric value (constant marginal cost in ``$/(commodity_rate_unit*h)``). + - ``"buy_price"`` — use the technology's own purchase price input. + - ``"VarOpEx"`` — derive marginal cost from the tech's own ``VarOpEx`` + divided by its annualized total production. + - ``"feedstock"`` — sum ``VarOpEx`` from all feedstock technologies + upstream of the tech in ``technology_interconnections`` (graph + ancestors, so feedstocks behind intermediate components are included) + and divide by the dispatchable tech's annualized total production. """ def initialize(self): From 0022143344eca96dd243b691ca633f6f60b06563 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 4 Jun 2026 13:08:10 -0600 Subject: [PATCH 116/132] Adding curtailment to more techs --- docs/control/system_level_control/system_level_control.md | 4 ++++ h2integrate/converters/hopp/hopp_wrapper.py | 5 +++++ .../converters/water_power/hydro_plant_run_of_river.py | 4 ++++ h2integrate/converters/water_power/tidal_pysam.py | 4 ++++ h2integrate/converters/wind/wind_plant_ard.py | 4 ++++ 5 files changed, 21 insertions(+) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 66bec95ab..6f26f4e95 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -2,6 +2,10 @@ System-level control (SLC) within H2I is meant to operate to control the entire plant with performance and cost feedback driving the operation of the plant or system in a closed-loop. It acts as a supervisory controller meaning that it can work to coordinate the entire system and can work with other technology level controllers. +```{note} +The SLC framework is *technology-agnostic* and works with any H2I technology (converters, storage, feedstocks, demand components, etc.). It only cares about a technology's [`_control_classifier`](control_classifier.md) and the commodity it produces. To opt a technology in, set `_control_classifier` on its performance model; for `flexible` models, also call `self.apply_curtailment(outputs)` at the end of `compute()`. See the [developer guide on adding a new technology](../../developer_guide/adding_a_new_technology.md) for the full checklist. +``` + The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_demand` signal to each controlled technology. Each technology group contains a controller that converts that demand into the `{commodity}_set_point` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the set-point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the demands in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. ```{note} diff --git a/h2integrate/converters/hopp/hopp_wrapper.py b/h2integrate/converters/hopp/hopp_wrapper.py index 994ae6cfc..06c4b55c8 100644 --- a/h2integrate/converters/hopp/hopp_wrapper.py +++ b/h2integrate/converters/hopp/hopp_wrapper.py @@ -204,5 +204,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): outputs["power_capacity_to_interconnect_ratio"] = total_power_capacity / interconnect_kw + # Honor a system-level controller's set-point by curtailing + # `electricity_out`. Done before caching so cached outputs already + # reflect the post-curtailment values for this set point. + self.apply_curtailment(outputs) + # Cache the results for future use if enabled self.cache_outputs(inputs, outputs, discrete_inputs) diff --git a/h2integrate/converters/water_power/hydro_plant_run_of_river.py b/h2integrate/converters/water_power/hydro_plant_run_of_river.py index a7034046b..56de3b8cf 100644 --- a/h2integrate/converters/water_power/hydro_plant_run_of_river.py +++ b/h2integrate/converters/water_power/hydro_plant_run_of_river.py @@ -86,6 +86,10 @@ def compute(self, inputs, outputs): max_production = plant_capacity_kw * self.n_timesteps * (self.dt / 3600) outputs["capacity_factor"] = outputs["total_electricity_produced"].sum() / max_production + # Honor a system-level controller's set-point by curtailing + # `electricity_out`. No-op when there is no system-level controller. + self.apply_curtailment(outputs) + @define(kw_only=True) class RunOfRiverHydroCostConfig(CostModelBaseConfig): diff --git a/h2integrate/converters/water_power/tidal_pysam.py b/h2integrate/converters/water_power/tidal_pysam.py index 6c245ec8b..41ef504d4 100644 --- a/h2integrate/converters/water_power/tidal_pysam.py +++ b/h2integrate/converters/water_power/tidal_pysam.py @@ -229,3 +229,7 @@ def compute(self, inputs, outputs): outputs["capacity_factor"] = ( self.system_model.Outputs.capacity_factor / 100 ) # divide by 100 to make it unitless + + # Honor a system-level controller's set-point by curtailing + # `electricity_out`. No-op when there is no system-level controller. + self.apply_curtailment(outputs) diff --git a/h2integrate/converters/wind/wind_plant_ard.py b/h2integrate/converters/wind/wind_plant_ard.py index 929f0b0a9..3b05d10f9 100644 --- a/h2integrate/converters/wind/wind_plant_ard.py +++ b/h2integrate/converters/wind/wind_plant_ard.py @@ -86,6 +86,10 @@ def compute(self, inputs, outputs): outputs["rated_electricity_production"] = self.plant_rating_kw outputs["capacity_factor"] = aep / self.plant_capacity + # Honor a system-level controller's set-point by curtailing + # `electricity_out`. No-op when there is no system-level controller. + self.apply_curtailment(outputs) + class WindArdCostCompatibilityComponent(CostModelBaseClass): """The class is needed to allow connecting the Ard cost_year easily in H2Integrate. From d38dc79af97ada3dd2cdfd33aac4e50a8551f4d3 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 4 Jun 2026 22:29:08 -0600 Subject: [PATCH 117/132] Updated SLC battery example regression value --- .../control_strategies/system_level/test/test_slc_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 0b341f0d8..c1dca6375 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -213,7 +213,7 @@ def test_slc_battery_with_controller(subtests, temp_copy_of_example): model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), rel=1e-6, ) - == 0.10902004 + == 0.10710679575878151 ) From 9ecca8deebc8b6a723b715db6156fdaa485426b2 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Mon, 8 Jun 2026 10:13:46 -0600 Subject: [PATCH 118/132] Adding notes that just one demand component is allowed now --- .../system_level_control/system_level_control.md | 6 +++++- .../system_level_control_base.md | 4 ++++ .../system_level/system_level_control_base.py | 4 ++++ h2integrate/core/h2integrate_model.py | 14 ++++++++++---- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 6f26f4e95..23fc99b1b 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -12,6 +12,10 @@ The most basic SLC is shown in the figure below, where the SLC receives a demand Every technology group has an *implicit passthrough controller* that converts `{commodity}_demand` into `{commodity}_set_point`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the demand → set-point hand-off uniform for every technology, regardless of whether an SLC is present. ``` +```{important} +SLC demand is set by connecting a demand component (for example, `GenericDemandComponent`) to the system. When SLC is enabled, only one demand component is currently supported. +``` + ```{figure} figures/slc_basic.png :width: 70% :align: center @@ -28,7 +32,7 @@ system_level_control: convergence_tolerance: 1.0e-6 ``` -To set the demand for the SLC that is configured in the `tech_config.yaml` using a demand block/component. For example: +To set the demand for SLC, define exactly one demand block/component in `tech_config.yaml`. For example: ```yaml electrical_load_demand: diff --git a/docs/control/system_level_control/system_level_control_base.md b/docs/control/system_level_control/system_level_control_base.md index bee202706..7319cad36 100644 --- a/docs/control/system_level_control/system_level_control_base.md +++ b/docs/control/system_level_control/system_level_control_base.md @@ -3,6 +3,10 @@ The system-level control base class provides a common framework that all controllers (advanced control strategies) can use to configure required inputs and outputs for both the controllers and the components they control or track. This generalization is necessary to implement system-level control in H2I. If the technologies and controllers in a given system were fully specified, this base class would not be needed. +```{important} +SLC demand is supplied by a demand component. When SLC is enabled, only one demand component is currently supported. +``` + The base class also abstracts logic that may be shared across different controller types. It includes methods that could be useful, but not all methods will be relevant to every controller you implement. There are several methods that are already used in the simple controllers that inherit these system. diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 8abcdcb6d..11d20fb72 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -19,6 +19,10 @@ class SystemLevelControlBase(om.ExplicitComponent): system-level controller therefore reasons in terms of *demand* values and emits ``{tech_name}_{commodity}_demand`` outputs for every controlled technology. + The SLC demand signal is provided by a demand component (for example, + ``GenericDemandComponent``) connected by ``H2IntegrateModel``. When SLC is + enabled, only one demand component is currently supported. + Information passed to the controller from H2IntegrateModel is input in the ``slc_config``, which must contain: diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 9575e5855..5ed23e539 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -483,6 +483,10 @@ def _classify_slc_technologies(self): to partition technologies into fixed, flexible, dispatchable, and storage lists. Also identifies the single demand technology and its commodity. + SLC demand is supplied by a demand component (for example, + ``GenericDemandComponent``). When SLC is enabled, only one demand + component is currently supported. + Returns: dict: Classification dictionary (``slc_config``) with keys: @@ -528,9 +532,10 @@ def _classify_slc_technologies(self): # NOTE: this error should only be raised if two demand components # are in the tech connections raise ValueError( - "DemandFollowingControl currently supports only one demand " - f"stream, but found demands for both '{demand_commodity}' " - f"and '{all_params.get('commodity', tech_name)}'." + "System-level control currently supports only one demand " + "component, but multiple demand components were found " + f"for '{demand_commodity}' and " + f"'{all_params.get('commodity', tech_name)}'." ) demand_commodity = all_params["commodity"] @@ -657,7 +662,8 @@ def add_system_level_controller(self, slc_config): 5. **Connect the demand profile** - Connects the demand technology's output (``{demand_tech}.{demand_commodity}_demand_out``) to the controller's demand input - (``system_level_controller.{demand_commodity}_demand``). + (``system_level_controller.{demand_commodity}_demand``). This relies on the + current SLC constraint that exactly one demand component is defined. Args: slc_config (dict): Pre-computed dictionary produced by From 8767b4a5eb7e4239acaff0d797955830f424d233 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 9 Jun 2026 15:56:30 -0600 Subject: [PATCH 119/132] Dramatically refactoring, renaming controller based things throughout --- .../system_level_control.md | 4 +- .../technology_control_overview.md | 10 +-- .../passthrough_controller.py | 31 +++++---- .../demand_openloop_storage_controller.py | 6 +- .../storage/openloop_storage_control_base.py | 10 +-- .../plm_openloop_storage_controller.py | 6 +- .../storage/simple_openloop_controller.py | 8 +-- .../storage/test/test_openloop_controllers.py | 16 ++--- .../test_plm_openloop_storage_controller.py | 4 +- .../system_level/cost_minimization_control.py | 10 +-- .../system_level/demand_following_control.py | 6 +- .../profit_maximization_control.py | 8 +-- .../system_level/system_level_control_base.py | 53 +++++++------- .../system_level/test/test_slc_controllers.py | 52 +++++++------- .../system_level/test/test_slc_examples.py | 10 +-- h2integrate/converters/grid/grid.py | 10 +-- h2integrate/converters/grid/test/test_grid.py | 12 ++-- .../hydrogen/electrolyzer_baseclass.py | 2 +- .../converters/hydrogen/h2_fuel_cell.py | 12 ++-- .../converters/hydrogen/pem_electrolyzer.py | 2 +- .../hydrogen/steam_methane_reformer.py | 16 ++--- .../hydrogen/test/test_h2_fuel_cell.py | 6 +- h2integrate/converters/iron/iron_dri_base.py | 12 ++-- .../converters/iron/martin_mine_perf_model.py | 14 ++-- .../converters/iron/test/test_martin_mine.py | 4 +- .../natural_gas/natural_gas_cc_ct.py | 16 ++--- .../test/test_natural_gas_models.py | 2 +- .../converters/nuclear/nuclear_plant.py | 6 +- .../nuclear/test/test_nuclear_plant.py | 2 +- .../steel/cmu_electric_arc_furnace_dri.py | 12 ++-- .../steel/cmu_electric_arc_furnace_scrap.py | 12 ++-- .../converters/steel/steel_eaf_base.py | 12 ++-- h2integrate/core/h2integrate_model.py | 69 ++++++++++++------- h2integrate/core/model_baseclasses.py | 6 +- .../battery/test/test_pysam_battery.py | 6 +- .../storage/simple_storage_auto_sizing.py | 12 ++-- h2integrate/storage/storage_baseclass.py | 4 +- .../storage/test/test_storage_auto_sizing.py | 6 +- .../test/test_storage_performance_model.py | 16 +++-- 39 files changed, 268 insertions(+), 237 deletions(-) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 23fc99b1b..c9b8a4a8e 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -6,10 +6,10 @@ System-level control (SLC) within H2I is meant to operate to control the entire The SLC framework is *technology-agnostic* and works with any H2I technology (converters, storage, feedstocks, demand components, etc.). It only cares about a technology's [`_control_classifier`](control_classifier.md) and the commodity it produces. To opt a technology in, set `_control_classifier` on its performance model; for `flexible` models, also call `self.apply_curtailment(outputs)` at the end of `compute()`. See the [developer guide on adding a new technology](../../developer_guide/adding_a_new_technology.md) for the full checklist. ``` -The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_demand` signal to each controlled technology. Each technology group contains a controller that converts that demand into the `{commodity}_set_point` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the set-point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the demands in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. +The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_set_point` signal to each controlled technology. Each technology group contains a controller that converts that set-point into the `{commodity}_command_value` consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the control signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the set-points in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. ```{note} -Every technology group has an *implicit passthrough controller* that converts `{commodity}_demand` into `{commodity}_set_point`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the demand → set-point hand-off uniform for every technology, regardless of whether an SLC is present. +Every technology group has an *implicit passthrough controller* that converts `{commodity}_set_point` into `{commodity}_command_value`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the SLC set-point hand-off uniform for every technology, regardless of whether an SLC is present. ``` ```{important} diff --git a/docs/control/technology_level_control/technology_control_overview.md b/docs/control/technology_level_control/technology_control_overview.md index 255be2d54..aeea2cbb0 100644 --- a/docs/control/technology_level_control/technology_control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,16 +1,16 @@ # Technology-Level Control -Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same demand/set-point interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. +Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_set_point` signal into the `{commodity}_command_value` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same set-point/command-value interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. (implicit-passthrough-controller)= ## Implicit passthrough controller -If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_demand` to `{commodity}_set_point` so that: +If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_set_point` to `{commodity}_command_value` so that: -- When an SLC is present, the SLC's per-tech demand is fed straight to the performance model. -- When no SLC is present, the demand input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). +- When an SLC is present, the SLC's per-tech set-point is fed straight through to the performance model command value. +- When no SLC is present, the set-point input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). -If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_set_point` output so the rest of the framework can connect to them in a uniform way. +If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_command_value` output so the rest of the framework can connect to them in a uniform way. ## Control frameworks diff --git a/h2integrate/control/control_strategies/passthrough_controller.py b/h2integrate/control/control_strategies/passthrough_controller.py index a48aabd17..9524c137f 100644 --- a/h2integrate/control/control_strategies/passthrough_controller.py +++ b/h2integrate/control/control_strategies/passthrough_controller.py @@ -2,16 +2,17 @@ class PassthroughController(om.ExplicitComponent): - """Simple controller that passes a demand signal directly through as a set-point. + """Simple controller that forwards set-point to a command value. Every technology group is expected to have a controller subsystem. When a technology does not define its own ``control_strategy``, this passthrough controller is inserted automatically so that the group exposes a uniform - ``{commodity}_demand`` input and ``{commodity}_set_point`` output interface. + ``{commodity}_set_point`` input and ``{commodity}_command_value`` output + interface. In a system-level-control (SLC) configuration the SLC output is connected to - ``{commodity}_demand``; this component copies that signal to - ``{commodity}_set_point`` which the performance model consumes. + ``{commodity}_set_point``; this component copies that signal to + ``{commodity}_command_value``. When no SLC is present the input defaults to a very large value so that production is unconstrained, making the component a harmless no-op. @@ -27,9 +28,9 @@ def initialize(self): types=str, default=None, desc="Units for the commodity rate (e.g. 'kW', 'kg/h'). " - "When provided, explicit units are used on the demand input " + "When provided, explicit units are used on the set-point input " "so the variable works even when unconnected (no SLC). " - "The set-point output always uses units_by_conn to inherit " + "The command-value output always uses units_by_conn to inherit " "units from the connected performance model.", ) @@ -51,38 +52,38 @@ def setup(self): if commodity_rate_units is not None: self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Demand signal for {commodity}", + desc=f"Set-point signal for {commodity}", units=commodity_rate_units, ) else: self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Demand signal for {commodity}", + desc=f"Set-point signal for {commodity}", units_by_conn=True, ) if commodity_rate_units is not None: self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=default_val, shape=n_timesteps, - desc=f"Set point for {commodity} (passthrough of demand)", + desc=f"Command value for {commodity} (passthrough of set-point)", units=commodity_rate_units, ) else: self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=default_val, shape=n_timesteps, - desc=f"Set point for {commodity} (passthrough of demand)", + desc=f"Command value for {commodity} (passthrough of set-point)", units_by_conn=True, ) def compute(self, inputs, outputs): commodity = self.options["commodity"] - outputs[f"{commodity}_set_point"] = inputs[f"{commodity}_demand"] + outputs[f"{commodity}_command_value"] = inputs[f"{commodity}_set_point"] diff --git a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py index 4455fb11e..baccb95b2 100644 --- a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py @@ -101,7 +101,7 @@ def compute(self, inputs, outputs): * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_set_point``: Dispatch command to storage, + * ``_command_value``: Dispatch command to storage, negative when charging, positive when discharging. Control logic includes: @@ -140,7 +140,7 @@ def compute(self, inputs, outputs): # the previous time step's value soc = deepcopy(init_soc_fraction) - demand_profile = inputs[f"{commodity}_demand"] + demand_profile = inputs[f"{commodity}_set_point"] # initialize outputs soc_array = np.zeros(self.n_timesteps) @@ -192,4 +192,4 @@ def compute(self, inputs, outputs): # Record the SOC for the current time step soc_array[t] = deepcopy(soc) - outputs[f"{commodity}_set_point"] = set_point_array + outputs[f"{commodity}_command_value"] = set_point_array diff --git a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py index d7a93c59b..07c716d20 100644 --- a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py +++ b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py @@ -141,7 +141,7 @@ def common_post_init_operations(self): class StorageOpenLoopControlBase(om.ExplicitComponent): """Base OpenMDAO component for open-loop demand tracking. - This component defines the interfaces required for open-loop demand + This component defines the interfaces required for open-loop controllers, including inputs for demand, available commodity, and outputs dispatch command profile. """ @@ -164,11 +164,11 @@ def setup(self): demand_data = self.config.demand_profile self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=demand_data if not isinstance(demand_data, dict) else demand_data["demand"], shape=self.n_timesteps, units=self.config.commodity_rate_units, - desc=f"Demand profile of {commodity}", + desc=f"Set-point profile of {commodity}", ) self.add_input( @@ -180,7 +180,7 @@ def setup(self): ) self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=0.0, shape=self.n_timesteps, units=self.config.commodity_rate_units, @@ -197,7 +197,7 @@ def compute(): raise NotImplementedError("This method should be implemented in a subclass.") def common_checks_needed_in_compute(self, inputs): - if np.all(inputs[f"{self.config.commodity}_demand"] == 0.0): + if np.all(inputs[f"{self.config.commodity}_set_point"] == 0.0): msg = "Demand profile is zero, check that demand profile is input" raise UserWarning(msg) if inputs["max_charge_rate"][0] < 0: diff --git a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py index 31624ed8a..1365237f0 100644 --- a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py @@ -247,7 +247,7 @@ def compute(self, inputs, outputs): * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_set_point``: Dispatch command to storage, + * ``_command_value``: Dispatch command to storage, negative when charging, positive when discharging. Raises: @@ -279,7 +279,7 @@ def compute(self, inputs, outputs): # Build timestamped demand dictionaries from simulation timeline. demand_profile = self._build_demand_profile_dict( - inputs[f"{commodity}_demand"], + inputs[f"{commodity}_set_point"], self.time_index, ) @@ -381,7 +381,7 @@ def compute(self, inputs, outputs): if soc >= soc_max: charging = False - outputs[f"{commodity}_set_point"] = set_point_array + outputs[f"{commodity}_command_value"] = set_point_array # insert warning message if for any time step the magnitude of # any negative entry in set_point_array is greater than inputs[f"{commodity}_in"] diff --git a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py index 418a8ec05..3016b45ed 100644 --- a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py +++ b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py @@ -72,7 +72,7 @@ def setup(self): def compute(self, inputs, outputs): """ - Simple controller that outputs `commodity_set_point`, + Simple controller that outputs `commodity_command_value`, the dispatch set-points for each timestep in `commodity_rate_units`. Negative values command charging, positive values command discharging. @@ -80,7 +80,7 @@ def compute(self, inputs, outputs): if ( self.config.set_demand_as_avg_commodity_in - and inputs[f"{self.config.commodity}_demand"].sum() > 0 + and inputs[f"{self.config.commodity}_set_point"].sum() > 0 ): msg = ( "A non-zero demand profile was input but set_demand_as_avg_commodity_in is True." @@ -95,11 +95,11 @@ def compute(self, inputs, outputs): self.n_timesteps ) else: - commodity_demand = inputs[f"{self.config.commodity}_demand"] + commodity_demand = inputs[f"{self.config.commodity}_set_point"] # Assign the set point as the difference between the demand and the input commodity # when demand > input, the set point is positive to command discharging # when demand < input, the set point is negative to command charging - outputs[f"{self.config.commodity}_set_point"] = ( + outputs[f"{self.config.commodity}_command_value"] = ( commodity_demand - inputs[f"{self.config.commodity}_in"] ) diff --git a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py index 350d90c30..e8eae8f53 100644 --- a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py +++ b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py @@ -81,9 +81,9 @@ def test_pass_through_controller(subtests): # Run the test with subtests.test("Check output"): - expected_set_point = np.mean(np.arange(10)) - np.arange(10) - assert expected_set_point == ( - pytest.approx(prob.get_val("hydrogen_set_point", units="kg/h"), rel=1e-3) + expected_command_value = np.mean(np.arange(10)) - np.arange(10) + assert expected_command_value == ( + pytest.approx(prob.get_val("hydrogen_command_value", units="kg/h"), rel=1e-3) ) @@ -254,14 +254,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_demand", units="kg/h"), + prob_rte.get_val("hydrogen_set_point", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_demand", units="kg/h"), + prob_ioe.get_val("hydrogen_set_point", units="kg/h"), ) ) @@ -396,14 +396,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_demand", units="kg/h"), + prob_rte.get_val("hydrogen_set_point", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_demand", units="kg/h"), + prob_ioe.get_val("hydrogen_set_point", units="kg/h"), ) ) @@ -516,7 +516,7 @@ def test_generic_storage_demand_controller(subtests): unmet_demand, unused_commodity, combined_out_for_demand = calculate_combined_outputs( prob.get_val("hydrogen_out", units="kg/h"), prob.get_val("hydrogen_in", units="kg/h"), - prob.get_val("hydrogen_demand", units="kg/h"), + prob.get_val("hydrogen_set_point", units="kg/h"), ) # # Run the test diff --git a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py index 492510c3c..5c0efb6c2 100644 --- a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py @@ -521,7 +521,7 @@ def test_plm_controller_basic_discharge_before_peak(subtests, tech_config_base, prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_set_point", units="kg/h") + set_point = prob.get_val("hydrogen_command_value", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Discharge occurs before peak (hours 8-9)"): @@ -679,7 +679,7 @@ def test_plm_controller_blocking_charge_in_peak_range( prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_set_point", units="kg/h") + set_point = prob.get_val("hydrogen_command_value", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Controller instantiates and runs without error"): diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 1af7e0eed..d94c4ca7f 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -79,16 +79,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable demand outputs to zero - for demand_name in self.dispatchable_demand_names: - outputs[demand_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable set-point outputs to zero. + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) # Dispatch in merit order for idx in dispatch_order: - demand_name = self.dispatchable_demand_names[idx] + set_point_name = self.dispatchable_set_point_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] dispatch = np.minimum(remaining, rated) - outputs[demand_name] = dispatch + outputs[set_point_name] = dispatch remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 15f1e3cda..bb83712d0 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -52,8 +52,8 @@ def compute(self, inputs, outputs): ) else: if f"{flexible_tech}_rated_{tech_commodity}_production" in inputs: - # set the per-tech demand as the rated production - outputs[f"{flexible_tech}_{tech_commodity}_demand"] = inputs[ + # set the per-tech set-point as the rated production + outputs[f"{flexible_tech}_{tech_commodity}_set_point"] = inputs[ f"{flexible_tech}_rated_{tech_commodity}_production" ] * np.ones(self.n_timesteps) @@ -80,6 +80,6 @@ def compute(self, inputs, outputs): for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) if commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{commodity}_demand"] = ( + outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( remaining_demand / n_dispatchable ) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 9275c0fc4..304f10cf7 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -139,16 +139,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable demand outputs to zero - for demand_name in self.dispatchable_demand_names: - outputs[demand_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable set-point outputs to zero. + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: mc = marginal_costs[idx] # per-timestep array profitable = mc < sell_price # boolean mask per timestep - set_point_name = self.dispatchable_demand_names[idx] + set_point_name = self.dispatchable_set_point_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 11d20fb72..2f283fb89 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -14,10 +14,11 @@ class SystemLevelControlBase(om.ExplicitComponent): Subclasses must implement ``compute()`` with their dispatch strategy. Each technology group is expected to contain a controller (either user-defined or an - auto-injected ``PassthroughController``) that consumes a ``{commodity}_demand`` input and - produces the ``{commodity}_set_point`` actually fed to the performance/cost models. The - system-level controller therefore reasons in terms of *demand* values and emits - ``{tech_name}_{commodity}_demand`` outputs for every controlled technology. + auto-injected ``PassthroughController``) that consumes a ``{commodity}_set_point`` input and + produces a ``{commodity}_command_value`` that is then consumed by the + technology model. The system-level controller therefore reasons in terms of + *demand* values and emits ``{tech_name}_{commodity}_set_point`` outputs for + every controlled technology. The SLC demand signal is provided by a demand component (for example, ``GenericDemandComponent``) connected by ``H2IntegrateModel``. When SLC is @@ -146,8 +147,8 @@ def _setup_commodity( (only if ``add_in_name=True``). - Input ``"{tech_name}_rated_{commodity}_production"`` - rated production capacity of the tech. - - Output ``"{tech_name}_{commodity}_demand"`` - demand signal sent to the - tech's controller (which translates it into a performance-model set-point). + - Output ``"{tech_name}_{commodity}_set_point"`` - set-point signal sent + to the tech's controller. Args: tech_name (str): Name of the technology. @@ -160,10 +161,10 @@ def _setup_commodity( add_in_name (bool, optional): If True, register the ``"{tech_name}_{commodity}_out"`` input. Defaults to True. initial_demand (float, optional): Initial value for the - demand output. Defaults to 1.0. + per-tech set-point output. Defaults to 1.0. Returns: - tuple[str, str, str]: ``(in_name, demand_name, rated_name)`` + tuple[str, str, str]: ``(in_name, set_point_name, rated_name)`` """ # --- Determine unit kwargs for add_input / add_output --------- # Either explicit units or copy_units from a reference variable. @@ -175,7 +176,7 @@ def _setup_commodity( # --- Build variable names ------------------------------------- in_name = f"{tech_name}_{commodity}_out" rated_name = f"{tech_name}_rated_{commodity}_production" - demand_name = f"{tech_name}_{commodity}_demand" + set_point_name = f"{tech_name}_{commodity}_set_point" # --- Register inputs and output ------------------------------- if add_in_name: @@ -193,14 +194,14 @@ def _setup_commodity( **unit_kwargs, ) self.add_output( - demand_name, + set_point_name, val=initial_demand, shape=self.n_timesteps, - desc=f"Demand sent to {tech_name} for {commodity}", + desc=f"Set point sent to {tech_name} for {commodity}", **unit_kwargs, ) - return in_name, demand_name, rated_name + return in_name, set_point_name, rated_name def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. @@ -218,7 +219,7 @@ def _setup_tech_category(self, category, tech_list): names produced by the *category* prefix: ``self.{category}_input_names`` - ``self.{category}_demand_names`` + ``self.{category}_set_point_names`` ``self.{category}_rated_names`` ``self.{category}_commodity_names`` @@ -235,7 +236,7 @@ def _setup_tech_category(self, category, tech_list): # --- Initialize the four per-category bookkeeping lists ------- input_names = [] - demand_names = [] + set_point_names = [] rated_names = [] commodity_names = [] @@ -245,7 +246,7 @@ def _setup_tech_category(self, category, tech_list): for commodity in tech_commodities: if commodity in self.commodities_to_units: # Units are already known explicitly - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -254,7 +255,7 @@ def _setup_tech_category(self, category, tech_list): ) elif commodity in self.commodities_to_ref_var: # Units are inferred from a previously-registered reference variable - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -277,7 +278,7 @@ def _setup_tech_category(self, category, tech_list): # variable so later techs with this commodity can # copy its units. self.commodities_to_ref_var[commodity] = in_name - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -287,7 +288,7 @@ def _setup_tech_category(self, category, tech_list): else: # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -302,12 +303,12 @@ def _setup_tech_category(self, category, tech_list): commodity_names.append(commodity) input_names.append(in_name) - demand_names.append(demand_name) + set_point_names.append(set_point_name) rated_names.append(rated_name) # --- Store lists as self._ attributes ------- setattr(self, f"{category}_input_names", input_names) - setattr(self, f"{category}_demand_names", demand_names) + setattr(self, f"{category}_set_point_names", set_point_names) setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) @@ -453,8 +454,8 @@ def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, if f"{flexible_tech}_rated_{commodity}_production" not in inputs: return - # Set per-tech demand equal to the rated production of that technology - outputs[f"{flexible_tech}_{commodity}_demand"] = inputs[ + # Set per-tech set-point equal to the rated production of that technology. + outputs[f"{flexible_tech}_{commodity}_set_point"] = inputs[ f"{flexible_tech}_rated_{commodity}_production" ] * np.ones(self.n_timesteps) remaining_demand -= inputs[f"{flexible_tech}_{commodity}_out"] @@ -468,15 +469,15 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if f"{storage_tech}_{commodity}_out" not in inputs: return - demand_name = f"{storage_tech}_{commodity}_demand" - if demand_name not in outputs: + set_point_name = f"{storage_tech}_{commodity}_set_point" + if set_point_name not in outputs: return - # Emit a signed charge/discharge demand signal: charge when remaining + # Emit a signed charge/discharge set-point: charge when remaining # demand is negative, discharge when positive. The storage tech's # controller (passthrough by default) forwards this to the performance # model, which interprets the sign as charge or discharge. - outputs[demand_name] = remaining_demand + outputs[set_point_name] = remaining_demand remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index 036e7ee40..f30ef906a 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -153,7 +153,7 @@ def test_base_creates_flexible_io(self): # _var_rel2meta uses relative names (no "slc." prefix) assert "wind_electricity_out" in prob.model.slc._var_rel2meta assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "wind_electricity_demand" in prob.model.slc._var_rel2meta + assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_dispatchable_io(self): tech_connections = [["ng", "demand", "electricity", "cable"]] @@ -164,7 +164,7 @@ def test_base_creates_dispatchable_io(self): prob = _build_problem(DemandFollowingControl, plant_config, slc_config) assert "ng_electricity_out" in prob.model.slc._var_rel2meta assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "ng_electricity_demand" in prob.model.slc._var_rel2meta + assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_storage_io(self): tech_connections = [["battery", "demand", "electricity", "cable"]] @@ -176,7 +176,7 @@ def test_base_creates_storage_io(self): assert "battery_electricity_out" in prob.model.slc._var_rel2meta assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "battery_electricity_demand" in prob.model.slc._var_rel2meta + assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_demand_input(self): plant_config = _build_plant_config([]) @@ -215,8 +215,8 @@ def test_equal_share_two_dispatchable(self): prob.set_val("slc.ng2_rated_electricity_production", 40000) prob.run_model() - sp1 = prob.get_val("slc.ng1_electricity_demand") - sp2 = prob.get_val("slc.ng2_electricity_demand") + sp1 = prob.get_val("slc.ng1_electricity_set_point") + sp2 = prob.get_val("slc.ng2_electricity_set_point") np.testing.assert_allclose(sp1, 25000) np.testing.assert_allclose(sp2, 25000) @@ -239,7 +239,7 @@ def test_flexible_reduces_demand(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # demand=50k, wind outputs [30k,60k,50k,10k] → remaining = max(0, demand-wind) expected = np.maximum(50000 - np.array([30000, 60000, 50000, 10000]), 0) np.testing.assert_allclose(ng_sp, expected) @@ -267,7 +267,7 @@ def test_storage_absorbs_surplus(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - batt_sp = prob.get_val("slc.battery_electricity_demand") + batt_sp = prob.get_val("slc.battery_electricity_set_point") # demand - wind = [50k-70k, 50k-30k, 0, 0] = [-20k, 20k, 0, 0] expected = np.array([-20000, 20000, 0, 0]) np.testing.assert_allclose(batt_sp, expected) @@ -310,8 +310,8 @@ def test_cheapest_dispatched_first(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap can handle all 50k (rated 80k), so expensive gets 0 np.testing.assert_allclose(cheap_sp, 50000) np.testing.assert_allclose(expensive_sp, 0) @@ -336,8 +336,8 @@ def test_overflow_to_expensive(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap maxes at 30k, expensive picks up remaining 20k np.testing.assert_allclose(cheap_sp, 30000) np.testing.assert_allclose(expensive_sp, 20000) @@ -361,7 +361,7 @@ def test_with_flexible_reduces_dispatch(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # demand 50k - wind 40k = 10k remaining np.testing.assert_allclose(ng_sp, 10000) @@ -394,8 +394,8 @@ def test_unprofitable_tech_not_dispatched(self): prob.set_val("slc.commodity_sell_price", 0.06) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap (0.03 < 0.06) dispatched up to rated 30k # Expensive (0.08 >= 0.06) NOT dispatched, demand unmet np.testing.assert_allclose(cheap_sp, 30000) @@ -420,8 +420,8 @@ def test_all_profitable(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - a_sp = prob.get_val("slc.a_electricity_demand") - b_sp = prob.get_val("slc.b_electricity_demand") + a_sp = prob.get_val("slc.a_electricity_set_point") + b_sp = prob.get_val("slc.b_electricity_set_point") # Both profitable, cheapest first: a gets 50k (rated 80k), b gets 0 np.testing.assert_allclose(a_sp, 50000) np.testing.assert_allclose(b_sp, 0) @@ -442,7 +442,7 @@ def test_none_profitable(self): prob.set_val("slc.commodity_sell_price", 0.01) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # NG cost (0.05) >= sell price (0.01), not dispatched np.testing.assert_allclose(ng_sp, 0) @@ -462,7 +462,7 @@ def test_sell_price_from_config(self): # Don't set sell_price explicitly — should use config default 0.10 prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # Config sell_price=0.10 > marginal 0.03 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -483,7 +483,7 @@ def test_time_varying_sell_price(self): prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # mc=0.05: profitable when sell>0.05 (hours 0,2), not when sell<0.05 (hours 1,3) np.testing.assert_allclose(ng_sp, [50000, 0, 50000, 0]) @@ -521,7 +521,7 @@ def test_buy_price_scalar(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_demand") + grid_sp = prob.get_val("slc.grid_electricity_set_point") # buy_price=0.04 < sell_price=0.10 → dispatched np.testing.assert_allclose(grid_sp, 50000) @@ -561,7 +561,7 @@ def test_buy_price_time_varying(self): prob.set_val("slc.grid_buy_price", [0.03, 0.08, 0.04, 0.09]) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_demand") + grid_sp = prob.get_val("slc.grid_electricity_set_point") np.testing.assert_allclose(grid_sp, [50000, 0, 50000, 0]) def test_varopex_mode(self): @@ -584,7 +584,7 @@ def test_varopex_mode(self): prob.set_val("slc.gen_electricity_out", np.full(4, 100000.0)) prob.run_model() - gen_sp = prob.get_val("slc.gen_electricity_demand") + gen_sp = prob.get_val("slc.gen_electricity_set_point") # VarOpEx=500k $/yr, production=100MW*4h=400MWh over 4h # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 500k / 876k ≈ 0.571 $/MWh ≈ 0.000571 $/kWh @@ -607,7 +607,7 @@ def test_cost_per_tech_default_zero(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # mc=0.0 < sell_price=0.10 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -634,7 +634,7 @@ def test_feedstock_single(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_demand") + sp = prob.get_val("slc.ng_plant_electricity_set_point") # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 1M / 876k ≈ 1.14 $/MWh ≈ 0.00114 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -665,7 +665,7 @@ def test_feedstock_multiple(self): prob.set_val("slc.plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.plant_electricity_demand") + sp = prob.get_val("slc.plant_electricity_set_point") # Total VarOpEx = 800k, annual production = 876,000 MWh # mc ≈ 0.913 $/MWh ≈ 0.000913 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -695,7 +695,7 @@ def test_feedstock_profit_max_unprofitable(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_demand") + sp = prob.get_val("slc.ng_plant_electricity_set_point") # mc = 100M / 876k ≈ 114 $/MWh ≈ 0.114 $/kWh > sell 0.01 → NOT dispatched np.testing.assert_allclose(sp, 0) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index c1dca6375..210eebae5 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -17,7 +17,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -26,7 +26,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_demand", units="kW" + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, @@ -76,7 +76,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -85,7 +85,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") battery_set_point = model.prob.get_val( - "system_level_controller.battery_electricity_demand", units="kW" + "system_level_controller.battery_electricity_set_point", units="kW" ) assert np.allclose(remaining_demand, battery_set_point, rtol=1e-6, atol=1e-8) @@ -94,7 +94,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "battery.electricity_out", units="kW" ) ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_demand", units="kW" + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, diff --git a/h2integrate/converters/grid/grid.py b/h2integrate/converters/grid/grid.py index 2e4d33c7d..9f73c2d11 100644 --- a/h2integrate/converters/grid/grid.py +++ b/h2integrate/converters/grid/grid.py @@ -42,7 +42,7 @@ class GridPerformanceModel(PerformanceModelBaseClass): Inputs interconnection_size (float): Maximum power capacity for grid connection (kW). electricity_in (array): Power flowing into the grid (selling) (kW). - electricity_set_point (array): Downstream electricity set point (kW). + electricity_command_value (array): Downstream electricity set point (kW). Outputs electricity_out (array): Power flowing out of the grid (buying) (kW). @@ -88,7 +88,7 @@ def setup(self): # Electricity set point from downstream (for buying from grid) self.add_input( - "electricity_set_point", + "electricity_command_value", val=0.0, shape=n_timesteps, units=self.commodity_rate_units, @@ -137,11 +137,13 @@ def compute(self, inputs, outputs): outputs["electricity_sold"] = electricity_sold # Buying: electricity flows out of grid to meet set point, limited by interconnection - electricity_bought = np.clip(inputs["electricity_set_point"], 0, interconnection_size) + electricity_bought = np.clip(inputs["electricity_command_value"], 0, interconnection_size) outputs["electricity_out"] = electricity_bought # Unmet demand if set point exceeds interconnection size - outputs["electricity_unmet_demand"] = inputs["electricity_set_point"] - electricity_bought + outputs["electricity_unmet_demand"] = ( + inputs["electricity_command_value"] - electricity_bought + ) # Not sold electricity if demand exceeds interconnection size outputs["electricity_excess"] = inputs["electricity_in"] - electricity_sold diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index a66b9cb0d..ebef96214 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -45,7 +45,7 @@ def test_grid_performance_outputs(plant_config, subtests): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("comp.electricity_set_point", demand) + prob.set_val("comp.electricity_command_value", demand) prob.run_model() @@ -148,7 +148,7 @@ def test_buying_electricity(plant_config, n_timesteps): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -177,7 +177,7 @@ def test_buying_with_interconnection_limit(plant_config, n_timesteps): # Set demand above interconnection limit demand = np.full(n_timesteps, 60000.0) # 60 MW demand - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -247,7 +247,7 @@ def test_simultaneous_buy_and_sell(plant_config, n_timesteps): electricity_demand = np.full(n_timesteps, 40000.0) # 40 MW out prob.set_val("grid.electricity_in", electricity_in) - prob.set_val("grid.electricity_set_point", electricity_demand) + prob.set_val("grid.electricity_command_value", electricity_demand) prob.run_model() @@ -272,7 +272,7 @@ def test_varying_demand_profile(plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -302,7 +302,7 @@ def test_non_hourly_dt_demand_profile(subtests, plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_set_point", demand, units="kW") + prob.set_val("grid.electricity_command_value", demand, units="kW") prob.run_model() diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index 94a5a50a2..75590230d 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -26,7 +26,7 @@ def setup(self): # Dispatchable models receive a set_point from the system-level controller if "system_level_control" in self.options["plant_config"]: self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=0.0, shape=self.n_timesteps, units=self.commodity_rate_units, diff --git a/h2integrate/converters/hydrogen/h2_fuel_cell.py b/h2integrate/converters/hydrogen/h2_fuel_cell.py index 36d2c1a76..773bfde9e 100644 --- a/h2integrate/converters/hydrogen/h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/h2_fuel_cell.py @@ -92,7 +92,7 @@ def setup(self): # Default the electricity set point input as the rated capacity self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_kw, shape=self.n_timesteps, units=self.commodity_rate_units, @@ -106,7 +106,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing hydrogen_in, fuel cell - HHV efficiency, electricity_set_point, and system_capacity. + HHV efficiency, electricity_command_value, and system_capacity. outputs: OpenMDAO outputs object for electricity_out, hydrogen_consumed. """ @@ -122,13 +122,13 @@ def compute(self, inputs, outputs): max_h2_consumption = system_capacity * kw_to_kgh_h2 # electrical set point, saturated at maximum rated system capacity - electricity_set_point = np.where( - inputs["electricity_set_point"] > system_capacity, + electricity_command_value = np.where( + inputs["electricity_command_value"] > system_capacity, system_capacity, - inputs["electricity_set_point"], + inputs["electricity_command_value"], ) - h2_demand = electricity_set_point * kw_to_kgh_h2 + h2_demand = electricity_command_value * kw_to_kgh_h2 # available feedstock, saturated at maximum system feedstock consumption h2_available = np.where( diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 0c5aada06..f9c5a5f5e 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -225,6 +225,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): # Apply set_point from system-level controller if present if "system_level_control" in self.options["plant_config"]: - set_point = inputs[f"{self.commodity}_set_point"] + set_point = inputs[f"{self.commodity}_command_value"] commodity_out_key = f"{self.commodity}_out" outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], set_point) diff --git a/h2integrate/converters/hydrogen/steam_methane_reformer.py b/h2integrate/converters/hydrogen/steam_methane_reformer.py index b469cbd8a..84a13e5bf 100644 --- a/h2integrate/converters/hydrogen/steam_methane_reformer.py +++ b/h2integrate/converters/hydrogen/steam_methane_reformer.py @@ -91,7 +91,7 @@ def setup(self): # Default the hydrogen set point input as the rated capacity self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_tonnes_per_day * (1000 / 24), # convert t/d to kg/h shape=n_timesteps, units=self.commodity_rate_units, @@ -169,7 +169,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, natural_gas_usage_rate, electricity_usage_rate, - system_capacity, and hydrogen_set_point. + system_capacity, and hydrogen_command_value. outputs: OpenMDAO outputs object for hydrogen_out, natural_gas_consumed, electricity_consumed, and unmet_hydrogen_demand. """ @@ -184,13 +184,13 @@ def compute(self, inputs, outputs): max_electricity_consumption = system_capacity_kg_per_hour * electricity_usage_kWh_per_kg # hydrogen set point, saturated at maximum rated system capacity - hydrogen_set_point = np.where( - inputs["hydrogen_set_point"] > system_capacity_kg_per_hour, + hydrogen_command_value = np.where( + inputs["hydrogen_command_value"] > system_capacity_kg_per_hour, system_capacity_kg_per_hour, - inputs["hydrogen_set_point"], + inputs["hydrogen_command_value"], ) - natural_gas_demand = hydrogen_set_point * natural_gas_usage_mmbtu_per_kg - electricity_demand = hydrogen_set_point * electricity_usage_kWh_per_kg + natural_gas_demand = hydrogen_command_value * natural_gas_usage_mmbtu_per_kg + electricity_demand = hydrogen_command_value * electricity_usage_kWh_per_kg # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -242,7 +242,7 @@ def compute(self, inputs, outputs): outputs["annual_hydrogen_produced"] = outputs["total_hydrogen_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_hydrogen_demand"] = inputs["hydrogen_set_point"] - hydrogen_out + outputs["unmet_hydrogen_demand"] = inputs["hydrogen_command_value"] - hydrogen_out outputs["total_energy_conversion_ratio"] = total_energy_conversion_ratio diff --git a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py index 2a49f9cbe..c15faa79a 100644 --- a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py @@ -148,10 +148,10 @@ def test_fuel_cell_demand(tech_config, plant_config, subtests): prob.set_val("fuel_cell.hydrogen_in", hydrogen_input, units="kg/h") - elec_set_point = np.ones(n_timesteps) * 1000.0 # kW + elec_command_value = np.ones(n_timesteps) * 1000.0 # kW # Set first 6 timesteps to test edge cases for set point - elec_set_point[:6] = ( + elec_command_value[:6] = ( 1000.0, # test case with set point equal to system capacity 500.0, # test case with set point below system capacity 1000.0, # test case with set point equal to system capacity @@ -160,7 +160,7 @@ def test_fuel_cell_demand(tech_config, plant_config, subtests): 0.0, # test case with set point equal to zero ) - prob.set_val("fuel_cell.electricity_set_point", elec_set_point, units="kW") + prob.set_val("fuel_cell.electricity_command_value", elec_command_value, units="kW") prob.run_model() diff --git a/h2integrate/converters/iron/iron_dri_base.py b/h2integrate/converters/iron/iron_dri_base.py index b9ac1348b..c0d6b4500 100644 --- a/h2integrate/converters/iron/iron_dri_base.py +++ b/h2integrate/converters/iron/iron_dri_base.py @@ -78,7 +78,7 @@ def setup(self): # Default the sponge iron set point input as the rated capacity self.add_input( - "sponge_iron_set_point", + "sponge_iron_command_value", val=self.config.sponge_iron_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", @@ -226,19 +226,19 @@ def compute(self, inputs, outputs): ]["Value"].sum() # sponge iron set point, saturated at maximum rated system capacity - sponge_iron_set_point = np.where( - inputs["sponge_iron_set_point"] > inputs["system_capacity"], + sponge_iron_command_value = np.where( + inputs["sponge_iron_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["sponge_iron_set_point"], + inputs["sponge_iron_command_value"], ) # initialize an array of how much sponge iron could be produced # from the available feedstocks and the set point sponge_iron_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_set_point"])) + (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_command_value"])) ) # first entry is the sponge iron set point - sponge_iron_from_feedstocks[0] = sponge_iron_set_point + sponge_iron_from_feedstocks[0] = sponge_iron_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/converters/iron/martin_mine_perf_model.py b/h2integrate/converters/iron/martin_mine_perf_model.py index b5084de4a..d0308bda9 100644 --- a/h2integrate/converters/iron/martin_mine_perf_model.py +++ b/h2integrate/converters/iron/martin_mine_perf_model.py @@ -79,7 +79,7 @@ def setup(self): # Default the ore set point input as the rated capacity self.add_input( - "iron_ore_set_point", + "iron_ore_command_value", val=self.config.max_ore_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", @@ -204,10 +204,10 @@ def compute(self, inputs, outputs): max_energy_consumption = inputs["system_capacity"] * energy_usage_per_processed_ore # iron ore set point, saturated at maximum rated system capacity - processed_ore_set_point = np.where( - inputs["iron_ore_set_point"] > inputs["system_capacity"], + processed_ore_command_value = np.where( + inputs["iron_ore_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["iron_ore_set_point"], + inputs["iron_ore_command_value"], ) # available feedstocks, saturated at maximum system feedstock consumption @@ -229,7 +229,11 @@ def compute(self, inputs, outputs): # output is minimum between available feedstocks and output set point processed_ore_production = np.minimum.reduce( - [processed_ore_from_crude_ore, processed_ore_from_electricity, processed_ore_set_point] + [ + processed_ore_from_crude_ore, + processed_ore_from_electricity, + processed_ore_command_value, + ] ) # energy consumption diff --git a/h2integrate/converters/iron/test/test_martin_mine.py b/h2integrate/converters/iron/test/test_martin_mine.py index a1865eb4d..052a51179 100644 --- a/h2integrate/converters/iron/test/test_martin_mine.py +++ b/h2integrate/converters/iron/test/test_martin_mine.py @@ -41,7 +41,7 @@ def test_iron_mine_performance_outputs( prob.set_val("comp.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("comp.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("comp.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("comp.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() commodity = "iron_ore" @@ -152,7 +152,7 @@ def test_baseline_iron_ore_costs(plant_config, driver_config, iron_ore_config_ma prob.set_val("ore_perf.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("ore_perf.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("ore_perf.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("ore_perf.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() diff --git a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py index 21bb091ff..94bfafd31 100644 --- a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py +++ b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py @@ -48,7 +48,7 @@ class NaturalGasPerformanceModel(PerformanceModelBaseClass): system_capacity (float): Natural gas plant rated capacity in MW natural_gas_in (array): Natural gas input energy in MMBtu/h heat_rate_mmbtu_per_mwh (float): Plant heat rate in MMBtu/MWh - electricity_set_point (array): Electricity set point in MW for each timestep + electricity_command_value (array): Electricity set point in MW for each timestep Outputs: electricity_out (array): Electricity output in MW for each timestep @@ -104,7 +104,7 @@ def setup(self): # Default the electricity set point input as the rated capacity self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_mw, shape=n_timesteps, units=self.commodity_rate_units, @@ -138,7 +138,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, heat_rate_mmbtu_per_mwh, - system_capacity, and electricity_set_point. + system_capacity, and electricity_command_value. outputs: OpenMDAO outputs object for electricity_out, natural_gas_consumed, and unmet_electricity_demand. """ @@ -149,12 +149,12 @@ def compute(self, inputs, outputs): max_natural_gas_consumption = system_capacity * heat_rate_mmbtu_per_mwh # electrical set point, saturated at maximum rated system capacity - electricity_set_point = np.where( - inputs["electricity_set_point"] > system_capacity, + electricity_command_value = np.where( + inputs["electricity_command_value"] > system_capacity, system_capacity, - inputs["electricity_set_point"], + inputs["electricity_command_value"], ) - natural_gas_demand = electricity_set_point * heat_rate_mmbtu_per_mwh + natural_gas_demand = electricity_command_value * heat_rate_mmbtu_per_mwh # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -181,7 +181,7 @@ def compute(self, inputs, outputs): outputs["annual_electricity_produced"] = outputs["total_electricity_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_electricity_demand"] = inputs["electricity_set_point"] - electricity_out + outputs["unmet_electricity_demand"] = inputs["electricity_command_value"] - electricity_out @define(kw_only=True) diff --git a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py index 0027989a9..3fd3b079b 100644 --- a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py +++ b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py @@ -375,7 +375,7 @@ def test_ngcc_performance_demand(plant_config, ngcc_performance_params, subtests # Set the natural gas input prob.set_val("natural_gas_in", natural_gas_input) - prob.set_val("electricity_set_point", electricity_demand_MW) + prob.set_val("electricity_command_value", electricity_demand_MW) prob.run_model() electricity_out = prob.get_val("electricity_out", units="MW") diff --git a/h2integrate/converters/nuclear/nuclear_plant.py b/h2integrate/converters/nuclear/nuclear_plant.py index 836d9ce52..869fb8e0f 100644 --- a/h2integrate/converters/nuclear/nuclear_plant.py +++ b/h2integrate/converters/nuclear/nuclear_plant.py @@ -61,7 +61,7 @@ def setup(self): desc="Nuclear plant rated capacity", ) self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_kw, shape=n_timesteps, units=self.commodity_rate_units, @@ -70,9 +70,9 @@ def setup(self): def compute(self, inputs, outputs): system_capacity = inputs["system_capacity"] - electricity_set_point = inputs[f"{self.commodity}_set_point"] + electricity_command_value = inputs[f"{self.commodity}_command_value"] - electricity_out = np.minimum(electricity_set_point, system_capacity) + electricity_out = np.minimum(electricity_command_value, system_capacity) electricity_out = np.clip(electricity_out, 0.0, system_capacity) outputs["electricity_out"] = electricity_out diff --git a/h2integrate/converters/nuclear/test/test_nuclear_plant.py b/h2integrate/converters/nuclear/test/test_nuclear_plant.py index 6c143693e..7f6221512 100644 --- a/h2integrate/converters/nuclear/test/test_nuclear_plant.py +++ b/h2integrate/converters/nuclear/test/test_nuclear_plant.py @@ -64,7 +64,7 @@ def test_nuclear_performance_demand(plant_config, nuclear_performance_params, su prob.model.add_subsystem("nuc_perf", perf_comp, promotes=["*"]) prob.setup() - prob.set_val("electricity_set_point", electricity_demand) + prob.set_val("electricity_command_value", electricity_demand) prob.run_model() electricity_out = prob.get_val("electricity_out") diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py index bcdb78223..fb1424e19 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py @@ -180,7 +180,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_set_point", + "steel_command_value", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -328,19 +328,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > system_production, + steel_command_value = np.where( + inputs["steel_command_value"] > system_production, system_production, - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_set_point + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py index a6ed8debe..6cf36e32d 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py @@ -142,7 +142,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_set_point", + "steel_command_value", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -260,19 +260,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > system_production, + steel_command_value = np.where( + inputs["steel_command_value"] > system_production, system_production, - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_set_point + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/steel_eaf_base.py b/h2integrate/converters/steel/steel_eaf_base.py index 8fdd9e131..8c6684536 100644 --- a/h2integrate/converters/steel/steel_eaf_base.py +++ b/h2integrate/converters/steel/steel_eaf_base.py @@ -79,7 +79,7 @@ def setup(self): # Default the steel set point input as the rated capacity self.add_input( - "steel_set_point", + "steel_command_value", val=self.config.steel_production_rate_tonnes_per_hr, shape=n_timesteps, units=self.commodity_rate_units, @@ -232,19 +232,19 @@ def compute(self, inputs, outputs): ].sum() # t/t # steel set point, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > inputs["system_capacity"], + steel_command_value = np.where( + inputs["steel_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the set point steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_rates) + 1, len(inputs["steel_command_value"])) ) # first entry is the steel set point - steel_from_feedstocks[0] = steel_set_point + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 5ed23e539..894d5513c 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -637,11 +637,11 @@ def add_system_level_controller(self, slc_config): - **Flexible / dispatchable / storage techs**: Both the commodity output (``{tech_name}.{commodity}_out``) and rated production (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. - The controller's per-tech ``{tech_name}_{commodity}_demand`` output is then - connected to the tech group's ``{commodity}_demand`` input. Every controlled + The controller's per-tech ``{tech_name}_{commodity}_set_point`` output is + connected to the tech group's ``{commodity}_set_point`` input. Every controlled tech group is expected to expose this input — either via a user-defined ``control_strategy`` or via the auto-injected ``PassthroughController`` — which - converts the demand signal into the appropriate performance-model set-point. + converts the set-point signal into the appropriate performance-model command value. 4. **Connect marginal-cost inputs for cost-aware strategies** - Only executed when ``control_strategy`` is ``"CostMinimizationControl"`` or @@ -759,13 +759,19 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_{commodity}_storage_duration", ) - # Every controlled tech group exposes a ``{commodity}_demand`` - # input (provided by either a user-defined control_strategy or an - # auto-injected PassthroughController). Route the SLC's per-tech - # demand output to that input. + # Route SLC per-tech set-point to the technology controller input. + # User-defined controllers generally promote ``{commodity}_set_point`` + # at the tech-group level, while auto-injected passthrough + # controllers expose it at ``controller.{commodity}_set_point``. + tech_cfg = self.technology_config["technologies"][tech_name] + if "control_strategy" in tech_cfg: + tech_set_point_target = f"{tech_name}.{commodity}_set_point" + else: + tech_set_point_target = f"{tech_name}.controller.{commodity}_set_point" + self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_demand", - f"{tech_name}.{commodity}_demand", + f"system_level_controller.{tech_name}_{commodity}_set_point", + tech_set_point_target, ) # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - @@ -931,7 +937,12 @@ def create_technology_models(self): self.cost_models.append(om_model_object) self.finance_models.append(om_model_object) - self._add_passthrough_controller(tech_group, comp, individual_tech_config) + self._add_passthrough_controller( + tech_group, + comp, + individual_tech_config, + perf_model, + ) continue @@ -969,7 +980,10 @@ def create_technology_models(self): if perf_om_object is not None: self._add_passthrough_controller( - tech_group, perf_om_object, individual_tech_config + tech_group, + perf_om_object, + individual_tech_config, + individual_tech_config["performance_model"]["model"], ) # Process the finance models @@ -1044,7 +1058,13 @@ def _check_control_classifier(self, model_name, model_object): msg = f"Model {model_name} is missing a control classifier" raise ValueError(msg) - def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_config): + def _add_passthrough_controller( + self, + tech_group, + perf_comp, + individual_tech_config, + _perf_model_name, + ): """Automatically add a PassthroughController to a tech group if appropriate. A controller is auto-inserted only when: @@ -1055,10 +1075,10 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con attributes (typically set in its ``initialize()``), or those values can be read from the individual tech config. - The controller's ``{commodity}_demand`` input becomes the tech group's - external demand-input promoted at the tech group level, and its - ``{commodity}_set_point`` output is auto-connected (via promotion) to the - performance model's ``{commodity}_set_point`` input if one exists. + The controller consumes ``controller.{commodity}_set_point`` and emits + ``controller.{commodity}_command_value``. The command value is + explicitly connected to the technology group's promoted + ``{commodity}_command_value`` input consumed by the performance model. """ # Skip if the user has already specified a control strategy for this tech; # their explicit choice takes precedence over the auto-injected passthrough. @@ -1102,18 +1122,19 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con commodity_rate_units=commodity_rate_units, ) - # Promote all controller variables so: - # - `{commodity}_demand` becomes the tech group's external input - # (this is what the system-level controller connects to), and - # - `{commodity}_set_point` is auto-connected by name to the - # performance model's matching input via promotion. - om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) + # Keep controller I/O unpromoted to avoid promoted-name collisions + # with performance-model ``{commodity}_command_value`` inputs. + om_controller = tech_group.add_subsystem("controller", controller) + tech_group.connect( + f"controller.{commodity}_command_value", + f"{commodity}_command_value", + ) self.control_strategies.append(om_controller) # Ensure the controller runs before the performance/cost models that - # consume its set_point output. Subsystem creation order otherwise + # consume its command_value output. Subsystem creation order otherwise # places the controller last in the group's execution order, which - # would delay the set_point by one solver iteration. + # would delay the control signal by one solver iteration. existing_order = list(tech_group._static_subsystems_allprocs.keys()) if "controller" in existing_order: new_order = ["controller"] + [n for n in existing_order if n != "controller"] diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index ac2f34dfc..687771d88 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -102,7 +102,7 @@ def setup(self): # Flexible models get additional I/O for set_point-based curtailment if getattr(self, "_control_classifier", None) == "flexible": self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=1.0, shape=self.n_timesteps, units=self.commodity_rate_units, @@ -117,7 +117,7 @@ def setup(self): ) def apply_curtailment(self, outputs): - """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_set_point``. + """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_command_value``. Copies the current ``{commodity}_out`` into ``uncurtailed_{commodity}_out``, then clips ``{commodity}_out`` to ``min(uncurtailed, set_point)`` element-wise. @@ -132,7 +132,7 @@ def apply_curtailment(self, outputs): commodity_out_key = f"{self.commodity}_out" uncurtailed_key = f"uncurtailed_{self.commodity}_out" - set_point_key = f"{self.commodity}_set_point" + set_point_key = f"{self.commodity}_command_value" uncurtailed = np.array(outputs[commodity_out_key]) outputs[uncurtailed_key] = uncurtailed diff --git a/h2integrate/storage/battery/test/test_pysam_battery.py b/h2integrate/storage/battery/test/test_pysam_battery.py index aecaedb8c..1044607f5 100644 --- a/h2integrate/storage/battery/test/test_pysam_battery.py +++ b/h2integrate/storage/battery/test/test_pysam_battery.py @@ -64,7 +64,7 @@ def test_pysam_battery_performance_model_without_controller(plant_config, subtes prob.model.add_subsystem( name="IVC4", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -351,7 +351,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob_init.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -419,7 +419,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) diff --git a/h2integrate/storage/simple_storage_auto_sizing.py b/h2integrate/storage/simple_storage_auto_sizing.py index 9dc579990..bd2049e0e 100644 --- a/h2integrate/storage/simple_storage_auto_sizing.py +++ b/h2integrate/storage/simple_storage_auto_sizing.py @@ -170,9 +170,9 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): 1) Calculate the max charge and discharge rate as the maximum of the `commodity_in` profile and oversize to account for charge/discharge efficiencies. 2) Estimate the storage SOC (in `commodity_amount_units`). The SOC increases when - charging and decreases when discharging. If `commodity_set_point` is input, + charging and decreases when discharging. If `commodity_command_value` is input, calculate the storage SOC as the cumulative summation of the negative of - `commodity_set_point` input (`commodity_set_point` input is + `commodity_command_value` input (`commodity_command_value` input is negative when charging and positive when discharging). Otherwise, calculate the storage SOC as the cumulative summation of `commodity_in - demand`. @@ -219,11 +219,11 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): # Auto-size the storage capacity to meet the demand as much as possible # 2. Estimate the storage SOC in `commodity_amount_units` # NOTE: commodity_storage_soc is just an absolute value and is not a percentage. - if f"{self.commodity}_set_point" in inputs: - # `{self.commodity}_set_point` is negative when charging and positive when - # discharging, the negative of `{self.commodity}_set_point` can be used to + if f"{self.commodity}_command_value" in inputs: + # `{self.commodity}_command_value` is negative when charging and positive when + # discharging, the negative of `{self.commodity}_command_value` can be used to # estimate the SOC (which increases when charging and decreases when discharging) - commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_set_point"]) + commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_command_value"]) else: # estimate the SOC (which increases when charging and decreases when discharging) # based on the demand profile and the input commodity diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index e1580cf67..ad1fd938e 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -180,7 +180,7 @@ def setup(self): if not using_feedback_control: # using an open-loop storage controller self.add_input( - f"{commodity}_set_point", + f"{commodity}_command_value", val=0.0, shape=n_timesteps, units=commodity_rate_units, @@ -274,7 +274,7 @@ def run_storage( else: storage_commodity_out, soc = self.simulate( - storage_dispatch_commands=inputs[f"{self.commodity}_set_point"], + storage_dispatch_commands=inputs[f"{self.commodity}_command_value"], charge_rate=charge_rate, discharge_rate=discharge_rate, storage_capacity=storage_capacity, diff --git a/h2integrate/storage/test/test_storage_auto_sizing.py b/h2integrate/storage/test/test_storage_auto_sizing.py index 3fa782f2c..077f0ee84 100644 --- a/h2integrate/storage/test/test_storage_auto_sizing.py +++ b/h2integrate/storage/test/test_storage_auto_sizing.py @@ -41,7 +41,7 @@ def test_storage_autosizing_basic_performance_no_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -228,7 +228,7 @@ def test_storage_autosizing_soc_bounds(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -335,7 +335,7 @@ def test_storage_autosizing_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 2ad903400..5daadbb37 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -1062,15 +1062,15 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): commodity_demand = np.full(24, 5.0) commodity_in = np.concat([np.zeros(3), np.cumsum(np.ones(15)), np.full(6, 4.0)]) - nominal_set_point = commodity_demand - commodity_in - nominal_charge_profile = np.where(nominal_set_point < 0, nominal_set_point, 0) + nominal_command_value = commodity_demand - commodity_in + nominal_charge_profile = np.where(nominal_command_value < 0, nominal_command_value, 0) indx_charge = np.argwhere(nominal_charge_profile < 0).flatten() excess_commodity_avail = np.abs( np.abs(nominal_charge_profile)[indx_charge] - commodity_in[indx_charge] ) more_than_avail_charge_cmd = nominal_charge_profile[indx_charge] - excess_commodity_avail * 2 # nominal_charge_profile[indx_charge] = more_than_avail_charge_cmd - nominal_set_point[indx_charge] = more_than_avail_charge_cmd + nominal_command_value[indx_charge] = more_than_avail_charge_cmd prob.model.add_subsystem( name="IVC1", @@ -1086,7 +1086,9 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): prob.model.add_subsystem( name="IVC3", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=nominal_set_point, units="kg/h"), + subsys=om.IndepVarComp( + name="hydrogen_command_value", val=nominal_command_value, units="kg/h" + ), promotes=["*"], ) @@ -1275,7 +1277,7 @@ def test_storage_half_hourly_known_outputs(subtests, plant_config_non_hourly): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/h"), + om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/h"), promotes=["*"], ) prob.model.add_subsystem( @@ -1378,7 +1380,7 @@ def test_storage_half_hourly_known_outputs_kg_s(subtests, plant_config_non_hourl ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/s"), + om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/s"), promotes=["*"], ) prob.model.add_subsystem( @@ -1468,7 +1470,7 @@ def test_storage_half_hourly_kw_kwh_2hr(subtests): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("electricity_set_point", val=set_point, units="kW"), + om.IndepVarComp("electricity_command_value", val=set_point, units="kW"), promotes=["*"], ) prob.model.add_subsystem( From f592e926ab3ec30104a06dd96409bab42cb6f503 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 9 Jun 2026 16:29:41 -0600 Subject: [PATCH 120/132] Added command value to electrolyzer --- .../hydrogen/electrolyzer_baseclass.py | 20 ++++++++++--------- .../converters/hydrogen/pem_electrolyzer.py | 11 +++++----- h2integrate/core/h2integrate_model.py | 3 --- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index 75590230d..9e1d9b3fb 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -23,15 +23,17 @@ def setup(self): # Define inputs for electricity self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") - # Dispatchable models receive a set_point from the system-level controller - if "system_level_control" in self.options["plant_config"]: - self.add_input( - f"{self.commodity}_command_value", - val=0.0, - shape=self.n_timesteps, - units=self.commodity_rate_units, - desc=f"Set point for {self.commodity} production from SLC", - ) + # Dispatchable models receive a command value from a tech-level controller. + # Auto-injected ``PassthroughController`` or a user-defined control strategy + # supplies this input. The default is a large value so an unconnected run + # leaves raw production uncurtailed. + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Command value for {self.commodity} production from tech controller", + ) def compute(self, inputs, outputs): """ diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index f9c5a5f5e..1dc2aa037 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -223,8 +223,9 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): "Annual O2 Production [kg/year]" ] - # Apply set_point from system-level controller if present - if "system_level_control" in self.options["plant_config"]: - set_point = inputs[f"{self.commodity}_command_value"] - commodity_out_key = f"{self.commodity}_out" - outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], set_point) + # Apply the command value supplied by the tech-level controller as an upper + # bound on production. Default value is large enough that unconnected runs + # leave the raw production untouched. + outputs[f"{self.commodity}_out"] = np.minimum( + outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] + ) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 894d5513c..c5d2d401d 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -941,7 +941,6 @@ def create_technology_models(self): tech_group, comp, individual_tech_config, - perf_model, ) continue @@ -983,7 +982,6 @@ def create_technology_models(self): tech_group, perf_om_object, individual_tech_config, - individual_tech_config["performance_model"]["model"], ) # Process the finance models @@ -1063,7 +1061,6 @@ def _add_passthrough_controller( tech_group, perf_comp, individual_tech_config, - _perf_model_name, ): """Automatically add a PassthroughController to a tech group if appropriate. From b88db1d782e9f89fb94efb601616044b3054b4dd Mon Sep 17 00:00:00 2001 From: John Jasa Date: Tue, 9 Jun 2026 17:09:08 -0600 Subject: [PATCH 121/132] Docs build correctly locally --- docs/demand/demand_demo.md | 4 ++-- .../converters/ammonia/ammonia_synloop.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/demand/demand_demo.md b/docs/demand/demand_demo.md index c0b0dd52b..0eb6a46b7 100644 --- a/docs/demand/demand_demo.md +++ b/docs/demand/demand_demo.md @@ -186,7 +186,7 @@ end_hour = 1000 x = list(range(start_hour, end_hour)) generation = h2i.prob.get_val("battery.electricity_in", units="MW") -battery_demand = h2i.prob.get_val("battery.electricity_demand", units="MW") +battery_demand = h2i.prob.get_val("battery.electricity_command_value", units="MW") battery_charge_discharge = h2i.prob.get_val("battery.electricity_out", units="MW") where_charge = [True if d<0 else False for d in battery_charge_discharge[start_hour:end_hour]] @@ -243,7 +243,7 @@ If we re-run H2I and set the battery demand equal to the electrolyzer capacity i ```{code-cell} ipython3 # Set the battery demand equal to the rated electrical capacity of the electrolyzer -h2i.prob.set_val("battery.electricity_demand",electrolyzer_capacity_MW, units="MW") +h2i.prob.set_val("battery.electricity_command_value", electrolyzer_capacity_MW, units="MW") # Set the demand of the demand component equal to the rated electrical capacity of the electrolyzer h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") diff --git a/h2integrate/converters/ammonia/ammonia_synloop.py b/h2integrate/converters/ammonia/ammonia_synloop.py index 99aea7a1b..3efd131ea 100644 --- a/h2integrate/converters/ammonia/ammonia_synloop.py +++ b/h2integrate/converters/ammonia/ammonia_synloop.py @@ -189,6 +189,18 @@ def setup(self): self.add_input("nitrogen_in", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") + # Dispatchable models receive a command value from a tech-level controller. + # Auto-injected ``PassthroughController`` or a user-defined control strategy + # supplies this input. The default is a large value so an unconnected run + # leaves raw production uncurtailed. + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Command value for {self.commodity} production from tech controller", + ) + self.add_output("nitrogen_out", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_output("hydrogen_out", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_output("electricity_out", val=0.0, shape=self.n_timesteps, units="kW") @@ -311,6 +323,12 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): cat_mass = np.sum(cat_rate) * cat_replace # kg outputs["ammonia_out"] = nh3_prod + # Apply the command value supplied by the tech-level controller as an upper + # bound on production. Default value is large enough that unconnected runs + # leave the raw production untouched. + outputs[f"{self.commodity}_out"] = np.minimum( + outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] + ) # Unused feedstock only (purge gas now in separate stream) outputs["hydrogen_out"] = h2_in - used_h2 outputs["nitrogen_out"] = n2_in - used_n2 From 520a3767d68cc97a892397aa7647a0e594b1b128 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 08:45:04 -0600 Subject: [PATCH 122/132] Updating tests and components for new command_value paradigm --- h2integrate/converters/grid/test/test_grid.py | 2 +- .../natural_gas/dummy_gas_components.py | 24 +++++++++++++++++++ .../converters/steel/steel_baseclass.py | 12 ++++++++++ .../test/test_storage_performance_model.py | 12 +++++----- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index ebef96214..203647ad6 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -390,7 +390,7 @@ def test_grid_integration_dt_1800(subtests, tmp_path): h2i.setup() demand = np.full(n_timesteps, demand_kw) - h2i.prob.set_val("grid.electricity_demand", demand, units="kW") + h2i.prob.set_val("grid.controller.electricity_set_point", demand, units="kW") h2i.prob.run_model() expected_out = np.full(n_timesteps, demand_kw) diff --git a/h2integrate/converters/natural_gas/dummy_gas_components.py b/h2integrate/converters/natural_gas/dummy_gas_components.py index f35537b74..92fa2143c 100644 --- a/h2integrate/converters/natural_gas/dummy_gas_components.py +++ b/h2integrate/converters/natural_gas/dummy_gas_components.py @@ -82,6 +82,14 @@ def setup(self): # Add all wellhead_gas_mixture stream outputs add_multivariable_output(self, "wellhead_gas_mixture", self.n_timesteps) + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Upper-bound dispatch command for {self.commodity} production.", + ) + def compute(self, inputs, outputs): # Set random seed for reproducibility if specified rng = np.random.default_rng(self.config.random_seed) @@ -132,6 +140,10 @@ def compute(self, inputs, outputs): rated_production * self.n_timesteps * (self.dt / 3600) ) + outputs[f"{self.commodity}_out"] = np.minimum( + outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] + ) + class SimpleGasConsumerPerformance(PerformanceModelBaseClass): """ @@ -163,6 +175,14 @@ def setup(self): # Add all wellhead_gas_mixture stream inputs add_multivariable_input(self, "wellhead_gas_mixture", self.n_timesteps) + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Upper-bound dispatch command for {self.commodity} production.", + ) + # Add some derived outputs self.add_output( "total_gas_consumed", val=0.0, units="kg", desc="Total gas consumed over the simulation" @@ -199,6 +219,10 @@ def compute(self, inputs, outputs): outputs["total_hydrogen_produced"] / max_possible if max_possible > 0 else 0.0 ) + outputs[f"{self.commodity}_out"] = np.minimum( + outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] + ) + @define(kw_only=True) class SimpleGasProducerCostConfig(CostModelBaseConfig): diff --git a/h2integrate/converters/steel/steel_baseclass.py b/h2integrate/converters/steel/steel_baseclass.py index 121ac3087..5f6b79b54 100644 --- a/h2integrate/converters/steel/steel_baseclass.py +++ b/h2integrate/converters/steel/steel_baseclass.py @@ -21,6 +21,18 @@ def setup(self): self.add_input("electricity_in", val=0.0, shape=n_timesteps, units="kW") self.add_input("hydrogen_in", val=0.0, shape=n_timesteps, units="kg/h") + # Dispatchable models receive a command value from a tech-level controller. + # Auto-injected ``PassthroughController`` or a user-defined control strategy + # supplies this input. The default is a large value so an unconnected run + # leaves raw production uncurtailed. + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=n_timesteps, + units=self.commodity_rate_units, + desc=f"Command value for {self.commodity} production from tech controller", + ) + def compute(self, inputs, outputs): """ Computation for the OM component. diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 5daadbb37..0a99ce09f 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -45,7 +45,7 @@ def test_generic_storage_with_simple_control_dmd_lessthan_charge_rate(plant_conf prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -239,7 +239,7 @@ def test_generic_storage_with_simple_control_charge_rate_lessthan_demand(plant_c prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -456,7 +456,7 @@ def test_generic_storage_with_simple_control_zero_size(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -637,7 +637,7 @@ def test_generic_storage_with_simple_control_with_losses(plant_config, subtests) prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -876,7 +876,7 @@ def test_generic_storage_with_simple_control_with_losses_round_trip(plant_config prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -1080,7 +1080,7 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) From e209414acccd8a47ea2ec41b2c3bce03fd0b01b3 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 09:41:59 -0600 Subject: [PATCH 123/132] Updating tests for set-point changes; simplifying sql timeseries test --- examples/16_natural_gas/plant_config.yaml | 4 +- .../ammonia/simple_ammonia_model.py | 12 +++ .../test/test_sql_timeseries_to_csv.py | 92 ++++++++++--------- 3 files changed, 65 insertions(+), 43 deletions(-) diff --git a/examples/16_natural_gas/plant_config.yaml b/examples/16_natural_gas/plant_config.yaml index aa30629f7..d28abbc45 100644 --- a/examples/16_natural_gas/plant_config.yaml +++ b/examples/16_natural_gas/plant_config.yaml @@ -25,8 +25,8 @@ technology_interconnections: - [solar, elec_combiner, electricity, cable] # subtract the combined generation from the demand profile - [elec_combiner, electrical_load_demand, electricity, cable] - # connect the remaining electricity demand to the NG plant - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] + # connect the remaining electricity demand to the NG plant's passthrough controller + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, controller.electricity_set_point]] # connect NG feedstock to NG plant - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect natural gas and solar to finance combiner diff --git a/h2integrate/converters/ammonia/simple_ammonia_model.py b/h2integrate/converters/ammonia/simple_ammonia_model.py index 79e8e2adc..a71f65661 100644 --- a/h2integrate/converters/ammonia/simple_ammonia_model.py +++ b/h2integrate/converters/ammonia/simple_ammonia_model.py @@ -1,3 +1,4 @@ +import numpy as np from attrs import field, define from h2integrate.core.utilities import BaseConfig, merge_shared_inputs @@ -50,6 +51,13 @@ def setup(self): additional_cls_name=self.__class__.__name__, ) self.add_input("hydrogen_in", val=0.0, shape=n_timesteps, units="kg/h") + self.add_input( + f"{self.commodity}_command_value", + val=1.0e9, + shape=n_timesteps, + units=self.commodity_rate_units, + desc=f"Upper-bound dispatch command for {self.commodity} production.", + ) def compute(self, inputs, outputs): ammonia_production_kgpy = ( @@ -64,6 +72,10 @@ def compute(self, inputs, outputs): ) outputs["rated_ammonia_production"] = self.config.plant_capacity_kgpy / 8760 + outputs[f"{self.commodity}_out"] = np.minimum( + outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] + ) + @define(kw_only=True) class AmmoniaCostModelConfig(CostModelBaseConfig): diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index 14a4dbaf3..e4c83d7a4 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -1,33 +1,35 @@ from pathlib import Path -import numpy as np import pytest from pytest import fixture -from h2integrate import H2IntegrateModel, load_yaml, load_tech_yaml, load_driver_yaml +from h2integrate import H2IntegrateModel, load_yaml, load_driver_yaml from h2integrate.postprocess.sql_timeseries_to_csv import save_case_timeseries_as_csv @fixture def configuration(temp_copy_of_example): example_folder = temp_copy_of_example - config = load_yaml(example_folder / "02_texas_ammonia.yaml") + config = load_yaml(example_folder / "natgas.yaml") driver_config = load_driver_yaml(example_folder / "driver_config.yaml") output_folder = example_folder / driver_config["general"]["folder_output"] driver_config["general"]["folder_output"] = str(output_folder) + driver_config["recorder"] = { + "flag": True, + "file": "cases.sql", + "overwrite_recorder": True, + "recorder_attachment": "model", + "includes": ["*"], + "excludes": ["*resource_data*"], + } config["driver_config"] = driver_config - tech_config = load_tech_yaml(example_folder / "tech_config.yaml") - tech_config["technologies"]["wind"]["model_inputs"]["performance_parameters"]["cache_dir"] = ( - str(output_folder) - ) - config["technology_config"] = tech_config return config @fixture -def run_example_02_sql_fpath(configuration): +def run_example_sql_fpath(configuration): # check if case file exists, if so, return the filepath output_folder = ( Path(configuration["driver_config"]["general"]["folder_output"]).resolve().parent @@ -39,11 +41,6 @@ def run_example_02_sql_fpath(configuration): # Create a H2Integrate model h2i = H2IntegrateModel(configuration) - # Set the battery demand profile - demand_profile = np.ones(8760) * 640.0 - h2i.setup() - h2i.prob.set_val("battery.electricity_demand", demand_profile, units="MW") - # Run the model h2i.run() @@ -51,15 +48,17 @@ def run_example_02_sql_fpath(configuration): @pytest.mark.unit -@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) -def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath): +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] +) +def test_save_csv_all_results(subtests, configuration, run_example_sql_fpath): expected_csv_fpath = ( Path(configuration["driver_config"]["general"]["folder_output"]) / "cases_Case-1.csv" ) - res = save_case_timeseries_as_csv(run_example_02_sql_fpath, save_to_file=True) + res = save_case_timeseries_as_csv(run_example_sql_fpath, save_to_file=True) with subtests.test("Check number of columns"): - assert len(res.columns.to_list()) == 61 + assert len(res.columns.to_list()) > 0 with subtests.test("Check number of rows"): assert len(res) == 8760 @@ -69,17 +68,19 @@ def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath) @pytest.mark.unit -@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) -def test_make_df_from_varname_list(subtests, run_example_02_sql_fpath): +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] +) +def test_make_df_from_varname_list(subtests, run_example_sql_fpath): vars_to_save = [ - "electrolyzer.hydrogen_out", - "combiner.electricity_out", - "ammonia.ammonia_out", - "h2_storage.hydrogen_out", + "natural_gas_plant.electricity_out", + "elec_combiner.electricity_out", + "solar.electricity_out", + "battery.electricity_out", ] res = save_case_timeseries_as_csv( - run_example_02_sql_fpath, vars_to_save=vars_to_save, save_to_file=False + run_example_sql_fpath, vars_to_save=vars_to_save, save_to_file=False ) with subtests.test("Check number of columns"): @@ -94,16 +95,18 @@ def test_make_df_from_varname_list(subtests, run_example_02_sql_fpath): @pytest.mark.unit -@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) -def test_make_df_from_varname_unit_dict(subtests, run_example_02_sql_fpath): +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] +) +def test_make_df_from_varname_unit_dict(subtests, run_example_sql_fpath): vars_units_to_save = { - "ammonia.hydrogen_in": "kg/h", - "h2_storage.hydrogen_in": "kg/h", - "electrolyzer.electricity_in": "kW", + "natural_gas_plant.natural_gas_in": "MMBtu/h", + "battery.electricity_in": "kW", + "solar.electricity_out": "kW", } res = save_case_timeseries_as_csv( - run_example_02_sql_fpath, vars_to_save=vars_units_to_save, save_to_file=False + run_example_sql_fpath, vars_to_save=vars_units_to_save, save_to_file=False ) with subtests.test("Check number of columns"): @@ -120,26 +123,33 @@ def test_make_df_from_varname_unit_dict(subtests, run_example_02_sql_fpath): @pytest.mark.unit -@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) -def test_alternative_column_names(subtests, run_example_02_sql_fpath): +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] +) +def test_alternative_column_names(subtests, run_example_sql_fpath): vars_to_save = { - "electrolyzer.hydrogen_out": {"alternative_name": "Electrolyzer Hydrogen Output"}, - "combiner.electricity_out": {"units": "kW", "alternative_name": "Plant Electricity Output"}, - "ammonia.ammonia_out": {"alternative_name": None}, - "h2_storage.hydrogen_out": {"alternative_name": "H2 Storage Hydrogen Output"}, + "natural_gas_plant.electricity_out": { + "alternative_name": "Natural Gas Plant Electricity Output" + }, + "elec_combiner.electricity_out": { + "units": "kW", + "alternative_name": "Plant Electricity Output", + }, + "solar.electricity_out": {"alternative_name": None}, + "battery.electricity_out": {"alternative_name": "Battery Electricity Output"}, } res = save_case_timeseries_as_csv( - run_example_02_sql_fpath, + run_example_sql_fpath, vars_to_save=vars_to_save, save_to_file=False, ) expected_name_list = [ - "Electrolyzer Hydrogen Output (kg/h)", + "Natural Gas Plant Electricity Output (MW)", "Plant Electricity Output (kW)", - "ammonia.ammonia_out (kg/h)", - "H2 Storage Hydrogen Output (kg/h)", + "solar.electricity_out (MW)", + "Battery Electricity Output (MW)", ] with subtests.test("Check number of columns"): From 38abfc2b5c4f51565b2e6ffc5e1e09726f66e809 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 10:13:40 -0600 Subject: [PATCH 124/132] Promoting controller parameters up a level --- h2integrate/converters/grid/test/test_grid.py | 2 +- h2integrate/core/h2integrate_model.py | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index 203647ad6..80d908648 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -390,7 +390,7 @@ def test_grid_integration_dt_1800(subtests, tmp_path): h2i.setup() demand = np.full(n_timesteps, demand_kw) - h2i.prob.set_val("grid.controller.electricity_set_point", demand, units="kW") + h2i.prob.set_val("grid.electricity_set_point", demand, units="kW") h2i.prob.run_model() expected_out = np.full(n_timesteps, demand_kw) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index c5d2d401d..e82dfe376 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -763,11 +763,8 @@ def add_system_level_controller(self, slc_config): # User-defined controllers generally promote ``{commodity}_set_point`` # at the tech-group level, while auto-injected passthrough # controllers expose it at ``controller.{commodity}_set_point``. - tech_cfg = self.technology_config["technologies"][tech_name] - if "control_strategy" in tech_cfg: - tech_set_point_target = f"{tech_name}.{commodity}_set_point" - else: - tech_set_point_target = f"{tech_name}.controller.{commodity}_set_point" + self.technology_config["technologies"][tech_name] + tech_set_point_target = f"{tech_name}.{commodity}_set_point" self.plant.connect( f"system_level_controller.{tech_name}_{commodity}_set_point", @@ -1119,13 +1116,7 @@ def _add_passthrough_controller( commodity_rate_units=commodity_rate_units, ) - # Keep controller I/O unpromoted to avoid promoted-name collisions - # with performance-model ``{commodity}_command_value`` inputs. - om_controller = tech_group.add_subsystem("controller", controller) - tech_group.connect( - f"controller.{commodity}_command_value", - f"{commodity}_command_value", - ) + om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) self.control_strategies.append(om_controller) # Ensure the controller runs before the performance/cost models that From 68bc172c58fbab8d1c57dc1d4be74777916e3499 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 11:00:32 -0600 Subject: [PATCH 125/132] Reverting naming changes --- .../passthrough_controller.py | 31 +++---- .../demand_openloop_storage_controller.py | 6 +- .../storage/openloop_storage_control_base.py | 10 +- .../plm_openloop_storage_controller.py | 6 +- .../storage/simple_openloop_controller.py | 8 +- .../storage/test/test_openloop_controllers.py | 16 ++-- .../test_plm_openloop_storage_controller.py | 4 +- .../system_level/cost_minimization_control.py | 10 +- .../system_level/demand_following_control.py | 6 +- .../profit_maximization_control.py | 8 +- .../system_level/system_level_control_base.py | 53 ++++++----- .../system_level/test/test_slc_controllers.py | 52 +++++------ .../system_level/test/test_slc_examples.py | 10 +- .../converters/ammonia/ammonia_synloop.py | 18 ---- .../ammonia/simple_ammonia_model.py | 12 --- h2integrate/converters/grid/grid.py | 10 +- h2integrate/converters/grid/test/test_grid.py | 14 +-- .../hydrogen/electrolyzer_baseclass.py | 20 ++-- .../converters/hydrogen/h2_fuel_cell.py | 12 +-- .../converters/hydrogen/pem_electrolyzer.py | 11 +-- .../hydrogen/steam_methane_reformer.py | 16 ++-- .../hydrogen/test/test_h2_fuel_cell.py | 6 +- h2integrate/converters/iron/iron_dri_base.py | 12 +-- .../converters/iron/martin_mine_perf_model.py | 14 +-- .../converters/iron/test/test_martin_mine.py | 4 +- .../natural_gas/dummy_gas_components.py | 24 ----- .../natural_gas/natural_gas_cc_ct.py | 16 ++-- .../test/test_natural_gas_models.py | 2 +- .../converters/nuclear/nuclear_plant.py | 6 +- .../nuclear/test/test_nuclear_plant.py | 2 +- .../steel/cmu_electric_arc_furnace_dri.py | 12 +-- .../steel/cmu_electric_arc_furnace_scrap.py | 12 +-- .../converters/steel/steel_baseclass.py | 12 --- .../converters/steel/steel_eaf_base.py | 12 +-- h2integrate/core/h2integrate_model.py | 55 +++++------ h2integrate/core/model_baseclasses.py | 6 +- .../test/test_sql_timeseries_to_csv.py | 92 +++++++++---------- .../battery/test/test_pysam_battery.py | 6 +- .../storage/simple_storage_auto_sizing.py | 12 +-- h2integrate/storage/storage_baseclass.py | 4 +- .../storage/test/test_storage_auto_sizing.py | 6 +- .../test/test_storage_performance_model.py | 28 +++--- 42 files changed, 289 insertions(+), 387 deletions(-) diff --git a/h2integrate/control/control_strategies/passthrough_controller.py b/h2integrate/control/control_strategies/passthrough_controller.py index 9524c137f..a48aabd17 100644 --- a/h2integrate/control/control_strategies/passthrough_controller.py +++ b/h2integrate/control/control_strategies/passthrough_controller.py @@ -2,17 +2,16 @@ class PassthroughController(om.ExplicitComponent): - """Simple controller that forwards set-point to a command value. + """Simple controller that passes a demand signal directly through as a set-point. Every technology group is expected to have a controller subsystem. When a technology does not define its own ``control_strategy``, this passthrough controller is inserted automatically so that the group exposes a uniform - ``{commodity}_set_point`` input and ``{commodity}_command_value`` output - interface. + ``{commodity}_demand`` input and ``{commodity}_set_point`` output interface. In a system-level-control (SLC) configuration the SLC output is connected to - ``{commodity}_set_point``; this component copies that signal to - ``{commodity}_command_value``. + ``{commodity}_demand``; this component copies that signal to + ``{commodity}_set_point`` which the performance model consumes. When no SLC is present the input defaults to a very large value so that production is unconstrained, making the component a harmless no-op. @@ -28,9 +27,9 @@ def initialize(self): types=str, default=None, desc="Units for the commodity rate (e.g. 'kW', 'kg/h'). " - "When provided, explicit units are used on the set-point input " + "When provided, explicit units are used on the demand input " "so the variable works even when unconnected (no SLC). " - "The command-value output always uses units_by_conn to inherit " + "The set-point output always uses units_by_conn to inherit " "units from the connected performance model.", ) @@ -52,38 +51,38 @@ def setup(self): if commodity_rate_units is not None: self.add_input( - f"{commodity}_set_point", + f"{commodity}_demand", val=default_val, shape=n_timesteps, - desc=f"Set-point signal for {commodity}", + desc=f"Demand signal for {commodity}", units=commodity_rate_units, ) else: self.add_input( - f"{commodity}_set_point", + f"{commodity}_demand", val=default_val, shape=n_timesteps, - desc=f"Set-point signal for {commodity}", + desc=f"Demand signal for {commodity}", units_by_conn=True, ) if commodity_rate_units is not None: self.add_output( - f"{commodity}_command_value", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Command value for {commodity} (passthrough of set-point)", + desc=f"Set point for {commodity} (passthrough of demand)", units=commodity_rate_units, ) else: self.add_output( - f"{commodity}_command_value", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Command value for {commodity} (passthrough of set-point)", + desc=f"Set point for {commodity} (passthrough of demand)", units_by_conn=True, ) def compute(self, inputs, outputs): commodity = self.options["commodity"] - outputs[f"{commodity}_command_value"] = inputs[f"{commodity}_set_point"] + outputs[f"{commodity}_set_point"] = inputs[f"{commodity}_demand"] diff --git a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py index baccb95b2..4455fb11e 100644 --- a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py @@ -101,7 +101,7 @@ def compute(self, inputs, outputs): * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_command_value``: Dispatch command to storage, + * ``_set_point``: Dispatch command to storage, negative when charging, positive when discharging. Control logic includes: @@ -140,7 +140,7 @@ def compute(self, inputs, outputs): # the previous time step's value soc = deepcopy(init_soc_fraction) - demand_profile = inputs[f"{commodity}_set_point"] + demand_profile = inputs[f"{commodity}_demand"] # initialize outputs soc_array = np.zeros(self.n_timesteps) @@ -192,4 +192,4 @@ def compute(self, inputs, outputs): # Record the SOC for the current time step soc_array[t] = deepcopy(soc) - outputs[f"{commodity}_command_value"] = set_point_array + outputs[f"{commodity}_set_point"] = set_point_array diff --git a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py index 07c716d20..d7a93c59b 100644 --- a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py +++ b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py @@ -141,7 +141,7 @@ def common_post_init_operations(self): class StorageOpenLoopControlBase(om.ExplicitComponent): """Base OpenMDAO component for open-loop demand tracking. - This component defines the interfaces required for open-loop + This component defines the interfaces required for open-loop demand controllers, including inputs for demand, available commodity, and outputs dispatch command profile. """ @@ -164,11 +164,11 @@ def setup(self): demand_data = self.config.demand_profile self.add_input( - f"{commodity}_set_point", + f"{commodity}_demand", val=demand_data if not isinstance(demand_data, dict) else demand_data["demand"], shape=self.n_timesteps, units=self.config.commodity_rate_units, - desc=f"Set-point profile of {commodity}", + desc=f"Demand profile of {commodity}", ) self.add_input( @@ -180,7 +180,7 @@ def setup(self): ) self.add_output( - f"{commodity}_command_value", + f"{commodity}_set_point", val=0.0, shape=self.n_timesteps, units=self.config.commodity_rate_units, @@ -197,7 +197,7 @@ def compute(): raise NotImplementedError("This method should be implemented in a subclass.") def common_checks_needed_in_compute(self, inputs): - if np.all(inputs[f"{self.config.commodity}_set_point"] == 0.0): + if np.all(inputs[f"{self.config.commodity}_demand"] == 0.0): msg = "Demand profile is zero, check that demand profile is input" raise UserWarning(msg) if inputs["max_charge_rate"][0] < 0: diff --git a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py index 1365237f0..31624ed8a 100644 --- a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py @@ -247,7 +247,7 @@ def compute(self, inputs, outputs): * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_command_value``: Dispatch command to storage, + * ``_set_point``: Dispatch command to storage, negative when charging, positive when discharging. Raises: @@ -279,7 +279,7 @@ def compute(self, inputs, outputs): # Build timestamped demand dictionaries from simulation timeline. demand_profile = self._build_demand_profile_dict( - inputs[f"{commodity}_set_point"], + inputs[f"{commodity}_demand"], self.time_index, ) @@ -381,7 +381,7 @@ def compute(self, inputs, outputs): if soc >= soc_max: charging = False - outputs[f"{commodity}_command_value"] = set_point_array + outputs[f"{commodity}_set_point"] = set_point_array # insert warning message if for any time step the magnitude of # any negative entry in set_point_array is greater than inputs[f"{commodity}_in"] diff --git a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py index 3016b45ed..418a8ec05 100644 --- a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py +++ b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py @@ -72,7 +72,7 @@ def setup(self): def compute(self, inputs, outputs): """ - Simple controller that outputs `commodity_command_value`, + Simple controller that outputs `commodity_set_point`, the dispatch set-points for each timestep in `commodity_rate_units`. Negative values command charging, positive values command discharging. @@ -80,7 +80,7 @@ def compute(self, inputs, outputs): if ( self.config.set_demand_as_avg_commodity_in - and inputs[f"{self.config.commodity}_set_point"].sum() > 0 + and inputs[f"{self.config.commodity}_demand"].sum() > 0 ): msg = ( "A non-zero demand profile was input but set_demand_as_avg_commodity_in is True." @@ -95,11 +95,11 @@ def compute(self, inputs, outputs): self.n_timesteps ) else: - commodity_demand = inputs[f"{self.config.commodity}_set_point"] + commodity_demand = inputs[f"{self.config.commodity}_demand"] # Assign the set point as the difference between the demand and the input commodity # when demand > input, the set point is positive to command discharging # when demand < input, the set point is negative to command charging - outputs[f"{self.config.commodity}_command_value"] = ( + outputs[f"{self.config.commodity}_set_point"] = ( commodity_demand - inputs[f"{self.config.commodity}_in"] ) diff --git a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py index e8eae8f53..350d90c30 100644 --- a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py +++ b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py @@ -81,9 +81,9 @@ def test_pass_through_controller(subtests): # Run the test with subtests.test("Check output"): - expected_command_value = np.mean(np.arange(10)) - np.arange(10) - assert expected_command_value == ( - pytest.approx(prob.get_val("hydrogen_command_value", units="kg/h"), rel=1e-3) + expected_set_point = np.mean(np.arange(10)) - np.arange(10) + assert expected_set_point == ( + pytest.approx(prob.get_val("hydrogen_set_point", units="kg/h"), rel=1e-3) ) @@ -254,14 +254,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_set_point", units="kg/h"), + prob_rte.get_val("hydrogen_demand", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_set_point", units="kg/h"), + prob_ioe.get_val("hydrogen_demand", units="kg/h"), ) ) @@ -396,14 +396,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_set_point", units="kg/h"), + prob_rte.get_val("hydrogen_demand", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_set_point", units="kg/h"), + prob_ioe.get_val("hydrogen_demand", units="kg/h"), ) ) @@ -516,7 +516,7 @@ def test_generic_storage_demand_controller(subtests): unmet_demand, unused_commodity, combined_out_for_demand = calculate_combined_outputs( prob.get_val("hydrogen_out", units="kg/h"), prob.get_val("hydrogen_in", units="kg/h"), - prob.get_val("hydrogen_set_point", units="kg/h"), + prob.get_val("hydrogen_demand", units="kg/h"), ) # # Run the test diff --git a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py index 5c0efb6c2..492510c3c 100644 --- a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py @@ -521,7 +521,7 @@ def test_plm_controller_basic_discharge_before_peak(subtests, tech_config_base, prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_command_value", units="kg/h") + set_point = prob.get_val("hydrogen_set_point", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Discharge occurs before peak (hours 8-9)"): @@ -679,7 +679,7 @@ def test_plm_controller_blocking_charge_in_peak_range( prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_command_value", units="kg/h") + set_point = prob.get_val("hydrogen_set_point", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Controller instantiates and runs without error"): diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index d94c4ca7f..1af7e0eed 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -79,16 +79,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable set-point outputs to zero. - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable demand outputs to zero + for demand_name in self.dispatchable_demand_names: + outputs[demand_name] = np.zeros(self.n_timesteps) # Dispatch in merit order for idx in dispatch_order: - set_point_name = self.dispatchable_set_point_names[idx] + demand_name = self.dispatchable_demand_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] dispatch = np.minimum(remaining, rated) - outputs[set_point_name] = dispatch + outputs[demand_name] = dispatch remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index bb83712d0..15f1e3cda 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -52,8 +52,8 @@ def compute(self, inputs, outputs): ) else: if f"{flexible_tech}_rated_{tech_commodity}_production" in inputs: - # set the per-tech set-point as the rated production - outputs[f"{flexible_tech}_{tech_commodity}_set_point"] = inputs[ + # set the per-tech demand as the rated production + outputs[f"{flexible_tech}_{tech_commodity}_demand"] = inputs[ f"{flexible_tech}_rated_{tech_commodity}_production" ] * np.ones(self.n_timesteps) @@ -80,6 +80,6 @@ def compute(self, inputs, outputs): for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) if commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( + outputs[f"{dispatchable_tech}_{commodity}_demand"] = ( remaining_demand / n_dispatchable ) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 304f10cf7..9275c0fc4 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -139,16 +139,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable set-point outputs to zero. - for set_point_name in self.dispatchable_set_point_names: - outputs[set_point_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable demand outputs to zero + for demand_name in self.dispatchable_demand_names: + outputs[demand_name] = np.zeros(self.n_timesteps) # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: mc = marginal_costs[idx] # per-timestep array profitable = mc < sell_price # boolean mask per timestep - set_point_name = self.dispatchable_set_point_names[idx] + set_point_name = self.dispatchable_demand_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 2f283fb89..11d20fb72 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -14,11 +14,10 @@ class SystemLevelControlBase(om.ExplicitComponent): Subclasses must implement ``compute()`` with their dispatch strategy. Each technology group is expected to contain a controller (either user-defined or an - auto-injected ``PassthroughController``) that consumes a ``{commodity}_set_point`` input and - produces a ``{commodity}_command_value`` that is then consumed by the - technology model. The system-level controller therefore reasons in terms of - *demand* values and emits ``{tech_name}_{commodity}_set_point`` outputs for - every controlled technology. + auto-injected ``PassthroughController``) that consumes a ``{commodity}_demand`` input and + produces the ``{commodity}_set_point`` actually fed to the performance/cost models. The + system-level controller therefore reasons in terms of *demand* values and emits + ``{tech_name}_{commodity}_demand`` outputs for every controlled technology. The SLC demand signal is provided by a demand component (for example, ``GenericDemandComponent``) connected by ``H2IntegrateModel``. When SLC is @@ -147,8 +146,8 @@ def _setup_commodity( (only if ``add_in_name=True``). - Input ``"{tech_name}_rated_{commodity}_production"`` - rated production capacity of the tech. - - Output ``"{tech_name}_{commodity}_set_point"`` - set-point signal sent - to the tech's controller. + - Output ``"{tech_name}_{commodity}_demand"`` - demand signal sent to the + tech's controller (which translates it into a performance-model set-point). Args: tech_name (str): Name of the technology. @@ -161,10 +160,10 @@ def _setup_commodity( add_in_name (bool, optional): If True, register the ``"{tech_name}_{commodity}_out"`` input. Defaults to True. initial_demand (float, optional): Initial value for the - per-tech set-point output. Defaults to 1.0. + demand output. Defaults to 1.0. Returns: - tuple[str, str, str]: ``(in_name, set_point_name, rated_name)`` + tuple[str, str, str]: ``(in_name, demand_name, rated_name)`` """ # --- Determine unit kwargs for add_input / add_output --------- # Either explicit units or copy_units from a reference variable. @@ -176,7 +175,7 @@ def _setup_commodity( # --- Build variable names ------------------------------------- in_name = f"{tech_name}_{commodity}_out" rated_name = f"{tech_name}_rated_{commodity}_production" - set_point_name = f"{tech_name}_{commodity}_set_point" + demand_name = f"{tech_name}_{commodity}_demand" # --- Register inputs and output ------------------------------- if add_in_name: @@ -194,14 +193,14 @@ def _setup_commodity( **unit_kwargs, ) self.add_output( - set_point_name, + demand_name, val=initial_demand, shape=self.n_timesteps, - desc=f"Set point sent to {tech_name} for {commodity}", + desc=f"Demand sent to {tech_name} for {commodity}", **unit_kwargs, ) - return in_name, set_point_name, rated_name + return in_name, demand_name, rated_name def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. @@ -219,7 +218,7 @@ def _setup_tech_category(self, category, tech_list): names produced by the *category* prefix: ``self.{category}_input_names`` - ``self.{category}_set_point_names`` + ``self.{category}_demand_names`` ``self.{category}_rated_names`` ``self.{category}_commodity_names`` @@ -236,7 +235,7 @@ def _setup_tech_category(self, category, tech_list): # --- Initialize the four per-category bookkeeping lists ------- input_names = [] - set_point_names = [] + demand_names = [] rated_names = [] commodity_names = [] @@ -246,7 +245,7 @@ def _setup_tech_category(self, category, tech_list): for commodity in tech_commodities: if commodity in self.commodities_to_units: # Units are already known explicitly - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -255,7 +254,7 @@ def _setup_tech_category(self, category, tech_list): ) elif commodity in self.commodities_to_ref_var: # Units are inferred from a previously-registered reference variable - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -278,7 +277,7 @@ def _setup_tech_category(self, category, tech_list): # variable so later techs with this commodity can # copy its units. self.commodities_to_ref_var[commodity] = in_name - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -288,7 +287,7 @@ def _setup_tech_category(self, category, tech_list): else: # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - in_name, set_point_name, rated_name = self._setup_commodity( + in_name, demand_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -303,12 +302,12 @@ def _setup_tech_category(self, category, tech_list): commodity_names.append(commodity) input_names.append(in_name) - set_point_names.append(set_point_name) + demand_names.append(demand_name) rated_names.append(rated_name) # --- Store lists as self._ attributes ------- setattr(self, f"{category}_input_names", input_names) - setattr(self, f"{category}_set_point_names", set_point_names) + setattr(self, f"{category}_demand_names", demand_names) setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) @@ -454,8 +453,8 @@ def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, if f"{flexible_tech}_rated_{commodity}_production" not in inputs: return - # Set per-tech set-point equal to the rated production of that technology. - outputs[f"{flexible_tech}_{commodity}_set_point"] = inputs[ + # Set per-tech demand equal to the rated production of that technology + outputs[f"{flexible_tech}_{commodity}_demand"] = inputs[ f"{flexible_tech}_rated_{commodity}_production" ] * np.ones(self.n_timesteps) remaining_demand -= inputs[f"{flexible_tech}_{commodity}_out"] @@ -469,15 +468,15 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if f"{storage_tech}_{commodity}_out" not in inputs: return - set_point_name = f"{storage_tech}_{commodity}_set_point" - if set_point_name not in outputs: + demand_name = f"{storage_tech}_{commodity}_demand" + if demand_name not in outputs: return - # Emit a signed charge/discharge set-point: charge when remaining + # Emit a signed charge/discharge demand signal: charge when remaining # demand is negative, discharge when positive. The storage tech's # controller (passthrough by default) forwards this to the performance # model, which interprets the sign as charge or discharge. - outputs[set_point_name] = remaining_demand + outputs[demand_name] = remaining_demand remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index f30ef906a..036e7ee40 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -153,7 +153,7 @@ def test_base_creates_flexible_io(self): # _var_rel2meta uses relative names (no "slc." prefix) assert "wind_electricity_out" in prob.model.slc._var_rel2meta assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta + assert "wind_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_dispatchable_io(self): tech_connections = [["ng", "demand", "electricity", "cable"]] @@ -164,7 +164,7 @@ def test_base_creates_dispatchable_io(self): prob = _build_problem(DemandFollowingControl, plant_config, slc_config) assert "ng_electricity_out" in prob.model.slc._var_rel2meta assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta + assert "ng_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_storage_io(self): tech_connections = [["battery", "demand", "electricity", "cable"]] @@ -176,7 +176,7 @@ def test_base_creates_storage_io(self): assert "battery_electricity_out" in prob.model.slc._var_rel2meta assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta + assert "battery_electricity_demand" in prob.model.slc._var_rel2meta def test_base_creates_demand_input(self): plant_config = _build_plant_config([]) @@ -215,8 +215,8 @@ def test_equal_share_two_dispatchable(self): prob.set_val("slc.ng2_rated_electricity_production", 40000) prob.run_model() - sp1 = prob.get_val("slc.ng1_electricity_set_point") - sp2 = prob.get_val("slc.ng2_electricity_set_point") + sp1 = prob.get_val("slc.ng1_electricity_demand") + sp2 = prob.get_val("slc.ng2_electricity_demand") np.testing.assert_allclose(sp1, 25000) np.testing.assert_allclose(sp2, 25000) @@ -239,7 +239,7 @@ def test_flexible_reduces_demand(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # demand=50k, wind outputs [30k,60k,50k,10k] → remaining = max(0, demand-wind) expected = np.maximum(50000 - np.array([30000, 60000, 50000, 10000]), 0) np.testing.assert_allclose(ng_sp, expected) @@ -267,7 +267,7 @@ def test_storage_absorbs_surplus(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - batt_sp = prob.get_val("slc.battery_electricity_set_point") + batt_sp = prob.get_val("slc.battery_electricity_demand") # demand - wind = [50k-70k, 50k-30k, 0, 0] = [-20k, 20k, 0, 0] expected = np.array([-20000, 20000, 0, 0]) np.testing.assert_allclose(batt_sp, expected) @@ -310,8 +310,8 @@ def test_cheapest_dispatched_first(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap can handle all 50k (rated 80k), so expensive gets 0 np.testing.assert_allclose(cheap_sp, 50000) np.testing.assert_allclose(expensive_sp, 0) @@ -336,8 +336,8 @@ def test_overflow_to_expensive(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap maxes at 30k, expensive picks up remaining 20k np.testing.assert_allclose(cheap_sp, 30000) np.testing.assert_allclose(expensive_sp, 20000) @@ -361,7 +361,7 @@ def test_with_flexible_reduces_dispatch(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # demand 50k - wind 40k = 10k remaining np.testing.assert_allclose(ng_sp, 10000) @@ -394,8 +394,8 @@ def test_unprofitable_tech_not_dispatched(self): prob.set_val("slc.commodity_sell_price", 0.06) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_set_point") - expensive_sp = prob.get_val("slc.expensive_electricity_set_point") + cheap_sp = prob.get_val("slc.cheap_electricity_demand") + expensive_sp = prob.get_val("slc.expensive_electricity_demand") # Cheap (0.03 < 0.06) dispatched up to rated 30k # Expensive (0.08 >= 0.06) NOT dispatched, demand unmet np.testing.assert_allclose(cheap_sp, 30000) @@ -420,8 +420,8 @@ def test_all_profitable(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - a_sp = prob.get_val("slc.a_electricity_set_point") - b_sp = prob.get_val("slc.b_electricity_set_point") + a_sp = prob.get_val("slc.a_electricity_demand") + b_sp = prob.get_val("slc.b_electricity_demand") # Both profitable, cheapest first: a gets 50k (rated 80k), b gets 0 np.testing.assert_allclose(a_sp, 50000) np.testing.assert_allclose(b_sp, 0) @@ -442,7 +442,7 @@ def test_none_profitable(self): prob.set_val("slc.commodity_sell_price", 0.01) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # NG cost (0.05) >= sell price (0.01), not dispatched np.testing.assert_allclose(ng_sp, 0) @@ -462,7 +462,7 @@ def test_sell_price_from_config(self): # Don't set sell_price explicitly — should use config default 0.10 prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # Config sell_price=0.10 > marginal 0.03 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -483,7 +483,7 @@ def test_time_varying_sell_price(self): prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # mc=0.05: profitable when sell>0.05 (hours 0,2), not when sell<0.05 (hours 1,3) np.testing.assert_allclose(ng_sp, [50000, 0, 50000, 0]) @@ -521,7 +521,7 @@ def test_buy_price_scalar(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_set_point") + grid_sp = prob.get_val("slc.grid_electricity_demand") # buy_price=0.04 < sell_price=0.10 → dispatched np.testing.assert_allclose(grid_sp, 50000) @@ -561,7 +561,7 @@ def test_buy_price_time_varying(self): prob.set_val("slc.grid_buy_price", [0.03, 0.08, 0.04, 0.09]) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_set_point") + grid_sp = prob.get_val("slc.grid_electricity_demand") np.testing.assert_allclose(grid_sp, [50000, 0, 50000, 0]) def test_varopex_mode(self): @@ -584,7 +584,7 @@ def test_varopex_mode(self): prob.set_val("slc.gen_electricity_out", np.full(4, 100000.0)) prob.run_model() - gen_sp = prob.get_val("slc.gen_electricity_set_point") + gen_sp = prob.get_val("slc.gen_electricity_demand") # VarOpEx=500k $/yr, production=100MW*4h=400MWh over 4h # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 500k / 876k ≈ 0.571 $/MWh ≈ 0.000571 $/kWh @@ -607,7 +607,7 @@ def test_cost_per_tech_default_zero(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_set_point") + ng_sp = prob.get_val("slc.ng_electricity_demand") # mc=0.0 < sell_price=0.10 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -634,7 +634,7 @@ def test_feedstock_single(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_set_point") + sp = prob.get_val("slc.ng_plant_electricity_demand") # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 1M / 876k ≈ 1.14 $/MWh ≈ 0.00114 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -665,7 +665,7 @@ def test_feedstock_multiple(self): prob.set_val("slc.plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.plant_electricity_set_point") + sp = prob.get_val("slc.plant_electricity_demand") # Total VarOpEx = 800k, annual production = 876,000 MWh # mc ≈ 0.913 $/MWh ≈ 0.000913 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -695,7 +695,7 @@ def test_feedstock_profit_max_unprofitable(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_set_point") + sp = prob.get_val("slc.ng_plant_electricity_demand") # mc = 100M / 876k ≈ 114 $/MWh ≈ 0.114 $/kWh > sell 0.01 → NOT dispatched np.testing.assert_allclose(sp, 0) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 210eebae5..c1dca6375 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -17,7 +17,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -26,7 +26,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + "system_level_controller.natural_gas_plant_electricity_demand", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, @@ -76,7 +76,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -85,7 +85,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") battery_set_point = model.prob.get_val( - "system_level_controller.battery_electricity_set_point", units="kW" + "system_level_controller.battery_electricity_demand", units="kW" ) assert np.allclose(remaining_demand, battery_set_point, rtol=1e-6, atol=1e-8) @@ -94,7 +94,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "battery.electricity_out", units="kW" ) ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" + "system_level_controller.natural_gas_plant_electricity_demand", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, diff --git a/h2integrate/converters/ammonia/ammonia_synloop.py b/h2integrate/converters/ammonia/ammonia_synloop.py index 3efd131ea..99aea7a1b 100644 --- a/h2integrate/converters/ammonia/ammonia_synloop.py +++ b/h2integrate/converters/ammonia/ammonia_synloop.py @@ -189,18 +189,6 @@ def setup(self): self.add_input("nitrogen_in", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") - # Dispatchable models receive a command value from a tech-level controller. - # Auto-injected ``PassthroughController`` or a user-defined control strategy - # supplies this input. The default is a large value so an unconnected run - # leaves raw production uncurtailed. - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=self.n_timesteps, - units=self.commodity_rate_units, - desc=f"Command value for {self.commodity} production from tech controller", - ) - self.add_output("nitrogen_out", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_output("hydrogen_out", val=0.0, shape=self.n_timesteps, units="kg/h") self.add_output("electricity_out", val=0.0, shape=self.n_timesteps, units="kW") @@ -323,12 +311,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): cat_mass = np.sum(cat_rate) * cat_replace # kg outputs["ammonia_out"] = nh3_prod - # Apply the command value supplied by the tech-level controller as an upper - # bound on production. Default value is large enough that unconnected runs - # leave the raw production untouched. - outputs[f"{self.commodity}_out"] = np.minimum( - outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] - ) # Unused feedstock only (purge gas now in separate stream) outputs["hydrogen_out"] = h2_in - used_h2 outputs["nitrogen_out"] = n2_in - used_n2 diff --git a/h2integrate/converters/ammonia/simple_ammonia_model.py b/h2integrate/converters/ammonia/simple_ammonia_model.py index a71f65661..79e8e2adc 100644 --- a/h2integrate/converters/ammonia/simple_ammonia_model.py +++ b/h2integrate/converters/ammonia/simple_ammonia_model.py @@ -1,4 +1,3 @@ -import numpy as np from attrs import field, define from h2integrate.core.utilities import BaseConfig, merge_shared_inputs @@ -51,13 +50,6 @@ def setup(self): additional_cls_name=self.__class__.__name__, ) self.add_input("hydrogen_in", val=0.0, shape=n_timesteps, units="kg/h") - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=n_timesteps, - units=self.commodity_rate_units, - desc=f"Upper-bound dispatch command for {self.commodity} production.", - ) def compute(self, inputs, outputs): ammonia_production_kgpy = ( @@ -72,10 +64,6 @@ def compute(self, inputs, outputs): ) outputs["rated_ammonia_production"] = self.config.plant_capacity_kgpy / 8760 - outputs[f"{self.commodity}_out"] = np.minimum( - outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] - ) - @define(kw_only=True) class AmmoniaCostModelConfig(CostModelBaseConfig): diff --git a/h2integrate/converters/grid/grid.py b/h2integrate/converters/grid/grid.py index 9f73c2d11..2e4d33c7d 100644 --- a/h2integrate/converters/grid/grid.py +++ b/h2integrate/converters/grid/grid.py @@ -42,7 +42,7 @@ class GridPerformanceModel(PerformanceModelBaseClass): Inputs interconnection_size (float): Maximum power capacity for grid connection (kW). electricity_in (array): Power flowing into the grid (selling) (kW). - electricity_command_value (array): Downstream electricity set point (kW). + electricity_set_point (array): Downstream electricity set point (kW). Outputs electricity_out (array): Power flowing out of the grid (buying) (kW). @@ -88,7 +88,7 @@ def setup(self): # Electricity set point from downstream (for buying from grid) self.add_input( - "electricity_command_value", + "electricity_set_point", val=0.0, shape=n_timesteps, units=self.commodity_rate_units, @@ -137,13 +137,11 @@ def compute(self, inputs, outputs): outputs["electricity_sold"] = electricity_sold # Buying: electricity flows out of grid to meet set point, limited by interconnection - electricity_bought = np.clip(inputs["electricity_command_value"], 0, interconnection_size) + electricity_bought = np.clip(inputs["electricity_set_point"], 0, interconnection_size) outputs["electricity_out"] = electricity_bought # Unmet demand if set point exceeds interconnection size - outputs["electricity_unmet_demand"] = ( - inputs["electricity_command_value"] - electricity_bought - ) + outputs["electricity_unmet_demand"] = inputs["electricity_set_point"] - electricity_bought # Not sold electricity if demand exceeds interconnection size outputs["electricity_excess"] = inputs["electricity_in"] - electricity_sold diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index 80d908648..a66b9cb0d 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -45,7 +45,7 @@ def test_grid_performance_outputs(plant_config, subtests): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("comp.electricity_command_value", demand) + prob.set_val("comp.electricity_set_point", demand) prob.run_model() @@ -148,7 +148,7 @@ def test_buying_electricity(plant_config, n_timesteps): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("grid.electricity_command_value", demand) + prob.set_val("grid.electricity_set_point", demand) prob.run_model() @@ -177,7 +177,7 @@ def test_buying_with_interconnection_limit(plant_config, n_timesteps): # Set demand above interconnection limit demand = np.full(n_timesteps, 60000.0) # 60 MW demand - prob.set_val("grid.electricity_command_value", demand) + prob.set_val("grid.electricity_set_point", demand) prob.run_model() @@ -247,7 +247,7 @@ def test_simultaneous_buy_and_sell(plant_config, n_timesteps): electricity_demand = np.full(n_timesteps, 40000.0) # 40 MW out prob.set_val("grid.electricity_in", electricity_in) - prob.set_val("grid.electricity_command_value", electricity_demand) + prob.set_val("grid.electricity_set_point", electricity_demand) prob.run_model() @@ -272,7 +272,7 @@ def test_varying_demand_profile(plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_command_value", demand) + prob.set_val("grid.electricity_set_point", demand) prob.run_model() @@ -302,7 +302,7 @@ def test_non_hourly_dt_demand_profile(subtests, plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_command_value", demand, units="kW") + prob.set_val("grid.electricity_set_point", demand, units="kW") prob.run_model() @@ -390,7 +390,7 @@ def test_grid_integration_dt_1800(subtests, tmp_path): h2i.setup() demand = np.full(n_timesteps, demand_kw) - h2i.prob.set_val("grid.electricity_set_point", demand, units="kW") + h2i.prob.set_val("grid.electricity_demand", demand, units="kW") h2i.prob.run_model() expected_out = np.full(n_timesteps, demand_kw) diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index 9e1d9b3fb..94a5a50a2 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -23,17 +23,15 @@ def setup(self): # Define inputs for electricity self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") - # Dispatchable models receive a command value from a tech-level controller. - # Auto-injected ``PassthroughController`` or a user-defined control strategy - # supplies this input. The default is a large value so an unconnected run - # leaves raw production uncurtailed. - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=self.n_timesteps, - units=self.commodity_rate_units, - desc=f"Command value for {self.commodity} production from tech controller", - ) + # Dispatchable models receive a set_point from the system-level controller + if "system_level_control" in self.options["plant_config"]: + self.add_input( + f"{self.commodity}_set_point", + val=0.0, + shape=self.n_timesteps, + units=self.commodity_rate_units, + desc=f"Set point for {self.commodity} production from SLC", + ) def compute(self, inputs, outputs): """ diff --git a/h2integrate/converters/hydrogen/h2_fuel_cell.py b/h2integrate/converters/hydrogen/h2_fuel_cell.py index 773bfde9e..36d2c1a76 100644 --- a/h2integrate/converters/hydrogen/h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/h2_fuel_cell.py @@ -92,7 +92,7 @@ def setup(self): # Default the electricity set point input as the rated capacity self.add_input( - f"{self.commodity}_command_value", + f"{self.commodity}_set_point", val=self.config.system_capacity_kw, shape=self.n_timesteps, units=self.commodity_rate_units, @@ -106,7 +106,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing hydrogen_in, fuel cell - HHV efficiency, electricity_command_value, and system_capacity. + HHV efficiency, electricity_set_point, and system_capacity. outputs: OpenMDAO outputs object for electricity_out, hydrogen_consumed. """ @@ -122,13 +122,13 @@ def compute(self, inputs, outputs): max_h2_consumption = system_capacity * kw_to_kgh_h2 # electrical set point, saturated at maximum rated system capacity - electricity_command_value = np.where( - inputs["electricity_command_value"] > system_capacity, + electricity_set_point = np.where( + inputs["electricity_set_point"] > system_capacity, system_capacity, - inputs["electricity_command_value"], + inputs["electricity_set_point"], ) - h2_demand = electricity_command_value * kw_to_kgh_h2 + h2_demand = electricity_set_point * kw_to_kgh_h2 # available feedstock, saturated at maximum system feedstock consumption h2_available = np.where( diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 1dc2aa037..0c5aada06 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -223,9 +223,8 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): "Annual O2 Production [kg/year]" ] - # Apply the command value supplied by the tech-level controller as an upper - # bound on production. Default value is large enough that unconnected runs - # leave the raw production untouched. - outputs[f"{self.commodity}_out"] = np.minimum( - outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] - ) + # Apply set_point from system-level controller if present + if "system_level_control" in self.options["plant_config"]: + set_point = inputs[f"{self.commodity}_set_point"] + commodity_out_key = f"{self.commodity}_out" + outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], set_point) diff --git a/h2integrate/converters/hydrogen/steam_methane_reformer.py b/h2integrate/converters/hydrogen/steam_methane_reformer.py index 84a13e5bf..b469cbd8a 100644 --- a/h2integrate/converters/hydrogen/steam_methane_reformer.py +++ b/h2integrate/converters/hydrogen/steam_methane_reformer.py @@ -91,7 +91,7 @@ def setup(self): # Default the hydrogen set point input as the rated capacity self.add_input( - f"{self.commodity}_command_value", + f"{self.commodity}_set_point", val=self.config.system_capacity_tonnes_per_day * (1000 / 24), # convert t/d to kg/h shape=n_timesteps, units=self.commodity_rate_units, @@ -169,7 +169,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, natural_gas_usage_rate, electricity_usage_rate, - system_capacity, and hydrogen_command_value. + system_capacity, and hydrogen_set_point. outputs: OpenMDAO outputs object for hydrogen_out, natural_gas_consumed, electricity_consumed, and unmet_hydrogen_demand. """ @@ -184,13 +184,13 @@ def compute(self, inputs, outputs): max_electricity_consumption = system_capacity_kg_per_hour * electricity_usage_kWh_per_kg # hydrogen set point, saturated at maximum rated system capacity - hydrogen_command_value = np.where( - inputs["hydrogen_command_value"] > system_capacity_kg_per_hour, + hydrogen_set_point = np.where( + inputs["hydrogen_set_point"] > system_capacity_kg_per_hour, system_capacity_kg_per_hour, - inputs["hydrogen_command_value"], + inputs["hydrogen_set_point"], ) - natural_gas_demand = hydrogen_command_value * natural_gas_usage_mmbtu_per_kg - electricity_demand = hydrogen_command_value * electricity_usage_kWh_per_kg + natural_gas_demand = hydrogen_set_point * natural_gas_usage_mmbtu_per_kg + electricity_demand = hydrogen_set_point * electricity_usage_kWh_per_kg # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -242,7 +242,7 @@ def compute(self, inputs, outputs): outputs["annual_hydrogen_produced"] = outputs["total_hydrogen_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_hydrogen_demand"] = inputs["hydrogen_command_value"] - hydrogen_out + outputs["unmet_hydrogen_demand"] = inputs["hydrogen_set_point"] - hydrogen_out outputs["total_energy_conversion_ratio"] = total_energy_conversion_ratio diff --git a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py index c15faa79a..2a49f9cbe 100644 --- a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py @@ -148,10 +148,10 @@ def test_fuel_cell_demand(tech_config, plant_config, subtests): prob.set_val("fuel_cell.hydrogen_in", hydrogen_input, units="kg/h") - elec_command_value = np.ones(n_timesteps) * 1000.0 # kW + elec_set_point = np.ones(n_timesteps) * 1000.0 # kW # Set first 6 timesteps to test edge cases for set point - elec_command_value[:6] = ( + elec_set_point[:6] = ( 1000.0, # test case with set point equal to system capacity 500.0, # test case with set point below system capacity 1000.0, # test case with set point equal to system capacity @@ -160,7 +160,7 @@ def test_fuel_cell_demand(tech_config, plant_config, subtests): 0.0, # test case with set point equal to zero ) - prob.set_val("fuel_cell.electricity_command_value", elec_command_value, units="kW") + prob.set_val("fuel_cell.electricity_set_point", elec_set_point, units="kW") prob.run_model() diff --git a/h2integrate/converters/iron/iron_dri_base.py b/h2integrate/converters/iron/iron_dri_base.py index c0d6b4500..b9ac1348b 100644 --- a/h2integrate/converters/iron/iron_dri_base.py +++ b/h2integrate/converters/iron/iron_dri_base.py @@ -78,7 +78,7 @@ def setup(self): # Default the sponge iron set point input as the rated capacity self.add_input( - "sponge_iron_command_value", + "sponge_iron_set_point", val=self.config.sponge_iron_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", @@ -226,19 +226,19 @@ def compute(self, inputs, outputs): ]["Value"].sum() # sponge iron set point, saturated at maximum rated system capacity - sponge_iron_command_value = np.where( - inputs["sponge_iron_command_value"] > inputs["system_capacity"], + sponge_iron_set_point = np.where( + inputs["sponge_iron_set_point"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["sponge_iron_command_value"], + inputs["sponge_iron_set_point"], ) # initialize an array of how much sponge iron could be produced # from the available feedstocks and the set point sponge_iron_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_command_value"])) + (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_set_point"])) ) # first entry is the sponge iron set point - sponge_iron_from_feedstocks[0] = sponge_iron_command_value + sponge_iron_from_feedstocks[0] = sponge_iron_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/converters/iron/martin_mine_perf_model.py b/h2integrate/converters/iron/martin_mine_perf_model.py index d0308bda9..b5084de4a 100644 --- a/h2integrate/converters/iron/martin_mine_perf_model.py +++ b/h2integrate/converters/iron/martin_mine_perf_model.py @@ -79,7 +79,7 @@ def setup(self): # Default the ore set point input as the rated capacity self.add_input( - "iron_ore_command_value", + "iron_ore_set_point", val=self.config.max_ore_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", @@ -204,10 +204,10 @@ def compute(self, inputs, outputs): max_energy_consumption = inputs["system_capacity"] * energy_usage_per_processed_ore # iron ore set point, saturated at maximum rated system capacity - processed_ore_command_value = np.where( - inputs["iron_ore_command_value"] > inputs["system_capacity"], + processed_ore_set_point = np.where( + inputs["iron_ore_set_point"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["iron_ore_command_value"], + inputs["iron_ore_set_point"], ) # available feedstocks, saturated at maximum system feedstock consumption @@ -229,11 +229,7 @@ def compute(self, inputs, outputs): # output is minimum between available feedstocks and output set point processed_ore_production = np.minimum.reduce( - [ - processed_ore_from_crude_ore, - processed_ore_from_electricity, - processed_ore_command_value, - ] + [processed_ore_from_crude_ore, processed_ore_from_electricity, processed_ore_set_point] ) # energy consumption diff --git a/h2integrate/converters/iron/test/test_martin_mine.py b/h2integrate/converters/iron/test/test_martin_mine.py index 052a51179..a1865eb4d 100644 --- a/h2integrate/converters/iron/test/test_martin_mine.py +++ b/h2integrate/converters/iron/test/test_martin_mine.py @@ -41,7 +41,7 @@ def test_iron_mine_performance_outputs( prob.set_val("comp.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("comp.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("comp.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("comp.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() commodity = "iron_ore" @@ -152,7 +152,7 @@ def test_baseline_iron_ore_costs(plant_config, driver_config, iron_ore_config_ma prob.set_val("ore_perf.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("ore_perf.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("ore_perf.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("ore_perf.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() diff --git a/h2integrate/converters/natural_gas/dummy_gas_components.py b/h2integrate/converters/natural_gas/dummy_gas_components.py index 92fa2143c..f35537b74 100644 --- a/h2integrate/converters/natural_gas/dummy_gas_components.py +++ b/h2integrate/converters/natural_gas/dummy_gas_components.py @@ -82,14 +82,6 @@ def setup(self): # Add all wellhead_gas_mixture stream outputs add_multivariable_output(self, "wellhead_gas_mixture", self.n_timesteps) - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=self.n_timesteps, - units=self.commodity_rate_units, - desc=f"Upper-bound dispatch command for {self.commodity} production.", - ) - def compute(self, inputs, outputs): # Set random seed for reproducibility if specified rng = np.random.default_rng(self.config.random_seed) @@ -140,10 +132,6 @@ def compute(self, inputs, outputs): rated_production * self.n_timesteps * (self.dt / 3600) ) - outputs[f"{self.commodity}_out"] = np.minimum( - outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] - ) - class SimpleGasConsumerPerformance(PerformanceModelBaseClass): """ @@ -175,14 +163,6 @@ def setup(self): # Add all wellhead_gas_mixture stream inputs add_multivariable_input(self, "wellhead_gas_mixture", self.n_timesteps) - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=self.n_timesteps, - units=self.commodity_rate_units, - desc=f"Upper-bound dispatch command for {self.commodity} production.", - ) - # Add some derived outputs self.add_output( "total_gas_consumed", val=0.0, units="kg", desc="Total gas consumed over the simulation" @@ -219,10 +199,6 @@ def compute(self, inputs, outputs): outputs["total_hydrogen_produced"] / max_possible if max_possible > 0 else 0.0 ) - outputs[f"{self.commodity}_out"] = np.minimum( - outputs[f"{self.commodity}_out"], inputs[f"{self.commodity}_command_value"] - ) - @define(kw_only=True) class SimpleGasProducerCostConfig(CostModelBaseConfig): diff --git a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py index 94bfafd31..21bb091ff 100644 --- a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py +++ b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py @@ -48,7 +48,7 @@ class NaturalGasPerformanceModel(PerformanceModelBaseClass): system_capacity (float): Natural gas plant rated capacity in MW natural_gas_in (array): Natural gas input energy in MMBtu/h heat_rate_mmbtu_per_mwh (float): Plant heat rate in MMBtu/MWh - electricity_command_value (array): Electricity set point in MW for each timestep + electricity_set_point (array): Electricity set point in MW for each timestep Outputs: electricity_out (array): Electricity output in MW for each timestep @@ -104,7 +104,7 @@ def setup(self): # Default the electricity set point input as the rated capacity self.add_input( - f"{self.commodity}_command_value", + f"{self.commodity}_set_point", val=self.config.system_capacity_mw, shape=n_timesteps, units=self.commodity_rate_units, @@ -138,7 +138,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, heat_rate_mmbtu_per_mwh, - system_capacity, and electricity_command_value. + system_capacity, and electricity_set_point. outputs: OpenMDAO outputs object for electricity_out, natural_gas_consumed, and unmet_electricity_demand. """ @@ -149,12 +149,12 @@ def compute(self, inputs, outputs): max_natural_gas_consumption = system_capacity * heat_rate_mmbtu_per_mwh # electrical set point, saturated at maximum rated system capacity - electricity_command_value = np.where( - inputs["electricity_command_value"] > system_capacity, + electricity_set_point = np.where( + inputs["electricity_set_point"] > system_capacity, system_capacity, - inputs["electricity_command_value"], + inputs["electricity_set_point"], ) - natural_gas_demand = electricity_command_value * heat_rate_mmbtu_per_mwh + natural_gas_demand = electricity_set_point * heat_rate_mmbtu_per_mwh # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -181,7 +181,7 @@ def compute(self, inputs, outputs): outputs["annual_electricity_produced"] = outputs["total_electricity_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_electricity_demand"] = inputs["electricity_command_value"] - electricity_out + outputs["unmet_electricity_demand"] = inputs["electricity_set_point"] - electricity_out @define(kw_only=True) diff --git a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py index 3fd3b079b..0027989a9 100644 --- a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py +++ b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py @@ -375,7 +375,7 @@ def test_ngcc_performance_demand(plant_config, ngcc_performance_params, subtests # Set the natural gas input prob.set_val("natural_gas_in", natural_gas_input) - prob.set_val("electricity_command_value", electricity_demand_MW) + prob.set_val("electricity_set_point", electricity_demand_MW) prob.run_model() electricity_out = prob.get_val("electricity_out", units="MW") diff --git a/h2integrate/converters/nuclear/nuclear_plant.py b/h2integrate/converters/nuclear/nuclear_plant.py index 869fb8e0f..836d9ce52 100644 --- a/h2integrate/converters/nuclear/nuclear_plant.py +++ b/h2integrate/converters/nuclear/nuclear_plant.py @@ -61,7 +61,7 @@ def setup(self): desc="Nuclear plant rated capacity", ) self.add_input( - f"{self.commodity}_command_value", + f"{self.commodity}_set_point", val=self.config.system_capacity_kw, shape=n_timesteps, units=self.commodity_rate_units, @@ -70,9 +70,9 @@ def setup(self): def compute(self, inputs, outputs): system_capacity = inputs["system_capacity"] - electricity_command_value = inputs[f"{self.commodity}_command_value"] + electricity_set_point = inputs[f"{self.commodity}_set_point"] - electricity_out = np.minimum(electricity_command_value, system_capacity) + electricity_out = np.minimum(electricity_set_point, system_capacity) electricity_out = np.clip(electricity_out, 0.0, system_capacity) outputs["electricity_out"] = electricity_out diff --git a/h2integrate/converters/nuclear/test/test_nuclear_plant.py b/h2integrate/converters/nuclear/test/test_nuclear_plant.py index 7f6221512..6c143693e 100644 --- a/h2integrate/converters/nuclear/test/test_nuclear_plant.py +++ b/h2integrate/converters/nuclear/test/test_nuclear_plant.py @@ -64,7 +64,7 @@ def test_nuclear_performance_demand(plant_config, nuclear_performance_params, su prob.model.add_subsystem("nuc_perf", perf_comp, promotes=["*"]) prob.setup() - prob.set_val("electricity_command_value", electricity_demand) + prob.set_val("electricity_set_point", electricity_demand) prob.run_model() electricity_out = prob.get_val("electricity_out") diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py index fb1424e19..bcdb78223 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py @@ -180,7 +180,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_command_value", + "steel_set_point", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -328,19 +328,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_command_value = np.where( - inputs["steel_command_value"] > system_production, + steel_set_point = np.where( + inputs["steel_set_point"] > system_production, system_production, - inputs["steel_command_value"], + inputs["steel_set_point"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_command_value + steel_from_feedstocks[0] = steel_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py index 6cf36e32d..a6ed8debe 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py @@ -142,7 +142,7 @@ def setup(self): # Default the steel demand input as the production rate self.add_input( - "steel_command_value", + "steel_set_point", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), @@ -260,19 +260,19 @@ def compute(self, inputs, outputs): } # steel demand, saturated at maximum rated system capacity - steel_command_value = np.where( - inputs["steel_command_value"] > system_production, + steel_set_point = np.where( + inputs["steel_set_point"] > system_production, system_production, - inputs["steel_command_value"], + inputs["steel_set_point"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the demand steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) ) # first entry is the steel demand - steel_from_feedstocks[0] = steel_command_value + steel_from_feedstocks[0] = steel_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/steel_baseclass.py b/h2integrate/converters/steel/steel_baseclass.py index 5f6b79b54..121ac3087 100644 --- a/h2integrate/converters/steel/steel_baseclass.py +++ b/h2integrate/converters/steel/steel_baseclass.py @@ -21,18 +21,6 @@ def setup(self): self.add_input("electricity_in", val=0.0, shape=n_timesteps, units="kW") self.add_input("hydrogen_in", val=0.0, shape=n_timesteps, units="kg/h") - # Dispatchable models receive a command value from a tech-level controller. - # Auto-injected ``PassthroughController`` or a user-defined control strategy - # supplies this input. The default is a large value so an unconnected run - # leaves raw production uncurtailed. - self.add_input( - f"{self.commodity}_command_value", - val=1.0e9, - shape=n_timesteps, - units=self.commodity_rate_units, - desc=f"Command value for {self.commodity} production from tech controller", - ) - def compute(self, inputs, outputs): """ Computation for the OM component. diff --git a/h2integrate/converters/steel/steel_eaf_base.py b/h2integrate/converters/steel/steel_eaf_base.py index 8c6684536..8fdd9e131 100644 --- a/h2integrate/converters/steel/steel_eaf_base.py +++ b/h2integrate/converters/steel/steel_eaf_base.py @@ -79,7 +79,7 @@ def setup(self): # Default the steel set point input as the rated capacity self.add_input( - "steel_command_value", + "steel_set_point", val=self.config.steel_production_rate_tonnes_per_hr, shape=n_timesteps, units=self.commodity_rate_units, @@ -232,19 +232,19 @@ def compute(self, inputs, outputs): ].sum() # t/t # steel set point, saturated at maximum rated system capacity - steel_command_value = np.where( - inputs["steel_command_value"] > inputs["system_capacity"], + steel_set_point = np.where( + inputs["steel_set_point"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["steel_command_value"], + inputs["steel_set_point"], ) # initialize an array of how much steel could be produced # from the available feedstocks and the set point steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["steel_command_value"])) + (len(feedstocks_usage_rates) + 1, len(inputs["steel_set_point"])) ) # first entry is the steel set point - steel_from_feedstocks[0] = steel_command_value + steel_from_feedstocks[0] = steel_set_point ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index e82dfe376..5ed23e539 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -637,11 +637,11 @@ def add_system_level_controller(self, slc_config): - **Flexible / dispatchable / storage techs**: Both the commodity output (``{tech_name}.{commodity}_out``) and rated production (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. - The controller's per-tech ``{tech_name}_{commodity}_set_point`` output is - connected to the tech group's ``{commodity}_set_point`` input. Every controlled + The controller's per-tech ``{tech_name}_{commodity}_demand`` output is then + connected to the tech group's ``{commodity}_demand`` input. Every controlled tech group is expected to expose this input — either via a user-defined ``control_strategy`` or via the auto-injected ``PassthroughController`` — which - converts the set-point signal into the appropriate performance-model command value. + converts the demand signal into the appropriate performance-model set-point. 4. **Connect marginal-cost inputs for cost-aware strategies** - Only executed when ``control_strategy`` is ``"CostMinimizationControl"`` or @@ -759,16 +759,13 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_{commodity}_storage_duration", ) - # Route SLC per-tech set-point to the technology controller input. - # User-defined controllers generally promote ``{commodity}_set_point`` - # at the tech-group level, while auto-injected passthrough - # controllers expose it at ``controller.{commodity}_set_point``. - self.technology_config["technologies"][tech_name] - tech_set_point_target = f"{tech_name}.{commodity}_set_point" - + # Every controlled tech group exposes a ``{commodity}_demand`` + # input (provided by either a user-defined control_strategy or an + # auto-injected PassthroughController). Route the SLC's per-tech + # demand output to that input. self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_set_point", - tech_set_point_target, + f"system_level_controller.{tech_name}_{commodity}_demand", + f"{tech_name}.{commodity}_demand", ) # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - @@ -934,11 +931,7 @@ def create_technology_models(self): self.cost_models.append(om_model_object) self.finance_models.append(om_model_object) - self._add_passthrough_controller( - tech_group, - comp, - individual_tech_config, - ) + self._add_passthrough_controller(tech_group, comp, individual_tech_config) continue @@ -976,9 +969,7 @@ def create_technology_models(self): if perf_om_object is not None: self._add_passthrough_controller( - tech_group, - perf_om_object, - individual_tech_config, + tech_group, perf_om_object, individual_tech_config ) # Process the finance models @@ -1053,12 +1044,7 @@ def _check_control_classifier(self, model_name, model_object): msg = f"Model {model_name} is missing a control classifier" raise ValueError(msg) - def _add_passthrough_controller( - self, - tech_group, - perf_comp, - individual_tech_config, - ): + def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_config): """Automatically add a PassthroughController to a tech group if appropriate. A controller is auto-inserted only when: @@ -1069,10 +1055,10 @@ def _add_passthrough_controller( attributes (typically set in its ``initialize()``), or those values can be read from the individual tech config. - The controller consumes ``controller.{commodity}_set_point`` and emits - ``controller.{commodity}_command_value``. The command value is - explicitly connected to the technology group's promoted - ``{commodity}_command_value`` input consumed by the performance model. + The controller's ``{commodity}_demand`` input becomes the tech group's + external demand-input promoted at the tech group level, and its + ``{commodity}_set_point`` output is auto-connected (via promotion) to the + performance model's ``{commodity}_set_point`` input if one exists. """ # Skip if the user has already specified a control strategy for this tech; # their explicit choice takes precedence over the auto-injected passthrough. @@ -1116,13 +1102,18 @@ def _add_passthrough_controller( commodity_rate_units=commodity_rate_units, ) + # Promote all controller variables so: + # - `{commodity}_demand` becomes the tech group's external input + # (this is what the system-level controller connects to), and + # - `{commodity}_set_point` is auto-connected by name to the + # performance model's matching input via promotion. om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) self.control_strategies.append(om_controller) # Ensure the controller runs before the performance/cost models that - # consume its command_value output. Subsystem creation order otherwise + # consume its set_point output. Subsystem creation order otherwise # places the controller last in the group's execution order, which - # would delay the control signal by one solver iteration. + # would delay the set_point by one solver iteration. existing_order = list(tech_group._static_subsystems_allprocs.keys()) if "controller" in existing_order: new_order = ["controller"] + [n for n in existing_order if n != "controller"] diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index 687771d88..ac2f34dfc 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -102,7 +102,7 @@ def setup(self): # Flexible models get additional I/O for set_point-based curtailment if getattr(self, "_control_classifier", None) == "flexible": self.add_input( - f"{self.commodity}_command_value", + f"{self.commodity}_set_point", val=1.0, shape=self.n_timesteps, units=self.commodity_rate_units, @@ -117,7 +117,7 @@ def setup(self): ) def apply_curtailment(self, outputs): - """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_command_value``. + """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_set_point``. Copies the current ``{commodity}_out`` into ``uncurtailed_{commodity}_out``, then clips ``{commodity}_out`` to ``min(uncurtailed, set_point)`` element-wise. @@ -132,7 +132,7 @@ def apply_curtailment(self, outputs): commodity_out_key = f"{self.commodity}_out" uncurtailed_key = f"uncurtailed_{self.commodity}_out" - set_point_key = f"{self.commodity}_command_value" + set_point_key = f"{self.commodity}_set_point" uncurtailed = np.array(outputs[commodity_out_key]) outputs[uncurtailed_key] = uncurtailed diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index e4c83d7a4..14a4dbaf3 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -1,35 +1,33 @@ from pathlib import Path +import numpy as np import pytest from pytest import fixture -from h2integrate import H2IntegrateModel, load_yaml, load_driver_yaml +from h2integrate import H2IntegrateModel, load_yaml, load_tech_yaml, load_driver_yaml from h2integrate.postprocess.sql_timeseries_to_csv import save_case_timeseries_as_csv @fixture def configuration(temp_copy_of_example): example_folder = temp_copy_of_example - config = load_yaml(example_folder / "natgas.yaml") + config = load_yaml(example_folder / "02_texas_ammonia.yaml") driver_config = load_driver_yaml(example_folder / "driver_config.yaml") output_folder = example_folder / driver_config["general"]["folder_output"] driver_config["general"]["folder_output"] = str(output_folder) - driver_config["recorder"] = { - "flag": True, - "file": "cases.sql", - "overwrite_recorder": True, - "recorder_attachment": "model", - "includes": ["*"], - "excludes": ["*resource_data*"], - } config["driver_config"] = driver_config + tech_config = load_tech_yaml(example_folder / "tech_config.yaml") + tech_config["technologies"]["wind"]["model_inputs"]["performance_parameters"]["cache_dir"] = ( + str(output_folder) + ) + config["technology_config"] = tech_config return config @fixture -def run_example_sql_fpath(configuration): +def run_example_02_sql_fpath(configuration): # check if case file exists, if so, return the filepath output_folder = ( Path(configuration["driver_config"]["general"]["folder_output"]).resolve().parent @@ -41,6 +39,11 @@ def run_example_sql_fpath(configuration): # Create a H2Integrate model h2i = H2IntegrateModel(configuration) + # Set the battery demand profile + demand_profile = np.ones(8760) * 640.0 + h2i.setup() + h2i.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + # Run the model h2i.run() @@ -48,17 +51,15 @@ def run_example_sql_fpath(configuration): @pytest.mark.unit -@pytest.mark.parametrize( - "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] -) -def test_save_csv_all_results(subtests, configuration, run_example_sql_fpath): +@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) +def test_save_csv_all_results(subtests, configuration, run_example_02_sql_fpath): expected_csv_fpath = ( Path(configuration["driver_config"]["general"]["folder_output"]) / "cases_Case-1.csv" ) - res = save_case_timeseries_as_csv(run_example_sql_fpath, save_to_file=True) + res = save_case_timeseries_as_csv(run_example_02_sql_fpath, save_to_file=True) with subtests.test("Check number of columns"): - assert len(res.columns.to_list()) > 0 + assert len(res.columns.to_list()) == 61 with subtests.test("Check number of rows"): assert len(res) == 8760 @@ -68,19 +69,17 @@ def test_save_csv_all_results(subtests, configuration, run_example_sql_fpath): @pytest.mark.unit -@pytest.mark.parametrize( - "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] -) -def test_make_df_from_varname_list(subtests, run_example_sql_fpath): +@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) +def test_make_df_from_varname_list(subtests, run_example_02_sql_fpath): vars_to_save = [ - "natural_gas_plant.electricity_out", - "elec_combiner.electricity_out", - "solar.electricity_out", - "battery.electricity_out", + "electrolyzer.hydrogen_out", + "combiner.electricity_out", + "ammonia.ammonia_out", + "h2_storage.hydrogen_out", ] res = save_case_timeseries_as_csv( - run_example_sql_fpath, vars_to_save=vars_to_save, save_to_file=False + run_example_02_sql_fpath, vars_to_save=vars_to_save, save_to_file=False ) with subtests.test("Check number of columns"): @@ -95,18 +94,16 @@ def test_make_df_from_varname_list(subtests, run_example_sql_fpath): @pytest.mark.unit -@pytest.mark.parametrize( - "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] -) -def test_make_df_from_varname_unit_dict(subtests, run_example_sql_fpath): +@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) +def test_make_df_from_varname_unit_dict(subtests, run_example_02_sql_fpath): vars_units_to_save = { - "natural_gas_plant.natural_gas_in": "MMBtu/h", - "battery.electricity_in": "kW", - "solar.electricity_out": "kW", + "ammonia.hydrogen_in": "kg/h", + "h2_storage.hydrogen_in": "kg/h", + "electrolyzer.electricity_in": "kW", } res = save_case_timeseries_as_csv( - run_example_sql_fpath, vars_to_save=vars_units_to_save, save_to_file=False + run_example_02_sql_fpath, vars_to_save=vars_units_to_save, save_to_file=False ) with subtests.test("Check number of columns"): @@ -123,33 +120,26 @@ def test_make_df_from_varname_unit_dict(subtests, run_example_sql_fpath): @pytest.mark.unit -@pytest.mark.parametrize( - "example_folder,resource_example_folder", [("16_natural_gas", "11_hybrid_energy_plant")] -) -def test_alternative_column_names(subtests, run_example_sql_fpath): +@pytest.mark.parametrize("example_folder,resource_example_folder", [("02_texas_ammonia", None)]) +def test_alternative_column_names(subtests, run_example_02_sql_fpath): vars_to_save = { - "natural_gas_plant.electricity_out": { - "alternative_name": "Natural Gas Plant Electricity Output" - }, - "elec_combiner.electricity_out": { - "units": "kW", - "alternative_name": "Plant Electricity Output", - }, - "solar.electricity_out": {"alternative_name": None}, - "battery.electricity_out": {"alternative_name": "Battery Electricity Output"}, + "electrolyzer.hydrogen_out": {"alternative_name": "Electrolyzer Hydrogen Output"}, + "combiner.electricity_out": {"units": "kW", "alternative_name": "Plant Electricity Output"}, + "ammonia.ammonia_out": {"alternative_name": None}, + "h2_storage.hydrogen_out": {"alternative_name": "H2 Storage Hydrogen Output"}, } res = save_case_timeseries_as_csv( - run_example_sql_fpath, + run_example_02_sql_fpath, vars_to_save=vars_to_save, save_to_file=False, ) expected_name_list = [ - "Natural Gas Plant Electricity Output (MW)", + "Electrolyzer Hydrogen Output (kg/h)", "Plant Electricity Output (kW)", - "solar.electricity_out (MW)", - "Battery Electricity Output (MW)", + "ammonia.ammonia_out (kg/h)", + "H2 Storage Hydrogen Output (kg/h)", ] with subtests.test("Check number of columns"): diff --git a/h2integrate/storage/battery/test/test_pysam_battery.py b/h2integrate/storage/battery/test/test_pysam_battery.py index 1044607f5..aecaedb8c 100644 --- a/h2integrate/storage/battery/test/test_pysam_battery.py +++ b/h2integrate/storage/battery/test/test_pysam_battery.py @@ -64,7 +64,7 @@ def test_pysam_battery_performance_model_without_controller(plant_config, subtes prob.model.add_subsystem( name="IVC4", subsys=om.IndepVarComp( - name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" + name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -351,7 +351,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob_init.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" + name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -419,7 +419,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" + name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) diff --git a/h2integrate/storage/simple_storage_auto_sizing.py b/h2integrate/storage/simple_storage_auto_sizing.py index bd2049e0e..9dc579990 100644 --- a/h2integrate/storage/simple_storage_auto_sizing.py +++ b/h2integrate/storage/simple_storage_auto_sizing.py @@ -170,9 +170,9 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): 1) Calculate the max charge and discharge rate as the maximum of the `commodity_in` profile and oversize to account for charge/discharge efficiencies. 2) Estimate the storage SOC (in `commodity_amount_units`). The SOC increases when - charging and decreases when discharging. If `commodity_command_value` is input, + charging and decreases when discharging. If `commodity_set_point` is input, calculate the storage SOC as the cumulative summation of the negative of - `commodity_command_value` input (`commodity_command_value` input is + `commodity_set_point` input (`commodity_set_point` input is negative when charging and positive when discharging). Otherwise, calculate the storage SOC as the cumulative summation of `commodity_in - demand`. @@ -219,11 +219,11 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): # Auto-size the storage capacity to meet the demand as much as possible # 2. Estimate the storage SOC in `commodity_amount_units` # NOTE: commodity_storage_soc is just an absolute value and is not a percentage. - if f"{self.commodity}_command_value" in inputs: - # `{self.commodity}_command_value` is negative when charging and positive when - # discharging, the negative of `{self.commodity}_command_value` can be used to + if f"{self.commodity}_set_point" in inputs: + # `{self.commodity}_set_point` is negative when charging and positive when + # discharging, the negative of `{self.commodity}_set_point` can be used to # estimate the SOC (which increases when charging and decreases when discharging) - commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_command_value"]) + commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_set_point"]) else: # estimate the SOC (which increases when charging and decreases when discharging) # based on the demand profile and the input commodity diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index ad1fd938e..e1580cf67 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -180,7 +180,7 @@ def setup(self): if not using_feedback_control: # using an open-loop storage controller self.add_input( - f"{commodity}_command_value", + f"{commodity}_set_point", val=0.0, shape=n_timesteps, units=commodity_rate_units, @@ -274,7 +274,7 @@ def run_storage( else: storage_commodity_out, soc = self.simulate( - storage_dispatch_commands=inputs[f"{self.commodity}_command_value"], + storage_dispatch_commands=inputs[f"{self.commodity}_set_point"], charge_rate=charge_rate, discharge_rate=discharge_rate, storage_capacity=storage_capacity, diff --git a/h2integrate/storage/test/test_storage_auto_sizing.py b/h2integrate/storage/test/test_storage_auto_sizing.py index 077f0ee84..3fa782f2c 100644 --- a/h2integrate/storage/test/test_storage_auto_sizing.py +++ b/h2integrate/storage/test/test_storage_auto_sizing.py @@ -41,7 +41,7 @@ def test_storage_autosizing_basic_performance_no_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -228,7 +228,7 @@ def test_storage_autosizing_soc_bounds(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -335,7 +335,7 @@ def test_storage_autosizing_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 0a99ce09f..2ad903400 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -45,7 +45,7 @@ def test_generic_storage_with_simple_control_dmd_lessthan_charge_rate(plant_conf prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -239,7 +239,7 @@ def test_generic_storage_with_simple_control_charge_rate_lessthan_demand(plant_c prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -456,7 +456,7 @@ def test_generic_storage_with_simple_control_zero_size(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -637,7 +637,7 @@ def test_generic_storage_with_simple_control_with_losses(plant_config, subtests) prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -876,7 +876,7 @@ def test_generic_storage_with_simple_control_with_losses_round_trip(plant_config prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -1062,15 +1062,15 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): commodity_demand = np.full(24, 5.0) commodity_in = np.concat([np.zeros(3), np.cumsum(np.ones(15)), np.full(6, 4.0)]) - nominal_command_value = commodity_demand - commodity_in - nominal_charge_profile = np.where(nominal_command_value < 0, nominal_command_value, 0) + nominal_set_point = commodity_demand - commodity_in + nominal_charge_profile = np.where(nominal_set_point < 0, nominal_set_point, 0) indx_charge = np.argwhere(nominal_charge_profile < 0).flatten() excess_commodity_avail = np.abs( np.abs(nominal_charge_profile)[indx_charge] - commodity_in[indx_charge] ) more_than_avail_charge_cmd = nominal_charge_profile[indx_charge] - excess_commodity_avail * 2 # nominal_charge_profile[indx_charge] = more_than_avail_charge_cmd - nominal_command_value[indx_charge] = more_than_avail_charge_cmd + nominal_set_point[indx_charge] = more_than_avail_charge_cmd prob.model.add_subsystem( name="IVC1", @@ -1080,15 +1080,13 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), promotes=["*"], ) prob.model.add_subsystem( name="IVC3", - subsys=om.IndepVarComp( - name="hydrogen_command_value", val=nominal_command_value, units="kg/h" - ), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=nominal_set_point, units="kg/h"), promotes=["*"], ) @@ -1277,7 +1275,7 @@ def test_storage_half_hourly_known_outputs(subtests, plant_config_non_hourly): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/h"), + om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/h"), promotes=["*"], ) prob.model.add_subsystem( @@ -1380,7 +1378,7 @@ def test_storage_half_hourly_known_outputs_kg_s(subtests, plant_config_non_hourl ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/s"), + om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/s"), promotes=["*"], ) prob.model.add_subsystem( @@ -1470,7 +1468,7 @@ def test_storage_half_hourly_kw_kwh_2hr(subtests): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("electricity_command_value", val=set_point, units="kW"), + om.IndepVarComp("electricity_set_point", val=set_point, units="kW"), promotes=["*"], ) prob.model.add_subsystem( From c4be6297d293dde9b73e1e65f887a78faf5a3664 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 12:06:32 -0600 Subject: [PATCH 126/132] Reverting final changes from naming --- .../system_level_control/system_level_control.md | 4 ++-- .../technology_control_overview.md | 10 +++++----- docs/demand/demand_demo.md | 4 ++-- examples/16_natural_gas/plant_config.yaml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index c9b8a4a8e..81dbdaa50 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -6,10 +6,10 @@ System-level control (SLC) within H2I is meant to operate to control the entire The SLC framework is *technology-agnostic* and works with any H2I technology (converters, storage, feedstocks, demand components, etc.). It only cares about a technology's [`_control_classifier`](control_classifier.md) and the commodity it produces. To opt a technology in, set `_control_classifier` on its performance model; for `flexible` models, also call `self.apply_curtailment(outputs)` at the end of `compute()`. See the [developer guide on adding a new technology](../../developer_guide/adding_a_new_technology.md) for the full checklist. ``` -The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_set_point` signal to each controlled technology. Each technology group contains a controller that converts that set-point into the `{commodity}_command_value` consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the control signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the set-points in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. +The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_demand` signal to each controlled technology. Each technology group contains a controller that converts that demand into the `{commodity}_set_point` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the set-point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the demands in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. ```{note} -Every technology group has an *implicit passthrough controller* that converts `{commodity}_set_point` into `{commodity}_command_value`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the SLC set-point hand-off uniform for every technology, regardless of whether an SLC is present. +Every technology group has an *implicit passthrough controller* that converts `{commodity}_demand` into `{commodity}_set_point`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the demand to set-point hand-off uniform for every technology, regardless of whether an SLC is present. ``` ```{important} diff --git a/docs/control/technology_level_control/technology_control_overview.md b/docs/control/technology_level_control/technology_control_overview.md index aeea2cbb0..255be2d54 100644 --- a/docs/control/technology_level_control/technology_control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,16 +1,16 @@ # Technology-Level Control -Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_set_point` signal into the `{commodity}_command_value` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same set-point/command-value interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. +Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same demand/set-point interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. (implicit-passthrough-controller)= ## Implicit passthrough controller -If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_set_point` to `{commodity}_command_value` so that: +If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_demand` to `{commodity}_set_point` so that: -- When an SLC is present, the SLC's per-tech set-point is fed straight through to the performance model command value. -- When no SLC is present, the set-point input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). +- When an SLC is present, the SLC's per-tech demand is fed straight to the performance model. +- When no SLC is present, the demand input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). -If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_command_value` output so the rest of the framework can connect to them in a uniform way. +If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_set_point` output so the rest of the framework can connect to them in a uniform way. ## Control frameworks diff --git a/docs/demand/demand_demo.md b/docs/demand/demand_demo.md index 0eb6a46b7..c0b0dd52b 100644 --- a/docs/demand/demand_demo.md +++ b/docs/demand/demand_demo.md @@ -186,7 +186,7 @@ end_hour = 1000 x = list(range(start_hour, end_hour)) generation = h2i.prob.get_val("battery.electricity_in", units="MW") -battery_demand = h2i.prob.get_val("battery.electricity_command_value", units="MW") +battery_demand = h2i.prob.get_val("battery.electricity_demand", units="MW") battery_charge_discharge = h2i.prob.get_val("battery.electricity_out", units="MW") where_charge = [True if d<0 else False for d in battery_charge_discharge[start_hour:end_hour]] @@ -243,7 +243,7 @@ If we re-run H2I and set the battery demand equal to the electrolyzer capacity i ```{code-cell} ipython3 # Set the battery demand equal to the rated electrical capacity of the electrolyzer -h2i.prob.set_val("battery.electricity_command_value", electrolyzer_capacity_MW, units="MW") +h2i.prob.set_val("battery.electricity_demand",electrolyzer_capacity_MW, units="MW") # Set the demand of the demand component equal to the rated electrical capacity of the electrolyzer h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") diff --git a/examples/16_natural_gas/plant_config.yaml b/examples/16_natural_gas/plant_config.yaml index d28abbc45..4fd21b8a1 100644 --- a/examples/16_natural_gas/plant_config.yaml +++ b/examples/16_natural_gas/plant_config.yaml @@ -26,7 +26,7 @@ technology_interconnections: # subtract the combined generation from the demand profile - [elec_combiner, electrical_load_demand, electricity, cable] # connect the remaining electricity demand to the NG plant's passthrough controller - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, controller.electricity_set_point]] + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] # connect NG feedstock to NG plant - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect natural gas and solar to finance combiner From d3133d9b3a4dfd3459ce72e22782e5e8bdcdde12 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Wed, 10 Jun 2026 14:47:28 -0500 Subject: [PATCH 127/132] doc figures --- .../figures/curtailable.png | Bin 0 -> 149068 bytes .../figures/dispatchable.png | Bin 0 -> 123613 bytes .../system_level_control/figures/slc_basic.png | Bin 0 -> 109323 bytes .../system_level_control/figures/storage.png | Bin 0 -> 290437 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/control/system_level_control/figures/curtailable.png create mode 100644 docs/control/system_level_control/figures/dispatchable.png create mode 100644 docs/control/system_level_control/figures/slc_basic.png create mode 100644 docs/control/system_level_control/figures/storage.png diff --git a/docs/control/system_level_control/figures/curtailable.png b/docs/control/system_level_control/figures/curtailable.png new file mode 100644 index 0000000000000000000000000000000000000000..c62a49726e2e1e0f7b5cd4533b09a182d73dacf3 GIT binary patch literal 149068 zcmeFZcUV(d*axVHf-;JZ3MfrwEOZz^dQk+FE+8F(ARr<|LWdC1Q5>ouO}f%l1f=%_ zM2J#C?~ouZKnMXs2p6cK8|oZBbo$Vq zJ$nw{xPHxK&z}8g;B$%n0C2@_@B6#J*IuxR&ec67NWLZDk3XC(Z@3s3>=6Ol?0fd_ z{dLd2om+sPJ$p~@+5cC2&mP^qyt{3ay_f#Ehh@*62)8|~|J-8@eD5@McYf`D@5|Zy zy~iAuZ+GuU=j_{UU)p)j@A=^l;On6Gbt~|mJ-;{aeD+?tV?D8FkH(%G*RGfa?p>K; zYy3?sQ(?{8=SXJ)7@1IU{peAxYp)-&yJ#`9zN$!b1TXL*yWXBj*so>$obSBQDc0nS z9 zl!v|1OZmXbw~uy*)ExM$!hMyg_aW#18K;?nL-IR0%aDWrK5~tQ{jBH-@%Lfhy8n4@ zZ!#WEhs@X8KK}Q|bEa4x;c;B%>OVjAjYejM8f#5Hb|o#}r}QJ;dOgF(#vyx&#}^Bl zZ99wOT|nOPo~TFe$G<&)l&7kh5P(i7P$hqU(-Uy++gmh9tgPq;S9}Nm(Pz!n`y7VL z%}KW3X`rFZ>glGFzx>;`rCNOW(9Kop;mWW7J`Q8?y)C4B#G2t>cVGNtLxT-?oAQ58 zf200Cy!Ic}eq@qe0sN0!eiZR<5_sl6ZuyT}c9}ur;eS%{pOpMyko@1HgA2A<4p8yo z0w+^lW5)(Qkuf)pW702nU&j8ixh>OEC~Tyfo)z>pU!cjUM(g38aMUr&Kvdm8|8ef? z;4U@y;LRmWzYv*97~?M7LLRO^{*$@0_ztjgEXZ~l8m{}zZSQ}rYz;0dz>QcbdQ^}5 zxWVccE;WU77Z~bUOof4zFqDY_tC6X!5;(P`fA++$Jd!MU2>pUvO3Vn4Zv&?a!v^@et2jVrC-n)BsqO)uAp(wIO@O;wD&FX`R9MM}4^>IQ6{;Kc~s@UoLnQb-m zgyplntt_1qQ?^@2ht)KwVGc1qCkawpF-<%OwxAZ&8t2blQvVj;Gqu`?PDG>*_qamLIUlyaWc)4Bo7ME+rSiL` zf~;R!<^|7$f(w(lvQw+O-S3ILD5Qw!RbcS5piqan%H~OMzEDrYyOrm&h9DsYD-jOvP47QUQb{eTpJhCy-;!9f zvzbSY_*@nFSdD*UuVGyL+MQHb<`R3n$T31Baz@r#erE zB8dTcQ?Q_G!7DE@r~SPuH~QVOX&gd-?#jtdgJJ=APEe|Or-;~xPge;kNMhJ}cR-Bg ze2K8pTznSuo`U4U(`*lO(AmRMhuDwu1hAAsyG7jMx<}k<@othvM%0BqYzhOL^%PRf z_36^KqyU}N--?dsE=&GN@#H}Fcac$WNRjhNF3a~{9N)eW47+b8GBQbSZsuDfUPMeb zb{bk=GC*>0ZaJpyAg>94s05^(PVn@4;XtdA+CWr|;$oJ|7j-Mk&{t%WO*Dt30WXg@ zuaFBUE6XAPXB;W~WQJli2U7j?4BeM!&A;CHr>l+?;%V8aa zSY;rxPp2x~mnFt*Wh_#)xHIIN65vGwVasEE<^xrPh3pXI32b2WrgEtTO?mGKM>f81 z%k*NX?c-f~YsdiZpUdwZ2cw+Km3E4iJ1BXlA09Y@El!vrUL_z^ z7irvuhI*v={f=JsUb>Wdw4_1Gqz@^FPUI~TmlKA}K9n!8B7A%nKXXM>S}O-@l&$u` zQso0=+bX3{9TaA|1atg~9k!Nk!VuH*EOVs8%8Y4pS0+i$L4!EO5p-6p3VwNW4m=OB zd0$fvnSt_4y+JNk(4pS?9sz0cBrCBJ-k>LKT!wuqebv{?a#qF1u=Nds`s#|fnN71V zlS2<|Ri;M+ibnFL zJr8J#^nP1M7Cohv z6seaoh~8-4^@lj|^!G_yA-LdurWtM2!Y$QPoU5L&0Nr{rLwKns=r*1g52=MMUn!j+ z+SxQRse&OQ{It#&uC^gKXKo`r+HIh+B~ovm*<^XCI|aSZ)fS9xR-wxrxwrB9IKx0< zYJJ8Z3Y!=+;z#&g`HnvZfajmyeCdKz)_wrczl1ltia)b#;Gntg7?)=8{{HoW=EH*WVdYJ(|KO%LiRYxT`iP#pxwU)s_(Q6@*%%PKo++ z9bYa}RtO9-oerR3@$k_<-l_W|L%l@jgVu!b<$b4@HdNAx%1|XqwkrG^_50JrYWLDa z`}7GJTM?8KZril9v2Lq;3C+JD%MBWLji{vbM_pFE;QtBYmAP*-UVUp}q(G2KoY~AZ zmF%D^&$-F?djh7+VrO_8L=yI3T+FL(lttqDl&EUqd};x;5aLzM#aw{NYPiY7i!N=^guem~*w4W%{+IU%OIAVaKl!&9CDuFR4 zIIY7H1WzEC2cl*D`k{HG%fpC(Wx`Z!*lBkT;;~)NEY&K!{cDDdO)lZ!(ZzZV{o6;u zRotdxAA>^$4)W)^AbwYk*BM7Rmb6v&Bx4J<-%_rdj!kx6v<vuM`F{0X#-QYmibX+07c{2bf~e}~jr#uPkagN< z?DUWuC@^5We9a+$Wi(9K-2#M2RD(89k`EN9>Me+SDZI&ZD5Y767t9i_#D5> zP)tZW98_FCm*?Acamz?BwAFr=F$^DY%73DP?e#}a^Wo4cCDFkfA(J(O~J|~Ifg8(_2-U)=?sK~O+JsfoxU{O zBifR&onB*znF`cVBA4?5J`U=#X;gxJ8s>Z)xh1M)E%o^J3f5B+b#(w&v#?|kxs>*W zRLCP|o$YA-_^|oCUw*guLqPU{qY$(vViZsN$ESip1IfbLb;Cx8IGq-3{bM;9LbgNnON@IpFdIv!njF%lv*&4(;$f`K0h74 zWwcW7*ILQr)d_yjywFn^>Q{ZrEs`9IHPx5&`FMVWv#UptW56)OYjv~W@CZ+>KmEbF zl0ft)_DRRcCjv&>2*04cCK$1_NaH6xbDx3+Kb^R>P7nDU4=pY|SA}ix@73DSR@t1m7jrVQ zZ6Bv1K4|WXFI6+HAW+IgziAHCSW|{tebPg^OLcoMKB%*snQ#yTTrGr&sU2(Z^)m&J z6sIE)1x`#bQ#Rm*u&(1PnC0CM)uRq#?@wLXW=}?(%XT(3{AK7<>Iex=g0|*pI_jpf z+t<_^-yN$w)pisAAY9zsCal-bQHVv68j2wW$w04%)LN`DmROI6YP#jn=WT9?TFoLNlxkW0ya;xn# z-SUmp2B@S~kxqNuz=`i%{ z17>hRo?G~NVbHSRWo=byFWPW6Gw7Xos@?mLTHN+6WQ~!Uy1H27``gDBQp3c;;vcN0 zpwVm1-ps}WpKl|wUS<_h&zm&B+#}pu)jgY(A-GTA{-heT^5R*K^+x+mNz|;R2WbY= zFcfxLbRY41Oyq6^kh2(n_0Et*_1sbBR|-;4aAf1z*7l7svE@^Q8Pr;<(Jx&?4c+6S z3)2Sfhm|DQ96)budS#H2b&p7+jSpl)tYX~7D=b?-lP%9|#s!%LN(0f1^0wE$gFzN4 z2T)kf=qFCIEmx(R{JT#^X*t#Nx6sSU^XddDT#gkL#T|R>Grp7aNaWs)7z_IgxJ(_z zxC^S8j~BeCt2dVdg6eY|o2n>bq2pSIbF5d(@CQ`#gn%z>l#EQR2qV78G zIgC2-1s2O@x_;)3nwEy5T1|1D_(thb$D31>6WL#1NHo2I-JSkwCfNjKo0`ha-icnC z8!6u(#b^uRE5aFuxmNk~2rU(wFN1&i4w#;Y*kJ*t=&FOh8q*nA{B@hKg~Fw0e0TWo z8BWg>izRS7LlBpF0rmQ*AO)j1<0LW4vscY5vTv&}QLM2Z?LH#7TzQJ>FKH#Vv8e*l zAGFbTCJ0Kxyvdh_XX?1oJ{Dz{#9_wnn9CWXjxD?!l6xYTGO%7=>^@v^Z#~fKy-rKq zuC~?_8S5m#{FR&aE0T1qq_3h?e5O-aG&7HfzxB!twO=|boz0K{Q9bHcOW5>CBZtz5 zZf1z&`-iI2aCbn6j~(1oliOjainfT~rL_#CGm~`;5Q93zw=V!>^K1agQzzB?_qCAZ zQ^Z)6<(OCJ!8(~)g0+}@-@-bPW5xVf`-!hZN|b2X_5t&so12`SUb8S#P%fsf;|rSzlZ$XwOvi~R zkLon8ZZIcvd0KTqa)UP8UGTbYb2y~G_(|K%Tn2>ju}CxD@}bNl8c}!^mvJGgs@-<6 zt&;YdqmTgG2oHY?p0Q8QA1J9m??D5p3nW58zc%0ZXI$@`4R1~h(#@otFntnz=Vq6J zynw<9ofl87DqwHm_H=BBphu|pO*ouEgv6;@!4=<)bT3;ve%-Hq3nZC67z0z2(|*VO zsIBbH2Jf&JtxBtDDi&L;^g%!qVkI_xI!bD!(6jO_gMtg4x{o5bVDD5C?3b~zAc3ZW z56x~Xa3Gk6<#b;nK9QfY3Z6WIl~X$^rn)xt(K6NdH(``sTcsJdIzi|q0?tj3N_MK6 za?i%cZw^?VdK2;8qgUQf0gv8RZW}bn;be6TTP1j=sytWs`{d@9sWL*vj@T(;ZuPe- zva3zJ*Hll53VP;b{WO)4BgX#{W6$geQ$9R?a=<2Ze!HT-bD$HWcPV{hdt0x>z5ebU z6@~3Jq)px!VG+QuD=&Ih>+C4L_GWSm{_5EJiGH%Yp+IWztD*guuvp%x5j~^(zx<9k z_Y9lFI`XsubzJeY5@>2uT{><92u$-?-g!_9)~Qf0p#Ay83iA@Yb)~T9a%V3-p7I#+ zI+j8SCi}@#loswXow9Q2nG=Vz5Fw@F!#6Hs;`_Tz#u8=9JT)Kaz5s|hrW)r*24XR$ z*3O}EzB1xtzg?eNE;U%js}@B4`Lfe&qM z5ikw6_94DIL3axQQ(W0^$iN|k-4;rEEbP-Yz)Psdr(ur8#V@B9kJr9&E53oBxIN%I zTvd}_p{HFS7|>U>LXx8nnmbjE9c<7gK3 z&03iO3ldbb_--%S%H`$r%RNyyv>CRj<9pu_JZqh%vzY$G;-&S*HT%N;ybHN&MoM$d z(sfUOIOk~fbjaj1hbix4yin76{NQ@#WB*hB!MWvFCdSLi04iYx&RH4tPx31&WqP*^ z9d04vhOHFERq&Jfc%r4uS#21%>6mMYjfV)zM!8yWxo?{4XaJMBpguWnW~5bQDf5~q z6m-930SM7&si)z#yW&O$IT^*{r2jL8G_ac76G7a|7c_EQ0sh)f)eIhKOkFqf+eYE=gqkd{^d<93hvc(ci2-)=RRcK)-4M0-QOK2y8-|3DH?di*W zi5y`mr4?{bU!qnMr)WX}NTp6y&avQ;l@>K2X z%ZI}~w}?CO)xEcSRHjU=#vAe)$7b56?wgJ^#W{}+kZ;ctB;{gzQNhJ05gWe?mAHRR zz<*&A@PZUSo!Q^H00QMn9X43c5b?73Yc{vSINg=M>2(b}d#Zmy0Oe!m(M7B9Qs(;P zPW+@m-lMiXCnQ6zhsqz7p|-xV?{SBdkaiyf8?Mv;PR}r{Oj3JBTS`j%{fJ34Y%1Rv z9~JZm=0?yFtoeYZk;)6lj(AA{i1xVOY}HPLJIy}ju`9=1-+*R*Et7LTXg0;_PRk}N zJ9AWOglLS3y@Rfhls!N?w`j42eHcGzqrA01Ef}8dz@C_dhH*W~buC z6{pLpbnb&=7L#iCpE}#d`yeD~$Eftk1{PmU@;7SQ ze9HB*&u&(c!U_`gWaMUgMXA_?>VUIp);-(7^_SfC`hrxnsZ0H8*!$^0Q78W9H7`q2#5RSU6$fJ$PObJyVjm$aXKr-v;`M%!fq3u zzLV$)|MK!64DH*~de~39#h7pa@C<>V&l=z#O4MAlzKF4$mfOK{9ne}&I7EiPw9jJb z)^CDHzs&K}334p*rwZyex>I8YUZ0OT6$S+4#<@eG8)Huk04QL|J(4G9Htf3pSZJJz zz(Aq|iP#)`*sp~oHR(?9W806`E6g}GBQt`#Tt$U=cg)Mnsr(l0E|38|d3?atfIrtQ z)4s-^Y<9T}rX`*95+PkyyD{_vFDan5vels{*6*!PbG$CX{U!lwWkbiClBqxB9mD(B zQwb2+d&r%%BT4qulz?ebmwuXP&kOtHr)l+Pv}f9%jXRD@#)ZYn;%&issq!#2)l}{i zDx{~%%Teuf#8x0*3nLT~1`4t%59&9z+8su86&0$suNF&cSn?^V3>u)&cS;uIlC6B- z4Cs=y)VtJ488RDH6n?VPQ*#jhC zk8sPzM6ea-v2E;olFEdo&RFabGJtMxhb?VohrN>!OsKYnkmJo~w=W;`Z77|s0Ixh5 zxm;ONy><@>YB&)j&7SH`-7_7#`jOB*HSX&9W-AdFMc(M_M+8hM8Kgn8%I$;>6is&A%WV&{U0Rj=aG&?J9O3f%rTqpVO%OgD3G>1s9VV#Q0V$dlhR3ZI%B&;Y3cbs zwu0h!l7e5bmeX4)Z1{L}Yz%WQvPw2BzZ`V9iSCExq&dDBQ*@pe44dUT+_nz5{1;M6 zhx)v|**Mx~8vNgT*4Qv|A?UcR#u}Z(dhC?oUY6EFGzP6m zFOE!RBV892tM^`lxjX@PU3OR6^iZC=nJy~F=RmG>MocGYJC z+mwK7%`V%0Y!?-u@;RfdJ(aS5-Lt+X)Sgpjj8dj7#g<>T>&!0A+Kz)I-3Eld|1!dkNQ5su+Wq=#sJHU%ajKEwAAL5SD zOgElwyDTAvV+OE%YxRe%k8C4mN-;@Y&d^bqasiMuYZ!BOO+KobmW+LAIS^-GA30*Uli5igeroBRRoCxInv}3(;NtRJOxr@~d0;~86AKsH-0hk2 z#_L-rYtS}ghJA5(&)X7|7(&2Gyx>&L?T(i_jyZiRLzH(Jm-Of_s`~$5Q#G+PXA~QN zV*nXtlj$}$$wGX#&lL(~uh)GA&-Et@M(Wh&)qS}R%m>)1r7ab$?zsp7y@0v+sbkMU zeqXfumxHdf^WaVi6}$Ebp*u~wZimgNcVKQv2ngoR8Z|60@ZAwmnb)E}ker*Q-AF+h zg9bPKqSvAvT3m`GlowOkJG$kl@0SqJrr+A$&>SP%ZlJUFEr3t~g)=4nXDsMfoO7jX z>|FDGX%{)K7ur5>${L{eZGO}1}@BJdz z5w@AD8|K!JgT<2OMmR_7HdB7BDo~-*qLw5rE=xSKodD4$VlGd~&Hq^$`gKHUT}o=$ zwRWvQ*))2?>$0ogI>TlxR_o;m($o@XR<7M1O18Kt{iJgzZtrk*DIK4l;24e#)HoX6 z<4kx)JIQ6EP+YtH(Jkfh$aRjnJ)sqw18}

r)Vc-1Q!{706*u4)}Vke8C6?kHOEg zJldkWKYJtOVywHIU#@{Px1X4~wSI#~ zy?-R%(x*nt7t7nsvp)IS*I^n zN_FdtrbIp5QbQ|>Ol9u-ByO2Hr4OlvJvbUv z>q~%e7VZo4?s`68{)FM9(DRmiI>IuNrGrreyExPUn!$@HKJ>GD! zwW{MiHTzsSt5>kA|?a4Ia|2u-NmOmhhCW4E@g+S<11(qsa;*Bv8A4bigC zAx^0)s!b*9M8sZDB~EfIIWa?YBl{i|=K+y3qop`zEi6ehLS@0VkSWx}#6bCYik0TV z&nttz#J8}&TiqfG^}ir9@=;uiE+Czwgk%*tU8~5OCDMh&yCxSWHchgwilVS1^JJjb zE*7?y?KUAvJJ)udnEKk)rC-=$GO?Pn(xc56SZYVW6oS&Wn2bKn61|(s)!U>x?!tl| z`q$0Pco0*uE%DCm*_fdKoMlzjz&~a}aG_xs3|or*UVsLas`04UR)TEa+OdjAc;oCi z^Hkw*1j|H$tGNn!8TCwCf^$)Wy!V9+rCA7}q<%6uV*z?p$%PP3m%;Qv{ z59=+UjKnZ9NpC>SrXgxoLl36D-!STDTx~eCY!SBPWoor|k7%yxA4< zXQRKCe(CR>V#k-g+`B;NWI>bA3#CJAXhe3>R!8>GzM3iT>4u6iYo03JXG_mY(n8VA zkDCTcVRCJ>HJNl|9V51qaWU+<|JdE`O(gEJu1!f9?fI>Cmh$yx8CZZ0WzFF|O#W$O z%UOTq3a~_z(Df~)CBYGazo2!frp7cI@4smZQEt5OJ=D#?f}@uX+uwZ^vKX?n!)GyL z^0PX!}Z7@we=f>9_6E!F-sN;J%s%_8k_MdP;b@{uSU!( zm8q6Z=?WmKAUE(;5LNUF)~!ZY-xmeDyuzb(r3)|6vS9gKnqg?|kaa?6(&^YBQ2C;S zxo9f3XTn|h(YBss0$#C)0Gsst6l71)%L9*3XthgSga9JE0 zp-%Xyw-ipZ<3ygJ=~;v{Bkxv4?& zpYj@wA;51cVjNj~yu|^F%QmDDT#wwdoZd)K;ih?_6&z`@A2Yw9fYPNi+o&t|Q@#}p zM3*&-IoW0}1JQD0kq>Rloj}TJwi%rr;J37X=wG%fMY{rNhxN&j)y!svW2xY3tASTk zS)?-kZWihS*SW;+LHFJK+h+R1{T9?>ovH|pxPzZUKcQ9crc}1*>d8%xdG*wtYm)M_ z)~sXsUMaL|$j{notU(${In;~2PAogI&&m-lY{5Y?GdWEGY7JRx>*oua3z1fR$$f=R ze3`->qADf@p@=St0=ypv-bzvpP4SG`jpXe%n!A9AMNdX{#lfRI;TrmK1V(md>W&~B z%a}L*w|N->^P&-7DqrXwV3D7s8&g`z7Mzo_qGaY@Oi<>Ur8j~iI@HfCH1vZd4RA}; z0PrqVzBk&h0{w`c7`pPX`Iqp&fam9m#J~M&Gb@K=5qbNGe_6|&B?5MM0j0z{$Qf* z_5(CcS`CZ2xC?+kHh|I-c36$(t<2r-erg!I0W{SOfVcmPEd00J|1I}Vvh<&H|AYzO zRMvme{S&18gFgRX2Jb&tm7wyWfC)AtFS7bhY2d+jVY#lVI5 z%_}7gIK<%Zvj9wBUDeJhX^{T@2t&wRIH6-pSZGI4mYq!9F-K!PV(#ty{g*uP=m9#Y zY|zZYf|aJDV=-!%xF`G&N7u%2HzbO;O&4C>g%!I^{aZr!Y$Hl9kVXXNA5lk z=oP2E1IWz>n0u%H#^c@;7Q(!Frpa9^R!EIx;@C=Kb38c#)Dsl@F&}z!bT!`qUueI4 zm~{2qt9mT}H47QaJgxcn6*G-940^T4t4tvB$bF<@%q3j7jv+r!LuEK+k-jK0B`~7k z)uB21V3F!9Y?pi6n;uS6Yw=eP?<$JLv*8sRP1k<(h2PXZR78t14)lipK$P7sfD}#0 zj>3|^CG@|j7Te}ZnUm0cch&y-|C`k2#=54?1->YKR0`p-VhtF!X$7Y1Ei_(3_F!n& zk#P$u;;wEVG-wUJOBvjqiqWfIg6<)4x)qqn+2GDOzI`S$bZ;-D&qt0XIee4x5loR2@4PclWMsOk29x0RV|M?^h zo+1A^=xs(66BX%hpGa6zWQt%AU;&ZhqyWZm81`CikzsD<<367L_y?=&4~)4@x*+yY z_%Sh5$*LMxcPToP(BNZ#9%Ic*=-l){k`_W8k?I}fk_^|&#p$Bk4#} zRAI&Jmjp?$r%PIZoI%@VM0m(NAMvtY8#wC=TYE@#@k(I8w-Y= z#bnQidLT9P*J)v=-`Q>bz|y-`1DYiYM))wx1;M0%gnJ^i9)939VQpe2f?2(Va>nn$ z6a=YHGjv{@vpl`G*Sz#3LN%V?3YIt!4(^NIETi4~&5tWChR~1%?EPC0yLV-l`I%~e zX$+*IRy~`-!h8Y7P11a>39}4y&)J%jjGg7@!Tx-GNer*K&@v>?ZFMsdr6+pgO_K0u z&5$x=Id0oeOXdD)kr)hVz!+B^x2sn*dJg_V6bx1ksPKID4K*J%pChNjF|_0i9g0_` z_=aNP0T14Q6wUi)jD8mRDgo@8lh>eT6oc$b3>p!FITa$2Zk?|_S zs3U0A-0+REOCgQYp8>M57zQG78{yDy^6}ydMey6%?`@7h`9bptuK8XrdUN^R~(7dPDS)?#VbY zVd@I8gch(AJ{@&QPcen2Oo3XCZ4vmjhQ>UDNYZk-uq|q~xYGz}MW5ZVi|hq#cXoNp&en%=7ym~%mAY4*BaVv}9n zK~y$HP&NUgsMD(u7XHBtiJiCAr_Md%nS%H~(77FAf?@{*?=g7_B4m0i9C3<4|Z{LNHN1dgWuG6{g_NVft;)Q2&a2Utk$VU2QzwSRn+2EvrKqEHE)@SEjcNZV@18+GS?0C1(>fFRu2yD9(F#4DXUYFd6`z@+U_0**&G z)cyuJ;k2*-vUeZoPNbZxk_v+@c-Fq_Oxg~K6d?Q}x>Awm3I)4ezT+U{%M(m6HDlqp+JWLf+IIDG595hmH zVA(0^e17k>{Fi^ozJS zDEFxob*kLaIR?zn2zyf>8gggEmUpXCW54VV;O2-JV_1J-82F4GIzR7ZSE*MbRiJ@u2klIV|gDc%P>Q>-jh7VGD>I(?0CW=Wl&l}5_4YC-hy#FQZV4WDtM`7aGyOF-tQ#7fj;(wVVC17U27c#&Kwm z;-hsaQjw*&IIk^@&)5IOMm!f{P=21`?$l=_BFoZKR2`s%0 zySB1ewiy~X6*uvHXNGZ5_%^5Uw^ImujabyXViXlHuGV)4uaZ-nz<^BPJIS9jMtXv3 z2gSD4CWDGsLG?rXM13ar8H}H5Avub0z~Ik0BN_Y#k<%g4M8~zJz_{uksJvJX*as=f z&GUa>3$JFUsf^SIBjFu&NoPVQuj!L~G>{f^w9E|5=Q^v%9EkEjrN6n_5p0+enxJ={ z)Z}o(>Oo>K->>1M)E7|MxA&D&%5#`^m;H}?!!2O#AYwpdKyB65;BUYFB=@tox~Ocz zMIV$X#ts|?K|1f9uvHQ2P6N?hk)896UPxzfV#@x_><&a$D#0=ji+G)&_ReW_GPykB zY)^7!+57un6K1W&MU-paGi{1{9{gbNm|X*$_jCNkFaNrh^O5D)B|5H1k%6lSLMp@4 zjs+NI%O3hx;KKX(4TG>CG$<_-n3e48spn69>nncfJY+dfP6)K?6Ce{ z*Nl&avnP&VzNYaDrE+!#&1Xo8D=M&5>m?_mZA`edu(HB}?*dmFWePsNohLt4s{H~h zXJa)u!k^OS98O4WrN<`>%W_1Qn)s}EYxT)@Ci4xhoIW2B+xa>Ssvgs6_+Vg{e6zdx zq`z6bV?QiC$|-D%Li@6z$*b#hFRf<5w)&E*)tcNRyuAEiLjQsD&aEdi(>McPOQ^pD zd8LCZ2JcG`lhZSMo#u1Ne$63z}oKthmLTFCWwGNI$9N z5Rm&3xlOXNYOe9ORJn91y&*Jye6K2lv=|DN?tl+fYN>e-Bs^x?nwX0!m2JIV#fNNQ zT_9Egqd6%|xw}~Ac zyeJ{cHS7WG{blBQHf(JSklP~Mc{OPE=UABNlg6aD9(;AR$>o%tB{6-katQs_aVA_7h6 zV|HS2O+ISsnA8Zkm=PXQ+ ziipn}K|c1EG3?eU-TN7#5^)+hI%=;x$4!2!X6$2H%!+cl!)!T^xhzU? zK}pMDyyp2JH}$~_kDMc)oS)E{D=!a`Q1rFs+HrPjSp&X9%h1u({L|fox__e_aLj7T zT=i-aI9fr_Ao%y}&8&=0E;A2vbO0fi?h}?bwpTL|aY8r((`bN{rZfzl7^vc#T5eJG zo#ZAoh00>K&o^H;;c2@|EY$HaQQHbB%_6O__e8a3cPbYArgRAtkMdG;w#{Fsgq^nd z?3w({n$EEXWO``XtN3q|^wu#2IeFji3?WM@iHjFvpted^l*|Nsh$M0u@hhy1(wI)x zFWD!V;G8>)O!@P8h5^!Mp3ihpC5>?1B)S@{j_C%+l9x+?(|R&M9d&A|X7Ij!z)7_s z+c%NC3w(Qtg+3)l>r$_iUyDn3cNHi`+!Tc$`WzvbHvqn|X`pgOvGlf=)0Ith1lV2# zBY1gLpgeDpe}MZiso6mmbHeMjrOpGU_rxrbE^FJcvWo|2dga1rjB*?Ng(UR(BoX?9|mi$1W67>P``v(4wnVSkHkoH0JO zR|qZI-D6_4myg z|CsZCBk%w4HvUH^8cblbH^~cq@6^AK&G!ai?dh#a=>62^ZYOk6Kq>7Uq_unHr$+C2 zK(qcg@m&@8t?}QA|HtY-i17cvWxV+hhDX{rY!f<`>f4(VheY6~J}Oq|r#{zZ9$wcC zb`B19{wUfyBu!6RqN@3SdUf%afDHOiSh91nArD#2J_HH*t6nNxnkz79e6Vz0MCgMW zR;o^RO`zt5(?)An_Ju~DPA8o__1JY>(Kk)-51wu&0#Iw@7m@yV2w>`XAni@5ZA$L) z#cJx23;ISN!=>IOVDkgz2M>P7@RJ8%zTqu?{I3z^AXp0w(kb&68s4sr^ry=1i|B0L@MP$5;P8c5m~cMuQHVmx$Vzxx)36^2rebZsfo1f9$X4rNUUp z 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

menvDC3oMVE}!$IgKt4FIq{&i$(}R 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 literal 0 HcmV?d00001 diff --git a/docs/control/system_level_control/figures/dispatchable.png b/docs/control/system_level_control/figures/dispatchable.png new file mode 100644 index 0000000000000000000000000000000000000000..d0441a611a8a0eb48ad10e22a8e12b3a1d76d8a9 GIT binary patch literal 123613 zcmeFZc|4Tu`!_BTn+GcExiyTDfs&a;%Fg$cla{&2OveA~o?MH(1$ zvas(u#Ik$)7T^!dEn4}hlbn#?0oLd z+x26{Jl5}bvt#pie;>1TZa?RehPnfM?7eg82AGBA_vY=tyH4M-8DU}3Wx0Iu+_lhM z-^Mr^Pv~W{OxRclIHYEQ51x2w;d|IHrPsABt4$91;W zb57#R$i=gEpHBW*)7q2fcTItBms0+j#au0_Zhp{d@#KG4Gq0TZruLWjrDor!|Mk8q z-h&Zk_HZx7f2Y^D^6munB3Fa5Fi+24gd%sIc`k>;XG5e>NJM;cBhzi@wiNutks#142|I0x7Aix8b8+`vxgt@}5 zcjU13n!!WAOuDmFcGhSjpLj|1FH`QwYyPD8rb8KH(B{YLfBu;lx&Q-NZ(aXR$j)D-_UQOH!WsCT^WDc!rxb8M;B?opNR zEA{#sNuAkC(9QBdGlpoy+UFbj4QX$GaYcESfCs9Y_l-Z<QSc~7O6 z->WQ(KL zkM?A#592E|lCg10*?em`H@sAez?b>z>3A*uwnyf=)xrxOF0`82uy;Hk$EraHR&^|(dpE%d z1yT`#Zk&u>7TG&U%`0ytwgvb$4OHcP-vM`ZL$)Ka=~7G9r{|p-_FJ08(DB+*te5jm z6de2p0%>mJPY&qJzF$lFz|6uOVW`^};(5f)%bUYwq|Ib)!?8;c_5AzCJwAY{bHyx)a@MTtg*%<|0V z4u!`kV-9k2`PD8U1J`}da3GTF)Xijg<4nwKL!&CUe(&q8hWI?@BPH9rdgRcWw(ivs zllbkO7=a&)1yV(>Qh�R>8PfehPYofM{(vu=4r+UO&A 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�rekh^uD1u#Fc@FJjL=6p~1Z5}7s*Oq+75(<=tc>jz8 zz;ZGp^EycRhK&e+J4_u#8f#GVho%_mj-umt2T6s6h;++lely5S{be-{;Zgi%@0|GQZN4fNrhmM6X==Efnz9FxgYeOOXe+7losv<#J@`*GI5I>t z52ssh103vQ@vuGTh%3w!v+tz`Z1Z>^dH!&2*vxH(vdR!iGWy2cT$b&39-LuKIqK?b z>ZM8S*mzXwwfKA+h!E=SL^jv}`|&$*_cB&5B41T5U59oK3X#;X!HN#jTea?sqrcxL zeNVtZ0cH86eRWS+LN?VTw)T|e%KGW@O&{{Hxy`WFr0}X8GtOhcR0a*UnWpQ&lhx~? zQl#IAi)xZri1ZY8YsL8C_T9!O*tf{Pt*g7258$mm^uJt6UdZv;Ixu{?PF1!1`@&2* zZUQe)(4C~rjc*sBk|Y3@FGLa5kCE;fb&rEcz)XO6GSkO2woDPWcBt|DB0VZWlSBgY z8OM(QihX974RkRJN6$0%0WFiXUN_krD{T%iVo`S7rk4YeK(f^*?JsPvE&oGO-~7!k za{-jRjX_$9pJ3;JxvUg{9(nSL7i@^Wz!;`B3e1JjI*aIo%efv(3eH9!Y^i~_l?;rB zdpOnp6064dNt{lBpToxX33j}ELVZ;6D9Spg^5$6)WoLH8x%|{@$;w%WW6|d%MQo|( zw)nAOg8M2%v(H};iafFJ-g6GkI;CfMJY{?w)eNZ*=C7Du*+`-H_OEC{=GDy8xaP{k zZSNDt6B8#Cw?1Re2oo0aC;G5TI@D?+e)|J+lTSdnrsJ+FyHvBYMoem))VuInWcA)e z0ML)Mp&{YOJq$UhxyRhBiPuJ4Ou1>{gEvv%!m}*+<&K7VA30c#T2H-e2sfo}de@Z^ z=DT)KX)j{?W3O}kY*$pT6%i4ZU?^5>8?M?AvGv)}xM+l|H>9HYa=s+u5 zy7ORvR80)?v-rK(?#JamT>e|vn|IMk# z?jKkNqDESzIw|~SlKOmub)Dxc4|IeHWv5|1l6#XHxaM0hEDbrfpXo*G^}l-a;- z8{rdU(X%VTDbKFPNe%0kWw&!{pW97cZ#B_dRgoW zj2q`~Vzs<>gxQ(*S-{GwkR`8FdWOGO_QwSEbbT`eSv(ZS8Zeti-9TGHBHQ@D_E>RZnzHdh|B+hO&KmC>(> zCb%8&kh;sX;xLi!Y(pw(B)T=K9N=efGOLeOkVb+l%d+5xzJ zV~G7G*gdKMo^gPgvSCIn^QE+4hZbSP)|vC%rdFx9Cx3=^w{{Y@H-4tCzOH{KWO=b% zs6vKYwCe|s;^-J^iglfpuEUxR>+m%WECn!`F(|`zr9Z(%3e( z0g{zx@?jcNv>2}Lq^j50kQi>g4HgJJ-$Mg$*yvtQD<0Lk^ z`0Bc@zCb2^h5C@N?!0U=+^X6Wa+3l*_o}GviwS+a)%UG>MhR(PjEGbhN$$)<;xju<^ihp8?c|3)$Y`1uF^YUN!_k=b9w8^UEI}_-RWb zR9$Gn$;nZLQf=HppK>X2%i93`&xUJ1ieS2dOgp&z6z$BjYt4sU>u!4Z&lJ6SV5boh zFfL}uCvE(HQa$H&Gh0k+yUmZ&_F_)Hzkg_`-FNN( zHE)MzJs6Ks)!Z$;&|{bN_i?dTz3~tH({~0iw$)-3p%K@vAG-7Y@+6B9)5h26v3%k` zgMJLZ2HSh<)>sKkpj7PS!Cs`6mWKhYh28RYX!+SPn=#KCdkh<%P1O2BAJaZI4x3IXQkD!rWh1F;A< z$*22%yw!iFR2#WRQh*MI)`2=E|N&{kg9|NB>J z%z+VzgXaJH_y1WP#-61GTDbm0g8uuafBr4A4;V3V=j;Ce^`Cz}@)Z#7463%of0pF` z_e^d;88E^A5261d82@9;wN{{fD_CIX|NSeD)xZdq<5fSj*8edv>i}m*f`0oEQv4r3 z@aG&{LjWV{Q{uS)dH?@4CQjj-G&))HZ@;9FH#AR({5?pvHh`ROh}_IWT(vcI(NfrZ zOq*xqmyl@JZ?;|TS~8pY-3Ew$YG zfczxCKaDb~HRo}_%0edqPzJ3(VfjcRBU9P7bYEVN>bGRP(@|BgojddrvV=FC4~o&^ zUii14!qE`p*7Df-SQA0W_fEC4(BuP1c;FzAfJAJuS81&Yew zD>xYGEJ|{5|0713ti3tmTmrIEe@^N7+nJc(#L~m$rY}Fi>rR8gdt`Osek;{9m;2#- zrr|kmZ&XLK{L&T$ozYBVm`!4po|`Im=83E35=CSLUAKOAc@!IV zP3~Z@e+i%Lc54V(vM-fZtHCK3QYEtQRS8cuO9E-OL-I zA>if%IRxhW`@fzOG4=K?7wx8Jz-OvP%hTNg2aW_%tP5g>R6;TI$u_Zu&6n;Qy2wTu z@xZppHGIhmU{%z(W%d5Jvd};dP|rmIS{i`D9XT=fbW?EhHgR0tjAjyOFa7gbzcHouh#t|G#^C}>mpl+ zES|$x@SmC*P8xE%t_!>?tPMr$nw?Gg^`FxD=X;dy#niPqmjlF9-+YYVcIZa25)&>a*mG} z+(&T7j0kIn?RF&FG+MrF9a8UGH-%8YQB=Li=HcbVZ3PKukayCjHQy`sp?3RU?U}Pi ztn<#G#+v*pscAInsF5wnA4gnqzs@7I}oVeQsvH>u~> z>Tg|BjaX&)&uyAA5nl3MnR;3lVm_PHM%g}FjIvi6U!@z85 z22Ga<=vf30v+%I0&-utV`fIuS%(YM;;qoS%2QW zdSModbqF2JqiL&oZkl03Pgau}2J&HVH3r0k1AP!&#pW6QwSENI$+8lS0K^NVgL<5G1px39K2jpTA0n61biI45X`KS zK2VR;o^0~*L%ttiZfU}L2wL@8%wmj#ztFi7`tz;4A#9AEm1=Pf5KO8O2*0LJV8z*vc+>E1t!XxgI1cKhlCemRC;Ut zBqedwUtrXsO^#agXt1I}V_yV`C_?p{cv^<{525Ja6{@CMbQf{L_p$IfXNi8C;916) zi`hj1_&+Dv!PyX$|I!5fHA*~lUx>MP4#lbq zuUIQn)_9{WTwSdeCCa3{bzr~OS(+p^C%0gw8b(pJ$r!?vrYDyQmhsWq(5LigokBt>hfK zH`KMsP$S(|6WV@^4TE z=C#nj(>0qtzY*L!H)-KMwsMZG6c6@z(?THw@OW|f*hREhb*yN^bZQx9N8!YIP4Z~x zJ%+Rp?y{IeanMSg6+Ji*}O2)(w5NTv7jy$o(vM z!`vnMu;@&rL8>Unq?yecEf1fr!cf_Bgd^O4w9j-0mOUe>y`rp)KFop+juY!gra%IiNpXA=p%axNP@kW1#NoQvGk<8DQ zPG_H{c0t`|c=#5mK@$cgx!DL8GY~twd7%}+1uo3n^?wK5>vPeytPmZ+a|$5^?@0EZ z?3#{Dkxofxbhw+r4jJvR5l9=5fT?;UwX=gvo`h$Ov}`$F&(^Fj*#yn&nl5S!N<>=A z)L8Fia3&BEzVw!cRsR<+nRZ^y(*d9P5%aCQbaPEM7lis22HKL_0?~~0lZ`F49w-mYYYvJu6^e8T#Tx;Lr#h8|Dp#sFUL|L*$ zoJHFR)x7Kh>wN5m>e4SGWm~^@B*vm14q?tBHW$Ah&65t@GV0FHQKXGq-G4)?XowQk7KuiAV+6 zyJI66CmLqnoP`(_Zy)}KIWhfxpu!7OwzUjj=Fu@~X1u+>QPcgxul>7ziCaiBNH7!U zb*PEsiWXb;U139j=kijDhG%*Kl)1H+MmPm`wpc%>^El)FE+FdR@tAzbM+P z!(+a$XYv>HT8%`L;4E^}yd>H%GPCX)$;7S`nNZa)42?k(QT^<~JegYyUtK)NP?-J-9 z#pM+|cnGXoH3o-IT!6Xr@M3L@EW(||MB&gditH8^K5#=$svP!0wj6~E;Xs;2h_)L? zL;5%xpDE)W=}(@P&1{M-=`mx_sF8P^#!0JK8AXbd2+SW7jiS0X)tNlAQ6{shDnW7q zFDAFQQIo%5H?ZT;A(I>bcE5ZKc#w~yB?HQI$EaG6ILnrv?6=SopPy|k`zrI6J4ZW}So#ZuK_5GzZ>SNVbq35}%{z*N- zJhv-d>y1()b!^9VrM>vxN>kEwgtXE3x+0-RNkMpQqK7^}al5 zMfR>H;BfR~|DGm-OhN7IprOGeP=+k!6&o#0q0`&@eQ=Fq_W7nod|y z;pm0@fpI_0^L*ViIbU{iXgd?+7R=3IT;L3lY1M4rbkKb$Qu5s>m%C77EdFee-n6Q! z=BXo*yCn(6)5dxl``CUrxpi~)Z%l7?p!i9l)au=;EwQ;@3tmd)bU%f1&Oa*tDI1P4 zar%wD*3QCrao9G)rFMKhOQ5$MwK-|zo2E<~3PkbB_S~=cX=C@lgK}Ury8fblg7`ND zb89GMBB71`UV>U_;5x;c;V#esrfM}j~y5@w@ z7_7(2;u<_quWReob^pG}G4x$f<;j3U-4Q+atPCSVSG~JoWxM6myI%^Z&Eb|> z_j~T|%a*YA@+W-vy*{0F)OP)4$L90!V!eWOe`tcW_My2T8))7f-qfYydr06%LvGdc zAx(6@MvHz4gB0=lg<}4SgdV#8Sm`5;2Z+tAX@?Y!PJoVM&p=JV~PQ z)!ZkzT=l7zX1|f?j6Ky^%#=d+gkL8#{xu^!a zc;Ch0F1IHbne^uzf~GyG?|3-1Nqjrhf6lOVy;2wt=S8P!kZQ$>AD7@(;8&hv!*GQT z7CRT_JUGL+h}ReHF>^jbu56d4u67TUpIX34&Drtk4eyEw&HSS`}`Co11e-Z^Q|!9JnrDQ{#$CV6 z=ahu(qQX8lwZPU-_Scg0 z>xnRMI%Hy|@x<$ap1m9#!PxLY5;I!|m$lo!Lr9B#zC01Qk|FBm1MDAf> zR^cRR06V)MJUtzRHx7&$S)IreI<0w`I!?I2Xeb5xM9a-9dKxJZg@0N^|4NFW*)R#Qu%JtGQ zl3s3R1O?_ujYa2BZG7|zO#S1I5+gs2XTY0qEX>ehv8VgWGtWON#W~y~z0SXlLmE+b zAmi5unq1_rh|ywsV5~% zAkncRHnIlE&PyvZfyI6wyzx7HAaZK<%~AmtIl56wVEDAlUBAf&kJZcT9``@^eQt>T ztw7E$6Zg}aiO3=-1V870;sF2fwfrWt(l4l?x6)(3oR}=U`v^?ZzhCr%R&LslXdTV0 z9QsWsF`3Bt3h+aeve3mxBI)|-XbBce0AeJ;-M*EIS#^ZgRcR^O-bqHIn*7b}qCH^MxE-B)1qm-un73Ydo z*+!}O5bqIGV0-ss*MAf^vZJwR#wJF)HrBwBsEDiJlU)^W-Iw<`WJv{3^tck=b1-+a zCFq+l0-JsrX2bITtn3MdK_Emk4gV!aH?>WS9E{wEx~@)TnrOYL|QC090dmSxhtNK7oJf<2~ zL}%IGB`6Uq71qSc8?_W3Ayu`b=?iZyv;?*a=~}n(&Lg+(Fb!-m^sg2p4=k98x$qmRUGjJ#?zKW@~?TB$9m{Q?r>L zEAj#q%ru~x7Hl2bQlpDNQ%|#Ri;tv@dU4P>^nQdHpMx$p(Pg@&B#$O}Vd4BOZfE}L zQ!7D-&J{06#~)`0nzfMz43k16HMa@PkM4P?Ww8$C5W+j0`oKC zB%1JP;rHh8!tS4d-MDaGpnAWR_BclK)r3V=kddQCb%S3*(BxNd&e?joIX)fE)p!Sd z~%pP~281(5k*qy=1->vRt{S&Mkd%Fvt4|!^qpt}bJukHU+I!0ASZ}qnSx569aT5G=wYNP7 zZE=Y53{F5uKyVp4=1|NDmjF{O&HGWRRtd57_{%-sG?@pw=b8&MJ#iG8=z7q^P|o?E zP+g0{bH-;5NFN`PuNd>0Mp&hqD&I`(F;^x47vi>EX3?vM?kv3ZK`(oR7O(ali{^B4 zU7vIzFqQ`jLbzX0gH~!=?iCkF@PB!wyTi=!5;k|c#61$pO;9e=LSGGeOf>@ezV)#Z zR5I;zL!Un#l9>1G_JyFP4q{z~zOR02hgcmfBvllYzWT{h;`jcXx5X@~@W_`anUJ4u z8!6~e9PqpM+I?+Jjg(&WbO>CH|204$KUz<#&b4=|o)l;nMT&;Y+U@MVUu%^5?fZUe zC^O1d%To_~LOw4|6&iD4t67X_re}CPXne|e6dN`pPz?zf{7S`{xJbqhV5F|NbCQPy|)aDYHb5X6+sb1R7yc&ia~A2l-QPLC&yVj9*IcZ% zp1SYn?hq(c2qN2^@~oAHOf{4Td<*A7!L3LG|F#V|LdBbWE%OtJb1`DVH90`i_# zn11-aVx+BPx+$|<{8s_3^gHZ|afRmS1X(L*ZR}!qlYb*(r}QC{hsOCM>uVbq;3{Jl zJXd41qmE4!DKKj>Xt|gDi>e;9qFTA6QhK-1eE3!0x&u+?yxEzQp{L5>TvObjChuua z?M&C35u^fb>%;ER=w&v-zDt)cOp<%32l~NbdypWaBD0vVify$tkDm_}LmH$wn_orK zr)Dk1?ehI1f5%G6ak<3cea;RWhr>AufhT)*ulr_6sc2E=+Ip8sWjwIs@4Cuwq9)$& za=>9Bg}++%CXr!y4H=%1CEKVL3Blf;a0X|myV>9oc58?H#KwjQZy}vT-|309++ng? z%{27kMV8O9N=EP3ag;+V&dY81o~y%ewnYd$dtf*E#=t?-n*!2lgqm2dOHKz=-Z)~? zKu=NQACJ+HuTEOi+POPcH8URiUkX7YM(%(`&}D49PP{zxSEZFWCA(8}*~iE&6U?TX zb!=~k=*{5H@+^Oz`V@`3A|ly1y56}r-4A|7Y^rlT^Sc_6%KSxtZWHa?>b?GmPXl}A z#ocP0^J3NyOHIq2SEF-NL;)C-)TYT!T<314=Q8VN#mAX_6Gy8^@Re^=ePaA|ZZe)7 z_^1VIZ};xII^owWLJ7v}nOXp02%*oDu_kJqq3cKfR9%?+q2dT{*dV%3f28L#cW6is zK`u*$uT=eJR@|^thC>(n@oD3UD+i5y`%T9OGTqM7EiVG*&+wwg-SwN7DLKq{>LPNT z{M9iz$#44ye`d_+H}A9d1?W%WG3+}O59W#tk!rx*+m_Ej{A0Q^!j8@m4 z^Iz|l-=&c5DSu{VtY`s{=r z$uJLgwP9>kX8r+<-~Kl9Tb|5?G%ErpdecMSYT@lehygWLm6`!3O$FkVblF`sZ}`B! z7B_o`vJ9Tp5jY_^t;dp5He?W?=PIzpSI-jPVI%y;ii4cvF0Z&?E_M>`f@);hG}(+J zEcp%yz)HC^nk(LFbH?fCHEClEL{n-^e0Mek(~!3(61Q&sI0W}dWQS#2{H%L$YL7`T zi0hW(nnt9u(JV^ljL&eE;{=m71urCX7gr^;d9sHjvKozW+?t9p<;}dH9I+ z_$ws-D5_%tH(CM^aP4o-`TpuI8c{4(`TSsSyfRfap*-Bcv3nh1J8GhALT=%NW(p|v7q#9?ZuTiGZN7L z%Uny@SWa6vKDQeYenPgX1VHyxx0hTDbUC^yih!XtG85~$9yd~ktKP1toSc|bPO+5M zn)^jbsG5zik*2xbBS$<#K|%%nE+5kK`I46&PB_k!Pei+Gph9{k3W5;t-4D0p`3JmT zM5nF2uj&mtaA?4nn)WTT>J*^C(wf508x3_^mNRJ7Dm2Uc14VVXTTH5ZU+CJ`IT0}L zEfeJ;RJnDO zT$MwOm!*2r=TuMHxytjI?Y|K4*we}dnu`N*M}DeQd$9hoOs_5y0~~W6NKOfA^&&zW zVC35)>e=Q`(g#8~(4b8FLKVNPP`SJ~B{)wuN>hdvhx&@u}WdWd~BXn4gb&B78SM6FZyJ@=6&w zt3_4EJ$HP5kprIfFO9_pxsinou4Sz8wn`Fi6J~w`is_FdOQW3>>-}7*vB;k{csP+8 zRaLLeNQs;K?G-tczOn-_!OKHz}^XUqZ##C&^J@0l)`LdFJUvLxa=NnWUL32|Q**cBX6 ziu;)o6{sy0J+bUH);H)%M&ZE0x4jbcOV=IixF8zOpAtk*-kZ;*g@Oso!}CgRPsYu5 z0xdfIYuI(gLdx#NInioXv-mEjZxtu?BBUZQ@qOi*84uMOnKi$Un;paN9`4Z!&D?XAGyb@Iw;(*W%(3(9GD^PrW> zLy9YVmD)1<*rb^^L2(Z{cSA=UTLxM9A|5@56L7n4mlv>mzZv*#eiCe84aoDGo_k8x z)%4*(87W#8hRyWLRD4B)t&$Y4=RB|>1fo>^YHA7foT6cdE?MR+@uy~!AUZPrBR+TM%|F?;<{B>Ixyf`axz-qzDM!!cMlGG5IIN_?2+|=hlO_uHPve|%JZ8OfUxsf;XVB8Usz6XC#s95h5D^p zedkPM))?6^P;`nm1u)}|;DM__gE(kvH1XCgH4Kt>8V_4Q5TfV{_YRJNLHy zKyth`Q|G#va=NbK%G<%x5L|{XPOpIy|z7Selt65W?Qv=DEaj#=s4ilTqZ4$ z8Zf4~WS)AKheMl`%?q#qZ{*9zze zxj}!4Yath}?z4%?R#h}c&UI%DOES#{&3q9sMqrWZcifHVPB`{Uan97 z;4a#46%+;y=UI!ILt}inQW&I1wsUceI;fC9NcQr8uRC|*M-}hNy?qGpRYkLaJ?wih zVY|Ll89W}89k8x~c^I3V;N%h;q+MT!$STrtQFswe!l&l;z4+`n72gZYrblAk-vXH_QeIpNONZVXux&(1ABgQST9 zq*ugx&t5xZpUw1hiA9aE^?>=;JsLAGVIOyeQ?Aw7BpYdrUZ;px8(ILg$7?GrpjEA2 z7or6sk#f=A7zSOq0NoA69N52qE1@%gnP~??Mf=?3U)nCS&Q*NuJCv-9J~ZTC1e(W> z@zhoA&wZmd+>(tP(90fymZVhggU5>CM!ebj8@wG|QKQD`V{R1^%hHmfA0gq^UWzm< z&ij+Br48I%(pX*P2+ob^B&E^EGxh^Q8`Yaozku@0Y}y2Aiv7z7n#PJR%&jzE5i zC~g4T+}GJKods|CiQHjvaH&{D@ToUh_exK7_unSrPWz~b0fCFGBQD<@@EstpbhVF4 z(N|0>_?~icun$a{-XG_!ELA-2ZCm@iJQ_7)fw?gtHs0IkrfAtd#RcujHV(OgYg+e| z>U#r(A2f`zQR;{ec@@EoLcDa>nusZ{aPQe>dG?V$0>#Rzv~511!sTz4F?@~hH+k{C zd^h6rrf`3PMwy2}dZ6*J+-IBj!}K`Y?bVHa1Z1bjZN9OT+V65y(b*>iG+6opTht=6 zvC4S$OtCX;s8n=C#YilDd%@Cy@iDR(axH?6Pj%TKRj^X$ zPYTZ{7(8xXrPFij9m4c(e4InoWS4ck1INsH@LkY}=Q}|V2pkb;v~}`Y)vc`lMFf*2 zu0c1GQkvc{!*eF$eW{hzZ?5*LFRq0=3#`;^U@Tf$W&BXmF-qh?ubr9I#J0 z`luIH;}NArSPD_)QPDbpt;2V%@9xa+aCCWTlGm8>H-KJ??uxWZ(hRh-*7v|EpgRKMJFrd4mT1SS*JT_fnkIauvw@;S zK)xy{IS5}GPrI*KE7{1a_D)Vo$@-fBc#ERXdxLUCZ}~irG_UtWHBXl1b*_x)$L%J~ zhK;azdwJ{e1&Z96wDs_=fox`E2bEQ23+F(k#%^u&wn(Bup9MH_OkiUzRQM}Ncr0~$ z?9LtXn3N)Z>GD#)oj|NAW9&rHZQ(393)M4pZl+?(P$IH<<o)YrXr>!tv2~@jvk0Aq8j?`C=?0UWUR*wZpl8Uk{D!JGJk7FfU>@jjoU+ITz8=3f`6D(6lgSguWin&0P4EJpcTz9D&gL?5| z4>?FaWA^>-)trebv9?^>TowbBdOo=>QYGlU!h24BOn0gSp&+pHqld4H8see1Nm~MF zfu<%!BzLz^v$P*S7)u}{Y`Wy$@yff;|LTQ4=cwvu%4G+IvhH+1mqCI}6R z7U5iH8^{8j?5X^oR@%ZsUTe_C);x2CZQ%?(42cM)MFFZyxrBML?^q|#O~t2w_gTmT zT%%pNH8!(ll$5*Duh#uc{Rs(p3dA{z@~L{tLp)kJb7$uKRKdYK*>%ttl6=zpn!?8rq zw*_wZmL+=Kd>r9sv*zuP=|3BIl|*d^Q#!o9GX|tOob52?mJg^t zErN1lOGZPkhkjv{YE{>Xyq!g^eZ|B%1qQV!xhxmH@-UrMp~e zU`T*U^B^*~SGiEQ-`sK`=r>l*Jbkpxt2rUrwUWDBW6Uj5J7YTpMDUDmAC@1<3?R3C zG0JH8T&GOrIvzFxY|RM9^?tC)r};24Om-8D`bQ_u#W5?$+@=E7UP%oIVP_&Pk(M&7 z*Xe1!$+KM5iXQ?ElT@;BOtVETuoz!&FX2Hg9Q)$N&VwjK4dS;bdRg%$Uyq2=B@rC+7{0n9-g0pv%3GT#vP_AT3y=;#TDiD|@9&GR z2=B*;>xTE%~v?#5bV-+A^+HBVMLgctmf zA5m$S5~V;DaidRP=5Gm^}PB++Ncuidw>>en-ETLmJ>a|kG6V@iXOrG_GE&9_K z54cJ|r$66(F2~8!%3SgJXue(shc4P$5c|%z=s{hD)0nB8bKma^f_zV@xPaUwij_8Z znAMzaNUVV3TuA~sIdtjGxzXGj;aX0*k3w?AeYrb8fL;91MBU9N>l`SOlA%ya3{RoaRGEH6K=JG>oarcy3d@cm2#jwko zJ?aTxNrodJ`S-ac=2-S^)1kTtNsB7_3nE0>P(a8%csa~%4RP*58K3)R6U}CkuJdFw zv2~bp8W!y}fDHC7gTm3l%32Rk?WUcSKJ!mywIiFV_}CN9-^Uq}yxa%kg-|7HjqX-P z#Vh>3Js+yy@oNxrc9OY~I0~h41$FXGVfq!OHA}@JOM`7X3^EOIvjOqtn^nVU&;o9# z7T~>?`%OTtA_225yI1wCC^u<6kllrMYh8bujwklT0+&j7%wCP5b*ipKj#`@UYFO}1 zBQ~Sd@|mnzq)eoc6rQnMVvIroXa6*iMd+-l5)Q43D_`Y58( zHs3X;0c~e-%>Mi=TnXQ8Wyr|dRkIB?{Gg)D1B5Y3`VgnYxF3q*`@%6fx~s{-kypcC zkZA4}Z#Wn&rS@FzAjlJo7J*^+DlWhvZ=z9kZhO#Xvi-)93v=C;ZyOhOajo(41*1dA za=;f{n3E*babAP7-jcDqdvtTpe8sCpm`;5dQ6=lXR48P*kYK4 zXiy4rEJmz#Kd+mO+w$6I0dxST`fFAe)x290Y4$80Nsp1{qMmEJ+w!nR<+REg%J9XJ zOp`kIQGNA%dzGHdy0z7i$0_&RmPi}R<q2m4eS)uqrdIjlyKY`6@?DvWD4| zB%`Exj4PNbooo?6P_O9s6og3`#PVGWy{niAD{}K7#AQJKv=>#U8emhhq{u4V!8sv& ztlB8t9`s285e^z^m$zR?3Nl^LwR7*<`%N{53de+rR;*AFZ15LEcPmQj`{Op}i3#{H ziK!%{$`X#GnsJ68s$yRfb8R}H2rWj*A#~TkW7T<3n7-tEFS*M8irQPgQ9m<3XvIHk zEeLudHzQnsMG$qA$Rx6K8t)7f)Si^$5qVTgy1Q6C zJ|`6Ng;Ria@q%?e!&j^1`Pnb}K~7Avl}cIXzp7=RrUzw_P1ulOE^lvMIUNIrw!IXW z4N|^Q$g7TTDAh%OZ>+1MpW!E%MId|gSwQPc{JwRUvQR1sOY?1iuYz*9v|-oPFNhY| zm<_uu`hA>=K%kFpP{GQz$?E2vgzspVvU!gOE+ZlKx-Mn7-G)+-4G7y&y+7`|pLJ-a z*wxG+hl=d%R=TDeI2g?|z0rc#?aAcZrSt7YsW5At!O;;r&`+lnbqQvgHyY>IxQ7ov z^l`;We|RwmDVfr9FPII+QhBYMA1U!I{+Rgu6%fu&;HQlnyT3tE+MvZw)$62A@ERg> zCYy)LZeeMIfc16L8?7QFbp9WZEMtM}#`s3~%{iq$cb z-YZddSk4*u)~U#LB!6X>(>qW8w?R2%RJ4`WE(%MC7CNu?YCc1yB^RmF4U!z>?Qkw(nV z92)hU+@~2Q8n&#%`#y*+(w7SH3CT!vkIzY~)+ZC$q_JUlrv z30!S1M4JXUCZB@q7o47jRqkCzTUY*`kGeYbNqI^KH*J%~&y?6)S{#`6Bt%AZ2?#Ct zJyRkl>L&+5Jrua+rSQXDtOu2IzJmt(E5nMe1<7olENH1nw+SC!6Iz_qR&Gm7yR{)0 zkvh*702tCs5^R5jf#O%h@`n)(%}iSkFqBbZM~}gnBGU6(RV&8*S21b$bi&t7+9@^S zQFe34hT*=3!O`fzC@amKCpwVx8p*#;orG zqU$$Q$sc=~Zksymw%DYF-%bf9=4kY2F-K}~Eg+|`U*A}pOEm6ZS+1BfZ-7- zmRt2?DHkgr1gh&?ektmf(Mt&9lnbV|B5r={ep5_NaqJbrhlnIS{%X!X-$1Wv?rz%& zY{tMZ@5!8^Cpt(VFZ+{k8^ENd5mR>MT%<)>I3Vrq)kClGyd>XJu<6=jUHzy5Mtjow z`)XqJR&o6ETXL%+wd-@LA2=+HzRhV#yb#bHmm#@BUjh3Si4v_?z932oYF_V;_eNh4 z==L3I2!zVjE6u_#Mdc3-8Z#aq7u2PXzR@T+SM}{Q#u2|Xr?bY+1{BuaZQuMUHu3tKD2)00eao^ z;|P_rv5G{+t$`SWU{xgjs@dkbkw|OhVT5&WRYOf9E8i!(0)3-pc`V@8vzNatnc{b8 zOIv_rQ}>CP*+!+`X;+h%oShHZmwHQaS1>%{x!8hfsgd&MvgnNqJ#cZnNUgrjg2p;` z?ZC65lwu=z4}sF>ZKBt*8hz(f5-1D75jiy;&Mh~p!Vw0z)Qg z0#SvdX0NBv^2p5^vaHzGFZgoyX1es<@q}{NwUZJuwVux~ajvF%%+L?ztG10QfwKq3 z;$D?XdPeH^XB+Mm&S@Gb``8jhZafaA{=9*@Y*GqDR!NhnZjQuKY2J1=l5#DD z$3NghkLC8tl^6>ldmn60nb1Z#i+j0Z{n|UYvv?nwXAjnAzg$ja-Tdm?l9Wvw(V;XZ z-mdL4z-aABiPmy@KZ?=vajtIMRME+%fCcL}h}rj^e{U7M@a-mOsJ*Tu_1F2;%yQB` z5Bc8u;-qLy?vz^QoU!Q57`t|iRK?aJrg^u&q&cvKYr#!}x{bT$+viH3o%f#mi#!?v zd*C%{^>*9LIalKQ;oqA$&;u-;wGs5o< zGGjlyuf5mrGEeYiIifU2x1-|Dy|>C^KaX;*85GhEY}y;O`9p_8P+ZmcB9U|}$mpMA zn>UaKS_5P$VlK(VuKx;%-~HTms*)WiM2iCh(99bYu%B4TWALy8t=2a+m;HOSg%XFu zUu7QWNgiiE4<975S2p@{9w#RIoWG)Bm(P`xTYTXPSABNA>ZzQ5l!Gd6bdWB+G}SV8 zoR%#vOl(oH8<^v#wR$;XVv70AuFLy>r$KkVJ6O~jq(J^;Q9O9qs&Jm+yWpCE)(Jz2 zf3GOxA_rlOv&(%e68ki{P?`oC{6#&3{kUQ4yW z8mh|h_z+KXWqISo(|(OGZ4vrx;0cHb{-_4of)SVgCsq9{{+)kpHp%KoWv#sjDt9jDnFhs@JrC~uOb0Hv)6!L zQ}(phTalRaUzGUve32=Gkyq#NaGGwF(2dN0|3?X43^@ zzwSKkKR56MiF3r2h(?l2=9+csQAcwtnB#pPuQX3D4lx4i9GrsVuV0WSJ~peOPMFUt zYK`qb3I78lQyHIIwr?U+9~-6}f;jql0^fE!qrRN;(vacbZ)e>4FzTe^F+7rCafw*+ zaLR;Od@VmDaXQo4>#Mv$*KzwWKuyv}c5aPfzOvDTDJ53vNb-;^T!V)-mXIr3T{kjE}i3bGX5h!pG+mLOn6(ML?#8A`rzWA z^ue}#zKH`_+jX!xN{c_cI{D?(O#CygGJCH=s(~;EA~VMRI&NmBmw8cgrh?Bk27P*7)p_A3)#@ z2@BjEXv1(g0kr}H*EU^c=Co&6is3Qw_%pm5r^4;!XR^vud8osG%CTG_^9bv}=uP_- zEu8r;_FS>a(WqizYvc4f8iO}c{N-x(;Ds0Yq`gvaUc{fA<0%ni&|?sUyL&J}x0&vr zKO$(ml{D`vm{ zy#C0CyD?09)ZG2Ye%8;6*N>Qq_&FlrBVF0<{cEoQrh4=5gC*p+V*2nXAi&3%9Pn3h zH(|!E1w2}`PGE98sRi)$!43bz?)Coz$xa=--)tt6@mbbfOh?o@VF>?)9}@oPr@*^M zZD?a*)xi_X_UT0?B6upOZ2IHM5dz)*aNR>+0VApwc*f)ZL|y&0^F^*Xr>ml3hmnd|m;SCFlCTD> zrDwbGi|FG6)M3?6FkP*7S^WBYCO1~_@3R$8up;j*jd<-ephrlPEbp=|J zkze;7(g;xf2ZG`WaRh;VZn<-wMk7Z((%aKA9w970=#GgF>xVnr`^y$< z^xt@^v{kNgi}MytNoLbkb04_O~lgFNxYap7Wky~Rn~)+y>H2ogXx$G$bjRv$)m zvFb87u3|?dl`+*0FJ@06dpvN0D?aeDNMp3<;jMg1$;!6Q@n*{@rF(Y(%iylFS< z4aU~}!vzCn9FoT|rR*tN?kTI9m;Xl7&D#m#JkoEqkkUfIhmbVo_xS`6YcRA?sEup= z;Z0%2|MI7VRAA+LJplnBho3<1`A9Yo#f8G$o%43iKW-DYZs!UA}kFWc8@!x##S1L>Q3U1_HwtOVxbmR26j_42&^`9yMARLJ^7TReuqY!_@E&eeC7 zHFLI-KSg8N8Fp3P?Pj)6WxdjW(eo2t1GQ%HqO*y*ohQdpL3SUhtE`o?m1hF`yy68+ zN)QDk5hX%ZE2ytvE+2~<0F$>y5dTdEt#0Fqn4iiXEZRxVBB`VMHc=%JO^QMWfNvUbG&+xHaaX<2O zieL5NzW~qPa+l5DvuZ$wQw_;T{Y_?Gi>Km&TR6*atN)UXi^@Mf{~GZCndKL0HP|^8 zPV?U(CHAqAD_?mpPW?ge6MQ_6A2{HKwAu1iDdNj3w!k~uNHJUIY&4SCIkUd@Z7#8X z8yzUshC$-LU#H>+UKo=WP*%PW9CCOcA(}pc1aPPvXi95xONAu&6HfGbz{KBs?e#yi zU<{smkVkR&WRpAZDUtr~TMB%^W{0Blg+1EB~Pxrl7NZZt64TZ@TY0 zFSRt@4mLTdLd9_fqS5Be$t^dPS>Xq8rf+_J|3TRs#L3bEQ#t`GJYyVc$E+Aeq*63n zNj@w0wX-`PBXe$PX0cx~($(I$l8ZfyS}@e-@8vUm$QEy|6%NTVcGu9LIRtPlF)#+^ zQP5=*ZV%nJQ&dsK)P}b}dbVb%1l1jjE4E?M)JIFs~u514E%EJMc}` zVTR2o6zk9@>31*vePt{Nlz`893%N;KoidN+J%hK&tq?I@sX>W9E zH=B9h!(!p(f=T44Y31Nr@ZaR}j86$MD}hC{j7{X6=;tpFN6_z>jxMM|44!Js4&4}x zcL&~g2B@?2SvQJ8jijUbBoy<{P>>Je!?l(6wC&6t?r%Fa4|}eP_Yl3j<`I=6RwV4C z4^;WlfmJjmp7FSVNz+>WOXmW>0LiK?G7L-6FbF98jf(Sqf1;$_`tYzF{Z`u`EQ_S5 zCi1NW(ZNj_W<%fnQ=91o{C8MBF!u$6tH@k(zX{4dI{3G#l}{^RByB~ddU#moQ?I&R z3Z-84xqcG1bn@jD)0o$I$ldH%9l|OW%-ti!&!-#zK530PO2`R`t-;<%9OuY#9LNE>C#w`339jmh;bCv^a=Z?av1Ma^ zdF@!PV3kOK`5}jAi_W@ux-y*6|D|Y5`EQZK$DfK254qq}bYzA}j)_b^A)PmUq6urv z>t#u5xx0&F5T>+$L*2)iYTIt_i%!N@hs*e5J%aZrj;O088RRRl{-p3Td+PC?<3a$p zlSNy^oU#9#xGOZ`5mj~2frQ%VidY+k(~Y|o?vWgiL8Xwh8O?qI!fuPf6A(sAe?2#Ml7wI{XV9 zYmvF;_3YgJJlSKSS0&!o??Kw)xHzKEW_tcjKtnY%iQIqDcTqRt4KGhgCN0OR*ix1o z+@ys5a8o{R6p*24q+zG4vRF+&xDFvz_j+{|GLS(aPqNK=!~aOcJ7ulCnXkPN&uO;4 z#0Z$EHS030#$5~ieFQ~Fw74!lyciwnpPCYWM#RiC!>K*b;4c)oL?9!}lSG2J+X=4H z|2)B5aOe1icUK@Wg1u8*!(iT)1-qvAfwNIb;OOk|<$|Ibp{tp2?`~{X1uiF9?8wH&_T%_1u&k+ieP6rjRebNeLj_5@sg zl%2?~uhwBrSZ2^_jxK5=I(qd)UjD-_Sk)6qfbV5yoRCIPM>xAP zw)KSY3=#9b1m-p>FCH(x1pX1gGrsL z?Pw%}M_P(|MSH)au4Al$?cU#-IfD`dVVQZdUX;42LNVaHJ7g2$2~POY%-dY+*5_8; z_;94VP@tsO>K**amM$Z@f59rjmcTc`edjFtTZmHYB?}#5ybmWUIaTk!?|Ge0&sN9=xhTAfvRajMEh&4`P}_C zYxCKqAoN`x_Tx_tzxdCG9?>^-vPavYR(d^N>8t@I`56^YHm0qU6J_w98{soduJGCu zAp9$cQMet=vyc%1-<4DCFQE$v`E9(}1;(H7Q)PSNF-PD!nNCX&Sv|?8I=Wp=Y7CGD zI{e|{Ed!0WrO9u5?^95|IudONdwl={y3DS=4@=ug3A^E4?C*%InmM*_T*kk5$xtU@=iPt(3j~@ZZKa6nVy&uKT`)nxjYC&f7h^Tsw^uf+Dz{K4mQql()UuK!_9SWO&gj#V7VbK*EYkHUd zz{7uva~{~xr@HbP_ReU(aYUJ?N_o&YzaRQb9||NcVja)5z$9}@Nb-($aQSc8&8M4i9hCb&j z5hW=V+}fVdoQT!Z;1RnnqagNS{NL#MAz!@Z$EIh@BPne1M@`6&Lp2h(Z>$GJRd<|T zwUv*{>d5xC?)dEJD2Ry+y|y9E{p%pE5oi%LI=OWF&-jxWaQ7M#9^VHQHJ~tO#Ad65 z8L{u?*PPE0M+_xzgR&C)-6*Qz{A20Xue=jknn?j{c@K}E%)oONZ{e$A;jQB<$@&m* zz8gRJe;uR%=+_h%!Hf7?Px&KwQUj4Ea`uoR z#eb2R)8~MZGz*x;gsIK#f0p)#k{P|9_<&(MsZQ$E~6j`F@gos|?4& ztQbRBPQN1HhvfBG0~aBrt0F&XePswem@4|`|PkQW9K-4dhY39Tb!xWbtiOhPvvqBXXQ zTOlDvZxzMW0mA5A8xoBB8%G)q^e1iXrUiM|39+)lD&1S0oc+~o<;yn~2r3vapttM}(e zxSjs6s|0+2>N6SKV>@QKy&6!=@RC! z*8ZWApilvns+JKjx_r!*Af9LYgf@flUe9TwK?tz|tLOv2Ii#j`vxKM`O}VMI$(;*F zs%EcYs(jq&kxL}zxq2zx3zoX1i1QlGK8_Q-y#0v897*cuzoioTJHA_xYY-nVt0)GL z0-cgf8jg3bAn5~n9o60WO|!wVz!d+=JIXJne&~Xg2Z-=F&u@+cTId2tX-TN+c^9&u zeTiu1mSpG9>{ma0S5z^=9Tl?K#8I5}qE+oW2h+4Z)Hvyu{E{6=ZP2#vKe4e75n5c$ zk8Zr>e~<7ie!*3jA8JWCA7y*_q(a)Z@}CRb{9j-&i?^ehg~yk;j+QKUD}ndQMB;FP zy#IwmYaAr6R=cDsj4^USKkOE>;g#c^0bW8zB0yUFnba(HtS`UjzWe+9v$YG|2PPmD z4TEQIqZ%jwaQ4N6a^;R5tAh^5=Wa^nbGbw<<&%O$(4A(J>=pJ+mG2HEufV$O+G&Ag zV2&*bM7XsOqPszDu%)6SJ4SD|+3(f7aZ~X9D8+V*IyZ#j$Our*+&WKapr*vC%5jFy zC?-NF0B_lGtnVL+m{ZSjGSE0RuKoR~;ia6QzZeGUuQ->b-6up~hg}aPap|nUWV`p$ zYreoq@nhfjFI&R``*-Bo?}UWn?T2Zjtr5*~=}9+7Cy;*n8o053f>#&aZF_yK=r z94mGb633Si{UJpw-2HOJTp1i@=fX->Y!F442waLUE&D~TMLX8rm$|srk184Aq6*In zb#-ZI(df9>Pf}pTiJ&ax(s4+d#dNayhIou zQ^zah9CyjB3L33Gm6LB}i}*3)f>6`~nzW30mp*RYI7hSP^>fvYMg^$NN_K81AYeUz zlYW+jz2E({oK3VqS7ATS+**UF{rgDutL}emV25PjC1c)bLZP*`Ri_{-sj`r?-IzTv zN0QH(Vw9w!Be4CdXdN|wSwn?^pc(ECYf*}0N@TI6e_FO|Wt>5UfMpy^M)#{6s8M?$ zia7H7nYoUvnAs50{yCiIKk5#k3T}iSmfD}fxmmS5;n}+T2(g@BMP<=x@O9hw3RZ9lK}^iGwOHr~_k zUCJp1=(J;yO)!l^a7gDpU1lp^>Ki!@Qi^<0VFeQpLw1$;H&@@ix6U)PXY?OvN!WUT zTx{@PKGKo^8THN`pg?=#H;xml5B1}5@sTi0wsr{#CTVyIm%s9XyrpwDynvZ4FMT)~ zbuBWbc2b|p;o@fsTE4;5!OD4+w`8mk%oBvll)eC6bNcc~->h(Bg`KRZrMo*&g69&t z>AsIZ@eX-e?q;IOGcQF>cY;`1HuK@1it>3n%FU0!7Q;gt8>OlwbTEMwj#-H~Xz zqkt=8qsXT@owm4b%3`~`zgPoZ<49DKYY~e#0xhy4M(o*DkSK6&H)5}{VFb2Pl>Y=w_uQ}0PGd0Wz5lX2+p$AS9h@FzX`O3S z6W}A&Hyw#`L0A<(mv^rM$J(XlTEf=)N%FW@W%0Q)R?#=KXLBF5^tExv&UsywC!#Hx`%-C`&@Hj!GQ++}_ zK_TI?T@Cw#`MC{jk&XO|fKi%z(8#o3)C2Eh5hMPO=|jJ&pIs}nD-2mJRmWyjj|f_& z64ZwkLW!C%D0T%ToKWMg>{z_uRn++wC9zeqY-OP+$ht7i^=C9_=L$LdEJs_+)zaXY zM74R6%sETzFr%@)y|H583N1)AuE$xIsk41?NMZx)k;sw-hYIO=wWC*sHnrq^w-LQN zajD6ZYLN7=}&@VF+JJl=Muq2P}BO-0;^z<1O&(9?pfwYuw2ZST!-MN{f8ko`Q01RYyUM6uY#0q4O-$Hv&Z_(&L?D;cOu%pB(EE;{ zo_QF4wqMs$chu`Arv%qbq!xT@OK4Uo&P}GCn{?!LYOL#KLY+(Pf#b#Efvuz^|%a4!jN#-(>4=3%X9lH?Ksq zZTItCndkd2yw;sB5z2Sf7HB>-tMjjCeYxmx?u9VIzcHBfd?TlX0BJMZX5R9$V{4Mt zo!=T}x_biw)aciaUs7aOJ@ewM{Fg*1T}icQ zXn73^@nw7FBF)`q`Y)Z{sUhwhh921=N{h@;Nc9^MtdE}e1q7&-CUwmGmj90580vxs zF7#@B0bMWMoNhm+>9m)NPc*=S_3Q)QkQ|vL&-m~Ya+sjvuH3`fU#;JJ$UgWQk}xW{ z|3-3`;sI!=LRlgf{2jwLSDcN_LbWLGzb41p3S8Kdxt9xiUjnk+VOV~1v8RDE$@zzf zZ4%h?Kn%z=G!TMf6VsSw*x-Xd=OXS)2+L!NvT<$iEU%N_;}9{WL1>DK)arR#z!=B! zAbK+$=$3YV19NW!e=L9%ugZe54m8_LxlQuhRjt0hM1k)mMMXQHJF8VZSAuWO zeQkd_EJ1qplEGt1{Kr=mI)%j(Im{$|2?GhaFndsa53L}$8hYc+%EH$<<=g@5w9JZ% z%0*pKo(^SYVR`x}jCr4;PAS|z*t}JACt4QTM6tz+qGyOrc5q3}=T_G26OG0+f90OP z?!Dc~?&>Qxx62s;RZ!e&3~-Ni{(_yVK>C~UG@eG4DF0JCjZwM87<*)%F=!`pQCjn8 z2qBWMvQBxouzaUXkkWXa^mlmqe8s1A!ytS1kDl!hnc<$JGy5#b1!8Z(60eXq7w4fj zMFQ=5s+yYCKmcnvd%;mIqbxxF% z*`hO_k@jxe3nE8UMw!zl!wqdH3CsPxO1~5Q8;%-PY1Zu^LpqMoj5x}1DAcrFtZAKL zBf^`aMiom4e`}MwWRf8#sklO#yOI+(6GzYed&5OBHA}q<2YCb|-FJ&MA3Ow*r9k7U z%a4p30MJj;e}MjChsFz^Yd&+3(M(nQOfma_X|*y8J8QH|IU<|qXM71v6O&~X--lUGo??n0E$H_-mKl%zSm@QN2XGhq_r$0zgZ;0FqL)4h3 zyX%}f28d zu`@9bikTWACTpa*R%r!|%%WogLtOkA?BaEAh^>LG&HA>HrFHTuJ`Sg>12JU}LDaA# z=%Id*zZFglvdS#Aq+-ef$qs-Pc3?~pWFH4H%!BN%L-k(NH0xv^yWjDi)yU7+c3B)tFik`p$_pku?oLhN4T%Vq4>330wX!rAar}LnUw(qj zMlvmW9E$G`Boh>lEXa(uu2_5w`z^;B8<{OPQHBp7lRBi{`K8b@j-uNdY+twHhz?QA0;V6<-nV|S(P$MWv}K&4UIdDwcYW}<)qFU66m<(JNHQxP_l}HhxZfmr5?51NPn*!}ML6U54dO%w^aF?n6N<)7-F(nU z*kXg>w6n}7D>Q8se|>d^9XrN!kyW!^5y^R@a#OmuZJ}}FltJ#-9npGbz{;RZQcgdC z4kdA+rR;jz0RRlU8~bG5mA`h~p;zELtB~fayI}>*_m2h2txV1x51T-xtd?HvfikbS zW=Q*_e0acAjFfAzZZduJc1$1=LDKD?zciUYLxL{5tD5ee>yC>L32*egddJiX`NjtY zyFNmMlFK!{O(vMFuISSrvgC7nKas;DG25u*oG>A*!8$Pu#1r>QmY5_b(A;%P*5EB% ztI5#52w3H@@{`N}4h(bIp&LQjv&eirCWue4%2gq00m^}1Tm4qOvJ=-?-x0UKG4QT( z)b6J>9H9@9{Lk`H9^yM%K03qtBhe7h?7de4WKScnF@_TO!d6TmzP6wClGh^hImU08 zZh>|dj>~wCnKuvceL5zo>ZCeDFhmwV>4E^3VXHW4^Tx9}9J}w$6+Ju#jQ6ys@)C_! zWbt@(FlhV+?4H;hbk010giC!NUCVb>cCKi}rkfg-BurPAZ&sAZmdkU9hoM5{0bAjQ z!|8Txg=W)Upb;Q(-Gw}_+**z$4G=TygzCu+h$Q;5>u!ANUm1}*-hLaLyuP&U!|aib zKyj5g>XY$JMozX*LFRKVssp|PWA(x0{xBLgZiV$C#xKSc9pyd}ydYf7#;FfK0vb5wl*3 zE;m+^1ShofDWy$937nZuSjibLZ>UdqaVLT_+x@(sUa>BdF7Wh#mQt6WZFFT7Jwd>J zq||lLGdqK?S176Z{g!jry6qTmmbY!zk6=-aDd+M{&L7nhzzV5Buqr0x;B4wKDrH4U zYh%g9>Rw(Vk;nfwg=KFUtvCh+a1vFD21FzOXPjpw%#^j1A$F zlyYT1GH^U(H_0!{ue;Ga#+{r{@pEUfU{yG@r0&K%)p?s~VuBj?%-X(=x1ZyCNP_h! zsBKWqQb`&#y%ifgk`4PtKGuGl-r-%37^QBf#dd1QGgG zusOC*c_rUG{1O$#(X?d9pd{wNF2^Oq=z|Qeqo~P7XE!jWz^mnKF=V#BvZP_Kx7s*A zd`t_S4YF>;bln#`F6?1MyE)4K_BZvqm+xTOxN9rd0t8%9Y0H5JJViP{*w;%h2uzN{ zHf!;{R=9S;8w2-pFK)`v^x0KUG@qao_R9)_?15*&pANvp6YEm=mlE#|)cwGl{w<-l zf2#d8vP0{~K6K*sW89h3&)GU9DyL!JtQy}DX*v9P%CJ%>!F9c0({OK4T z)Xdx?LQH>jXZHAaGw)_Pa&v?EI>?WcTfxZHNxvRA4Yxq{qVSD(fu@K#1>*Ocs6r;N zaL%Xu6jqi<5;~p9VY2$8*j&4dWlALbRhAg8Z|=;_M}o=YMv5ID`G-E%++*{41BvzZ z6dz9R(*S~{0;e9=400?JwKsEWi6418)1eXzd>g(W+VXG8ycp% z>cqA+dJ8ba1i^>dt*G=>9l>p_xNAg}Q7}nf#KYjzr~O`_Q$N9pEvNSK6Q{r2>4bh) zxv5t*nRD}I=u$R!`Ec2oN>Vb#X$1hIX(rc9&2_oiKU#>*ax)0_$#3cro{_R;E_%IM zy)S4UCdB9d8i#!G^c#L+=R@K;K)B&~d+Luhn{dHT}r(# z2YyjAad^4-5=QCS`acn~U%n++0j{a1gYtv_DplB(5I_VlhFexQ*#Ai}{PInXA2<*; z{PuL}r%vrYygOZ*)jLf5Zy^5&=>MHWG{b5x*eymDuAG4=B9lyrNGrZv4c^pJQ`b^U zF4jYScUjBH3JQ8W!seW`&6juOKd+>+B=b`Dxu-r_7>4>-d;BfI!%``((;(CF;^^U= zuF;aOl0Wv79S^EpY}r`Kg^==E-kv&mwtWi0dR)lM81EfG&q z`sQpr!8EB>18jcFB;|0itJ^mkC&4Esya^BdWn@_p2VIzCKWL#HjQH-a`KWz2iW~p9 zvx>M_A7u11R0CYiea?@Pd4cQPkpT-r6+h98zJc}>@i2_Zleu=~>K;Fj{l6iGOFHH9 zo+uaZp*R<}C%`Ka<&FB;y0k4K^p(AY<{zm+;#!vQp zS;QrLOv=Ov)p%CxOqBv)xqp@)|E4N5y=ukOwe^x^)sfPUq(rY$%YAr9G@gz5x}{wNnVx|e zb8q`{g|n5nG>X?EW0`Ms-JRATO-#zT8QRsxDRdd?kmL1g%m`mxxZ()erhYo0<%DTx z$^;PB?*z1?g2yEBFp#Inww8G3UVHunv6+iZja6tgGa+`ieTfKTptJVXD&FqjI>v^A zQGL(^u(UAEY>}u()6^?jZT+ns2D06-v?9C0AOoUWIHRdgMaqN~^JTs}5UH-rrVyV6 zD|lNseo;5Yu{gh?*5+vX3ve|Gm1CT9LUpb?L}2E$j)8*a==2x~?BpN+0;xzhdaV(i zx$KQ*W#fZ~o_55MX0LQ)G@R;v#vd0b-WgE8!QHZvpVNXM-pqIZlf9cP%BF;+sr^Zp z^DIdc4xaOluBdMlUSAuggj)pCqg={rDJdi^T>N0diL+7{$o@rVcrRJ7>cA8XtgI%H86Efg?|bB5`DU)u<3dn^%-%sQchyU~g4GhJ=HVd}cYN znyydA*wI%y-&1a2D5M00aL5a6zZRWlXey52-k5h@(CDT<%#qKcw1|be+qM75^?#f9 z*26it<&p7T3$M?bibsblwvM|59Ao3ocJnSMe$I@5P?Fa-n^P+L;uU>XNh)YCxJtiL z`$8GxB##&7G=#)7idj$}pw#IqK`sxGpRS6Cw1pEU8(;f_;y!D(gFis-R$*!zG1Ie* zeM_RP%tDzigjKak$$IE$ALo60QHxD4aBP-w+6_V^fqbvo4P3TP5^mu!fO^(~P|3YUmhBE2c*j%Lrm0R*2UxV5W42#F*fcbyTuhZtMp(nNE z`GDEn>2K#CEp>D@HQJX~tS3OfIW5k=H*kJ^yb>F-5s0vrZ!Qtnh4hMRB>N1fO%v53 z<3*YV48xe}?!$Q*YrKhelr;W^>eB1jhE3D+=E)_!elTG)W0E&}m{YnZpYn8EDb-hL z)&;7Kh5N74H@8g~%Z;QVMuI#9=0qR`1Pb=(tz)jchf2CK$(^BDA3GfsM1)M3t7YsYrg%V>_Ty${KqS5O`e5)J$?pR#D! zxY5i%qDHSoVDmQ4;jKVbZ!A37p_^qzs@SFh;$%Kib#W~)B3d|0zneN%EVm3Fy@Psg zLZQ1^cW>O>kVIUGgm*mQB~S$x2q$qTX4Ic{P6si1EHVu|F^3*t@kuSFZa&b~@ zyU;S|bnL|PwXYw*1mW@shpC{^2U8_JQtRDlLQG>yZ}vihrZ-OY!#Z3!4asE{Z%)o_ z;!ZOb5?#or|F($o3YDWTdB`8t>!KrC7ZJFzSTt6oN54zUoqufLWS}jaw})q6FBN@S zI;h%sQb3q?a;7(iC}g=hKg(e``gp5gI+uj?v~HX29-bCf$oCDmy#6{(KzN)P@ER_9 zbKc#3fuef`mu!5=HiyW8O#K`jkR4tnj_i@gOf)*8L=9ute}_J#ON!pSBvrx=i#5Br zK^xw(3Lt%4yF~TWjU?rpXU@V?dN-0#<6Hw73Ru{H@LXukt%( z#NKL;wCe8tT?$5y>(|u9j%WKOCK)eI1+C_S&22g7;riS8=mJA`p7?n~JW80MmmhRm zi%Z0<;&j#2#Yv^aKIPZ^*qT-GCyapexuiup*m|~q;Mlx86F4~Xpn=xI3ad?Z8lbXm zF?nUZx5w?(d9OcCqfXeY1(>4nU@t#y)|zpFkV@z1;Fkfx4q=(bqQ`z$r&Q#agUd9g4!2Xq=SP-4~i2BaqA`t%aA$j z_KkUODh7R5A1a^M8$?X&0}j^+g+`x*F(Xw6wJ4kxm44+3(4*Y)Z~&=H18fU%=F1S& zaD3^H9jae*$HHTww@^%(ge|RUT@E4!b;}v5cQ!9EW^mu1R+y~?$ z<*A#GmW~2k-=+Gr*5NQ&)z>{6WCGYaGdN$o!s9&FM~tB#PB8-UwUv=V4JSg%)FzQj zsf`WZrUucNPBt)M<>WN9t97wFo{glN(o44QKgveZ==5lcNxm`fLk+S`eLwUGaxsf4 zE$M!?Uxqic+tTcAq9sU4sd#0Zi>kj-%{`w+=beHSHe2N;p8e+l@%NV`!1)%nltyJ1 zSR^5nG&pgR^+sL=qi4|ToMO%>Q6tS&>t0z6cN$L`bk=L}Wv`E0_uhf&L!r0pT;l{y zZok%GX4iTh(J8N2PaQKR#KgY0(f;rVYL8S@>{Zw(l(7AWSXp zYZlI?4d|kPY|JBAC1)10(b)>voZ0rFbn~?bmhZti92?kGkl_n__X=}(h+U0FqOyqs ziZ96Z4Hge9wnx={*p!ssKC^1q7J0gOx&GrjhjH&x<6iaLD4(O|e0iPrtMtx9hFKF# z>yaI$DtolE+Do%{BLpouv)04$X|~u2Hr(!CFwxtV3|@&SfENIBU~hl^UWrNJo;|1H z)URDJ6o-p#OWmC`_P$JFAWdJBdkJL}JSD&t4>z zVVN+Hcg|bE4y&vl9~a)5bEVNq)@{OG6xS_ zYrW#PDYVUfHlg_+Pb{d$(oqTKdSCyo(>A9lwzf)Gw2N#276~lK0`}W25dIc8yr)a? z!#OPmD>K>liVc+|yh_+%r%h*(%gapCDj~7ey)|5&uNQga>(oi|k9#cshA;|Gi7&d9w#pM(kn|bLhZNQ9JZj6|@3hUU zF4jHUinkjQL?P|wH$08I@+$8iC9sF6C0y8x`-1t$6aM4Q@OxrzPHG01Fl+qWuBkqxdbR?LT)0A{WDaaaz4~CKg+1S~)E*Cn!MC2*m&-j9Iu;x<)H^kg_Xi?m@=i)ut^sKR* zhtYHl)vb1GHG*-zu#=B_v&=NS?XWywQYG~dgWKa0j_q|beIhv5j8|0MbB2+gx6bP# z>6-oTRolA`b$I&|g_#yo+CGJIG|!9=s-NWv8~Hdh$3e4EhT%D!I4`eoPNJ``1+dgM zO)7M)p^aEp+wJm;yn)D$H=2|Fh9wWvDh0RmFVjXHkM$mxueIu=+$c2_DAc0Sx_ahG z5(#GB?c8bX+%J^JS!SajjB}3fCLsV%B=-37+&ShOGXcChm~YL~{iq?2#dzLHchAG_ z3T3WFf+Ed6mP$Pv!k;2a*jeN5Y}o;SiA&;fuWD+$Ft-|8dkEq>!G3x!B{Z`mPQ5av z?aGmETdM^(ElN|j9AAbhM%F6~L-H>fzg|4wrb)2Wi@CN&3SdWvhdF=Ks))p#^FFa; zpQPO9a@kSN`gEC|Y$J2)_puev>S!N>Endv099BtfRT=Kj3#F^ujpHLdrqRc(+1yAk z;*V^U=rYt3b3W%~2j2%p_BW`WvJjx6vL1P6Y+j!n`alP$+z)*J!^1~NP^+&Gi&t4)EfIy9#kMD@^W93Qzuz!g!v?8I0(SI4Eek9K zrii?glLTjerZf#lXelmDobGH$R>}bai|jrf>j$lm3(;^6$fQlbT0R+?sh+eHBDBk~ zA*Cyux@PdmaqNCVNlW=^T)z>j>?jN6*n{!bZAH$r|9A*4B(@LZCtbY!+q`Y}O^eE> zqWspymsFdyE`q4PdHcG^eCBARr^swASwZ^sq_&V|N}Mxyh8|2=^axzQBPB18>q;L@ z?u)uY(4&-=)SuF>(cWHjiGbUy@z5>?@Kw!uRa?dgF+!ggcb&k7@t)l>WeC4jI(tBe z&__kMcBY^JBb_>c3OjA4ULCsXtiP$UD7hGIQ$+Vx9Rf0RkA`m>j$k?99)pQAI!L~? z{)$hfrfcPx2Kq1HMnhW0`96&%Y)-;9Ob-gFKfXB-JDFmOqUSi(rme?(9Sknc~4wL6O@fP+MO2z}XG8*F9ircpr!IzFTQjKi ze27hl{#LfV5(8~0WZ%30`dJ`0{rqp)AJx=A$R)5wH4CoGw=r+TV{f*OYvu>#!n z;F}HVYmY4~7Din^CNM0n+fM}%p@WH^Q+2Xj!Usc+z4b0oLh#6{ZM_R#rgdH>bFp%v zdVOwf=Xj)GNEO0N7kqc&fy#U2d@o}|z$Sb}3DmC~#h0M(3&mwF_qKmxCcY19Qq1eS zearwb%ay~D6Z7BAvZPnXf&Fr#K-e@rFtC0%RTswQHQD!(V^~^e^Ao8cH|pMrlnO?G zqE>Wje_4`_&KK2h|-MlS!|AI^t#BL z_4O&mIZ!v&g0xa3?KOhmN98d%JIOzR=tk$~hMkQU{7Vfh-)$ML(LX zg4JNL&q*7ALsULtm^z5~Q)_5+X5dr1vH`2c{Xb^1l((-AbYJce+l?~q@mo5ykj3wv z^tVZB5SnotB& zr+M4NiHnoWTgM0|vx3jwp7x$U)GxUu^)R(4!IF?&%C0k3HDG?B%h`UR&YG)nYM9fC z*>RY8D>Av0#Sv(6L=q7{Iw>H8vKO2epz>wWzMeg9$n9H2=1EwdfJZ5KM5hBN4S@Yf z4Z!$JGeqS*VkXO|XDMq2x3ReKq73+=I?sGLJ$X26CyqY3Pm{9iwD>9RkIOE1he=fn z#du!dA_WxOEflcPUS8F_mG_yWts;QO;*j@!)E`X>>f|O}qqiGpgK!sEg7&Tuq(I7V-orlb9#OQDTjhW};P)5dz=oN%D6=)((+86*daYT|t!WY)M2YsP)7I zLo~#3J3pS9vh>Z^UUt0nd8d13 z$)O}TpRXj?ZFKXeh=`mxHt7bdtBS3|uWgE|ZhoFFI1HUR)Q&{O^G$fe{qi_qle}pK zi=e8GH5FDWk*8_kB-N#Vpue2-BDD9fc-}Uu8Sng+?YawY zrU^vpdD%8q%5H6_UnXatF@*Lu$)TVJb2#pN5ay#=c23Yl!b{jQp8}b8m4B{V zq2E1?O&39V2)dCk2T-Haw8C8Z_#%$CIaLrDa*wURuB_7z;T?f8wyvmd8XtZx@{B_M zh7_J~k(!0JDO$UfSi3LGlgasX_4IuB%Lbvbh>D!^_-X|;Fdx*&yJj`50a;_yT2?o3 zBCsSbaHZODOm>FrtTy*zVnM-lL-%NiPv&a$vjRz~m^IC(Lf^#LO`eQfS|g9RAW_Q8 z=kQU$5vBS{;T$^{@ojSwfgT^r8^tDXeg;I=I#%aKz$q=lTI_GR(_T?%h${(L#`j zfP8$yV!W`nzG+&idcN|?L)HGXQ6A7VX3y|GaQ3<4!FTh(*3#FXz3oUpflruKk^91A zMFvjnkG7}k2MACh>g!wq0z-W1Ub&V>RHO2s_2U+Aee)!9Q(rdJQeL2J&9h3)T_Y^N z?6{BvC1sCHZ;yYeUwfZBonUdPV`93YAMFN$35P&q(ptC*Lu5h zaPsdie(ERY_m<=Tov`To!x%OCu>p%)eiiASB zFKRbKY{wdzMGN>wS-0po2d29WKcw1@fI%?q60-o1oB1^EZ?`8%Qb1ZmHIWQ5Gl6k^ z{ep4vPrE`GJ@mDRr&?z&#nDg*(njEdardpufZjQcd-v75ec^~$k&X7j<#Du%y8tSD~fYIl5U z*KxYt`7HvWl)Pae?Y>Cai9p1X{T=uJ_NVdPgk+iT(8!%c*`1TD)mhpQmC-{Ra1*T6k9>$l83UNb0Dg z0z1L$D8u{-<8ce-ebpQ0{WcEp{f#V{3Sv7%C#hO}^bii&A<=%DxKBraUH&fzf0)Q| zp)7qaD+_me0Yc5L!41TlF4xE$Zy+71GFKTd3(@_kdEOAIm*(&#Nqnvbr8j8y@Jaa1 zCb}Gn8Jk~v5BS46GcU)xzPm)2?jt z6HWl4`ey0aYc^b5x4Kp+BKGp9=`a#!=%g4L1D>6KAg73=!$U3Q@!}wQ znuvQ%d+ilutWdq&!bur;M2Km^GVIG>PR31KSDUopalttriY`c*&<h(j_T+iiRR7Wa7bI0Qn)Z1M9v1sy*y!UVj!?K(RGrI>0rM85tk7nmz&EW zrdz60{kEZ#cxj<~DNZ6XtZThb2VGZ6=&zS4T2XLVlQs5ip+(KBljXr4@7YhI|$e*1LcG$rs)^QxJMiJh?*Xhl0ZTX7F~ z@s@0H=g2EcXN*bD8}V8}uv4Bi=Y5V3tQHQ~dKfI4WYni{kemp|80jA;8a+_&$2Zkg zdTm#EZ8I9r$U1g@3p>mIc~Bc@qlDTDJAUA&gZ~q>w8xLkYSej-cuZ`bd6!(Ld%YyC zMg_W?}NBlpHPJ2 zk?FpDS|wNSa4pKGSuztUXkchO@A@48R_Ip-lqFCHdEh>~u<(Bbw8+Mt)tsB^RWugF zhNAdHiRn!pw%tpJ{lhq)BRAm~fF^R?L1+)Y`ua;xDS(#QobAPh@A*4!zL;F0O{Mjm;S z5aoH66|CKd;XPtM@xVXTa97?nMLY0G$1^ukyC&1Y%>I;1Q+kZX08-de| z29g$?my_0a%RT;!)|~}l&O#9fAM8HzU$p)|9LQS3Fw4nZ^^5((YeeMeRyue}lu!z@ zvYBcpx&e*!LtDC|BO^V>Xpz?MCdfnS4*hJz>e<7jt*?lt&%X*$LX|~COV46v_ZooT zPf4H{m8ok}*yRxO^o;EZ^XWc==?q1DOG~`XTQTZ2_j9`_#h>#c(a!=w%Ev9Vef9aF z>KWoLYXQAHkV}``wCHDk%Pw;mZkcvcTuM0S&(o^6t4O;9G@tFD$1Z3W{rO!hr&y8X zGNtxtX(m0`{6_ZhG*OE5BFeD+QReivEK1%>$;F?# z_+7Cc>>w=D0%VoG8z9Wtk#5qZHN`JCFt;{_4~hu<($i)p4WRr_0IsHQzf<+hc5>9_ zlBZEssN)U5O#cTLH7E8*`10+Od-tO!Qzwg-FGW6kSROJVd31NU--mQ(eMhf{!!CVC z8cD3MBr|rX>d-{59Qb7wZ0}(4btJOBXT~K2_FpgCj)juk#@;4k{^R|7SSUcv0lk`c z;s=F0Mt2OeiMKY|M1O`5zfZjc=Z;(SB3V2ByEHS-NT9n(IX>7kT0H-0;Jay4j%KOLLEi6%N1wqL|MIWDpb5W7 z`CZweT4jGm{nxJg13T<%Ip%$5q2?^x?*%*TV`Mste(7X<=jo16|G*gh7-}vHJr8(4 zwP^Uz`u9G=KPLgO%NUY-YR30&ay6#MXYOwRGc~;$dzJW$g4qC~nl}2ONq#0Q?%xJ_ zTp;`xmeNcC?uGd7l>ealdH>uF_tej&vd4bWlY2W+BA{RT{P$NqfF|_L0h9khj@xv% zF8v4bggSsFPcN4TC%==3<;XDEQSP=QoV(?pyF8tU2Ur>}oNoHA6PhW?{X0Z;CR{pz z<{1B834YH2J#{|#_D5ec02p1iGx_lYqiI&ZD3t$>m5<<3`ytVE*0CL$?Xv{Gwx2+a z?~mLAXtpQl?t*tA`#W}MlKk*azr4Im5ZD$>x!t$F_mrqPxc{5#@$KbL|MwsPwj$&J z_;0$?joBYNpXi|n8`PG{NY8eh{cxhF+3V(C4cV?y{Dq7E{km&q|0l5jT#Emb%m00i dusXKM6f)rTDVEYE?E!w&Rkg3>UA^<<{{Vb@O+^3z literal 0 HcmV?d00001 diff --git a/docs/control/system_level_control/figures/slc_basic.png b/docs/control/system_level_control/figures/slc_basic.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea756873fc272439f6aed8e50c71f3f5cd7fa1a GIT binary patch literal 109323 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ț<^?zrY{7vA0wyQt=*8>FrokUq1|KVk3 zJh&+xq^8Eh|8U>$f)KDNv^dkbWWw_gFS{xMEc2^21H*r3>;8S$A18|fT7C1=FFzm( z{(UvcUvXo5@s`HvKa~7mANk<{KyUy>fBoaKQ(;f^&)m`~RM!qbI`8Nnh`oM&({Lzy zO!{@!6Gk(RBK>ombQT;IK}8=gWoVwpW;EeVsk0U}lUViNwp3=!g5rxP#VVT*U{M6F zj_8ePUiK3HBX9ni-oulbni`~_<6;*(d(Dpb?0D55&-~N={(T=XH2R;NAo~$v|IqCE z6dPVIN9xD^Q?sM~nJD9^q#)>@qDmwlolM2~!GDS>r+lylhtjkjm*A1I<5G%k-C*2bn%`{8P0Q2Bd;E)w}agt&Ry_Cfeq52JheX{0G={ zLI_Aj_^9LAKShU!fRahGcK^f6mO=rkoQ$i9|5MDA29!+eSMz_0nUM1`(Hp&WkN&Ak z(7XaD*-aV8f9MkaXL{ci*#AuLdsg{B)BB!O&i~K!{u*z53nG30=k>lLm7nqc=k>nh z-yi?a>wQNmKl%QD2b@+TNhv)}A3eoU7e&_y?I)pM{Sl~uQQ@HHKzLdB057iT?V4H< zo0`PQ9pWm*y^JupNYg3dc&t}zmydI%W8bt@ETnesls)~ zauN(Xg>G$)K+nJysD8!TH@X$kntVLucmCQAt7zuk479UZAyCGzpZ8$Ih`5N zj_(pIrgwWQ7%Cw*6HI%?c(E`ZuhY$M+1gMIA~g4MVQQfq_qoA@D-Wdl%+;bLQX07gIDz!{aw}Fj zeO+uaw@vQKA6dumC4g9hsZ{sDH)igmV*!~=O_5``5@eTOL&Vj$TO}8)In0?0tvS4n zcNR6jcjrI9(7(1yzY0Hc{o0_sRbfp%g|!g1y+e}H=J>YciSNA!NEyio$MH#sY`k(6U!oLV@sragcZ9z4(6#&3%nY$1q4#smac|D^;i6 zc!f~KVzo32MV!*_AL=V;U|MuFO9-{9St_!a)5u>FA>=ifc(FW$Gw42m4`)8Z{hr`Z5;I;rqU!ILU~Xoc9a{?Tb&O zp207Jgz)RpL-eFNaP{KH>5t_;^!WGRIV7I61o@Dq$bdJgiw>@X_F+pV6#*W@XTk~G zuHP?|A@>fFvBNFsOG`j(H=5mo9JH#2gI-xZD%qE_HEsNM*CY*ei*_8o+Le2jEC z6b>=@rbEA}T+0-|S6!8OoKL1{me3Vufa}DtD z3P#pM>MA%*&eL!Iy(sx5_p^REJt8xK+~oJO06zYvMSn${tQ+dx!d)uANdDiEFb(j_ zQ>Z>^*xS-(D$k_dLHXPhCly`6-!5ZK!mEhxHOM>2>e1Tb)V%lYuUVv!wy#hfJgOSDi3Do+)8a!NOakRX1-1QJ=*m$}K&@Oo=~f;eXym7~^x!pPeK8%Isjkp@aQ{ zphSwWaErLe_%(D4ln69)$KIwXw^PRmzc+}75d{8KCBidE5+VA9TO3Z4x+?jSI#>ur z$(Ap`ML#P@x8zTu!W%dn}7^+kkvRDIs-Da>$D7*4Q#UvqFXrXU+N~r z-VPhRbCz#DH_%_=h?%Oo(x@4&vUncOBId;~hfin?`1hSSI<(*eDn0V8SI{UiL;}cE zfr>Q2hjy+BI_v*HHZo*)%mJC@?JYW^vK0-jrBO`{nn`fMsslwD0nWKlP^?U3hza*J z?e06buFE#95+8nXNCoD2FgBuc)gJ1igFEIGW^t_|A*fBL1~K!z@sUd|k`!NvD2&K< zXUd9CgD*Cpmvt@yKxWhi;f{I^9g!>V$Y5GY(k(tOGlY#&n|y4w1f%*y9a?T;>pc^9 z0n*ARLrpd^F;hpG?*h_1eupEnzqj{z%15h7gAhXA?^Nu>QM)WRR1ngt1iBW0!}{+y z*1rOy>XYQ<^Svs!H4D_L%!7o$t#DxwxXW3gJXr3O9t2)m{5X@}VbZTKv$v^7voWHO z$=knVPRM(R`I&N0W5vYHP-(^+4I}gumvQu>Ch3Im7*?X(+?B>@PP_TNPaQ?&dJ;?5 zZWBm;mro5d0LSBXH^5>u}S zo+Yx7dBEEJdf>8J)n?#=jue(1gt8I{d{0EZv(bJXmAn&QcoYUjIsuUsvkhegb>P7( z`}S+A4u*q^gzjpq6%q)3&pw_ zp{EsAn5!CIX6hrh8OFL&i?NsrEMLtB$ zGau%zAW+9`nCVI{)vO^ct_6%SB`JR>Bi_py&0U`7wXA1~Y~U*5wGDE6B07p{)DlZN6v{n= zYF^4sek^CAQcc))nX^@Ft-r9wRX!UlVnH>@e_jFcU zXuCkkR4q*%x+jnsJCh=Wp3MYppCG27Uh=bG(5!^dL&H(1{X(>T1cAEid>hxok$j@1 z$^!IRyn2L{21Gr@yABB{e5bdlOx-(fJfoL}97|QF7`78(hPt@x*!zf{7La*LAg~;Y zYKeqb0XvLRI+HCwz6%~@l5Xe6bQd4{IGrZP5+j;Y;YMF!AUTH8ZvS$YU^iV+^Ql9< zntC44=yb-h97lc}BAy6ys@Ehes!gIm&--adp5|I`Tf2?Q0%zEPx~LqproV%6E~1-I zLL#2b-n+@Jz5U}dx(oW=al=pX(B{75OttMIFI~ z;`nsoSb{NJ&m;?Tv(X@|ljWHRZb&Y2KPWG~ia#(STBn;lD)=ASa^ezNaJ$Z{uV=Pdmj{kM3|;oByaE5s;1 zRDb}i7~*u?5!=)2e|!Q;Bvy!JOqkXt3kx^%xi_~%n7+OHOjY)jyh2+pzN@`9eS7`c z26>pPaBdu9!ig8{To?fDm{@4e`=h%kD;-XEm_=3jp8M!DU_mv{goWok3Dd&U(^fM0 zx9jdwIU3GadX+znh<}hU>Fo!NujI2Sc2b@#y-s~Av~?lysk=5}9|$yMnc{GIhisNR zjfkZ@*=w6+1NF`a5?Jp<_sl!gLxlkW`*iB&6TI}go|(9x>s?sC6^h4bCN ze{lHUfoMriKZZ`mR!hGo=bhzy4{wfY;}ioq3jv-vf;U|Ail*WVwi5B&%vJf!DAw3; zpSVa!z}rb;vLvdiixSGRr%a61bf_5&kRxSjs8HSThdZw2b{zI^oufHrocsKip}j`T zTPI*-|+^v7lazeMG2ByUKUhh#+5dmBcxz_S1oH zj>>*X9B%3kH=K42Jg{mWlNz>#zK{#BP}C&}_Tit~rVI9)K%CDRy;@6!-rb+4&&<^l zj{8H1Q><$1?VmP_aIbUk=I8SkS$&<-`I``mrqa^9YY7Za&@Jto}p866R z9?3>CPd68E+{=^W2lqr$?AW|^C!I6z02_S`CFL8de@8ASNUv-4NSkf@*m?_dMB^L| z@A8kyBqizc?sw{XW5e}q;bTVpl6rOA`~`v_c$?9e6B_4v-NhHn^>?Do)X^JeYSn4( zqeK}|!|8yNP2p^Po~R~^ve6tKUZt_OQgQHKnN=Pek)=T+p4Kr(gr~z!TYXn)(EHWb z#JAIXGvOlZGc@Z*nBq{Rm0n(OO-w^*s)o{$C_eiPv`%{?|g&Dybr;F>KQbVZ(?(9Un7WxcF zV(kv$s)K=iq?;qZC)QO)kUdM|p; z5BamALVhqtO&KwvTK|9~dSBbTrpMh9`}KAo@0%x-3T?ybiOjXw=?9UrGf)`xi|`%Z&pi5YVn~B# zvRYERQl)5tel}ClcNbh;TlUU29AhOrKh>f*{_y=p60-OkRVdPJYo*p^JYIu}oFQ3` z0!`R;7qyN?;JHaXpotf%Cb{V0k7O4$M58KNU+4|4g)(1bvVo|3-{k zO6L}5?`)P!75%m}Wh)8S;mfw^ns)_K3q|NJIWL9^m=HONv;IvHD(zXqAK$G?=is)} zD%kOnFS^MvQ>J`LTslH%XWGDnhMD-s)dk=2ON^bbmq{DZ&_OkB%CC{V@KyIblI{f)w>?rQhAC0D$|8B6s$DTpQ=MGWFX9suuAPwd~# z@Sa!U2u~VoNbMEghiAy&eXrq5 z5t;F8cjvh5LDi3xuFxFlBIs&MwrAe>uOjQ1-#;F$CXu{roXeGD4P*DPJOc}X5!%2+@`As`xUd$bGtI?DP zluzdh|7t+niS0cW&Z>sED}grDRT9M8Y1x9QsTPWkT@x>J(=m&2PO~iRK3^hPGy(W;||y5-q@W8hAmcS*fM(y zj7Sq@)Duax20MDc-gUKeM=m;owjGVM-7S=skyK%9aB{EuMn~= z`8U^m1ReAOcxdNV2@elQqr_Lf9 zEmYtV$QiAC7yO8dbgMYv8r6-xL;Uz-cou^nFiYuH34r%E>*8wn>oC5_~8O+Dj(%DPL(`wt zS@Rmgi1BRGZzk9tYjt#avSfYX$EpZ4RTgfjw_F~?-m2N3Ce)D`nf_=Ot*z0PC!WJG zq7jn0(vw%!GfXzfSfMrxV=2^Z9p-5Dn0Zr~!#IEB6w#auxY#8g6qPsjsgM%jE-fu1 zt;2haj$#OBtxBF>pV;4uU;i0)?<~nUP}9AkKH~3IPx;eq$id;yO|L_dq>+>ktlF{7&a8fE*Od(UIsa`n_%XUgA&uZVvU>F=(3lMf)M53fVLdRXrX=4-&z z{bAeCHz6ToKJVWk-C~3iOB}n*&3>%QIGF`qVH|k9Ol~;uU^t-$>bW!B$5voV>5K{< zbCAh5S26!}T27WiJROVVQiMF_6cw7*`)lat7{OiP-- z;w?z$FsY1?c8wAeimb{otSTSw4a86E(@%k=cDsU38RkA*SVyKv0t)SJ$9~}qhz_ig z>tzw68WdrXXVWyz421%{t3M)K>Z*l&V)7Nt`vpty}G>Ta#==8qlfDU%kYFc>XvJ(qH@?_J1`=qEO`I*+qaJR6H zDC44+Z4elB2Ywp}&gQ0UWxT_42JRPFr@n$uI!7&#rj>ZAHkoiT&<8trs_*A>cFMo6 z)9Zek&Nj?QFPp5G?4;ejTI6G}Ff!#8wO>o%p1pB?MtN!FH0qJv1hVQ-((4bKE1gNv=!I$V6>EJYB&Mm&9uqgfLIAW9-J;qSl?O@|qGU&eY( z?)n+}VzZ&bIm>H^Sg)CfWvknkoRmH=Iu=>|o4!CoU^--FHXU`{f<&*(WcYS<+FT@pvcsz83>rV=QMD6>R>b&iW$aPlCDD0SsH7zWPay&E}EUid<8djsd% z;ucNCKji=Hlix_m&a=U{=Fn{sZ=@5Vr*|e`AS1xVhUeQQ0WB_9@sGt&i=FPg;o>zo zpnBsKH&igfaq1&`I?x6w?pyrQHl6*>HV#v(ei!Vn7U8NwJ46(%hJ%8^UqG^isSoA?@led ziwknwxn-%<2RAQr9?H~b_R)bA>T-dAeuAD1Yu^ntk4Arzl&9^hFcJhW`M?XCCq*~# zaj%>tI`3Dmp&v1!t6efv?cc;1sFne_9WxLm9Rl^LYZat7)ULWqzZ24~6S01Ua^dwf z9qQx_^CI1Fg`>+)u9z?F(XDzEN~7f#o$6ms2z9&t={^#Z)I8kVI6z~bro958TnB#3Pg!R_wj7D4+eYJWen2M;1na&tE zigY}$Fp))UBj~AaKtm}GZiF>U`dNaGtt}>o(vxmp4au?O03S+Qv}`rR9&;>nlaTm0 zA+|RLRFcS1(5bRF3zHdAdP`NTd^IW7evT7$K-!_0sJb}?cJRBk?VNqA*l?M!gl|M` zhXOX~;(jI^N&wouub1PMwN-31BFvscd`cfq-{GohyXT_aeOWh00;n zGX$l@s+3&5r)NrkMp$RNM!m9`Qj~`-$H7jlctLi%G*PrFPT5)w(+cRV+~oRB(9i+T zCk9)bETJ#z)OHuVu|u~lmpdO^XR%)UP!$i4L#@wC`RG#cGZ*FCSOe*a#p>s$>Ahv2 z4IN_uJdJw?c=s4=CloH?HM#vo{mVz_#ZsL@v7=#uR?T0Ol+N^ig9N+Ab5pxo)h6AH z;7CF43+gMv;4yEWIYK7x7qe#AI_Sxj&IQV}Ntwr|jb;$JlzJ_|NM2SXa3r)25P(jZ zQ08CW>O+C`8MvHdgI z$@u$w@`SVgZqH>WA;HJXoYrp#Nm~O=uc`&P*Led0z=7u!tCoI5 zMu|z}&h^3>y2QR3mvG6W@#EvH3pDj^VMPAaWEcwd6ceDEGbYRwMR0z$m9V;5bkmr#wct2Z5=+3;L}C^5m2P^aC^3^*mYvxWQZviEU^OcBl1;j> z`qt_!bIq8Z_7xWYthnc@TG>-BLlPp^$&mD+ z)19y`bg+nYut~J1(eAX<=RJt%WKx$MW9N|bY|r@h)}BMDrfJjC@VZ+kLJV`3>`Rcc z-l98J@0rh}$X1Mf=$cR)xEM^!@k#Ef4IwINi#0#w6v95&sg#SHQ{U$Xg(Rki(go_? z45lL4TA>RryT^JC7iYNpV2^%bEbbHzb`udzjPrhQXdHO_Yn#Of_~h2%RW*3I0e|-j zKA?Q3?k6U)Lvw;fL!StdvZYQXZ&Y_EEV-WMoh7QcBm+?LcR#!|BB|$Cp(5T&g|4>v$>8Sl#B9ldzsFw0}Sol&tDj6C74jlyb z1RAHN%l0CN$gD2^?pASa-ux$>)$v|?zXCQHKjEO!eYs09S-#by&KB{yT{wuxRO$n| zdD}Ipji2tilpdW7(oH^~4P93u;j~3XJk7yu>mTVHu0Km?ZL*af-ttQO%Uf?gQ^(xU zU>?talQ6wf57#Cgnz!|=TO|)MR>eyeiAJ(5nP;eA0BK`3Fl>+*P~h^FMKsV)Y)WV@ zop3hLOo=(Dh4;zk7U7X7qN$b~WTN0uJTyq-66$8tR6#TG0e-ZgMYBP=B~1t+wRaa) zTYx{6NY^$f3RZOI9uMTsS+7gwm{GKudM33lU1jgBGQ8KHZlP7|GZVVkUsTUbzaQde z(NqD{lHy;StUv{*Aq;b1!p8JYqgtoj2#3b`Y|lj3Xdj0rYnl)!kI)^6&kgC}s)B?pQvy!nr9s}K#IY=I8r_@yi;f&%4eC2#qXfLm9=jd}BSaZS5!}`jC(Z%^xkO_x{O?~2u|836-uIzdfuw^*o%c@r4dkE` z>~k)wRE{@ynE?Jo_g%SQq&s+dl|~hYXlkNB+9B9VWPuiCk0$9WBm-LtgKGATC2e5C zF$spNI|R3cE0|q0GVL`47OSF(0wK4z#-YPrSm-c|=(tchNT(uiEVe-WWSZVVM_HJG z&s{`JBFP_fob*d%(e6TgxBZMT0Pb262-A~c!oxSIpG?h!5(({fUjN2l`jgpZ-5NXG zOk&_8+jC^!zbCon# zaC^{^UH#m@${=KytwypU#C5KC3G;O>iQJKy5h}X=3dkUpF6}O>_tsF3PH(wgxe^$1 zNq|WgU^Mh(v<8);9gNRo9C{XcW@{haANjWhe%B8@j%Z-Yxhbt$FXK9)TdZU02tXZc z(PJNRq0GWvl`#IgcPP-pPBwv<_n(~Af8j(F4&g{s@FQ2S?yQhE1dg%I!Y+D~;k$lKjg;eT_-fGcFH~-g4Qs37gD)7lmV``YzmT>urr1 zwc6IQ*w*=ItG0w#c`6t1cc=QF)(K?TgZIBW5_k%NTTY~!)UH^6#64c${d^*2oX2AW z$9k%&UXpE{^bOUetlg^pWc7`)&&9Ba>U*kQqD`4JADRj6;7mPrrL=$S>VI7Sn_IZ` zBZt;LA;nH5Ijuk9oQeJx{Mop0X#WU^ z2j@lo=>!6v89wmvZw$7-h~`fr{cr1d9EIm@x?ub;s^x9uM$2Jko3N1vs}&gcJFEM4 zaaryfuKaJj8GW|%tD1cliwmVRSOrm8nSNA6=kD zfiMT32tsk<==1bFUOVc(Tmhb48F#3tO?z?iF1dN&A@?u&2YFQmXLh)e4})(u)1cjTZFIaA3R0Kli0f0>nZPvPonIU9!l z0b32P&0GIZ&}aMy0Rs@^ecsR{7eA{Zebcv>z}RKTzah#Go=Kt#P+Z?kmvIIC;D>)l zN1_bMbH6?I%oj4|0xKk_v9!MZ4_8Si!++uL&;NlAsH+3Rq@*sR6Rbb@;otFCCfenf zf4Iqog@DIoS<5do_=f_CW?jGi_vioMJ@pNM8DQNp9m~ca{P6Fp!)h?W_J>;j{eQo^ ziiXd?gluhL&B)ucBFVp0LH~29(V3p`hwAvgA!ar3FmTPgdIsLXpZDi~2KI*{{LjGt zrgc_tztH&#&d;6$?L#ZAn>IzaU7J^_#UBK+ylee5LLBFAKZN}V%EZkb$>Q$^yp_Lg z?gj9r>;W#ZUTCGz(|eEg7tV9}tE{UPRm0Lwg94^Nsx@@FO|=$rz%jiyqnnSg8AZkX zqHEM)N%t~E54@k=<#>=EPJY+?X|lLJ3CfZa_F*IDWp8%kI&0(i+WN^_zQ&2H2@p{? z#il`;4eGFh)(C#Fg(XC}{rb?J-j`WJq79v*I|acQQdNX95R4~hHwg7_77zsY22b&W zPVdciJ>>`35Y@M_F04Tw)lPeOQj@B81KBjpBPz3@q{uLJQ zzzY%Tv+!J_%-d~#pcyiIebM0;%g?OsDwe(SzWvNsf%Z83irQXYL_5Tl|Xy> zAzQ*yawX*8oLURU0u^PWQu`W&hR`pLuG>HPM#LK|v z7t@LDWZ|VXGr(apK(VGVwKu*`OJ#$|{}*GApGVsV$yWdwEf8(;mU$gbk$f-HWfj-I z1D3&x@KCU}JSF}nnP_fb?xvUf2^CN70H1>+xc4R2?Vd|oFpw9>o&PpbX68zfx9LF- zJV0qnBl;&_THFI(@J}s%uPMx`t3M7TU7WWQxe}i;{q_KUUuz@Lg7_MRJ2!sD^Cq>E zok9zm9RmYpalk;?h27r<%D(VbRYgPsJGIHX@O@YE_>xumiz~ngS*>0OS5hbs?_3U) z9jGK6v$(a!%-{yb)G4s-a zZzray^ZD)=28L3PuhcZJ{@cVD!NV_nhWA`or)-883;dBTX;*QYz<$fkbob;Up}P)u zJ_UKiELl`mwpPaKxzTpci?29}FlF)o?}Pv@+smRmg1 zWZq1H#4n;dr?Y4Nrt|c^@X0SI7245Z>gVB68}%<&p{JsilQ&)Sbamf@l~v-h)s^_0%6WpX;3KaS~2ekKt zND!{_^$b(s*asj|fqRWUT>U^9zWNFLe|?kD&u@}9QSE6ojPQ0x?GpYunFA~L5`6=$ z@O!@ZUoKAOKRU4OO$xBQ=ltyKM= zJ+n5WSc-u>ZRgG3i#c*k9njO1|J~+Q1p;=yzLD*ZrAXfo9H))9LUI2&U+kZL>a&03 z!^}(e<4{Vh&)b7PDmT1VrTF8GCx1no9jd(O_1pio zjDPosP50Y(W%bqZ^;Qtr(GuH)vA6%N(&{quA=(9rwM~Y9_IxHmeKnkF)N3uUE$P25GcU9M)btMg#`#=4~Ui_!g}vKpPhH zp8Xty-)qj+g2AY?NS4MrR|!u@uljbGH~&L?_RC4@BfsxQ*>+ss-BUToiqOjz zdp9UaEZ+_Gv%7+e)#7i2fBS@-B)0hK<8?Ihsh8t@#nK3WB+@|e-i5geP`x9)>Ff;n z--5NJN;Ak7fz;3;I=eoIv@_TtjXNT@AGI2$HMu+s4?)|xqit}w0Pe!NZ+P1;blzEF zlUDA&M2cf`ZL_ZPtM`MH0Pza&pf3%nlMTMot{$P{{6vfF(u|u|3|P3$HPhmIKfNrz zE4*QALZ@@>gd#U1qr)2Ey#QObq0Smm#Rx(uX}#Y3yiqHEl{)vlW$Jr!%6%2*Vh+EM&G;zFS#;(G-^Qb(nRE*)y z^wJ09N0>PxaGv;pr8K=novjM)C6;n0m)|G1=Wx`SjJnIQRE`~rS?xQ%O09|3t0}Wy zDK?L=2b!p0&1&nKM|Hqi;SZ+}FaNKZL-)J(97$MhdMD95{b_a>P~xz?@A7eS?TX{d(#1ORvxh)l zUoyP>ojYdq$l^nm?HyPS9Z)HBjVpBMsC4xZqkd8sxHFQ&$FwTY@}oK zBF5M`J4xJ8G*O`OMTZrG>pHLo1~C)d?x{vUKbo-p1hQj}$I!m9D+}zKg~;ODt~Lw2 zaJtRA^%nUSB0n_s683Y@(smOkeVxpi_XlJ8Ka%2YiY%%#DVul)gEu5R8r;I!Oq*-V z0s|egEfm8gR&l}V9JmH~Ql8aNW#`~1cSl2Awa6oM!cM@<`LYiQQRr3Yd2Zum&n=*_ z9m>!Et&V{v3<7KnX*p1mRS$iP_~<>@OANKqAeTX5@&|o`1Nxr#vDx=$tRr?r>>16B z$jo(Ic7ym4vb8uMY%kMA{@~Ji{htv z{d3hbb$xw2UJ6pCK$T$y(d~e&hz{tnt_R$y-f1zgd>esxC?Xi#nR-1Cb8IboG^8wPkfrJJai z97pxz3-nM}Dqa^v`IY!)@wf@jc;7MG)*J5V;=4nB6gTT-EJ~orij!GI*6^z6BK}pl zQMKleS@KO%#C2G%0{yVHho&qv*?HhLXKT#?W!|K{( z%1IuLpi!lUF2~IsSnI0hqF?OdoCZ(<;)d+!#RtA~x4>)8@<6N?L-K%vx64s4Ol|h1 zyyoN29XAS0rZs?}6Yi?+V=97SX00yLtFMcDru^I{TT*S0jMRo_Mx56la3t=C`Zg{jOoCk1?dlHoKbU12+ux31n7ib%LZJFPt#gvXbzfcOZl zSu}WyQ2OY7L||N7LTqO=$v&mI$toEgQ+@jpRrmE=ojLHJSm%r4Mm?iZZm+3eGOo36L?B>*opY-4x(dZC z7sgwn;QH)g5TM)K#NUn7vFFTF=mrwGL!}?s{obNx8``T!zgWR`dR-$_E@WkSu|u*$ z`8b`Leys}!|7RA!#3QhrfI`FMRX3VNmoI=y&Il1p4Kd;uF9A(`j_1Q1TaUQd zR^xing?#PV?_05|_atUsGy=z`Z1~6Vsqoxy(7N5BW1o~T^A}=x3oyu+J|+gf6F&dl zTKm5vp`gLnigy=SgkLE5EG8uE{OmBG65m1sQs71FGZ6<$HqE{w6v;$A<130)Rr66@ zsb&{cJkoo75puJypRY=LrMmPVMcEi%@4J=#Q?IE*drww-<}ms2h5s~3Rk7K|WU_If7(8olzSoX9+Y7`pD6HtI8TdwkXq8hF3JB5$EA^F-z5%Gw(z{Rc9QDaND-C3h zwfki&64f?!haIq*=GegTgIGCoOUFC1^k!+`={qC$yF<{tkv|`QDO;lYuJH)$y4-XA z`m&n?pZHKmC1=}Z1nrbICVf6JAVo`N=D>UnwH!p>ML?#_ zf##U!E2qt6erUTSSl*@PXVa3h=qPU!0)rm!#_0l@X5}nr47|C2tf+CH#S*7SIx&JFx^`fHh*B?D-qlv;ye<0D>JtEfb-kS_{onQ@s@0huYNWS$B7TNn$+ z&#!0BZvjTF;LctveX#Qkq;ZXFW_Xx1k2sAgHXv&>{f9J`D`-D4Sj+6HnW$Y{-4M|! znb&u?Gk`GfUyA9QC}Fq9d$e0^E{W8KKK>*gKNA=4u@Sy{7c_%ZSChc`GowcpBygda z3V1?v_F&Ejseut+PUL{jEYL9gSnZX$08j5zL#MK+Q2#IQ$!i3O|-{yY-U z^FGedeSeLkx3i+)wex;rlcCPsan!_2%szdZK+rxVA|?UzMX7`jsTyni zc+j7|?hA^V$B3B$if$166+PR!1T%AucX(i75sAjyTr;iVP9U)o`+6+3o12SpzDo+q zi$MY58e3eK+1=op=#y4rA}Nk>C+!0_8M<+{b;YpC_gd$)nukAJMkU=coT~G`6R=iX zl=Q(5KNELyid2AO#;JN4O<5a|5^*@>b|caeIjZbjMSeC)mB`F?nPZC&&kHI0T^}_C z&2@(t&~?H4RT2t!sj`IHo)J`)X}NH4CQ_y zvNP*|Xjr)6{UnSG;Q;mkMB;5rexk z2^*8Inw$A)2`vTKAaljL;}NW#;hM*Shq&s_lN`M-^Lr+4MQow;__)U)qF)%43g_{w zA8)n7{Hhnsj1(C-E7Ece#X!J}?0QUERf?NtX#KN5pCgf3nOaSBKya zcn!x!|G3bv8f%Jt>mevBe$j1Gb03Uj{5D^&UMh#&)Et8i$nBr?_jt=+SOP%L@9kIE zqvRk0i$hQt5$PDC%~-Bxt1_;LBZk`=Mb=}4JKByIh-46GR{zNL7jOREg;D28E1O^; z!AFJsF-u5dZOkONk!@TuKMjQa(~~X2WyO52ftf9~x1pr5(fK zE8dC<8LX8GAHfb_UqG;Uqv;PWlXFADj4G!B-rU0}@wxs4RWE+0AIEyZA2iplQPOkk zNuxp41+NJA9fbkbuZOK(Mu>3kx84t%6C1*K{N>&<(rZ#_b8kVMrF%@V|H(y}*rdSTln=^}VX)45S_V!GBp zM6v?>3TH;?6mJj4_D5gik@8KZgev?R_dmo2(_KL@fqVOTlsQ0Js?a$HaAnM+1VYA6Hgi5xS;cbM_2VF1vx@>u4(NFGv2G6EM?<(WINkC6Ck2YsB+UP}FXjFt zpfX2{v+UUO+obIGp!G{@LC0EPfV}e0tF^mo7i${p*Ssb^Emp{o7cMYRis{+Gw$LM} zR$pk>b)JDlkQ>BQ3?oCt86IDD6tA}xq-%WSd_{5}!m|7xDetTzHx3?}&q;B(-D#H8 z4P1sr{@|j;Md>*gAYJm1Xd)1CkB>r5;MAqe8v9l{`-qr0BE? zcO`k=TuB*~V?HOiQnJQfq(lNZeKWgm>P_|^@$bX4=+katOyp60a+_@uy>Va>`|LTZ zqbT$QeeTW=?=t^I1^9P(Drq1c!n=kUIDONKgx=w@tXZZn+5(mVIL zbCC=~Jh9WW4ZnkxIf{gsCS>T@)DU-6pZ7c(>X@74L}Ye zPtXzmrPyAC2jP5G28a99Ic~SbwHE6kNqzSyu6aPqcKHmr#u@So#Odo_1Pur?yL~m z?S)UDg5oB9jssf9seE8`P_p69*{zAfea|NA6ML?lOWpY#I`avb!Gbt>XrVcnvPYCG znhb#QLO;$OzmI-H)(&EVJ|*j;SSj7ioo53vz@UX+>96ugUg+j4g4@0`i3Nl zHNo|%K1ljSOK*(B}sw6*svmtZuc(%X~Q%-H-huooK?_}P6U|6-)XrG^T z2eI0sY94}!OEvonRyhF)WFbtA=+vKiB-Re#9MHdyRKr68lo6&`dj(5Y%POKd06=u< zn=8iH2}Ebhh6h5U_Ayv``9i~099|~(+|onNijPaxW7Tl&{w98{21eR5G(^^tJ$8=y zQJL_4Mk-aIsiPu3Y{JjoDN^)My`ITD%L7Wt zG8<(9O^9!;#k@LXNz1lG%ssv0%vl|5!>NcMcv>h03Iq2Ca>lbmmQ_Y0uu8gny zyuJQx(oII%EHwc~(??_;n67U&(+|@ErmgTUE=!m1n9HU|1a#@jo8FtgS9w3HD^JC~ z57uy~r&`5!H1JbEmkz3u>iNYgZRcLzN5RC2yqD;6DG^`0x{knq)xFilY-6ffe}6cz z;B&eP>p@?;Nfz(N8oCqWQ>9t zOhLInd|;ljd>OGN6s&eruE6AH4l69upcJ}Zbe))`zt;6E%zha(@On8yxK78<2S>ec zJPo5iKVKhVm^7{SSbGP$X?v1~^D)Sy~bTBqqYWsvB6^gmoj^&jF{lZ3*8M4kI&b0Un03al;R7(paA?o2L*UnigSRJc0$)~StoYw z@?>x%dghObtv5)4qS1D}E5*gHNAC|bXM^G4?C*#5o4>_oKiP;mjFmz#@~!>GncdM= z&4!2imw)0al>8_q^fUG#OSP0M*)j7)_Ir9}*wE&C#FpB+jb#=P`lk6=A_G%ZtS15f zrg>QK!TN?_frE#2PSU`&DM)rWK)0}{F0a7=8{=b^4B6kh}Jy+Q$o9;sTg~xwr6u81JJN9;G zufBGP6zWcaN5B`B7f9N3A_wK1v2F}lOk5aJkQQZF~&06 z>uHVWY0;*pOZf$hbG_Gfy`)|UHe^tT4Q*=bTLPxkQkusi-KL%{O$5A6xF*EfzbXE^ zgYmj`W@q-)&fM|vqYC3~8Uw&#__ivp#W&Te_xtYLJ9pM)S@4|?{Ag4*MO{-p~V z-uLhT3Tbj~WwqRgvLNUDc0CZ9&tD|7>;s0AbRNM>CW}1@+=nfZ&v>xwgGASL?QP@}JgqoKZ z3+<$5%93=^+O>N|E;A$D&;rF+Lo47g_=eNM%RLmzagH_AafWU4jt#ov775i5K?Ho& zms`X++C^%+?0@$w%BEi3F{EsQ2jx?+%pgYT z>4=@Y4bQ1^OyHd-J0Om(#~0@JPOEq|q3|26MEb4$lG2R?d_Ee_`5t`&5WlL`*uVa) zBmH8!UV`wuKv83r7FdLK+o|44k5{*h|JvE82u+cf5=Y+~VKuP5Jm_A7_NUUME>nW( z!K<^pVr9j~rJw8W%Tbyk0>sM)->#A?TC?*Y3Y08V$nHL(`T$t?BR9Pps9__n8+dyo zt+$V&igRx3j`KMB7X`N&f5(U*x0RVe;#Kr=FyB#t7cMnBaDum>@~s&JBON#q%Xee| zeuzKQPSUc`&uad$**%XeBn)*xB3O>>sr>vIaDMYD%@A=hbqt?Rh|S*tW;Qfx1OatCk^`v>hGYulor1;HfOn zM~{6+;y7qMW}%A;iPT=F+&mbPSyA9aOM;4t$3RA&J}Z}CE+9J~Z}rL|{=!&KIOemAb8p2@EhP(z$;CnUR@b+`Uv&l2CiH}J!9fRlojL{RsuveaqXO2vzi{sXoJxR^( zRijb>?>Gpzn;4K$u`YF~j%6f=QP#uXd!#jAI2Li*oKcv9PZ~0ia5%O;|J%cdd)Z;8 z%q5Wv@r;p7nEiz!>pHFpMi4rWX0U2?WtGX{axK}P)*#Xgp~%o(ddnC#+<|D|;!`NZk)KaK9B z9N66)^?J_<&~3;c7Q-rYF}~*46saYh?%J z+x3joPaaQx^JmN+-vxei#zb#UZpB?uj871ZK!GJ5H*1>De98M?!ET*=HnzWFS=y-~d2^j) zJv+8r0ao+q=I+8%k=&u)9(($sy=rlt8^%EoUKvOk1igAg?Y}kWsa&9U!@Pbp_U|e|z{O60T7+5fGPrYyojRD|i~6ZB?6Q zHk(;z0t&NMJ!Nbk8}9+yc!@ z9(Axa^gE5O1y~_qjRNMh(CJc6!Bt-O*XB=jh9l6(CZV~&^#;ACm+g0XT`^1DoIahx zlJ-VBcpQhRImSH>G=KVZDY-;pBgD9N>Es2;)a<*2XiBr56jqL@;+s{$GmKUiigTyc zpJO*EJNLxw7`b55+aB!FiyYKZ>EqOIMEF)F6kZl+m=<6E6f;dbHMC)r59hzB5V3H3 z`~J4t%@iv6S{2(f)Z3)e{Z@LQ19t2-hIF6`@QZy}W#t_%S$*+2|GN=?-Bs}01Me0S ziNMtu``K_rQF270JIpHk6iqsjR2eE;%lQV=SPQ#7MFaPv)D>paK#mEEl;(%Z7gM<_ zkEmjDH8jO?C3ijU%ZP8)6%TaA(aWbzoOmiO#!%K%Ap`rJXQh}|@~p4KDM2tzfuh|$ z>5Ubd+YHv0lwelgO7U{}7?jYtKCkly-p3KE@1xgsb}BAVfdQBczR9nG?iI7n6b?J; zq`%p`+M*>rsVqS}Y6KR)PSV(?M57VFmIlAy74dHxDGG07h{24CEpxu!YtRfod__Re zL1=v$dCg2FT<-qw@qr>Y&@F*u)a!YTxWWC$S+S6_pZ7&Jww^&BOEfd=IrQXV!`|`0 z+_IrCePwmkSq7-K#IvkfArh|pbE~#z@}uu&g52nT@6vY(7Za6ht*0TQ_0B^nuS{hg zDP~+Xe_j4B8Btk>J;e2Xe!In5U_e3I^a^w!;bUe@|fi69orNxU%XSRc)l0Eh2W*CYs z9r=A=wwoFtD>=CvGcK5MVU3AMey-=9q3Ofy# zyi~Xgu9!XZT=T-LBIs4&?!3K)UX(7xO%zI>Nh{7%)%&$$GbC446kOPvt$U)jru*8S zOuUpg5F3|@zN!mo8HUr8JD(4wUKQWvHAT$fb4Kf2++LY&Y~RV7i8=(!!Qkudp!D6b z{ur4T*=w5cn{{H9BU8c`Mboq!geT5Xs^1OtTXc9eNO>uR*`hjBvxKkwGo9H7s!QcWz zVxL@;l+n>~epxlKc(;OFh8>52OadQ?9+k;Q`=z*TzD4%-ux5}>H4(jEf;2AO1FC(@ zCGN3n7i=^!p{WzC!?pTkfz%n{ccG98L*|V;8|f?}($PTV)PN5#m)4$nZkg0hMS-`X z7i%Z$W}c7RU$}I5Vzv8Y@28_1>6dt^qfb~~(W;VCWjXmdajU>ZCO1{Qx`Be3|abKRKB zC{hJfu)x&k-^aq^UM3;ncT*4J!gY*i?T0s8rRGe33cqVLh$bT&f+}eY&C|gikr~Fx z4j;ao!l|W_oyZ}?yFtz8MM+JeBE;ba-vrmvLx&0(G*{z(&$;o-O&mEd;53A09agF) zYZ*uI`jwW~M`?al|7_&GYP*-t_v8z%&m;F6Jh<*5@Q}ZFPC!EGTUF_M&w%9U_qdqR z!bnrx>2NLW*%u&=>Swe(W^aw%ofJ-c5O~MCtI7$1zuOydy*282M*XAQu)p9^LlMf( zxXc=!r7L}T4t$x#&gJzhORlC$P3xR#4=`*k0PDkFk`KG=%t@>X>m19Z9msz!gKi6zL$ocdl|09@sx>VtydXd_K z`;g+Rh)*(vzHzKw6A3c(T+j_jF@FTncMIs-!d4gTcdPNpBfjNPhzaoLFT6=sgdb;= z;yl2LNayMr;rwnIb3Je|>46i-EUV#pRqdL5@6oP`q!%ev?HQF2vu3|#xYdsGn0Pix ziaL{8n6{NPSZ!_l#phnTjbEU)ww!I3`ak&cbc4vF?S`(ibLxgVD%&MUeA;F%Na#sV zIzJX#^!x=-lAA2FPAuG(jbQjGsV*Sr$HZIN>4{ml`rB7u{& zR}olQLgHN+@#tt3RP7h16L@h9JqZ+Ox-RvR8Hg}Jo|Ng%3Dvc|R_g4E*c=ABoBa902bK9Nt) z0_k2*Iqg3+uE^AlUgMt?%;XqBS@ss$r`IcyXah1w6zn&leQx$NsPGlXdW{I^*eyJ) zOL}ysh29zDnG`QG*ISAu5TJLOv%N@>xwTl|7r{-g5c@6{X=W|=&PU}mFk8e9;oz^| zS`T7f9iIYM2$)-4HrPl3Y0RAKmKF0~Qm0OMjWJWW^J>`niFeMYW}-VCpJwT8$`GTY zy-d^lecFs|FHETu*S$fBW^eEOW*l|Zp_kGIgLXNVm_>K`*jyO8_{7x7Z74Xm?6kMT zO&?q6sUcub+-}_qjP!GuPhV@=U$u0yi~lDyB}=a@2C1cXk#|70<8RRG(npQN>MOI9 zhbIkL<@7sUS+5R8O6~m#_|@u#exJ5N0F$vL*6u1&=bYL58bLz0>R`IPjPBI6iwmP~^Z zLn*t8wSmQ|^i-GLSGPz$NcD617_xwkuApxR(vFC^14Ds3%u~3T=n)k4+d1f5cIuK^ z>B*bZ24T?FD-syIzi#;T)-D1|A-(WigXASaw+Z-r!;L)X2}NEE z(f}wRH3Aey`kL2JkqbGf$;xSJm}~ZB?O6zPWY^r^*v!4m>QM89mB11E%Ame%V7^x` zCiAMD|HplDjjg}quo+AH%?Spr7s1P~3M;WbdRpfs z1d0?;B{C#rOxSxE^!k&Lu%z6bk0(FKNr)Zyy$-=WSW3r#Z$lDn!}^%e`BL+DUeLm& z_yeQf;M?A+pYUFpj2Vx8SzR@AvISDBi1JHyshO(GvQqIX zw!dNv-?DXM|Ee*kUZ68}5ksFS33dUVc31KTZcxBuTU(n#pt7bMYkaPGiB+}3eL>Wc zISzcM$fV=u6v81bY}vX*@FeNyNu=L8Q25GG|8c`)c~Q$<&t<5gp%Mnim$8`XV<$*I9)tz22?G%KS`WqLxq<$JSHaM(usUf=sOi|| zP#hmnGdpb8CwS*vAiU48A;V*)xSFK8ft2`Rh^8$WNpOL-$Tk;-n zXo;58viyZ%Y^K-`Y!TYUGcm@8;9}a`Gd|=GAF5)ci&0<@O!d-9mS5i^gqsQP^$6*7 zz;nS`@xRUFR|el*jG1i2ICn1DwuJ>L^m0~9t~A}o#eBH*cjBWqH9ps@v*_R~kK6p% z>QaDcn>A*}khnw0Cc~YjX8%y=?;3qDdPrT^b?+oepL-Pa?Q$8uz=nv`B|LV9CFg4GilMrqo;M8JYCY^*l^Nuk^y-&-NL zd-C0-&ZL7d7*wIu{jIA>crn{_y=6K_P1^yL;9d}RWTz>eKc&rHHSQ)RWbLdJ4>7d} z3*jvU)b{Yp-*n?xx%NslUOwWbU1QiUZV9CrG9@ZQmY0Ru7j8^sgqxZ)7LN>@-C!s< z{{erDc!2!Ky|4hc?F(xh8ODm4eh3uq_e!c?kaW_t(h`7Rx?xzEed!2ulL=4Ka2jUA zOfanU^VewepuX$8GfIJt+rJ70z^>-UZ9iCG0lkYko)a=zVqP%P%^ZFFJeLnpwa>_5_2brSfMnt`-<*nFwey}^bu+)$~45c_sKPtj|M#&tk zlsAG--{|3RGpckR+t?@-JY72d`Ygt)_UvcOqm1IGOLsAUIJ0Y>H6XBtgs@5!LO~Fd zYQ=u-!AW0YL6wfE^HK+N&`+(PrdZ5k=FUI`bIQkYO53TE$t=lGP?$ZwOEQumC=+yk z`0$++{()fT86~$X$v^Vhsf#x3*`C6IQC6948Iw~ZHZ<3qaI?Hd1f1~(%FZ8EHRosB zV>5am4xWGZjC~DL6W7kiJ=%9*NaZT#g`nFUVvS2!T5w1J z9Ax2+gjDutZQm}=jaiBoVZM*zFwad7evFIx+gfR6ce}FKF!8618%_SoAt5F$gVip5 zWiF+G4i_sE<{AQFPKjy?!wlOL4&7BEGo<9Yd@W!xjcM5=brQ~z{+(a59xQ_J>iehm zEpq9^_Kn}=3NTz3sGj)Hh7w6!XxtumyS56msWItU;3V~H!aaH}+4Eq|WcBT0k0+6M z16Jur*NF!SlO2BI=TkUoGL6eSc|YQ==d6jlxXpOY8s%dC$3&I*BPFG13kJ>kBkOyK zW4!vGl`cDjLYKWSIrAUQSbqqd7zLvKM)IX_(`(qxZ?;Y~@fi8Z#i=5nwd$oekwsxT z_xOdEI{XW~)2@dTpk^iR*6cvypp7obhn{8&9g~(3y9XVkY-$(SUpOFX)^B2G$IuYz zyC?IV`l-&xzJyx4>^*P^^`eiHbFDG&2Tix)FyPfFEel5rU4?^ie|t+N4ATAM&^h-N zAsmJsi;GO`87>7ML9qBoZxME+RY{!(@{%BONe%+wuM0A}#ffjF%psfiZ#|dT}9ys?ciy zv$Pr)euu*Dr@w%EQPt-b$PAP9ls%V<3erO49AR=fLJrPwwQjwcF#k6 z#%QTtHYZ@T@EGS$09pLKP~rOTm+^N78QxI=Z@kL?T(vY(wvK`urpt#{=53xeC*uU;^Br@b6=*^}eij_03vH}YF}dUeE)xYtN3 zt3oFuUci_DojVa?jN)iYFk=CJsiPxU;lfI9#v51wWJ&Y&CC;aw{L46jg{6CSbLN`p z$5Zagt)6R+UiDi&3VC5AZxgJd8}PobZn?Lly0*nBlxMJDDh$klIElZRkGb+@5z>BP z1z%nx{#Fi!;UF1dg~wU7%~qv6YjDEaN&Cn$-vk3U6Jfoz>S;khzcH%RowuIJzGZO* z$FLNqz*d)WaX8bNt&dfRNY=rAT@XTGNScQ zXPO=u*+A~7?Kl`FJ1cmjtTUoj3sr%nF$ZRN1${9wfmW@XG|S<`O7;EU`db1#a!vNo zf3+9#x(wSs07reJJ{$89fMxt{4|JCvR#i}D8|HbZV|rYQaDtC|eQD+;XbWhPMnEAx zZc3{9FQo>%iSloUubADEC?vm>vaaOcJtVp+40~~6nNu2~r`+vBwMfa**UKeu*xrju z!3{aHTh2>KN&E#D1Dly@8CcqbS3+YS9tmBWmV=vx1zxNE(>L8cijaKEI zWezwUTMk6BbcEK6kWNV~XUm7b{V*oSzHP9+YDQ@+hD*Be^~?M z6L&rZufgiNvm3VO^dEma+4bj+71XHsw1yo%k4DQK?cf;y$tCEFtBgI!CXg~kT!+F% zPXa@MXZP(62upF}D1dOK8LqHleyB;-E$9`T*GtC)>Uff>Yz4)v7F7zg+*Y`*771)j zFG@@JPVG7WHX{|IP=dnED zz{7qzXjch%9ls!S2qC!sy3O4o)#~*R!X1`6 z7i3Lv$=C|?(kbc)7fqa~0BA0(3*Pn1$`e*0)>t_r7~*i(B1KD=AT5D2IfC&}mLBSW z>$n3{yu*Y};iD{?2m>A;W&xQpiI>aoo0Fhxs^In-&aae&-7AgM+;#Xs6-+m1XC`>R zH4rxA)9QBYccw))OZQ$3g()w%&vBbn7xGY(;Zo=wE$4@jCFbygc?1pV0}(m(P9onT zS1e^{c^O~x_H8z)x}&Z6d(L40F&J>83#@elymlgSZbEgI4GKz7KQsFb1jk*b@w8?0 zy~X3Cz$t)z11$sozkIOlcg9IOefusxYDP^$Jo$-fYlH#*{H#0(&UX`e*m1o$BCesg z&FylHj4W&Aa?H z5fgH%+&aXP$(&C0qf`4}7P51tDm`$>u*F;<-EA3kLO1ur?61%CGq$;dNQyo= z-85ERTLS$hMN+q_lT6IgBkvcoH5g7wGl*DtFB8o1Z~7@?%FU&(N9XX$N?;gl$X6T5-love2VO zgB8KVjx_}6qC`l_Oj~Q%y~4|gpGO;HGhqhy`f{L(l@4GWB*ddf@l~`Y|JeFBk$^n% z5JN}M*Ss}Nq957W`aK8iU3YF_DfX{-<0%hK9-1hf0D^Ci!fN=r{A384WAcT<2zA&^ zR)MuUg8jt%JpYWF(BBN5o4YljiaT_CSI^nc?LXM+Ic=BvileFy%WTLbz5>%|Fpxo0 zSidnvTQQxGawMsa*&O1GOSFeQX>|c3POtYMhrsWFtD{J_>JM{xgvEh@tqstST{bC| z`RmCS9sS?yGew=VN^}DhJuvX0F|i zh(ExsD=Ib@DB5UVnpf#LS)?i6U?Iapcv~;KWKt{A7e1b{E&Ov;P#J(t_Vv=r)`^7P zjT=w*tBtziDvrcOv!wB~39MgN6}E$z@lw$P?jP{I9i-W%IH@TifTniG7hG$9E1A?l z6JOtOx^ij8?jT;~3wut*6ERW}anB?Rvkahva0zVdbA$>?T-!mR! ztU!W6#%tzJYRI&+(~;akL;Ei2v3VhY%z%6AUd~@S7k{lo(P$NY{NhlmCt-3Y!w#*s zU?@rW1J==YzWU-wIl$UNh9yN)*tZStpNv%fiJWRS{T##}TQ9TG)29?N9#5EcotxNT zyO;ER-i3AUzXEwYRPchU4XbQhG@l~9Q7RZw;&^DV^!q)VYOggYhueof-ei>{Cz*~vzS?GV(t%sz(C!M@K-C=uTz|7BGd7^~u`rxQd zTv_LyFJ=((?s{sv=D!ydY`uC9fMfrgys)D@t@G^e8$=fd?`tppamM$?R1HxXv6&;f&Z z*ZwG-HEN>+)f4Emi<@2`p@f1BjkQXkYy(dsPlJ5KH@3RNS0X_;(G9-lv{jYa|D58Ho6cxrEs;h5)BogdfIaIY2;m3vmSo!$n&d(7T|C9O|6Rs|R$wIlh zLmzJYh=r4Re~y6A@uOF?(*DaE_zmUj%}ybXj(dJ4vxQF?Z@pQUK_aaeBi=XKK` zwZz|yZ(scsu(7QhBd?@EFI#AwF6rR<*S>(@{R&F^n!0>G0dDji$WwT6D}T|2kBmsD z%a7b?Xxt7ot_y8FFm+;DVDawPX9H_d;WewpHfxlOrvQ&lF_R$KFEWO3s=Py0t6F3H zO!qO=RRCqoHzeF_0TMUXvy$BsbfSkE^fK$Bz`7>MTu61~9irm68xW1e4w=Pw77H&B zP13~mUj!kyorgrJs1LvF@|pw+#A=Vf&f|4P-wrb(ik{359ypX(-LG|wXi4ATrOh>{;+*K3rO})yjpbONB%esyjzD&XzMPW* zFn-Q(ee(g1su;?otXAhAne~}VUc0a^S2NO*BFcAw`{`1#ko~Mn9XLpsx^oBeTKADC zWikH=->@B}g|kExCLC8{!M>H=Y?>G43uNT%)JyiG=P|z--?{o}GkDW1+M9NKJrB5( z&J|>}m1*{}>)||F)_Ylq`)+_FC*d%1A3ZSAKyTPqMG^ z1Pt$cdFuo*e%q_{{QQvOM!7_S&0zG?CCQVA`J(`i3uZPkGUowON|vR)e#5~k#SmdVILt#1`VE&0ZC}SvYR)Qw|9X(W+9N?% zIK%aAZI;q#+!&|Zk%~52zzC&J?adMkJP2f30Zw~`khiCA)FB@Cs4TtdXPDI2t_DB$ zXkz^H@|s9@flh@^z87RioLdemeA8dDhSj=!k9Tg?JG|Oqrev*o_80s3$<6%4(9a+1 z_E-)FOcD_mB!fPQ=N0ntUUythhdk`PdEa4=Dmv{%&WDhNB)FJBqS<{`2a+q0bVbiD zNU;V*DguNH=eZ?Fih;=Kbu!Yf|IGZbTbMBf@pUWb+9Q$t)mw^Yh%>eR5S@?gmq?(Z zVtYA5MfXf^>zXls#|0uVpM71ru;J5VZEWTWma?npzO%ci5iIIRQ&+QQPk*s71(DJ* z^ead$X0e$3;<V%)$i-dQ~NIB;)L{LfEI@^_|si?Uu1+|sRL-4tZ+pI#D z<}?TEP0TL?)mpD_X|(bzg_d-;AK`u+1r$d-=o$)h&&tv*s2L=(m>gn&wy2`_AU5dW@m+ zXlsj+?X)Sc(yKznxAQbKLDMw_f=!Py1aLgBJWqVo!*(nc%{)WEPpS2OV(aaEmqN>H ztGhJiGenuD$m2v>bEC;(W~AsR2tJ@Qh9`7G6gdX+XM}jU+E*4xu7?k55MF%|15m$b6B$!V^s)2Y$!MwC z-MqgCqR>ucQ}A{e&~F7+OcD_l#4tunlzh@y>bd!LWs_c5NluJ;j7VhPEbMB!Urp}4 zg(TxUoqQU!QKv0JuzQk=1ZYN{s1?6!)g36No(;V?lQ?ul)<|rU(n=IL{?C%jvbx6Qw>U1WCXrNI@RgQxfWSE`&ofW zV`{w=+ACQwsyk$K_TjU-kUSM(7^M=u;|!}{*pz}MA%Rv)vaUoNKU<}**5 zv;rF#C9!m|4>S?HWE#eJPuNJ1!Dd-TcB$m5v*IxE!KB&EP1^BAHxjWGYnuWEk*W<< z&Z!<77sBM+JIeAyR^7?#G&CcQhEFdwR;ly6wkY&N3vx1MR@!wqP z1WL3H*5AaD3KJSt3qo-*50Xkh_ZqEv-`3GhaiGdZEPA~&P;aP3+3Q%WGuC$Yiq?U> zq({IIOw*Jr)U^oYhD#t*)yJu*_~kE18ja3SIO6gcUp?zDKgV)`jtm>{0F*r^;yD^h zQ{ImN0d_MN?>0bYzs~%=2ibEfIJCd%2r;;;k89us2&nrSYAv{1Z2WZTc%M9qbxTlL zVYc@5QTXYO*vBuTXr)FgfIC6+{JL`84;jh_GzTY*utod_H#pg0MjH73u}F$>#aXYN z<^_hTWi!zsy+w-NLJZj9PgFBQj`;!R2OR%c@{H6}?z|vtFaM$>k-ju4)UO5TarS+D zz3qy?r4QY36BiTi=Flxgqyw>zk?_NU@a$XV^A@&vHw7VBxk)N0YtwQ53#pgC_5#Q* zcorVMwxF=~Nw0|}H!Lj2B8J$HdqtXU>)H@~Q) z1{zE;rtkozvO=bZC@I0EvO4oC`X4-wE=Vin->{IlCHOOSz*|X&+C*D%LG~UFrncF( zoDgppOGQ-NGghbeV0&`$6wYh6_<;YHd~}N-OOD9hDqb((O6uSr2;4jc80G%*r>g& zILFTkP*(T{%Cf2NEGYX*nN2ISA(4Z?CJ!r9)Y)PUBp7e5`|LPOJz-0=g+fub)K+S% z5V4h(KxKG$QEA~n1dEsk9sJ(Y;d;5Wp0msqIX$_ogIdvPQB#W*SE*D2a98^hOxTTW zThZ-fqb&{inqowE>b#^99>!wLy}A}qlJ84}-OD_nCTX=Ur7eNI=wVf4DN&haL*nS` zd>xsDvA8`)Kg5pvo4aw6KESmykT5~Bp|NWE?y8)-o1fw+8}m1_`JHW!xh z*@HgAK(oW3YacFs?>+4{8SOluA$M#sul&BfcLD5_baFv;ymaX~V2ilm_Gb8I0Kx;D zQv>0D=d7#hkBdro+q}e*=T)ex#19ga=YPH4E4wrkQF*+`g3!6UxT!HW21xN1CrKZYs6z2kS%*o4 zT*@lryCBuBfy2kZLB*eyZ~}*eCBwib-*m2rt65LeEbaD7+K7|EmhhtB-fW?pKhNHO z=&m$hWrXN<^8;hIvWI%%mMNqY6Q<)~Np=z4&tAfQoxGuVe|Ts>zIjW#GmSjzZ8_ch zvsXKF*#- zix-yAbvPm?dwvz693u5{OY<7TLP97^KuNAIv0=*gDspEGcJ8eB+m!C3?OK8h?8VlVBnwinT>3iJPoq=Br&r%4LCcr; z0-1DUx7efU-C!sEBVy1fQ^Si>f<4(I&QnQQ)byIl3f%qk(1f-+04!jz9asC8l0N^iu@Eb~^+UVH%aFQ(szF(_l}ZiZCOydWcx}83%)N zJQC=G#NNIKlJNkxYU3PeM_zj#vTeQW=bu8d1q<|@XCFS|r?&ICctJvJpZWY&^1(P-6 z2$1(EUXZd6TrOKa7b7P?B*+&%SIGd!#R)%C3q@fEb~RFq6+iuCMA~^W_yU}_@?AJb z|50bQPOY24Rov0{W8BL~4s}8&^JyptyPUkqpMo# z=7CKA^myOfNBAP-%^I1@0=dIhpd|!}jf?W6?nf1Lg(R;fy{48DThCC|eZ92Fn4Bwc zN6FxZp@tahS(C`4@En{Wh)-ls;F~i*H+>O!GO;Nnwdg!eu{NrPOxnu315rT+tbI)* zdX1dutSK5IVF2wyPA%)D)cXT`AA8fEv;VaM_jR>_OZ@L^RG%w zw)}PV=fZ*VA71e&7fL^43p5>Kr6v$rqYG&Yl`-2?M=H9K3Y@Z4Iz1kws6lQyPI)TW zt#KuP83g3v6Bt5HuC*a%#MG0UE^qnG6&_uPP4brrkX=eb*f{6{7qeV)yj<1mW{Pag z)&y!h{AZO!yQzVyt%Djszb`KY7_2D#Oacb#Z;U-mXq#UgbxXEAq{w>x=~}%kD3;A= z4XEBBM#mt4YCfq&7u83XiU1Zk@LHcZ%W4VWMyLn%qBl^!szJTmMIMOtL!QohB9?A+ zm3ck^L=Lo@%x%qR=T&d_yXRY2zASshkkK{%AhzyS`Y5sLgKo% z_ArlYlA;F?_##jN>Zrp|QREEx(m4))AA7evEn%7`BaN|sxJ{OHoS$Tu#)9qCkq4bx zY-tPz<|M(9WWF^i@j!P)D^20R39;^r1BRd@!e$h*N}80%XKP+pJR=8ceGH+yY3P;wJji0E9KNe7j9sx5F?FLhqzIjHq+H)Rg zg1p_1(x0dr`{_D9P!&4cB931leEot&WOU+s*eb?MCg#wDfA!xls z$C{3ds+kKyv@=&m3@ikKR?J@lmB|oso?+eys-m5Ky>QT>2KSY|-qtFrLFXG=w!)iF zxT02*wv{9wTb+O<=+*G{vlI3#F6+v(Kxlzf{E&1H9(Wd)WK;}lissY|jLo~D*|ekj&#XrZ|h>McUzu^rbJ-VaTB=Kb??;U%hrbtI;7q;C! zzx$>Ge%?HQ_16WKk;R$Ws?(fk`AO2H3IUvj{Xtjrf=AcXh{l%P<@LeYxkM<+NJ)l zhc;aOyPtJH_e9A{EhN~t^s!6@6js|nF*K4a6z@F->m#VW-K&vpH19Is*8s^m!uRq~ z+-cBREANGCAQ$hOL_{Sgaq?xLhQglKdYeF4>>nE@6{yLRVvh{t71n=XPte6e;1oq* zHHuTy3}<~j5KMM3i5Y@(9jHP7Nc%Ite&yiKe_qMs+MJ|>qH1?8D( z0Lge%pMM`$3yG-^6PYAJ&mydW<0|o$$5w>Lim55dGkJ8$hf_Yyvw_;ZE(4{F#ihWx zDN+H!Xt#J3F-R(Xe(#!CH*k8vj|K557fO2uc*9iKVvT{iQsvTtr6}sVE-+Ey>Ar{0 zB%{$sz>D5_21qjS=IQssbW=;Q1xW@$BXq3_3rd_o%FBsKuh%=@&nPi1NW(&dKJm*q;TEkx}tROg%&Qt-I+$^m1)^=oGWM z1h0N6l-{ZY1|FEliB*C7M;8{#+pMexZx*>1B)^@%C(_NT8w6_&`U z^+$*YNx>R7OilDDhq*uzdb(p)RwhzF|DfOl@O6Wj-`ML{2l$7N%FJ+w{9V{*=?YQm zvvd_9QeiJ%$@FKD%vv#>v7_lRf)s9k-*6l`AyBG>jJpGiF zKOpSw^ItIaCv*Hsy^OB{Nq++O)!!2R(|5o7jyC-vuBdmiq^Ex|_dmU3oL&ahfiFpa z{M?QVKH;WJ2&9%T0EokAUeA`|@o0?g`S^C8;qTObp?8}m>CXXLS-G+sDm7dxN;AR>ExZd*Vya@BcufXJtCz# z9#HTtfS1oKf=x)<3{jU(4t^&qj5J6Hg>@<}jHs0g18#lK13BBo=Y zZa67SjIZUDf~B{6=EsR?&yA6~`~LW)zfwVP(!rL|I^BJkQiH8WA5fWBqJR>cas|MD z*F^t&Guay!o{0nHassk=02}>*UfM&dD%&l~|A7c>oJaQ`nG_z_8xpezb_Rf7hLBXk z@8As+0ST4Aa>nF)-+c!jLI_|&c37MH&+Yd9$3)NSbPD{IYk!_%S>3h)eULVN`)@ov z`IOb1>K}Dg+wjnNsm95;*Sh~>9zW0FdTx+j%>gzjO%X zD#O3tTlL6f?e`=8nX&uk^`mt5&1(-__RZ@@vjJAGee>Eysr}XKr=@a#_1d$Q{nhJ7 z&u8B`+_RN^=kO=Lao;)oYAgR kfbm`1OL8rn}D;=8Q5yVhIC=SG^gGj|*6h$tiz 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 literal 0 HcmV?d00001 diff --git a/docs/control/system_level_control/figures/storage.png b/docs/control/system_level_control/figures/storage.png new file mode 100644 index 0000000000000000000000000000000000000000..421982d26f93bbe3a96c8cdbb78724625d4ef7e4 GIT binary patch literal 290437 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

ydI~b5-#O$l#GI&Jbl`OQ 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 HJb(W$LBSmP literal 0 HcmV?d00001 From de3d2f32310a9db9f9ca1e1553d246095f4b0591 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Wed, 10 Jun 2026 19:26:39 -0600 Subject: [PATCH 128/132] Dramatic renaming for control nomenclature --- CHANGELOG.md | 1 + .../system_level_control.md | 4 +- .../technology_control_overview.md | 10 ++-- docs/demand/demand_demo.md | 8 +-- .../adding_a_new_technology.md | 18 +++---- docs/storage/storage_models_index.md | 4 +- .../run_onshore_steel_mn.py | 2 +- .../run_texas_ammonia_plant.py | 2 +- .../direct_ocean_capture/run_wind_wave_doc.py | 2 +- .../run_wind_wave_oae.py | 2 +- .../12_ammonia_synloop/run_ammonia_synloop.py | 2 +- .../run_dispatch_for_electrolyzer.py | 2 +- examples/16_natural_gas/plant_config.yaml | 2 +- .../run_pyomo_heuristic_dispatch.py | 2 +- .../23_solar_wind_ng_demand/plant_config.yaml | 2 +- .../24_solar_battery_grid/plant_config.yaml | 2 +- .../run_pyomo_optimized_dispatch.py | 2 +- .../33_peak_load_management/plant_config.yaml | 2 +- .../run_peak_load_management.py | 2 +- examples/test/test_all_examples.py | 24 ++++----- .../generic_converter_min_operating_cost.py | 2 +- .../control_rules/plant_dispatch_model.py | 2 +- .../pyomo_storage_rule_min_operating_cost.py | 4 +- .../converters/curtailable_component.py | 4 +- .../test/test_curtailable_component.py | 2 +- .../passthrough_controller.py | 32 ++++++------ .../pyomo_storage_controller_baseclass.py | 2 +- .../demand_openloop_storage_controller.py | 10 ++-- .../storage/heuristic_pyomo_controller.py | 4 +- .../storage/openloop_storage_control_base.py | 12 ++--- .../storage/optimized_pyomo_controller.py | 6 +-- .../plm_openloop_storage_controller.py | 10 ++-- .../storage/simple_openloop_controller.py | 20 +++---- .../test/test_heuristic_controllers.py | 12 ++--- .../storage/test/test_openloop_controllers.py | 12 ++--- .../storage/test/test_optimal_controllers.py | 6 +-- .../test_plm_openloop_storage_controller.py | 4 +- .../system_level/cost_minimization_control.py | 10 ++-- .../system_level/demand_following_control.py | 6 +-- .../profit_maximization_control.py | 8 +-- .../system_level/system_level_control_base.py | 50 +++++++++--------- .../system_level/test/test_slc_controllers.py | 52 +++++++++---------- .../system_level/test/test_slc_examples.py | 10 ++-- h2integrate/converters/grid/grid.py | 18 ++++--- h2integrate/converters/grid/test/test_grid.py | 14 ++--- .../hydrogen/electrolyzer_baseclass.py | 6 +-- .../converters/hydrogen/h2_fuel_cell.py | 18 +++---- .../converters/hydrogen/pem_electrolyzer.py | 6 +-- .../hydrogen/steam_methane_reformer.py | 22 ++++---- .../hydrogen/test/test_h2_fuel_cell.py | 2 +- h2integrate/converters/iron/iron_dri_base.py | 22 ++++---- .../converters/iron/martin_mine_perf_model.py | 22 ++++---- .../converters/iron/test/test_martin_mine.py | 4 +- .../natural_gas/natural_gas_cc_ct.py | 22 ++++---- .../test/test_natural_gas_models.py | 2 +- .../converters/nuclear/nuclear_plant.py | 8 +-- .../nuclear/test/test_nuclear_plant.py | 2 +- .../steel/cmu_electric_arc_furnace_dri.py | 22 ++++---- .../steel/cmu_electric_arc_furnace_scrap.py | 22 ++++---- .../converters/steel/steel_eaf_base.py | 22 ++++---- h2integrate/core/h2integrate_model.py | 30 +++++------ h2integrate/core/model_baseclasses.py | 16 +++--- h2integrate/core/test/test_framework.py | 2 +- .../test/test_sql_timeseries_to_csv.py | 2 +- .../battery/test/test_pysam_battery.py | 12 ++--- .../storage/simple_storage_auto_sizing.py | 16 +++--- h2integrate/storage/storage_baseclass.py | 10 ++-- .../storage/test/test_storage_auto_sizing.py | 6 +-- .../test/test_storage_performance_model.py | 20 +++---- 69 files changed, 366 insertions(+), 357 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad3c66a5d..335536a0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- **Controller signal naming overhaul**: Standardized controller input/output names across the codebase. SLC outputs are now `{tech}_{commodity}_set_point` (was `{tech}_{commodity}_demand`); technology-level controllers take `{commodity}_set_point` as input and emit `{commodity}_command_value` as output (was `{commodity}_demand`/`{commodity}_set_point`). Storage performance models in feedback mode receive `{commodity}_set_point`; in open-loop mode they receive `{commodity}_command_value`. The SLC's own input (`{commodity}_demand`) and demand component I/O remain unchanged. - Change commodity in DRI and EAF model from pig iron to sponge iron based on likely carbon content [PR 670](https://github.com/NatLabRockies/H2Integrate/pull/670) - Bugfix for round-trip efficiency handling when calling `check_inputs` around `StoragePerformanceModel` [PR 684](https://github.com/NatLabRockies/H2Integrate/pull/684) - Bugfix. Include nuclear in electricity producing tech list and improve error message for zero-length electricity producing techs in model when electricity is specified as the commodity. [PR 685](https://github.com/NatLabRockies/H2Integrate/pull/685) diff --git a/docs/control/system_level_control/system_level_control.md b/docs/control/system_level_control/system_level_control.md index 81dbdaa50..ad2ff2ecb 100644 --- a/docs/control/system_level_control/system_level_control.md +++ b/docs/control/system_level_control/system_level_control.md @@ -6,10 +6,10 @@ System-level control (SLC) within H2I is meant to operate to control the entire The SLC framework is *technology-agnostic* and works with any H2I technology (converters, storage, feedstocks, demand components, etc.). It only cares about a technology's [`_control_classifier`](control_classifier.md) and the commodity it produces. To opt a technology in, set `_control_classifier` on its performance model; for `flexible` models, also call `self.apply_curtailment(outputs)` at the end of `compute()`. See the [developer guide on adding a new technology](../../developer_guide/adding_a_new_technology.md) for the full checklist. ``` -The most basic SLC is shown in the figure below, where the SLC receives a demand. Based on that demand it emits a per-technology `{tech_name}_{commodity}_demand` signal to each controlled technology. Each technology group contains a controller that converts that demand into the `{commodity}_set_point` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the set-point signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the demands in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. +The most basic SLC is shown in the figure below, where the SLC receives a `{commodity}_demand` signal. Based on that demand it emits a per-technology `{tech_name}_{commodity}_set_point` signal to each controlled technology. Each technology group contains a controller that converts the incoming `{commodity}_set_point` into the `{commodity}_command_value` actually consumed by the technology's performance model. From each technology block there is `{commodity}_out` (potentially changed by the command-value signal) that is connected via feedback to the SLC. The SLC will then attempt to converge the system where it will loop through changing the per-tech set points in attempts to meet the system demand until the overall system stops changing how much `{commodity}_out` each technology is outputting. ```{note} -Every technology group has an *implicit passthrough controller* that converts `{commodity}_demand` into `{commodity}_set_point`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the demand to set-point hand-off uniform for every technology, regardless of whether an SLC is present. +Every technology group has an *implicit passthrough controller* that converts `{commodity}_set_point` into `{commodity}_command_value`. If a technology defines its own `control_strategy`, that controller is used instead. This convention keeps the framework consistent and makes the set-point to command-value hand-off uniform for every technology, regardless of whether an SLC is present. ``` ```{important} diff --git a/docs/control/technology_level_control/technology_control_overview.md b/docs/control/technology_level_control/technology_control_overview.md index 255be2d54..79b687b53 100644 --- a/docs/control/technology_level_control/technology_control_overview.md +++ b/docs/control/technology_level_control/technology_control_overview.md @@ -1,16 +1,16 @@ # Technology-Level Control -Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same demand/set-point interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. +Every technology group in H2Integrate contains a controller subsystem. Its job is to translate a `{commodity}_set_point` signal into the `{commodity}_command_value` consumed by the technology's performance model. This convention keeps the framework consistent: every technology exposes the same set-point/command-value interface, regardless of whether a system-level controller (SLC) is present and regardless of how complex the underlying control logic is. (implicit-passthrough-controller)= ## Implicit passthrough controller -If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_demand` to `{commodity}_set_point` so that: +If a technology does not define its own `control_strategy`, H2Integrate automatically inserts a `PassthroughController` into the technology group. This controller simply copies `{commodity}_set_point` to `{commodity}_command_value` so that: -- When an SLC is present, the SLC's per-tech demand is fed straight to the performance model. -- When no SLC is present, the demand input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). +- When an SLC is present, the SLC's per-tech set-point is fed straight to the performance model. +- When no SLC is present, the set-point input defaults to a large value so the performance model behaves as if unconstrained (the model typically saturates at its rated capacity). -If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_set_point` output so the rest of the framework can connect to them in a uniform way. +If you add your own controller via `control_strategy` in the technology config, that controller is used instead of the passthrough. User-defined controllers must produce the same `{commodity}_command_value` output so the rest of the framework can connect to them in a uniform way. ## Control frameworks diff --git a/docs/demand/demand_demo.md b/docs/demand/demand_demo.md index c0b0dd52b..51d8a037e 100644 --- a/docs/demand/demand_demo.md +++ b/docs/demand/demand_demo.md @@ -107,7 +107,7 @@ If we wanted to change the demand profiles for the battery (`battery`) or the de electrolyzer_capacity_MW = 60 ## Set the battery demand equal to the minimum electricity needed to keep the electrolyzer on -# h2i.prob.set_val("battery.electricity_demand", 0.1 * electrolyzer_capacity_MW, units="MW") +# h2i.prob.set_val("battery.electricity_set_point", 0.1 * electrolyzer_capacity_MW, units="MW") ## Set the demand of the demand component equal to the rated electrical capacity of the electrolyzer # h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") @@ -186,13 +186,13 @@ end_hour = 1000 x = list(range(start_hour, end_hour)) generation = h2i.prob.get_val("battery.electricity_in", units="MW") -battery_demand = h2i.prob.get_val("battery.electricity_demand", units="MW") +battery_demand = h2i.prob.get_val("battery.electricity_set_point", units="MW") battery_charge_discharge = h2i.prob.get_val("battery.electricity_out", units="MW") where_charge = [True if d<0 else False for d in battery_charge_discharge[start_hour:end_hour]] where_discharge = [True if d>0 else False for d in battery_charge_discharge[start_hour:end_hour]] -ax.plot(x, battery_demand[start_hour:end_hour], color="tab:green", alpha=0.5, lw=1.5, ls='-.', zorder=2, label="battery.electricity_demand") +ax.plot(x, battery_demand[start_hour:end_hour], color="tab:green", alpha=0.5, lw=1.5, ls='-.', zorder=2, label="battery.electricity_set_point") ax.plot(x, generation[start_hour:end_hour], color="tab:blue", alpha=1.0, lw=1.5, ls='--', zorder=3, label="battery.electricity_in") ax.plot(x, generation_with_battery[start_hour:end_hour], color="tab:pink", alpha=1.0, lw=1.5, ls='-', zorder=3, label="elec_combiner.electricity_out") ax.fill_between(x, generation[start_hour:end_hour], generation_with_battery[start_hour:end_hour], where=where_charge, color="tab:cyan", alpha=0.5, zorder=0, label="battery charging") @@ -243,7 +243,7 @@ If we re-run H2I and set the battery demand equal to the electrolyzer capacity i ```{code-cell} ipython3 # Set the battery demand equal to the rated electrical capacity of the electrolyzer -h2i.prob.set_val("battery.electricity_demand",electrolyzer_capacity_MW, units="MW") +h2i.prob.set_val("battery.electricity_set_point",electrolyzer_capacity_MW, units="MW") # Set the demand of the demand component equal to the rated electrical capacity of the electrolyzer h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") diff --git a/docs/developer_guide/adding_a_new_technology.md b/docs/developer_guide/adding_a_new_technology.md index 86924c747..fbf3322c7 100644 --- a/docs/developer_guide/adding_a_new_technology.md +++ b/docs/developer_guide/adding_a_new_technology.md @@ -37,7 +37,7 @@ class SolarPerformanceBaseClass(PerformanceModelBaseClass): # `annual_{commodity}_produced`, `rated_{commodity}_production`, # `replacement_schedule`, `capacity_factor`, `operational_life`. # When `_control_classifier == "flexible"`, it also registers the - # `{commodity}_set_point` input and `uncurtailed_{commodity}_out` + # `{commodity}_command_value` input and `uncurtailed_{commodity}_out` # output used by `apply_curtailment()`. super().setup() @@ -56,7 +56,7 @@ Note that the baseclass inherits from `PerformanceModelBaseClass` (defined in `h - Declares the standard `driver_config` / `plant_config` / `tech_config` options. - Reads `n_timesteps`, `dt`, `plant_life`, and `fraction_of_year_simulated` from `plant_config`. - Validates that `commodity`, `commodity_rate_units`, and `commodity_amount_units` are set on the subclass and registers all of the standard production outputs from those attributes. -- Adds set-point input and uncurtailed output for `flexible` models, and provides the `apply_curtailment()` helper. +- Adds command-value input and uncurtailed output for `flexible` models, and provides the `apply_curtailment()` helper. Every performance model must therefore define three class attributes and three commodity attributes; see the [Required class attributes](#required-class-attributes) section below for details. @@ -88,11 +88,11 @@ class PYSAMSolarPlantPerformanceComponent(SolarPerformanceBaseClass): self.system_model.execute(0) outputs['electricity_out'] = self.system_model.Outputs.gen - # Flexible models must apply curtailment from the system-level - # controller's set-point at the end of compute(). This clips - # `{commodity}_out` to `min(uncurtailed, set_point)` and copies the + # Flexible models must apply curtailment from the upstream + # controller's command value at the end of compute(). This clips + # `{commodity}_out` to `min(uncurtailed, command_value)` and copies the # raw output into `uncurtailed_{commodity}_out`. It is a no-op when - # no system-level controller is configured. + # no upstream controller is configured. self.apply_curtailment(outputs) ``` @@ -111,7 +111,7 @@ Every performance model (whether it inherits from a category-specific baseclass - `_time_step_bounds` (tuple[int, int]): `(min, max)` simulation time-step lengths (in seconds) the model can run at. Use `(3600, 3600)` for hourly-only models and a wider range (e.g. `(300, 3600)`) for models that support sub-hourly time steps. The plant simulation `dt` must lie within every model's bounds. - `commodity` (str), `commodity_rate_units` (str), `commodity_amount_units` (str): set in `initialize()` (or before calling `super().setup()`). These define the commodity produced by the model and the units used for its rate (e.g. `"kW"`, `"kg/h"`) and cumulative amount (e.g. `"kW*h"`, `"kg"`). `PerformanceModelBaseClass.setup()` uses them to register all of the standard outputs and will raise `NotImplementedError` if any are missing. -For `flexible` models specifically, the baseclass automatically registers the `{commodity}_set_point` input and `uncurtailed_{commodity}_out` output, and the `compute()` method must call `self.apply_curtailment(outputs)` after writing the raw production to `outputs[f"{commodity}_out"]`. For `dispatchable` models the set-point is consumed by the model's own internal logic; no curtailment helper is needed. `fixed` and `feedstock` models do not receive a set-point at all. +For `flexible` models specifically, the baseclass automatically registers the `{commodity}_command_value` input and `uncurtailed_{commodity}_out` output, and the `compute()` method must call `self.apply_curtailment(outputs)` after writing the raw production to `outputs[f"{commodity}_out"]`. For `dispatchable` models the command value is consumed by the model's own internal logic; no curtailment helper is needed. `fixed` and `feedstock` models do not receive a command value at all. 3. **Write the cost model for your technology.** The process for writing a cost model is similar to the performance model, with the required inputs and outputs defined in the technology cost model baseclass. The technology cost model baseclass should inherit the main cost model baseclass (`CostModelBaseClass`) with additional inputs, outputs, and setup added as necessary. The `CostModelBaseClass` has no predefined inputs, but all cost models must output `CapEx`, `OpEx`, and `cost_year`. @@ -196,9 +196,9 @@ class ATBUtilityPVCostModel(CostModelBaseClass): ``` 4. **Write the control model for your technology (optional).** -Every technology group in H2Integrate contains a controller subsystem that converts a `{commodity}_demand` signal into the `{commodity}_set_point` consumed by the performance model. If you do not specify a `control_strategy` for your technology, H2Integrate automatically inserts a `PassthroughController` that simply copies demand to set-point, so most new performance models do not need a custom controller. +Every technology group in H2Integrate contains a controller subsystem that converts a `{commodity}_set_point` signal into the `{commodity}_command_value` consumed by the performance model. If you do not specify a `control_strategy` for your technology, H2Integrate automatically inserts a `PassthroughController` that simply copies set-point to command value, so most new performance models do not need a custom controller. -You only need to write a control model if you want to override that default — for example, to implement a heuristic or optimized dispatch strategy for a storage technology. The process is similar to the performance model: the controller's required inputs and outputs (`{commodity}_demand` in, `{commodity}_set_point` out) are defined in the relevant control baseclass. See the [technology-level control overview](../control/technology_level_control/technology_control_overview.md) for available frameworks and supported controllers. +You only need to write a control model if you want to override that default — for example, to implement a heuristic or optimized dispatch strategy for a storage technology. The process is similar to the performance model: the controller's required inputs and outputs (`{commodity}_set_point` in, `{commodity}_command_value` out) are defined in the relevant control baseclass. See the [technology-level control overview](../control/technology_level_control/technology_control_overview.md) for available frameworks and supported controllers. 5. **Next, add the new technology to the `supported_models.py` file.** This file contains a dictionary of all the available technologies in H2Integrate. diff --git a/docs/storage/storage_models_index.md b/docs/storage/storage_models_index.md index d9a626d42..869459859 100644 --- a/docs/storage/storage_models_index.md +++ b/docs/storage/storage_models_index.md @@ -19,11 +19,11 @@ The inputs and outputs of storage performance models are generalized here for an - `commodity_in`: commodity available to use for charging storage If using a **feedback control strategy** (this means that the controller received the actual storage state periodically), the control-related inputs for control to the storage performance include: -- `commodity_demand`: the target demand profile to satisfy with the storage performance model and the input commodity. This is passed to the control strategy through the `pyomo_dispatch_solver` method. +- `commodity_set_point`: the target set-point profile to satisfy with the storage performance model and the input commodity. This is passed to the control strategy through the `pyomo_dispatch_solver` method. - `pyomo_dispatch_solver`: the control function from the storage controller that outputs dispatch commands to the storage performance model. If using an **open-loop control strategy**, the control input to the storage performance model is: -- `commodity_set_point`: the dispatch commands to the storage performance model, negative values indicate charge commands and positive values indicate discharge commands +- `commodity_command_value`: the dispatch commands to the storage performance model, negative values indicate charge commands and positive values indicate discharge commands Some storage models may also have design inputs of `max_charge_rate`, `storage_capacity`, and `max_discharge_rate`. diff --git a/examples/01_onshore_steel_mn/run_onshore_steel_mn.py b/examples/01_onshore_steel_mn/run_onshore_steel_mn.py index 7f35f4093..3132f54a4 100644 --- a/examples/01_onshore_steel_mn/run_onshore_steel_mn.py +++ b/examples/01_onshore_steel_mn/run_onshore_steel_mn.py @@ -9,7 +9,7 @@ # TODO: Update with demand module once it is developed demand_profile = np.ones(8760) * 720.0 model.setup() -model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() diff --git a/examples/02_texas_ammonia/run_texas_ammonia_plant.py b/examples/02_texas_ammonia/run_texas_ammonia_plant.py index 7fa013503..3508f6bab 100644 --- a/examples/02_texas_ammonia/run_texas_ammonia_plant.py +++ b/examples/02_texas_ammonia/run_texas_ammonia_plant.py @@ -11,7 +11,7 @@ # TODO: Update with demand module once it is developed demand_profile = np.ones(8760) * 640.0 model.setup() -model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() diff --git a/examples/09_co2/direct_ocean_capture/run_wind_wave_doc.py b/examples/09_co2/direct_ocean_capture/run_wind_wave_doc.py index 230801089..c329b8948 100644 --- a/examples/09_co2/direct_ocean_capture/run_wind_wave_doc.py +++ b/examples/09_co2/direct_ocean_capture/run_wind_wave_doc.py @@ -10,7 +10,7 @@ # TODO: Update with demand module once it is developed demand_profile = np.ones(8760) * 340.0 h2i_model.setup() -h2i_model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +h2i_model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model h2i_model.run() diff --git a/examples/09_co2/ocean_alkalinity_enhancement/run_wind_wave_oae.py b/examples/09_co2/ocean_alkalinity_enhancement/run_wind_wave_oae.py index e70f724e3..012d20fd6 100644 --- a/examples/09_co2/ocean_alkalinity_enhancement/run_wind_wave_oae.py +++ b/examples/09_co2/ocean_alkalinity_enhancement/run_wind_wave_oae.py @@ -10,7 +10,7 @@ # TODO: Update with demand module once it is developed demand_profile = np.ones(8760) * 330.0 h2i_model.setup() -h2i_model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +h2i_model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model h2i_model.run() diff --git a/examples/12_ammonia_synloop/run_ammonia_synloop.py b/examples/12_ammonia_synloop/run_ammonia_synloop.py index c0ee5d21d..df973f8b4 100644 --- a/examples/12_ammonia_synloop/run_ammonia_synloop.py +++ b/examples/12_ammonia_synloop/run_ammonia_synloop.py @@ -25,6 +25,6 @@ # TODO: Update with demand module once it is developed demand_profile = np.ones(8760) * 640.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") model.run() model.post_process() diff --git a/examples/13_dispatch_for_electrolyzer/run_dispatch_for_electrolyzer.py b/examples/13_dispatch_for_electrolyzer/run_dispatch_for_electrolyzer.py index 24b5f646f..5c2ad309f 100644 --- a/examples/13_dispatch_for_electrolyzer/run_dispatch_for_electrolyzer.py +++ b/examples/13_dispatch_for_electrolyzer/run_dispatch_for_electrolyzer.py @@ -31,7 +31,7 @@ h2i.setup() electrolyzer_capacity_MW = 60 -h2i.prob.set_val("battery.electricity_demand", 0.1 * electrolyzer_capacity_MW, units="MW") +h2i.prob.set_val("battery.electricity_set_point", 0.1 * electrolyzer_capacity_MW, units="MW") h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") h2i.run() diff --git a/examples/16_natural_gas/plant_config.yaml b/examples/16_natural_gas/plant_config.yaml index 4fd21b8a1..7dcdfc8ed 100644 --- a/examples/16_natural_gas/plant_config.yaml +++ b/examples/16_natural_gas/plant_config.yaml @@ -26,7 +26,7 @@ technology_interconnections: # subtract the combined generation from the demand profile - [elec_combiner, electrical_load_demand, electricity, cable] # connect the remaining electricity demand to the NG plant's passthrough controller - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] # connect NG feedstock to NG plant - [ng_feedstock, natural_gas_plant, natural_gas, pipe] # connect natural gas and solar to finance combiner diff --git a/examples/18_pyomo_heuristic_dispatch/run_pyomo_heuristic_dispatch.py b/examples/18_pyomo_heuristic_dispatch/run_pyomo_heuristic_dispatch.py index 98bec0f88..2c617f700 100644 --- a/examples/18_pyomo_heuristic_dispatch/run_pyomo_heuristic_dispatch.py +++ b/examples/18_pyomo_heuristic_dispatch/run_pyomo_heuristic_dispatch.py @@ -12,7 +12,7 @@ # TODO: Update with demand module once it is developed model.setup() -model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() diff --git a/examples/23_solar_wind_ng_demand/plant_config.yaml b/examples/23_solar_wind_ng_demand/plant_config.yaml index 417448b50..5bf31591d 100644 --- a/examples/23_solar_wind_ng_demand/plant_config.yaml +++ b/examples/23_solar_wind_ng_demand/plant_config.yaml @@ -27,7 +27,7 @@ technology_interconnections: # connect NG feedstock to NG plant - [combiner, electrical_load_demand, electricity, cable] # subtract wind and solar from demand - - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_demand]] + - [electrical_load_demand, natural_gas_plant, [unmet_electricity_demand_out, electricity_set_point]] # give remaining load demand to natural gas plant - [combiner, fin_combiner, electricity, cable] - [natural_gas_plant, fin_combiner, electricity, cable] diff --git a/examples/24_solar_battery_grid/plant_config.yaml b/examples/24_solar_battery_grid/plant_config.yaml index 8c9298c03..3fed5d46d 100644 --- a/examples/24_solar_battery_grid/plant_config.yaml +++ b/examples/24_solar_battery_grid/plant_config.yaml @@ -27,7 +27,7 @@ technology_interconnections: # subtract variable generation from the demand - [bat_combiner, electrical_load_demand, electricity, cable] # connect remaining demand to grid buying - - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_demand]] + - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_set_point]] # connect surplus generation to grid selling - [electrical_load_demand, grid_sell, [unused_electricity_out, electricity_in]] # combine electricity generated from solar and electricity bought from grid diff --git a/examples/30_pyomo_optimized_dispatch/run_pyomo_optimized_dispatch.py b/examples/30_pyomo_optimized_dispatch/run_pyomo_optimized_dispatch.py index cbdbefc0e..51de68b12 100644 --- a/examples/30_pyomo_optimized_dispatch/run_pyomo_optimized_dispatch.py +++ b/examples/30_pyomo_optimized_dispatch/run_pyomo_optimized_dispatch.py @@ -12,7 +12,7 @@ # TODO: Update with demand module once it is developed model.setup() -model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") +model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() diff --git a/examples/33_peak_load_management/plant_config.yaml b/examples/33_peak_load_management/plant_config.yaml index e7bc28ac4..93be1cecf 100644 --- a/examples/33_peak_load_management/plant_config.yaml +++ b/examples/33_peak_load_management/plant_config.yaml @@ -12,4 +12,4 @@ technology_interconnections: # include battery charge/discharge in the load - [battery, electrical_load_demand, [electricity_out, electricity_in]] # buy power from the grid to fulfill demand including to accommodate battery operation - - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_demand]] + - [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_set_point]] diff --git a/examples/33_peak_load_management/run_peak_load_management.py b/examples/33_peak_load_management/run_peak_load_management.py index e40497820..075ec6c61 100644 --- a/examples/33_peak_load_management/run_peak_load_management.py +++ b/examples/33_peak_load_management/run_peak_load_management.py @@ -45,7 +45,7 @@ ] ) -secondary_demand = model.prob.get_val("battery.electricity_demand", units="kW") +secondary_demand = model.prob.get_val("battery.electricity_set_point", units="kW") grid_output = model.prob.get_val("grid_buy.electricity_out", units="MW") time_series = build_time_series_from_plant_config(model.plant_config) diff --git a/examples/test/test_all_examples.py b/examples/test/test_all_examples.py index c9221816c..9b6faba5c 100644 --- a/examples/test/test_all_examples.py +++ b/examples/test/test_all_examples.py @@ -25,7 +25,7 @@ def test_steel_example(subtests, temp_copy_of_example): # Set battery demand profile to electrolyzer capacity demand_profile = np.ones(8760) * 720.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -137,7 +137,7 @@ def test_simple_ammonia_example(subtests, temp_copy_of_example): # Set battery demand profile to electrolyzer capacity demand_profile = np.ones(8760) * 640.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -270,7 +270,7 @@ def test_ammonia_synloop_example(subtests, temp_copy_of_example): # Set battery demand profile to electrolyzer capacity demand_profile = np.ones(8760) * 640.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -612,7 +612,7 @@ def test_wind_wave_doc_example(subtests, temp_copy_of_example): # Set battery demand profile demand_profile = np.ones(8760) * 340.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -874,7 +874,7 @@ def test_electrolyzer_demand(subtests, temp_copy_of_example): electrolyzer_capacity_MW = 60 # Set the battery demand as 10% of the electrolyzer capacity - h2i.prob.set_val("battery.electricity_demand", 0.1 * electrolyzer_capacity_MW, units="MW") + h2i.prob.set_val("battery.electricity_set_point", 0.1 * electrolyzer_capacity_MW, units="MW") h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") h2i.run() @@ -911,7 +911,7 @@ def test_electrolyzer_demand(subtests, temp_copy_of_example): assert pytest.approx(127705.51498100, rel=1e-6) == electricity_to_electrolyzer # Re-run where we set the battery demand equal to the electrolyzer capacity - h2i.prob.set_val("battery.electricity_demand", electrolyzer_capacity_MW, units="MW") + h2i.prob.set_val("battery.electricity_set_point", electrolyzer_capacity_MW, units="MW") h2i.prob.set_val("elec_load_demand.electricity_demand", electrolyzer_capacity_MW, units="MW") h2i.run() @@ -1041,7 +1041,7 @@ def test_wind_wave_oae_example(subtests, temp_copy_of_example): # Set battery demand profile demand_profile = np.ones(8760) * 330.0 model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -1155,7 +1155,7 @@ def test_natural_gas_example(subtests, temp_copy_of_example): "electrical_load_demand.unmet_electricity_demand_out", units="kW" ) ng_electricity_set_point = model.prob.get_val( - "natural_gas_plant.electricity_set_point", units="kW" + "natural_gas_plant.electricity_command_value", units="kW" ) ng_electricity_production = model.prob.get_val("natural_gas_plant.electricity_out", units="kW") bat_init_charge = 200000.0 * 0.1 # max capacity in kW and initial charge rate percentage @@ -1408,7 +1408,7 @@ def test_pyomo_heuristic_dispatch_example(subtests, temp_copy_of_example): # TODO: Update with demand module once it is developed model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model model.run() @@ -1695,7 +1695,7 @@ def test_windard_pv_battery_dispatch_example(subtests, temp_copy_of_example): # Demand should be met for the last part of the year assert np.allclose( dispatched_electricity[8700:], - model.prob.get_val("battery.electricity_demand", units="MW")[8700:], + model.prob.get_val("battery.electricity_set_point", units="MW")[8700:], ) # Subtest for LCOE @@ -2694,7 +2694,7 @@ def test_pyomo_optimized_dispatch_example(subtests, temp_copy_of_example): # TODO: Update with demand module once it is developed model.setup() - model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") model.prob.set_val("electrical_load_demand.electricity_demand", demand_profile, units="MW") # Run the model @@ -2958,7 +2958,7 @@ def test_peak_load_management_example(subtests, temp_copy_of_example): assert soc.min() >= 10.0 - 1e-3 with subtests.test("Battery set point sum"): - set_point = model.prob.get_val("battery.electricity_set_point", units="kW") + set_point = model.prob.get_val("battery.electricity_command_value", units="kW") assert set_point.sum() == pytest.approx(60.0, rel=1e-3) with subtests.test("Battery electricity out sum"): diff --git a/h2integrate/control/control_rules/converters/generic_converter_min_operating_cost.py b/h2integrate/control/control_rules/converters/generic_converter_min_operating_cost.py index 56cd25d47..17c6a0cd6 100644 --- a/h2integrate/control/control_rules/converters/generic_converter_min_operating_cost.py +++ b/h2integrate/control/control_rules/converters/generic_converter_min_operating_cost.py @@ -66,7 +66,7 @@ def initialize_parameters(self, inputs: dict, dispatch_inputs: dict): inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : Available generated commodity profile. - f"{commodity}_demand" : Demanded commodity output profile. + f"{commodity}_set_point" : Demanded commodity output profile. dispatch_inputs (dict): Dictionary of the dispatch input parameters from config """ diff --git a/h2integrate/control/control_rules/plant_dispatch_model.py b/h2integrate/control/control_rules/plant_dispatch_model.py index a28f29007..79074ed43 100644 --- a/h2integrate/control/control_rules/plant_dispatch_model.py +++ b/h2integrate/control/control_rules/plant_dispatch_model.py @@ -104,7 +104,7 @@ def initialize_parameters(self, inputs: dict, dispatch_params: dict): inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : Available generated commodity profile. - f"{commodity}_demand" : Demanded commodity output profile. + f"{commodity}_set_point" : Demanded commodity output profile. dispatch_inputs (dict): Dictionary of the dispatch input parameters from config """ diff --git a/h2integrate/control/control_rules/storage/pyomo_storage_rule_min_operating_cost.py b/h2integrate/control/control_rules/storage/pyomo_storage_rule_min_operating_cost.py index 6faf5b513..407585aaf 100644 --- a/h2integrate/control/control_rules/storage/pyomo_storage_rule_min_operating_cost.py +++ b/h2integrate/control/control_rules/storage/pyomo_storage_rule_min_operating_cost.py @@ -69,11 +69,11 @@ def initialize_parameters(self, inputs: dict, dispatch_inputs: dict): inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : Available generated commodity profile. - f"{commodity}_demand" : Demanded commodity output profile. + f"{commodity}_set_point" : Demanded commodity output profile. dispatch_inputs (dict): Dictionary of the dispatch input parameters from config """ - commodity_demand = inputs[f"{self.commodity_name}_demand"] + commodity_demand = inputs[f"{self.commodity_name}_set_point"] # Dispatch Parameters self.set_timeseries_parameter("cost_per_charge", dispatch_inputs["cost_per_charge"]) diff --git a/h2integrate/control/control_strategies/converters/curtailable_component.py b/h2integrate/control/control_strategies/converters/curtailable_component.py index 54578a5cb..b6d9d44aa 100644 --- a/h2integrate/control/control_strategies/converters/curtailable_component.py +++ b/h2integrate/control/control_strategies/converters/curtailable_component.py @@ -17,7 +17,7 @@ def setup(self): n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) self.add_input(f"{self.commodity}_out", shape=n_timesteps, units=None, units_by_conn=True) self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", shape=n_timesteps, units=None, copy_units=f"{self.commodity}_out", @@ -38,7 +38,7 @@ def setup(self): def compute(self, inputs, outputs): set_point_difference = ( - inputs[f"{self.commodity}_out"] - inputs[f"{self.commodity}_set_point"] + inputs[f"{self.commodity}_out"] - inputs[f"{self.commodity}_command_value"] ) # commodity_out exceeds setpoint excess_commodity = np.where(set_point_difference > 0, set_point_difference, 0) diff --git a/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py index a0042effd..8b4fc0538 100644 --- a/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py +++ b/h2integrate/control/control_strategies/converters/test/test_curtailable_component.py @@ -37,7 +37,7 @@ def test_curtailable_component(plant_config_base, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=10, shape=8760, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_command_value", val=10, shape=8760, units="kg/h"), promotes=["*"], ) diff --git a/h2integrate/control/control_strategies/passthrough_controller.py b/h2integrate/control/control_strategies/passthrough_controller.py index a48aabd17..589e7a598 100644 --- a/h2integrate/control/control_strategies/passthrough_controller.py +++ b/h2integrate/control/control_strategies/passthrough_controller.py @@ -2,16 +2,16 @@ class PassthroughController(om.ExplicitComponent): - """Simple controller that passes a demand signal directly through as a set-point. + """Simple controller that passes a set-point signal directly through as a command value. Every technology group is expected to have a controller subsystem. When a technology does not define its own ``control_strategy``, this passthrough controller is inserted automatically so that the group exposes a uniform - ``{commodity}_demand`` input and ``{commodity}_set_point`` output interface. + ``{commodity}_set_point`` input and ``{commodity}_command_value`` output interface. In a system-level-control (SLC) configuration the SLC output is connected to - ``{commodity}_demand``; this component copies that signal to - ``{commodity}_set_point`` which the performance model consumes. + ``{commodity}_set_point``; this component copies that signal to + ``{commodity}_command_value`` which the performance model consumes. When no SLC is present the input defaults to a very large value so that production is unconstrained, making the component a harmless no-op. @@ -27,9 +27,9 @@ def initialize(self): types=str, default=None, desc="Units for the commodity rate (e.g. 'kW', 'kg/h'). " - "When provided, explicit units are used on the demand input " + "When provided, explicit units are used on the set-point input " "so the variable works even when unconnected (no SLC). " - "The set-point output always uses units_by_conn to inherit " + "The command-value output always uses units_by_conn to inherit " "units from the connected performance model.", ) @@ -43,7 +43,7 @@ def setup(self): # (units_by_conn fails on unconnected variables). # Default to a large value so that when no SLC is connected the # downstream performance model behaves as if unconstrained (the perf - # model typically saturates the set-point at its rated capacity). + # model typically saturates the command value at its rated capacity). # We avoid extreme values (e.g. 1e30) here because they pollute the # solver relative-residual check and cause premature false convergence # in cyclic system-level control configurations. @@ -51,38 +51,38 @@ def setup(self): if commodity_rate_units is not None: self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Demand signal for {commodity}", + desc=f"Set-point signal for {commodity}", units=commodity_rate_units, ) else: self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=default_val, shape=n_timesteps, - desc=f"Demand signal for {commodity}", + desc=f"Set-point signal for {commodity}", units_by_conn=True, ) if commodity_rate_units is not None: self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=default_val, shape=n_timesteps, - desc=f"Set point for {commodity} (passthrough of demand)", + desc=f"Command value for {commodity} (passthrough of set-point)", units=commodity_rate_units, ) else: self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=default_val, shape=n_timesteps, - desc=f"Set point for {commodity} (passthrough of demand)", + desc=f"Command value for {commodity} (passthrough of set-point)", units_by_conn=True, ) def compute(self, inputs, outputs): commodity = self.options["commodity"] - outputs[f"{commodity}_set_point"] = inputs[f"{commodity}_demand"] + outputs[f"{commodity}_command_value"] = inputs[f"{commodity}_set_point"] diff --git a/h2integrate/control/control_strategies/pyomo_storage_controller_baseclass.py b/h2integrate/control/control_strategies/pyomo_storage_controller_baseclass.py index 94203ddf3..0f6822831 100644 --- a/h2integrate/control/control_strategies/pyomo_storage_controller_baseclass.py +++ b/h2integrate/control/control_strategies/pyomo_storage_controller_baseclass.py @@ -171,7 +171,7 @@ def pyomo_dispatch_solver( inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : available generated commodity profile. - f"{commodity}_demand" : demanded commodity output profile. + f"{commodity}_set_point" : set-point commodity output profile. commodity (str, optional): Base commodity name (e.g. "electricity", "hydrogen"). Default: self.config.commodity. diff --git a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py index 4455fb11e..74ad84d20 100644 --- a/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/demand_openloop_storage_controller.py @@ -96,12 +96,12 @@ def compute(self, inputs, outputs): Expected input keys: * ``_in``: Timeseries of commodity available at each time step. - * ``_demand``: Timeseries demand profile. + * ``_set_point``: Timeseries set-point profile. * ``max_charge_rate``: Maximum charge rate permitted. * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_set_point``: Dispatch command to storage, + * ``_command_value``: Dispatch command to storage, negative when charging, positive when discharging. Control logic includes: @@ -111,7 +111,7 @@ def compute(self, inputs, outputs): * Tracking energy shortfalls and excesses at each time step. Raises: - UserWarning: If the demand profile is entirely zero. + UserWarning: If the set-point profile is entirely zero. UserWarning: If ``max_charge_rate`` or ``max_capacity`` is negative. Returns: @@ -140,7 +140,7 @@ def compute(self, inputs, outputs): # the previous time step's value soc = deepcopy(init_soc_fraction) - demand_profile = inputs[f"{commodity}_demand"] + demand_profile = inputs[f"{commodity}_set_point"] # initialize outputs soc_array = np.zeros(self.n_timesteps) @@ -192,4 +192,4 @@ def compute(self, inputs, outputs): # Record the SOC for the current time step soc_array[t] = deepcopy(soc) - outputs[f"{commodity}_set_point"] = set_point_array + outputs[f"{commodity}_command_value"] = set_point_array diff --git a/h2integrate/control/control_strategies/storage/heuristic_pyomo_controller.py b/h2integrate/control/control_strategies/storage/heuristic_pyomo_controller.py index 5eebf4fb3..aeba9e66d 100644 --- a/h2integrate/control/control_strategies/storage/heuristic_pyomo_controller.py +++ b/h2integrate/control/control_strategies/storage/heuristic_pyomo_controller.py @@ -176,7 +176,7 @@ def pyomo_dispatch_solver( inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : available generated commodity profile. - f"{commodity}_demand" : demanded commodity output profile. + f"{commodity}_set_point" : set-point commodity output profile. commodity (str, optional): Base commodity name (e.g. "electricity", "hydrogen"). Default: self.config.commodity. @@ -213,7 +213,7 @@ def pyomo_dispatch_solver( commodity_in = inputs[self.config.commodity + "_in"][ t : t + self.config.n_control_window_hours ] - demand_in = inputs[f"{commodity_name}_demand"][ + demand_in = inputs[f"{commodity_name}_set_point"][ t : t + self.config.n_control_window_hours ] diff --git a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py index d7a93c59b..27b91ad42 100644 --- a/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py +++ b/h2integrate/control/control_strategies/storage/openloop_storage_control_base.py @@ -142,7 +142,7 @@ class StorageOpenLoopControlBase(om.ExplicitComponent): """Base OpenMDAO component for open-loop demand tracking. This component defines the interfaces required for open-loop demand - controllers, including inputs for demand, available commodity, and outputs + controllers, including inputs for set-point, available commodity, and outputs dispatch command profile. """ @@ -164,11 +164,11 @@ def setup(self): demand_data = self.config.demand_profile self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=demand_data if not isinstance(demand_data, dict) else demand_data["demand"], shape=self.n_timesteps, units=self.config.commodity_rate_units, - desc=f"Demand profile of {commodity}", + desc=f"Set-point profile of {commodity}", ) self.add_input( @@ -180,7 +180,7 @@ def setup(self): ) self.add_output( - f"{commodity}_set_point", + f"{commodity}_command_value", val=0.0, shape=self.n_timesteps, units=self.config.commodity_rate_units, @@ -197,8 +197,8 @@ def compute(): raise NotImplementedError("This method should be implemented in a subclass.") def common_checks_needed_in_compute(self, inputs): - if np.all(inputs[f"{self.config.commodity}_demand"] == 0.0): - msg = "Demand profile is zero, check that demand profile is input" + if np.all(inputs[f"{self.config.commodity}_set_point"] == 0.0): + msg = "Set-point profile is zero, check that set-point profile is input" raise UserWarning(msg) if inputs["max_charge_rate"][0] < 0: msg = ( diff --git a/h2integrate/control/control_strategies/storage/optimized_pyomo_controller.py b/h2integrate/control/control_strategies/storage/optimized_pyomo_controller.py index ddb9cef8e..58c6108f0 100644 --- a/h2integrate/control/control_strategies/storage/optimized_pyomo_controller.py +++ b/h2integrate/control/control_strategies/storage/optimized_pyomo_controller.py @@ -201,7 +201,7 @@ def pyomo_dispatch_solver( inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : available generated commodity profile. - f"{commodity}_demand" : demanded commodity output profile. + f"{commodity}_set_point" : set-point commodity output profile. commodity (str, optional): Base commodity name (e.g. "electricity", "hydrogen"). Default: self.config.commodity. @@ -239,7 +239,7 @@ def pyomo_dispatch_solver( commodity_in = inputs[f"{self.config.commodity}_in"][ t : t + self.config.n_control_window_hours ] - demand_in = inputs[f"{commodity_name}_demand"][ + demand_in = inputs[f"{commodity_name}_set_point"][ t : t + self.config.n_control_window_hours ] @@ -290,7 +290,7 @@ def initialize_parameters(self, inputs): inputs (dict): Dictionary of numpy arrays (length = self.n_timesteps) containing at least: f"{commodity}_in" : Available generated commodity profile. - f"{commodity}_demand" : Demanded commodity output profile. + f"{commodity}_set_point" : Set-point commodity output profile. """ # Where pyomo model communicates with the rest of the controller diff --git a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py index 31624ed8a..4651199ff 100644 --- a/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/plm_openloop_storage_controller.py @@ -242,16 +242,16 @@ def compute(self, inputs, outputs): Expected input keys: * ``_in``: Timeseries of commodity available at each time step. - * ``_demand``: Timeseries demand profile. + * ``_set_point``: Timeseries set-point profile. * ``max_charge_rate``: Maximum charge rate permitted. * ``max_capacity``: Maximum total storage capacity. Outputs populated: - * ``_set_point``: Dispatch command to storage, + * ``_command_value``: Dispatch command to storage, negative when charging, positive when discharging. Raises: - UserWarning: If the demand profile is entirely zero. + UserWarning: If the set-point profile is entirely zero. UserWarning: If ``max_charge_rate`` or ``max_capacity`` is negative. Returns: @@ -279,7 +279,7 @@ def compute(self, inputs, outputs): # Build timestamped demand dictionaries from simulation timeline. demand_profile = self._build_demand_profile_dict( - inputs[f"{commodity}_demand"], + inputs[f"{commodity}_set_point"], self.time_index, ) @@ -381,7 +381,7 @@ def compute(self, inputs, outputs): if soc >= soc_max: charging = False - outputs[f"{commodity}_set_point"] = set_point_array + outputs[f"{commodity}_command_value"] = set_point_array # insert warning message if for any time step the magnitude of # any negative entry in set_point_array is greater than inputs[f"{commodity}_in"] diff --git a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py index 418a8ec05..82e95d380 100644 --- a/h2integrate/control/control_strategies/storage/simple_openloop_controller.py +++ b/h2integrate/control/control_strategies/storage/simple_openloop_controller.py @@ -72,19 +72,19 @@ def setup(self): def compute(self, inputs, outputs): """ - Simple controller that outputs `commodity_set_point`, - the dispatch set-points for each timestep in `commodity_rate_units`. + Simple controller that outputs `commodity_command_value`, + the dispatch command values for each timestep in `commodity_rate_units`. Negative values command charging, positive values command discharging. """ if ( self.config.set_demand_as_avg_commodity_in - and inputs[f"{self.config.commodity}_demand"].sum() > 0 + and inputs[f"{self.config.commodity}_set_point"].sum() > 0 ): msg = ( - "A non-zero demand profile was input but set_demand_as_avg_commodity_in is True." - " The input demand profile will not be used, the demand profile will be " + "A non-zero set-point profile was input but set_demand_as_avg_commodity_in is True." + " The input set-point profile will not be used, the set-point profile will be " f"calculated as the mean of ``{self.config.commodity}_in``. " ) raise ValueError(msg) @@ -95,11 +95,11 @@ def compute(self, inputs, outputs): self.n_timesteps ) else: - commodity_demand = inputs[f"{self.config.commodity}_demand"] + commodity_demand = inputs[f"{self.config.commodity}_set_point"] - # Assign the set point as the difference between the demand and the input commodity - # when demand > input, the set point is positive to command discharging - # when demand < input, the set point is negative to command charging - outputs[f"{self.config.commodity}_set_point"] = ( + # Assign the command value as the difference between the set-point and the input commodity + # when set-point > input, the command value is positive to command discharging + # when set-point < input, the command value is negative to command charging + outputs[f"{self.config.commodity}_command_value"] = ( commodity_demand - inputs[f"{self.config.commodity}_in"] ) diff --git a/h2integrate/control/control_strategies/storage/test/test_heuristic_controllers.py b/h2integrate/control/control_strategies/storage/test/test_heuristic_controllers.py index 4530af4ab..1ac14ab73 100644 --- a/h2integrate/control/control_strategies/storage/test/test_heuristic_controllers.py +++ b/h2integrate/control/control_strategies/storage/test/test_heuristic_controllers.py @@ -223,7 +223,7 @@ def test_heuristic_load_following_battery_dispatch( # Setup the system and required values prob.setup() prob.set_val("battery.electricity_in", electricity_in) - prob.set_val("battery.electricity_demand", demand_in) + prob.set_val("battery.electricity_set_point", demand_in) # Run the model prob.run_model() @@ -399,7 +399,7 @@ def test_heuristic_load_following_battery_dispatch( prob.setup() prob.set_val("battery.electricity_in", electricity_in) - prob.set_val("battery.electricity_demand", demand_in) + prob.set_val("battery.electricity_set_point", demand_in) # Run the model prob.run_model() @@ -449,7 +449,7 @@ def test_heuristic_load_following_battery_dispatch( # Setup the system and required values prob.setup() prob.set_val("battery.electricity_in", electricity_in) - prob.set_val("battery.electricity_demand", demand_in) + prob.set_val("battery.electricity_set_point", demand_in) # Run the model prob.run_model() @@ -586,7 +586,7 @@ def test_heuristic_load_following_battery_dispatch_change_capacities( prob.set_val("IVC2.storage_capacity", 200000, units="kW*h") prob.set_val("battery.electricity_in", electricity_in) - prob.set_val("battery.electricity_demand", demand_in) + prob.set_val("battery.electricity_set_point", demand_in) # Run the model prob.run_model() @@ -806,7 +806,7 @@ def test_heuristic_load_following_dispatch_with_generic_storage( # Setup the system and required values prob.setup() prob.set_val("h2_storage.hydrogen_in", commodity_in) - prob.set_val("h2_storage.hydrogen_demand", commodity_demand) + prob.set_val("h2_storage.hydrogen_set_point", commodity_demand) # Run the model prob.run_model() @@ -954,7 +954,7 @@ def test_heuristic_dispatch_with_autosizing_storage_demand_less_than_avg_in( # Setup the system and required values prob.setup() prob.set_val("h2_storage.hydrogen_in", commodity_in) - prob.set_val("h2_storage.hydrogen_demand", commodity_demand) + prob.set_val("h2_storage.hydrogen_set_point", commodity_demand) # Run the model prob.run_model() diff --git a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py index 350d90c30..074bea700 100644 --- a/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py +++ b/h2integrate/control/control_strategies/storage/test/test_openloop_controllers.py @@ -83,7 +83,7 @@ def test_pass_through_controller(subtests): with subtests.test("Check output"): expected_set_point = np.mean(np.arange(10)) - np.arange(10) assert expected_set_point == ( - pytest.approx(prob.get_val("hydrogen_set_point", units="kg/h"), rel=1e-3) + pytest.approx(prob.get_val("hydrogen_command_value", units="kg/h"), rel=1e-3) ) @@ -254,14 +254,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_demand", units="kg/h"), + prob_rte.get_val("hydrogen_set_point", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_demand", units="kg/h"), + prob_ioe.get_val("hydrogen_set_point", units="kg/h"), ) ) @@ -396,14 +396,14 @@ def set_up_and_run_problem(config): calculate_combined_outputs( prob_rte.get_val("hydrogen_out", units="kg/h"), prob_rte.get_val("hydrogen_in", units="kg/h"), - prob_rte.get_val("hydrogen_demand", units="kg/h"), + prob_rte.get_val("hydrogen_set_point", units="kg/h"), ) ) unmet_demand_ioe, unused_commodity_ioe, combined_out_for_demand_ioe = ( calculate_combined_outputs( prob_ioe.get_val("hydrogen_out", units="kg/h"), prob_ioe.get_val("hydrogen_in", units="kg/h"), - prob_ioe.get_val("hydrogen_demand", units="kg/h"), + prob_ioe.get_val("hydrogen_set_point", units="kg/h"), ) ) @@ -516,7 +516,7 @@ def test_generic_storage_demand_controller(subtests): unmet_demand, unused_commodity, combined_out_for_demand = calculate_combined_outputs( prob.get_val("hydrogen_out", units="kg/h"), prob.get_val("hydrogen_in", units="kg/h"), - prob.get_val("hydrogen_demand", units="kg/h"), + prob.get_val("hydrogen_set_point", units="kg/h"), ) # # Run the test diff --git a/h2integrate/control/control_strategies/storage/test/test_optimal_controllers.py b/h2integrate/control/control_strategies/storage/test/test_optimal_controllers.py index d20666442..e85e54c65 100644 --- a/h2integrate/control/control_strategies/storage/test/test_optimal_controllers.py +++ b/h2integrate/control/control_strategies/storage/test/test_optimal_controllers.py @@ -216,7 +216,7 @@ def test_min_operating_cost_load_following_battery_dispatch( # Setup the system and required values prob.setup() prob.set_val("battery.electricity_in", electricity_in) - prob.set_val("battery.electricity_demand", demand_in) + prob.set_val("battery.electricity_set_point", demand_in) # Run the model prob.run_model() @@ -365,7 +365,7 @@ def test_optimal_control_with_generic_storage( # Setup the system and required values prob.setup() prob.set_val("h2_storage.hydrogen_in", commodity_in) - prob.set_val("h2_storage.hydrogen_demand", commodity_demand) + prob.set_val("h2_storage.hydrogen_set_point", commodity_demand) # Run the model prob.run_model() @@ -518,7 +518,7 @@ def test_optimal_dispatch_with_autosizing_storage_demand_less_than_avg_in( # Setup the system and required values prob.setup() prob.set_val("h2_storage.hydrogen_in", commodity_in) - prob.set_val("h2_storage.hydrogen_demand", commodity_demand) + prob.set_val("h2_storage.hydrogen_set_point", commodity_demand) # Run the model prob.run_model() diff --git a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py index 492510c3c..5c0efb6c2 100644 --- a/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py +++ b/h2integrate/control/control_strategies/storage/test/test_plm_openloop_storage_controller.py @@ -521,7 +521,7 @@ def test_plm_controller_basic_discharge_before_peak(subtests, tech_config_base, prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_set_point", units="kg/h") + set_point = prob.get_val("hydrogen_command_value", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Discharge occurs before peak (hours 8-9)"): @@ -679,7 +679,7 @@ def test_plm_controller_blocking_charge_in_peak_range( prob.setup() prob.run_model() - set_point = prob.get_val("hydrogen_set_point", units="kg/h") + set_point = prob.get_val("hydrogen_command_value", units="kg/h") soc = prob.get_val("SOC", units="unitless") with subtests.test("Controller instantiates and runs without error"): diff --git a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py index 1af7e0eed..869976d50 100644 --- a/h2integrate/control/control_strategies/system_level/cost_minimization_control.py +++ b/h2integrate/control/control_strategies/system_level/cost_minimization_control.py @@ -79,16 +79,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable demand outputs to zero - for demand_name in self.dispatchable_demand_names: - outputs[demand_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable set-point outputs to zero + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) # Dispatch in merit order for idx in dispatch_order: - demand_name = self.dispatchable_demand_names[idx] + set_point_name = self.dispatchable_set_point_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] dispatch = np.minimum(remaining, rated) - outputs[demand_name] = dispatch + outputs[set_point_name] = dispatch remaining -= dispatch diff --git a/h2integrate/control/control_strategies/system_level/demand_following_control.py b/h2integrate/control/control_strategies/system_level/demand_following_control.py index 15f1e3cda..bb83712d0 100644 --- a/h2integrate/control/control_strategies/system_level/demand_following_control.py +++ b/h2integrate/control/control_strategies/system_level/demand_following_control.py @@ -52,8 +52,8 @@ def compute(self, inputs, outputs): ) else: if f"{flexible_tech}_rated_{tech_commodity}_production" in inputs: - # set the per-tech demand as the rated production - outputs[f"{flexible_tech}_{tech_commodity}_demand"] = inputs[ + # set the per-tech set-point as the rated production + outputs[f"{flexible_tech}_{tech_commodity}_set_point"] = inputs[ f"{flexible_tech}_rated_{tech_commodity}_production" ] * np.ones(self.n_timesteps) @@ -80,6 +80,6 @@ def compute(self, inputs, outputs): for dispatchable_tech in self.dispatchable_techs: commodity_from_tech = self._get_commodity_for_tech(dispatchable_tech) if commodity in commodity_from_tech: - outputs[f"{dispatchable_tech}_{commodity}_demand"] = ( + outputs[f"{dispatchable_tech}_{commodity}_set_point"] = ( remaining_demand / n_dispatchable ) diff --git a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py index 9275c0fc4..9a8eb0a42 100644 --- a/h2integrate/control/control_strategies/system_level/profit_maximization_control.py +++ b/h2integrate/control/control_strategies/system_level/profit_maximization_control.py @@ -139,16 +139,16 @@ def compute(self, inputs, outputs): mean_costs = np.array([mc.mean() for mc in marginal_costs]) dispatch_order = np.argsort(mean_costs) - # Initialize all dispatchable demand outputs to zero - for demand_name in self.dispatchable_demand_names: - outputs[demand_name] = np.zeros(self.n_timesteps) + # Initialize all dispatchable set-point outputs to zero + for set_point_name in self.dispatchable_set_point_names: + outputs[set_point_name] = np.zeros(self.n_timesteps) # Dispatch only where profitable (element-wise comparison) for idx in dispatch_order: mc = marginal_costs[idx] # per-timestep array profitable = mc < sell_price # boolean mask per timestep - set_point_name = self.dispatchable_demand_names[idx] + set_point_name = self.dispatchable_set_point_names[idx] rated_name = self.dispatchable_rated_names[idx] rated = inputs[rated_name] diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 11d20fb72..45a2350e6 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -14,10 +14,10 @@ class SystemLevelControlBase(om.ExplicitComponent): Subclasses must implement ``compute()`` with their dispatch strategy. Each technology group is expected to contain a controller (either user-defined or an - auto-injected ``PassthroughController``) that consumes a ``{commodity}_demand`` input and - produces the ``{commodity}_set_point`` actually fed to the performance/cost models. The + auto-injected ``PassthroughController``) that consumes a ``{commodity}_set_point`` input and + produces the ``{commodity}_command_value`` actually fed to the performance/cost models. The system-level controller therefore reasons in terms of *demand* values and emits - ``{tech_name}_{commodity}_demand`` outputs for every controlled technology. + ``{tech_name}_{commodity}_set_point`` outputs for every controlled technology. The SLC demand signal is provided by a demand component (for example, ``GenericDemandComponent``) connected by ``H2IntegrateModel``. When SLC is @@ -146,8 +146,8 @@ def _setup_commodity( (only if ``add_in_name=True``). - Input ``"{tech_name}_rated_{commodity}_production"`` - rated production capacity of the tech. - - Output ``"{tech_name}_{commodity}_demand"`` - demand signal sent to the - tech's controller (which translates it into a performance-model set-point). + - Output ``"{tech_name}_{commodity}_set_point"`` - set-point signal sent to the + tech's controller (which translates it into a performance-model command value). Args: tech_name (str): Name of the technology. @@ -160,10 +160,10 @@ def _setup_commodity( add_in_name (bool, optional): If True, register the ``"{tech_name}_{commodity}_out"`` input. Defaults to True. initial_demand (float, optional): Initial value for the - demand output. Defaults to 1.0. + set-point output. Defaults to 1.0. Returns: - tuple[str, str, str]: ``(in_name, demand_name, rated_name)`` + tuple[str, str, str]: ``(in_name, set_point_name, rated_name)`` """ # --- Determine unit kwargs for add_input / add_output --------- # Either explicit units or copy_units from a reference variable. @@ -175,7 +175,7 @@ def _setup_commodity( # --- Build variable names ------------------------------------- in_name = f"{tech_name}_{commodity}_out" rated_name = f"{tech_name}_rated_{commodity}_production" - demand_name = f"{tech_name}_{commodity}_demand" + set_point_name = f"{tech_name}_{commodity}_set_point" # --- Register inputs and output ------------------------------- if add_in_name: @@ -193,14 +193,14 @@ def _setup_commodity( **unit_kwargs, ) self.add_output( - demand_name, + set_point_name, val=initial_demand, shape=self.n_timesteps, - desc=f"Demand sent to {tech_name} for {commodity}", + desc=f"Set-point sent to {tech_name} for {commodity}", **unit_kwargs, ) - return in_name, demand_name, rated_name + return in_name, set_point_name, rated_name def _setup_tech_category(self, category, tech_list): """Create OpenMDAO I/O variables for all technologies in a given category. @@ -218,7 +218,7 @@ def _setup_tech_category(self, category, tech_list): names produced by the *category* prefix: ``self.{category}_input_names`` - ``self.{category}_demand_names`` + ``self.{category}_set_point_names`` ``self.{category}_rated_names`` ``self.{category}_commodity_names`` @@ -235,7 +235,7 @@ def _setup_tech_category(self, category, tech_list): # --- Initialize the four per-category bookkeeping lists ------- input_names = [] - demand_names = [] + set_point_names = [] rated_names = [] commodity_names = [] @@ -245,7 +245,7 @@ def _setup_tech_category(self, category, tech_list): for commodity in tech_commodities: if commodity in self.commodities_to_units: # Units are already known explicitly - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -254,7 +254,7 @@ def _setup_tech_category(self, category, tech_list): ) elif commodity in self.commodities_to_ref_var: # Units are inferred from a previously-registered reference variable - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -277,7 +277,7 @@ def _setup_tech_category(self, category, tech_list): # variable so later techs with this commodity can # copy its units. self.commodities_to_ref_var[commodity] = in_name - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_reference_var=self.commodities_to_ref_var[commodity], @@ -287,7 +287,7 @@ def _setup_tech_category(self, category, tech_list): else: # Connection provided units — record them for future use self.commodities_to_units[commodity] = meta_data["units"] - in_name, demand_name, rated_name = self._setup_commodity( + in_name, set_point_name, rated_name = self._setup_commodity( tech_name, commodity, commodity_rate_units=self.commodities_to_units[commodity], @@ -302,12 +302,12 @@ def _setup_tech_category(self, category, tech_list): commodity_names.append(commodity) input_names.append(in_name) - demand_names.append(demand_name) + set_point_names.append(set_point_name) rated_names.append(rated_name) # --- Store lists as self._ attributes ------- setattr(self, f"{category}_input_names", input_names) - setattr(self, f"{category}_demand_names", demand_names) + setattr(self, f"{category}_set_point_names", set_point_names) setattr(self, f"{category}_rated_names", rated_names) setattr(self, f"{category}_commodity_names", commodity_names) @@ -453,8 +453,8 @@ def _subtract_flexible(self, flexible_tech, remaining_demand, commodity, inputs, if f"{flexible_tech}_rated_{commodity}_production" not in inputs: return - # Set per-tech demand equal to the rated production of that technology - outputs[f"{flexible_tech}_{commodity}_demand"] = inputs[ + # Set per-tech set-point equal to the rated production of that technology + outputs[f"{flexible_tech}_{commodity}_set_point"] = inputs[ f"{flexible_tech}_rated_{commodity}_production" ] * np.ones(self.n_timesteps) remaining_demand -= inputs[f"{flexible_tech}_{commodity}_out"] @@ -468,15 +468,15 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if f"{storage_tech}_{commodity}_out" not in inputs: return - demand_name = f"{storage_tech}_{commodity}_demand" - if demand_name not in outputs: + set_point_name = f"{storage_tech}_{commodity}_set_point" + if set_point_name not in outputs: return - # Emit a signed charge/discharge demand signal: charge when remaining + # Emit a signed charge/discharge set-point signal: charge when remaining # demand is negative, discharge when positive. The storage tech's # controller (passthrough by default) forwards this to the performance # model, which interprets the sign as charge or discharge. - outputs[demand_name] = remaining_demand + outputs[set_point_name] = remaining_demand remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index 036e7ee40..f30ef906a 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -153,7 +153,7 @@ def test_base_creates_flexible_io(self): # _var_rel2meta uses relative names (no "slc." prefix) assert "wind_electricity_out" in prob.model.slc._var_rel2meta assert "wind_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "wind_electricity_demand" in prob.model.slc._var_rel2meta + assert "wind_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_dispatchable_io(self): tech_connections = [["ng", "demand", "electricity", "cable"]] @@ -164,7 +164,7 @@ def test_base_creates_dispatchable_io(self): prob = _build_problem(DemandFollowingControl, plant_config, slc_config) assert "ng_electricity_out" in prob.model.slc._var_rel2meta assert "ng_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "ng_electricity_demand" in prob.model.slc._var_rel2meta + assert "ng_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_storage_io(self): tech_connections = [["battery", "demand", "electricity", "cable"]] @@ -176,7 +176,7 @@ def test_base_creates_storage_io(self): assert "battery_electricity_out" in prob.model.slc._var_rel2meta assert "battery_rated_electricity_production" in prob.model.slc._var_rel2meta - assert "battery_electricity_demand" in prob.model.slc._var_rel2meta + assert "battery_electricity_set_point" in prob.model.slc._var_rel2meta def test_base_creates_demand_input(self): plant_config = _build_plant_config([]) @@ -215,8 +215,8 @@ def test_equal_share_two_dispatchable(self): prob.set_val("slc.ng2_rated_electricity_production", 40000) prob.run_model() - sp1 = prob.get_val("slc.ng1_electricity_demand") - sp2 = prob.get_val("slc.ng2_electricity_demand") + sp1 = prob.get_val("slc.ng1_electricity_set_point") + sp2 = prob.get_val("slc.ng2_electricity_set_point") np.testing.assert_allclose(sp1, 25000) np.testing.assert_allclose(sp2, 25000) @@ -239,7 +239,7 @@ def test_flexible_reduces_demand(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # demand=50k, wind outputs [30k,60k,50k,10k] → remaining = max(0, demand-wind) expected = np.maximum(50000 - np.array([30000, 60000, 50000, 10000]), 0) np.testing.assert_allclose(ng_sp, expected) @@ -267,7 +267,7 @@ def test_storage_absorbs_surplus(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - batt_sp = prob.get_val("slc.battery_electricity_demand") + batt_sp = prob.get_val("slc.battery_electricity_set_point") # demand - wind = [50k-70k, 50k-30k, 0, 0] = [-20k, 20k, 0, 0] expected = np.array([-20000, 20000, 0, 0]) np.testing.assert_allclose(batt_sp, expected) @@ -310,8 +310,8 @@ def test_cheapest_dispatched_first(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap can handle all 50k (rated 80k), so expensive gets 0 np.testing.assert_allclose(cheap_sp, 50000) np.testing.assert_allclose(expensive_sp, 0) @@ -336,8 +336,8 @@ def test_overflow_to_expensive(self): prob.set_val("slc.expensive_rated_electricity_production", 40000) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap maxes at 30k, expensive picks up remaining 20k np.testing.assert_allclose(cheap_sp, 30000) np.testing.assert_allclose(expensive_sp, 20000) @@ -361,7 +361,7 @@ def test_with_flexible_reduces_dispatch(self): prob.set_val("slc.ng_rated_electricity_production", 100000) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # demand 50k - wind 40k = 10k remaining np.testing.assert_allclose(ng_sp, 10000) @@ -394,8 +394,8 @@ def test_unprofitable_tech_not_dispatched(self): prob.set_val("slc.commodity_sell_price", 0.06) prob.run_model() - cheap_sp = prob.get_val("slc.cheap_electricity_demand") - expensive_sp = prob.get_val("slc.expensive_electricity_demand") + cheap_sp = prob.get_val("slc.cheap_electricity_set_point") + expensive_sp = prob.get_val("slc.expensive_electricity_set_point") # Cheap (0.03 < 0.06) dispatched up to rated 30k # Expensive (0.08 >= 0.06) NOT dispatched, demand unmet np.testing.assert_allclose(cheap_sp, 30000) @@ -420,8 +420,8 @@ def test_all_profitable(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - a_sp = prob.get_val("slc.a_electricity_demand") - b_sp = prob.get_val("slc.b_electricity_demand") + a_sp = prob.get_val("slc.a_electricity_set_point") + b_sp = prob.get_val("slc.b_electricity_set_point") # Both profitable, cheapest first: a gets 50k (rated 80k), b gets 0 np.testing.assert_allclose(a_sp, 50000) np.testing.assert_allclose(b_sp, 0) @@ -442,7 +442,7 @@ def test_none_profitable(self): prob.set_val("slc.commodity_sell_price", 0.01) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # NG cost (0.05) >= sell price (0.01), not dispatched np.testing.assert_allclose(ng_sp, 0) @@ -462,7 +462,7 @@ def test_sell_price_from_config(self): # Don't set sell_price explicitly — should use config default 0.10 prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # Config sell_price=0.10 > marginal 0.03 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -483,7 +483,7 @@ def test_time_varying_sell_price(self): prob.set_val("slc.commodity_sell_price", [0.08, 0.03, 0.10, 0.02]) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # mc=0.05: profitable when sell>0.05 (hours 0,2), not when sell<0.05 (hours 1,3) np.testing.assert_allclose(ng_sp, [50000, 0, 50000, 0]) @@ -521,7 +521,7 @@ def test_buy_price_scalar(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_demand") + grid_sp = prob.get_val("slc.grid_electricity_set_point") # buy_price=0.04 < sell_price=0.10 → dispatched np.testing.assert_allclose(grid_sp, 50000) @@ -561,7 +561,7 @@ def test_buy_price_time_varying(self): prob.set_val("slc.grid_buy_price", [0.03, 0.08, 0.04, 0.09]) prob.run_model() - grid_sp = prob.get_val("slc.grid_electricity_demand") + grid_sp = prob.get_val("slc.grid_electricity_set_point") np.testing.assert_allclose(grid_sp, [50000, 0, 50000, 0]) def test_varopex_mode(self): @@ -584,7 +584,7 @@ def test_varopex_mode(self): prob.set_val("slc.gen_electricity_out", np.full(4, 100000.0)) prob.run_model() - gen_sp = prob.get_val("slc.gen_electricity_demand") + gen_sp = prob.get_val("slc.gen_electricity_set_point") # VarOpEx=500k $/yr, production=100MW*4h=400MWh over 4h # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 500k / 876k ≈ 0.571 $/MWh ≈ 0.000571 $/kWh @@ -607,7 +607,7 @@ def test_cost_per_tech_default_zero(self): prob.set_val("slc.commodity_sell_price", 0.10) prob.run_model() - ng_sp = prob.get_val("slc.ng_electricity_demand") + ng_sp = prob.get_val("slc.ng_electricity_set_point") # mc=0.0 < sell_price=0.10 → dispatched np.testing.assert_allclose(ng_sp, 50000) @@ -634,7 +634,7 @@ def test_feedstock_single(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_demand") + sp = prob.get_val("slc.ng_plant_electricity_set_point") # Annual production = 400 MWh / (4/8760) = 876,000 MWh # mc = 1M / 876k ≈ 1.14 $/MWh ≈ 0.00114 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -665,7 +665,7 @@ def test_feedstock_multiple(self): prob.set_val("slc.plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.plant_electricity_demand") + sp = prob.get_val("slc.plant_electricity_set_point") # Total VarOpEx = 800k, annual production = 876,000 MWh # mc ≈ 0.913 $/MWh ≈ 0.000913 $/kWh → very cheap np.testing.assert_allclose(sp, 50000) @@ -695,7 +695,7 @@ def test_feedstock_profit_max_unprofitable(self): prob.set_val("slc.ng_plant_electricity_out", np.full(4, 100000.0)) prob.run_model() - sp = prob.get_val("slc.ng_plant_electricity_demand") + sp = prob.get_val("slc.ng_plant_electricity_set_point") # mc = 100M / 876k ≈ 114 $/MWh ≈ 0.114 $/kWh > sell 0.01 → NOT dispatched np.testing.assert_allclose(sp, 0) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index c1dca6375..210eebae5 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -17,7 +17,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -26,7 +26,7 @@ def test_slc_no_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_demand", units="kW" + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, @@ -76,7 +76,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): with subtests.test("Wind set point == rated"): assert np.all( - model.prob.get_val("system_level_controller.wind_electricity_demand", units="kW") + model.prob.get_val("system_level_controller.wind_electricity_set_point", units="kW") == model.prob.get_val("wind.rated_electricity_production", units="kW") ) @@ -85,7 +85,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "electrical_load_demand.electricity_demand_out", units="kW" ) - model.prob.get_val("wind.electricity_out", units="kW") battery_set_point = model.prob.get_val( - "system_level_controller.battery_electricity_demand", units="kW" + "system_level_controller.battery_electricity_set_point", units="kW" ) assert np.allclose(remaining_demand, battery_set_point, rtol=1e-6, atol=1e-8) @@ -94,7 +94,7 @@ def test_slc_yes_battery(subtests, temp_copy_of_example): "battery.electricity_out", units="kW" ) ng_set_point = model.prob.get_val( - "system_level_controller.natural_gas_plant_electricity_demand", units="kW" + "system_level_controller.natural_gas_plant_electricity_set_point", units="kW" ) expected_ng_set_point = np.clip( remaining_demand, diff --git a/h2integrate/converters/grid/grid.py b/h2integrate/converters/grid/grid.py index 2e4d33c7d..fee16ddc2 100644 --- a/h2integrate/converters/grid/grid.py +++ b/h2integrate/converters/grid/grid.py @@ -42,7 +42,7 @@ class GridPerformanceModel(PerformanceModelBaseClass): Inputs interconnection_size (float): Maximum power capacity for grid connection (kW). electricity_in (array): Power flowing into the grid (selling) (kW). - electricity_set_point (array): Downstream electricity set point (kW). + electricity_command_value (array): Downstream electricity command value (kW). Outputs electricity_out (array): Power flowing out of the grid (buying) (kW). @@ -86,13 +86,13 @@ def setup(self): desc="Electricity flowing into grid interconnection point (selling to grid)", ) - # Electricity set point from downstream (for buying from grid) + # Electricity command value from downstream (for buying from grid) self.add_input( - "electricity_set_point", + "electricity_command_value", val=0.0, shape=n_timesteps, units=self.commodity_rate_units, - desc="Electricity set point from downstream technologies", + desc="Electricity command value from downstream technologies", ) # electricity_out is electricity flowing OUT OF the grid (buying from grid) @@ -136,12 +136,14 @@ def compute(self, inputs, outputs): electricity_sold = np.clip(inputs["electricity_in"], 0, interconnection_size) outputs["electricity_sold"] = electricity_sold - # Buying: electricity flows out of grid to meet set point, limited by interconnection - electricity_bought = np.clip(inputs["electricity_set_point"], 0, interconnection_size) + # Buying: electricity flows out of grid to meet command value, limited by interconnection + electricity_bought = np.clip(inputs["electricity_command_value"], 0, interconnection_size) outputs["electricity_out"] = electricity_bought - # Unmet demand if set point exceeds interconnection size - outputs["electricity_unmet_demand"] = inputs["electricity_set_point"] - electricity_bought + # Unmet demand if command value exceeds interconnection size + outputs["electricity_unmet_demand"] = ( + inputs["electricity_command_value"] - electricity_bought + ) # Not sold electricity if demand exceeds interconnection size outputs["electricity_excess"] = inputs["electricity_in"] - electricity_sold diff --git a/h2integrate/converters/grid/test/test_grid.py b/h2integrate/converters/grid/test/test_grid.py index a66b9cb0d..80d908648 100644 --- a/h2integrate/converters/grid/test/test_grid.py +++ b/h2integrate/converters/grid/test/test_grid.py @@ -45,7 +45,7 @@ def test_grid_performance_outputs(plant_config, subtests): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("comp.electricity_set_point", demand) + prob.set_val("comp.electricity_command_value", demand) prob.run_model() @@ -148,7 +148,7 @@ def test_buying_electricity(plant_config, n_timesteps): # Set demand below interconnection limit demand = np.full(n_timesteps, 30000.0) # 30 MW demand - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -177,7 +177,7 @@ def test_buying_with_interconnection_limit(plant_config, n_timesteps): # Set demand above interconnection limit demand = np.full(n_timesteps, 60000.0) # 60 MW demand - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -247,7 +247,7 @@ def test_simultaneous_buy_and_sell(plant_config, n_timesteps): electricity_demand = np.full(n_timesteps, 40000.0) # 40 MW out prob.set_val("grid.electricity_in", electricity_in) - prob.set_val("grid.electricity_set_point", electricity_demand) + prob.set_val("grid.electricity_command_value", electricity_demand) prob.run_model() @@ -272,7 +272,7 @@ def test_varying_demand_profile(plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_set_point", demand) + prob.set_val("grid.electricity_command_value", demand) prob.run_model() @@ -302,7 +302,7 @@ def test_non_hourly_dt_demand_profile(subtests, plant_config, n_timesteps): # Create varying demand profile demand = np.array([10000, 20000, 30000, 50000, 70000, 90000, 110000, 80000, 60000, 40000]) - prob.set_val("grid.electricity_set_point", demand, units="kW") + prob.set_val("grid.electricity_command_value", demand, units="kW") prob.run_model() @@ -390,7 +390,7 @@ def test_grid_integration_dt_1800(subtests, tmp_path): h2i.setup() demand = np.full(n_timesteps, demand_kw) - h2i.prob.set_val("grid.electricity_demand", demand, units="kW") + h2i.prob.set_val("grid.electricity_set_point", demand, units="kW") h2i.prob.run_model() expected_out = np.full(n_timesteps, demand_kw) diff --git a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py index 94a5a50a2..84f5ffdc0 100644 --- a/h2integrate/converters/hydrogen/electrolyzer_baseclass.py +++ b/h2integrate/converters/hydrogen/electrolyzer_baseclass.py @@ -23,14 +23,14 @@ def setup(self): # Define inputs for electricity self.add_input("electricity_in", val=0.0, shape=self.n_timesteps, units="kW") - # Dispatchable models receive a set_point from the system-level controller + # Dispatchable models receive a command value from the system-level controller if "system_level_control" in self.options["plant_config"]: self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=0.0, shape=self.n_timesteps, units=self.commodity_rate_units, - desc=f"Set point for {self.commodity} production from SLC", + desc=f"Command value for {self.commodity} production from SLC", ) def compute(self, inputs, outputs): diff --git a/h2integrate/converters/hydrogen/h2_fuel_cell.py b/h2integrate/converters/hydrogen/h2_fuel_cell.py index 36d2c1a76..f6288386d 100644 --- a/h2integrate/converters/hydrogen/h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/h2_fuel_cell.py @@ -90,13 +90,13 @@ def setup(self): desc="Mass flow rate of hydrogen consumed by the fuel cell", ) - # Default the electricity set point input as the rated capacity + # Default the electricity command value input as the rated capacity self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_kw, shape=self.n_timesteps, units=self.commodity_rate_units, - desc="Electricity set point for natural gas plant", + desc="Electricity command value for natural gas plant", ) def compute(self, inputs, outputs): @@ -106,7 +106,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing hydrogen_in, fuel cell - HHV efficiency, electricity_set_point, and system_capacity. + HHV efficiency, electricity_command_value, and system_capacity. outputs: OpenMDAO outputs object for electricity_out, hydrogen_consumed. """ @@ -121,14 +121,14 @@ def compute(self, inputs, outputs): max_h2_consumption = system_capacity * kw_to_kgh_h2 - # electrical set point, saturated at maximum rated system capacity - electricity_set_point = np.where( - inputs["electricity_set_point"] > system_capacity, + # electrical command value, saturated at maximum rated system capacity + electricity_command_value = np.where( + inputs["electricity_command_value"] > system_capacity, system_capacity, - inputs["electricity_set_point"], + inputs["electricity_command_value"], ) - h2_demand = electricity_set_point * kw_to_kgh_h2 + h2_demand = electricity_command_value * kw_to_kgh_h2 # available feedstock, saturated at maximum system feedstock consumption h2_available = np.where( diff --git a/h2integrate/converters/hydrogen/pem_electrolyzer.py b/h2integrate/converters/hydrogen/pem_electrolyzer.py index 0c5aada06..5ca2a80e3 100644 --- a/h2integrate/converters/hydrogen/pem_electrolyzer.py +++ b/h2integrate/converters/hydrogen/pem_electrolyzer.py @@ -223,8 +223,8 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): "Annual O2 Production [kg/year]" ] - # Apply set_point from system-level controller if present + # Apply command_value from system-level controller if present if "system_level_control" in self.options["plant_config"]: - set_point = inputs[f"{self.commodity}_set_point"] + command_value = inputs[f"{self.commodity}_command_value"] commodity_out_key = f"{self.commodity}_out" - outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], set_point) + outputs[commodity_out_key] = np.minimum(outputs[commodity_out_key], command_value) diff --git a/h2integrate/converters/hydrogen/steam_methane_reformer.py b/h2integrate/converters/hydrogen/steam_methane_reformer.py index b469cbd8a..19a46c667 100644 --- a/h2integrate/converters/hydrogen/steam_methane_reformer.py +++ b/h2integrate/converters/hydrogen/steam_methane_reformer.py @@ -89,13 +89,13 @@ def setup(self): desc="SMR plant rated capacity in t/d", ) - # Default the hydrogen set point input as the rated capacity + # Hydrogen command value (set by upstream controller, default = rated capacity) self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_tonnes_per_day * (1000 / 24), # convert t/d to kg/h shape=n_timesteps, units=self.commodity_rate_units, - desc="Hydrogen set point for SMR plant", + desc="Hydrogen command value for SMR plant", ) # Add natural gas input, default to 0 --> set using feedstock component @@ -169,7 +169,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, natural_gas_usage_rate, electricity_usage_rate, - system_capacity, and hydrogen_set_point. + system_capacity, and hydrogen_command_value. outputs: OpenMDAO outputs object for hydrogen_out, natural_gas_consumed, electricity_consumed, and unmet_hydrogen_demand. """ @@ -183,14 +183,14 @@ def compute(self, inputs, outputs): electricity_usage_kWh_per_kg = inputs["electricity_usage_rate"] max_electricity_consumption = system_capacity_kg_per_hour * electricity_usage_kWh_per_kg - # hydrogen set point, saturated at maximum rated system capacity - hydrogen_set_point = np.where( - inputs["hydrogen_set_point"] > system_capacity_kg_per_hour, + # saturate the hydrogen command value at maximum rated system capacity + saturated_command_value = np.where( + inputs["hydrogen_command_value"] > system_capacity_kg_per_hour, system_capacity_kg_per_hour, - inputs["hydrogen_set_point"], + inputs["hydrogen_command_value"], ) - natural_gas_demand = hydrogen_set_point * natural_gas_usage_mmbtu_per_kg - electricity_demand = hydrogen_set_point * electricity_usage_kWh_per_kg + natural_gas_demand = saturated_command_value * natural_gas_usage_mmbtu_per_kg + electricity_demand = saturated_command_value * electricity_usage_kWh_per_kg # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -242,7 +242,7 @@ def compute(self, inputs, outputs): outputs["annual_hydrogen_produced"] = outputs["total_hydrogen_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_hydrogen_demand"] = inputs["hydrogen_set_point"] - hydrogen_out + outputs["unmet_hydrogen_demand"] = inputs["hydrogen_command_value"] - hydrogen_out outputs["total_energy_conversion_ratio"] = total_energy_conversion_ratio diff --git a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py index 2a49f9cbe..cfce4935d 100644 --- a/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py +++ b/h2integrate/converters/hydrogen/test/test_h2_fuel_cell.py @@ -160,7 +160,7 @@ def test_fuel_cell_demand(tech_config, plant_config, subtests): 0.0, # test case with set point equal to zero ) - prob.set_val("fuel_cell.electricity_set_point", elec_set_point, units="kW") + prob.set_val("fuel_cell.electricity_command_value", elec_set_point, units="kW") prob.run_model() diff --git a/h2integrate/converters/iron/iron_dri_base.py b/h2integrate/converters/iron/iron_dri_base.py index b9ac1348b..83ed3e817 100644 --- a/h2integrate/converters/iron/iron_dri_base.py +++ b/h2integrate/converters/iron/iron_dri_base.py @@ -76,13 +76,13 @@ def setup(self): desc=f"{feedstock} consumed for iron reduction", ) - # Default the sponge iron set point input as the rated capacity + # Default the sponge iron command value input as the rated capacity self.add_input( - "sponge_iron_set_point", + "sponge_iron_command_value", val=self.config.sponge_iron_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", - desc="Pig iron set point for iron plant", + desc="Pig iron command value for iron plant", ) coeff_fpath = ROOT_DIR / "converters" / "iron" / "rosner" / "perf_coeffs.csv" @@ -225,20 +225,20 @@ def compute(self, inputs, outputs): feedstocks["Name"] == "Reformer Catalyst" ]["Value"].sum() - # sponge iron set point, saturated at maximum rated system capacity - sponge_iron_set_point = np.where( - inputs["sponge_iron_set_point"] > inputs["system_capacity"], + # sponge iron command value, saturated at maximum rated system capacity + sponge_iron_command_value = np.where( + inputs["sponge_iron_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["sponge_iron_set_point"], + inputs["sponge_iron_command_value"], ) # initialize an array of how much sponge iron could be produced - # from the available feedstocks and the set point + # from the available feedstocks and the command value sponge_iron_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_set_point"])) + (len(feedstocks_usage_rates) + 1, len(inputs["sponge_iron_command_value"])) ) - # first entry is the sponge iron set point - sponge_iron_from_feedstocks[0] = sponge_iron_set_point + # first entry is the sponge iron command value + sponge_iron_from_feedstocks[0] = sponge_iron_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/converters/iron/martin_mine_perf_model.py b/h2integrate/converters/iron/martin_mine_perf_model.py index b5084de4a..404fb9cab 100644 --- a/h2integrate/converters/iron/martin_mine_perf_model.py +++ b/h2integrate/converters/iron/martin_mine_perf_model.py @@ -77,13 +77,13 @@ def setup(self): desc="Crude ore input", ) - # Default the ore set point input as the rated capacity + # Default the ore command value input as the rated capacity self.add_input( - "iron_ore_set_point", + "iron_ore_command_value", val=self.config.max_ore_production_rate_tonnes_per_hr, shape=n_timesteps, units="t/h", - desc="Iron ore set point for iron mine", + desc="Iron ore command value for iron mine", ) self.add_output( @@ -203,11 +203,11 @@ def compute(self, inputs, outputs): max_crude_ore_consumption = inputs["system_capacity"] * crude_ore_usage_per_processed_ore max_energy_consumption = inputs["system_capacity"] * energy_usage_per_processed_ore - # iron ore set point, saturated at maximum rated system capacity - processed_ore_set_point = np.where( - inputs["iron_ore_set_point"] > inputs["system_capacity"], + # iron ore command value, saturated at maximum rated system capacity + processed_ore_command_value = np.where( + inputs["iron_ore_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["iron_ore_set_point"], + inputs["iron_ore_command_value"], ) # available feedstocks, saturated at maximum system feedstock consumption @@ -227,9 +227,13 @@ def compute(self, inputs, outputs): processed_ore_from_electricity = energy_available / energy_usage_per_processed_ore processed_ore_from_crude_ore = crude_ore_available / crude_ore_usage_per_processed_ore - # output is minimum between available feedstocks and output set point + # output is minimum between available feedstocks and output command value processed_ore_production = np.minimum.reduce( - [processed_ore_from_crude_ore, processed_ore_from_electricity, processed_ore_set_point] + [ + processed_ore_from_crude_ore, + processed_ore_from_electricity, + processed_ore_command_value, + ] ) # energy consumption diff --git a/h2integrate/converters/iron/test/test_martin_mine.py b/h2integrate/converters/iron/test/test_martin_mine.py index a1865eb4d..052a51179 100644 --- a/h2integrate/converters/iron/test/test_martin_mine.py +++ b/h2integrate/converters/iron/test/test_martin_mine.py @@ -41,7 +41,7 @@ def test_iron_mine_performance_outputs( prob.set_val("comp.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("comp.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("comp.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("comp.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() commodity = "iron_ore" @@ -152,7 +152,7 @@ def test_baseline_iron_ore_costs(plant_config, driver_config, iron_ore_config_ma prob.set_val("ore_perf.electricity_in", [annual_electricity / 8760] * 8760, units="kW") prob.set_val("ore_perf.crude_ore_in", [annual_crude_ore / 8760] * 8760, units="t/h") - prob.set_val("ore_perf.iron_ore_set_point", [ore_rated_capacity] * 8760, units="t/h") + prob.set_val("ore_perf.iron_ore_command_value", [ore_rated_capacity] * 8760, units="t/h") prob.run_model() diff --git a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py index 21bb091ff..ff540f950 100644 --- a/h2integrate/converters/natural_gas/natural_gas_cc_ct.py +++ b/h2integrate/converters/natural_gas/natural_gas_cc_ct.py @@ -48,7 +48,7 @@ class NaturalGasPerformanceModel(PerformanceModelBaseClass): system_capacity (float): Natural gas plant rated capacity in MW natural_gas_in (array): Natural gas input energy in MMBtu/h heat_rate_mmbtu_per_mwh (float): Plant heat rate in MMBtu/MWh - electricity_set_point (array): Electricity set point in MW for each timestep + electricity_command_value (array): Electricity command value in MW for each timestep Outputs: electricity_out (array): Electricity output in MW for each timestep @@ -102,13 +102,13 @@ def setup(self): desc="Natural gas plant rated capacity in MW", ) - # Default the electricity set point input as the rated capacity + # Default the electricity command value input as the rated capacity self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_mw, shape=n_timesteps, units=self.commodity_rate_units, - desc="Electricity set point for natural gas plant", + desc="Electricity command value for natural gas plant", ) # Add natural gas input, default to 0 --> set using feedstock component @@ -138,7 +138,7 @@ def compute(self, inputs, outputs): Args: inputs: OpenMDAO inputs object containing natural_gas_in, heat_rate_mmbtu_per_mwh, - system_capacity, and electricity_set_point. + system_capacity, and electricity_command_value. outputs: OpenMDAO outputs object for electricity_out, natural_gas_consumed, and unmet_electricity_demand. """ @@ -148,13 +148,13 @@ def compute(self, inputs, outputs): heat_rate_mmbtu_per_mwh = inputs["heat_rate_mmbtu_per_mwh"] max_natural_gas_consumption = system_capacity * heat_rate_mmbtu_per_mwh - # electrical set point, saturated at maximum rated system capacity - electricity_set_point = np.where( - inputs["electricity_set_point"] > system_capacity, + # electrical command value, saturated at maximum rated system capacity + electricity_command_value = np.where( + inputs["electricity_command_value"] > system_capacity, system_capacity, - inputs["electricity_set_point"], + inputs["electricity_command_value"], ) - natural_gas_demand = electricity_set_point * heat_rate_mmbtu_per_mwh + natural_gas_demand = electricity_command_value * heat_rate_mmbtu_per_mwh # available feedstock, saturated at maximum system feedstock consumption natural_gas_available = np.where( @@ -181,7 +181,7 @@ def compute(self, inputs, outputs): outputs["annual_electricity_produced"] = outputs["total_electricity_produced"] * ( 1 / self.fraction_of_year_simulated ) - outputs["unmet_electricity_demand"] = inputs["electricity_set_point"] - electricity_out + outputs["unmet_electricity_demand"] = inputs["electricity_command_value"] - electricity_out @define(kw_only=True) diff --git a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py index 0027989a9..3fd3b079b 100644 --- a/h2integrate/converters/natural_gas/test/test_natural_gas_models.py +++ b/h2integrate/converters/natural_gas/test/test_natural_gas_models.py @@ -375,7 +375,7 @@ def test_ngcc_performance_demand(plant_config, ngcc_performance_params, subtests # Set the natural gas input prob.set_val("natural_gas_in", natural_gas_input) - prob.set_val("electricity_set_point", electricity_demand_MW) + prob.set_val("electricity_command_value", electricity_demand_MW) prob.run_model() electricity_out = prob.get_val("electricity_out", units="MW") diff --git a/h2integrate/converters/nuclear/nuclear_plant.py b/h2integrate/converters/nuclear/nuclear_plant.py index 836d9ce52..d137cf373 100644 --- a/h2integrate/converters/nuclear/nuclear_plant.py +++ b/h2integrate/converters/nuclear/nuclear_plant.py @@ -61,18 +61,18 @@ def setup(self): desc="Nuclear plant rated capacity", ) self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=self.config.system_capacity_kw, shape=n_timesteps, units=self.commodity_rate_units, - desc="Electricity set point for nuclear plant", + desc="Electricity command value for nuclear plant", ) def compute(self, inputs, outputs): system_capacity = inputs["system_capacity"] - electricity_set_point = inputs[f"{self.commodity}_set_point"] + electricity_command_value = inputs[f"{self.commodity}_command_value"] - electricity_out = np.minimum(electricity_set_point, system_capacity) + electricity_out = np.minimum(electricity_command_value, system_capacity) electricity_out = np.clip(electricity_out, 0.0, system_capacity) outputs["electricity_out"] = electricity_out diff --git a/h2integrate/converters/nuclear/test/test_nuclear_plant.py b/h2integrate/converters/nuclear/test/test_nuclear_plant.py index 6c143693e..7f6221512 100644 --- a/h2integrate/converters/nuclear/test/test_nuclear_plant.py +++ b/h2integrate/converters/nuclear/test/test_nuclear_plant.py @@ -64,7 +64,7 @@ def test_nuclear_performance_demand(plant_config, nuclear_performance_params, su prob.model.add_subsystem("nuc_perf", perf_comp, promotes=["*"]) prob.setup() - prob.set_val("electricity_set_point", electricity_demand) + prob.set_val("electricity_command_value", electricity_demand) prob.run_model() electricity_out = prob.get_val("electricity_out") diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py index bcdb78223..0c5ab9764 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_dri.py @@ -178,15 +178,15 @@ def setup(self): desc="Actual steel production", ) - # Default the steel demand input as the production rate + # Default the steel command value input as the production rate self.add_input( - "steel_set_point", + "steel_command_value", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), shape=n_timesteps, units=self.commodity_rate_units, - desc="Steel demand for steel plant", + desc="Steel command value for steel plant", ) self.add_input( @@ -327,20 +327,20 @@ def compute(self, inputs, outputs): "lime": energy_mass_per_tonne["burnt_lime_per_tLS"], # t/t } - # steel demand, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > system_production, + # steel command value, saturated at maximum rated system capacity + steel_command_value = np.where( + inputs["steel_command_value"] > system_production, system_production, - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced - # from the available feedstocks and the demand + # from the available feedstocks and the command value steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) ) - # first entry is the steel demand - steel_from_feedstocks[0] = steel_set_point + # first entry is the steel command value + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py index a6ed8debe..dcacda28c 100644 --- a/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py +++ b/h2integrate/converters/steel/cmu_electric_arc_furnace_scrap.py @@ -140,15 +140,15 @@ def setup(self): desc="Actual steel production", ) - # Default the steel demand input as the production rate + # Default the steel command value input as the production rate self.add_input( - "steel_set_point", + "steel_command_value", val=units.convert_units( self.config.steel_production_rate_tonnes_per_year, "t/year", "t/h" ), shape=n_timesteps, units=self.commodity_rate_units, - desc="Steel demand for steel plant", + desc="Steel command value for steel plant", ) feedstocks_to_units = { @@ -259,20 +259,20 @@ def compute(self, inputs, outputs): "lime": energy_mass_per_tonne["burnt_lime_per_tLS"], # t/t } - # steel demand, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > system_production, + # steel command value, saturated at maximum rated system capacity + steel_command_value = np.where( + inputs["steel_command_value"] > system_production, system_production, - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced - # from the available feedstocks and the demand + # from the available feedstocks and the command value steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_per_tonne_steel) + 1, len(inputs["steel_command_value"])) ) - # first entry is the steel demand - steel_from_feedstocks[0] = steel_set_point + # first entry is the steel command value + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_per_tonne_steel.items(): diff --git a/h2integrate/converters/steel/steel_eaf_base.py b/h2integrate/converters/steel/steel_eaf_base.py index 8fdd9e131..6a8658912 100644 --- a/h2integrate/converters/steel/steel_eaf_base.py +++ b/h2integrate/converters/steel/steel_eaf_base.py @@ -77,13 +77,13 @@ def setup(self): desc=f"{feedstock} consumed for steel production", ) - # Default the steel set point input as the rated capacity + # Default the steel command value input as the rated capacity self.add_input( - "steel_set_point", + "steel_command_value", val=self.config.steel_production_rate_tonnes_per_hr, shape=n_timesteps, units=self.commodity_rate_units, - desc="Steel set point for steel plant", + desc="Steel command value for steel plant", ) coeff_fpath = ROOT_DIR / "converters" / "iron" / "rosner" / "perf_coeffs.csv" @@ -231,20 +231,20 @@ def compute(self, inputs, outputs): "Value" ].sum() # t/t - # steel set point, saturated at maximum rated system capacity - steel_set_point = np.where( - inputs["steel_set_point"] > inputs["system_capacity"], + # steel command value, saturated at maximum rated system capacity + steel_command_value = np.where( + inputs["steel_command_value"] > inputs["system_capacity"], inputs["system_capacity"], - inputs["steel_set_point"], + inputs["steel_command_value"], ) # initialize an array of how much steel could be produced - # from the available feedstocks and the set point + # from the available feedstocks and the command value steel_from_feedstocks = np.zeros( - (len(feedstocks_usage_rates) + 1, len(inputs["steel_set_point"])) + (len(feedstocks_usage_rates) + 1, len(inputs["steel_command_value"])) ) - # first entry is the steel set point - steel_from_feedstocks[0] = steel_set_point + # first entry is the steel command value + steel_from_feedstocks[0] = steel_command_value ii = 1 for feedstock_type, consumption_rate in feedstocks_usage_rates.items(): # calculate max inputs/outputs based on rated capacity diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 5ed23e539..2a79ec7cc 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -637,11 +637,11 @@ def add_system_level_controller(self, slc_config): - **Flexible / dispatchable / storage techs**: Both the commodity output (``{tech_name}.{commodity}_out``) and rated production (``{tech_name}.rated_{commodity}_production``) are connected as controller inputs. - The controller's per-tech ``{tech_name}_{commodity}_demand`` output is then - connected to the tech group's ``{commodity}_demand`` input. Every controlled + The controller's per-tech ``{tech_name}_{commodity}_set_point`` output is then + connected to the tech group's ``{commodity}_set_point`` input. Every controlled tech group is expected to expose this input — either via a user-defined ``control_strategy`` or via the auto-injected ``PassthroughController`` — which - converts the demand signal into the appropriate performance-model set-point. + converts the set-point signal into the appropriate performance-model command value. 4. **Connect marginal-cost inputs for cost-aware strategies** - Only executed when ``control_strategy`` is ``"CostMinimizationControl"`` or @@ -759,13 +759,13 @@ def add_system_level_controller(self, slc_config): f"system_level_controller.{tech_name}_{commodity}_storage_duration", ) - # Every controlled tech group exposes a ``{commodity}_demand`` + # Every controlled tech group exposes a ``{commodity}_set_point`` # input (provided by either a user-defined control_strategy or an # auto-injected PassthroughController). Route the SLC's per-tech - # demand output to that input. + # set-point output to that input. self.plant.connect( - f"system_level_controller.{tech_name}_{commodity}_demand", - f"{tech_name}.{commodity}_demand", + f"system_level_controller.{tech_name}_{commodity}_set_point", + f"{tech_name}.{commodity}_set_point", ) # --- Step 4: Connect marginal-cost inputs (cost-aware strategies) - @@ -1055,10 +1055,10 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con attributes (typically set in its ``initialize()``), or those values can be read from the individual tech config. - The controller's ``{commodity}_demand`` input becomes the tech group's - external demand-input promoted at the tech group level, and its - ``{commodity}_set_point`` output is auto-connected (via promotion) to the - performance model's ``{commodity}_set_point`` input if one exists. + The controller's ``{commodity}_set_point`` input becomes the tech group's + external set-point-input promoted at the tech group level, and its + ``{commodity}_command_value`` output is auto-connected (via promotion) to the + performance model's ``{commodity}_command_value`` input if one exists. """ # Skip if the user has already specified a control strategy for this tech; # their explicit choice takes precedence over the auto-injected passthrough. @@ -1103,17 +1103,17 @@ def _add_passthrough_controller(self, tech_group, perf_comp, individual_tech_con ) # Promote all controller variables so: - # - `{commodity}_demand` becomes the tech group's external input + # - `{commodity}_set_point` becomes the tech group's external input # (this is what the system-level controller connects to), and - # - `{commodity}_set_point` is auto-connected by name to the + # - `{commodity}_command_value` is auto-connected by name to the # performance model's matching input via promotion. om_controller = tech_group.add_subsystem("controller", controller, promotes=["*"]) self.control_strategies.append(om_controller) # Ensure the controller runs before the performance/cost models that - # consume its set_point output. Subsystem creation order otherwise + # consume its command_value output. Subsystem creation order otherwise # places the controller last in the group's execution order, which - # would delay the set_point by one solver iteration. + # would delay the command_value by one solver iteration. existing_order = list(tech_group._static_subsystems_allprocs.keys()) if "controller" in existing_order: new_order = ["controller"] + [n for n in existing_order if n != "controller"] diff --git a/h2integrate/core/model_baseclasses.py b/h2integrate/core/model_baseclasses.py index ac2f34dfc..183dab9d1 100644 --- a/h2integrate/core/model_baseclasses.py +++ b/h2integrate/core/model_baseclasses.py @@ -99,14 +99,14 @@ def setup(self): # operational life of the technology if the technology cannot be replaced self.add_output("operational_life", val=self.plant_life, units="yr") - # Flexible models get additional I/O for set_point-based curtailment + # Flexible models get additional I/O for command-value-based curtailment if getattr(self, "_control_classifier", None) == "flexible": self.add_input( - f"{self.commodity}_set_point", + f"{self.commodity}_command_value", val=1.0, shape=self.n_timesteps, units=self.commodity_rate_units, - desc=f"Set point for {self.commodity} production (curtailment limit)", + desc=f"Command value for {self.commodity} production (curtailment limit)", ) self.add_output( f"uncurtailed_{self.commodity}_out", @@ -117,10 +117,10 @@ def setup(self): ) def apply_curtailment(self, outputs): - """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_set_point``. + """Apply curtailment to ``{commodity}_out`` based on ``{commodity}_command_value``. Copies the current ``{commodity}_out`` into ``uncurtailed_{commodity}_out``, - then clips ``{commodity}_out`` to ``min(uncurtailed, set_point)`` element-wise. + then clips ``{commodity}_out`` to ``min(uncurtailed, command_value)`` element-wise. Only operates when the model has ``_control_classifier == "flexible"``. Should be called at the end of each flexible model's ``compute()`` method @@ -132,13 +132,13 @@ def apply_curtailment(self, outputs): commodity_out_key = f"{self.commodity}_out" uncurtailed_key = f"uncurtailed_{self.commodity}_out" - set_point_key = f"{self.commodity}_set_point" + command_value_key = f"{self.commodity}_command_value" uncurtailed = np.array(outputs[commodity_out_key]) outputs[uncurtailed_key] = uncurtailed - set_point = self._inputs[set_point_key] - outputs[commodity_out_key] = np.minimum(uncurtailed, set_point) + command_value = self._inputs[command_value_key] + outputs[commodity_out_key] = np.minimum(uncurtailed, command_value) def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """ diff --git a/h2integrate/core/test/test_framework.py b/h2integrate/core/test/test_framework.py index 85f3ab748..1dd348bd5 100644 --- a/h2integrate/core/test/test_framework.py +++ b/h2integrate/core/test/test_framework.py @@ -455,7 +455,7 @@ def test_technology_connections(temp_dir): h2i_model = H2IntegrateModel(temp_highlevel_yaml) demand_profile = np.ones(8760) * 720.0 h2i_model.setup() - h2i_model.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + h2i_model.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") h2i_model.run() diff --git a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py index 14a4dbaf3..318f2351d 100644 --- a/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py +++ b/h2integrate/postprocess/test/test_sql_timeseries_to_csv.py @@ -42,7 +42,7 @@ def run_example_02_sql_fpath(configuration): # Set the battery demand profile demand_profile = np.ones(8760) * 640.0 h2i.setup() - h2i.prob.set_val("battery.electricity_demand", demand_profile, units="MW") + h2i.prob.set_val("battery.electricity_set_point", demand_profile, units="MW") # Run the model h2i.run() diff --git a/h2integrate/storage/battery/test/test_pysam_battery.py b/h2integrate/storage/battery/test/test_pysam_battery.py index aecaedb8c..e6334f28e 100644 --- a/h2integrate/storage/battery/test/test_pysam_battery.py +++ b/h2integrate/storage/battery/test/test_pysam_battery.py @@ -57,14 +57,14 @@ def test_pysam_battery_performance_model_without_controller(plant_config, subtes prob.model.add_subsystem( name="IVC3", - subsys=om.IndepVarComp(name="electricity_demand", val=electricity_demand, units="kW"), + subsys=om.IndepVarComp(name="electricity_set_point", val=electricity_demand, units="kW"), promotes=["*"], ) prob.model.add_subsystem( name="IVC4", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -338,7 +338,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob_init = om.Problem() prob_init.model.add_subsystem( name="IVC1", - subsys=om.IndepVarComp(name="electricity_demand", val=electricity_demand, units="kW"), + subsys=om.IndepVarComp(name="electricity_set_point", val=electricity_demand, units="kW"), promotes=["*"], ) @@ -351,7 +351,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob_init.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) @@ -406,7 +406,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob = om.Problem() prob.model.add_subsystem( name="IVC1", - subsys=om.IndepVarComp(name="electricity_demand", val=electricity_demand, units="kW"), + subsys=om.IndepVarComp(name="electricity_set_point", val=electricity_demand, units="kW"), promotes=["*"], ) @@ -419,7 +419,7 @@ def test_pysam_battery_no_controller_change_capacity(plant_config, subtests): prob.model.add_subsystem( name="IVC3", subsys=om.IndepVarComp( - name="electricity_set_point", val=electricity_demand - electricity_in, units="kW" + name="electricity_command_value", val=electricity_demand - electricity_in, units="kW" ), promotes=["*"], ) diff --git a/h2integrate/storage/simple_storage_auto_sizing.py b/h2integrate/storage/simple_storage_auto_sizing.py index 9dc579990..785bf3b59 100644 --- a/h2integrate/storage/simple_storage_auto_sizing.py +++ b/h2integrate/storage/simple_storage_auto_sizing.py @@ -170,9 +170,9 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): 1) Calculate the max charge and discharge rate as the maximum of the `commodity_in` profile and oversize to account for charge/discharge efficiencies. 2) Estimate the storage SOC (in `commodity_amount_units`). The SOC increases when - charging and decreases when discharging. If `commodity_set_point` is input, + charging and decreases when discharging. If `commodity_command_value` is input, calculate the storage SOC as the cumulative summation of the negative of - `commodity_set_point` input (`commodity_set_point` input is + `commodity_command_value` input (`commodity_command_value` input is negative when charging and positive when discharging). Otherwise, calculate the storage SOC as the cumulative summation of `commodity_in - demand`. @@ -207,6 +207,8 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): commodity_demand = np.mean(inputs[f"{self.commodity}_in"]) * np.ones(self.n_timesteps) + elif self.using_feedback_control: + commodity_demand = inputs[f"{self.commodity}_set_point"] else: commodity_demand = inputs[f"{self.commodity}_demand"] @@ -219,11 +221,11 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): # Auto-size the storage capacity to meet the demand as much as possible # 2. Estimate the storage SOC in `commodity_amount_units` # NOTE: commodity_storage_soc is just an absolute value and is not a percentage. - if f"{self.commodity}_set_point" in inputs: - # `{self.commodity}_set_point` is negative when charging and positive when - # discharging, the negative of `{self.commodity}_set_point` can be used to + if f"{self.commodity}_command_value" in inputs: + # `{self.commodity}_command_value` is negative when charging and positive when + # discharging, the negative of `{self.commodity}_command_value` can be used to # estimate the SOC (which increases when charging and decreases when discharging) - commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_set_point"]) + commodity_storage_soc = np.cumsum(-1 * inputs[f"{self.commodity}_command_value"]) else: # estimate the SOC (which increases when charging and decreases when discharging) # based on the demand profile and the input commodity @@ -263,7 +265,7 @@ def compute(self, inputs, outputs, discrete_inputs=[], discrete_outputs=[]): # (such as demand profile, charge rate, and storage capacity) inputs_adjusted = dict(inputs.items()) if self.config.set_demand_as_avg_commodity_in: - inputs_adjusted[f"{self.commodity}_demand"] = commodity_demand + inputs_adjusted[f"{self.commodity}_set_point"] = commodity_demand if "pyomo_dispatch_solver" in discrete_inputs: inputs_adjusted["storage_capacity"] = np.array([rated_storage_capacity]) diff --git a/h2integrate/storage/storage_baseclass.py b/h2integrate/storage/storage_baseclass.py index e1580cf67..aa2e8e456 100644 --- a/h2integrate/storage/storage_baseclass.py +++ b/h2integrate/storage/storage_baseclass.py @@ -166,21 +166,21 @@ def setup(self): ]: if any(intended_dispatch_tech == name for name in self.tech_group_name): self.add_input( - f"{commodity}_demand", + f"{commodity}_set_point", val=self.config.demand_profile, shape=n_timesteps, units=commodity_rate_units, - desc=f"{commodity} demand profile", + desc=f"{commodity} set-point profile", ) self.add_discrete_input("pyomo_dispatch_solver", val=lambda: None) - # the controller gets demand from the storage model + # the controller gets set-point from the storage model # set the using feedback control variable to True using_feedback_control = True break if not using_feedback_control: # using an open-loop storage controller self.add_input( - f"{commodity}_set_point", + f"{commodity}_command_value", val=0.0, shape=n_timesteps, units=commodity_rate_units, @@ -274,7 +274,7 @@ def run_storage( else: storage_commodity_out, soc = self.simulate( - storage_dispatch_commands=inputs[f"{self.commodity}_set_point"], + storage_dispatch_commands=inputs[f"{self.commodity}_command_value"], charge_rate=charge_rate, discharge_rate=discharge_rate, storage_capacity=storage_capacity, diff --git a/h2integrate/storage/test/test_storage_auto_sizing.py b/h2integrate/storage/test/test_storage_auto_sizing.py index 3fa782f2c..077f0ee84 100644 --- a/h2integrate/storage/test/test_storage_auto_sizing.py +++ b/h2integrate/storage/test/test_storage_auto_sizing.py @@ -41,7 +41,7 @@ def test_storage_autosizing_basic_performance_no_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -228,7 +228,7 @@ def test_storage_autosizing_soc_bounds(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) @@ -335,7 +335,7 @@ def test_storage_autosizing_losses(plant_config, subtests): prob.model.add_subsystem( name="IVC2", subsys=om.IndepVarComp( - name="hydrogen_set_point", val=commodity_demand - commodity_in, units="kg/h" + name="hydrogen_command_value", val=commodity_demand - commodity_in, units="kg/h" ), promotes=["*"], ) diff --git a/h2integrate/storage/test/test_storage_performance_model.py b/h2integrate/storage/test/test_storage_performance_model.py index 2ad903400..86b52925e 100644 --- a/h2integrate/storage/test/test_storage_performance_model.py +++ b/h2integrate/storage/test/test_storage_performance_model.py @@ -45,7 +45,7 @@ def test_generic_storage_with_simple_control_dmd_lessthan_charge_rate(plant_conf prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -239,7 +239,7 @@ def test_generic_storage_with_simple_control_charge_rate_lessthan_demand(plant_c prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -456,7 +456,7 @@ def test_generic_storage_with_simple_control_zero_size(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -637,7 +637,7 @@ def test_generic_storage_with_simple_control_with_losses(plant_config, subtests) prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -876,7 +876,7 @@ def test_generic_storage_with_simple_control_with_losses_round_trip(plant_config prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) @@ -1080,13 +1080,13 @@ def test_generic_storage_charge_more_than_available(plant_config, subtests): prob.model.add_subsystem( name="IVC2", - subsys=om.IndepVarComp(name="hydrogen_demand", val=commodity_demand, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_set_point", val=commodity_demand, units="kg/h"), promotes=["*"], ) prob.model.add_subsystem( name="IVC3", - subsys=om.IndepVarComp(name="hydrogen_set_point", val=nominal_set_point, units="kg/h"), + subsys=om.IndepVarComp(name="hydrogen_command_value", val=nominal_set_point, units="kg/h"), promotes=["*"], ) @@ -1275,7 +1275,7 @@ def test_storage_half_hourly_known_outputs(subtests, plant_config_non_hourly): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/h"), + om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/h"), promotes=["*"], ) prob.model.add_subsystem( @@ -1378,7 +1378,7 @@ def test_storage_half_hourly_known_outputs_kg_s(subtests, plant_config_non_hourl ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("hydrogen_set_point", val=set_point, units="kg/s"), + om.IndepVarComp("hydrogen_command_value", val=set_point, units="kg/s"), promotes=["*"], ) prob.model.add_subsystem( @@ -1468,7 +1468,7 @@ def test_storage_half_hourly_kw_kwh_2hr(subtests): ) prob.model.add_subsystem( "IVC2", - om.IndepVarComp("electricity_set_point", val=set_point, units="kW"), + om.IndepVarComp("electricity_command_value", val=set_point, units="kW"), promotes=["*"], ) prob.model.add_subsystem( From 754fca6e5903ee2e9c540581a3417bd373efa520 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 11 Jun 2026 07:02:33 -0500 Subject: [PATCH 129/132] doc figures update --- .../figures/curtailable.png | Bin 149068 -> 0 bytes .../figures/dispatchable.png | Bin 123613 -> 156428 bytes .../system_level_control/figures/flexible.png | Bin 0 -> 180539 bytes .../figures/slc_basic.png | Bin 109323 -> 166066 bytes .../system_level_control/figures/storage.png | Bin 290437 -> 170580 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/control/system_level_control/figures/curtailable.png create mode 100644 docs/control/system_level_control/figures/flexible.png diff --git a/docs/control/system_level_control/figures/curtailable.png b/docs/control/system_level_control/figures/curtailable.png deleted file mode 100644 index c62a49726e2e1e0f7b5cd4533b09a182d73dacf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149068 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

menvDC3oMVE}!$IgKt4FIq{&i$(}R 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 diff --git a/docs/control/system_level_control/figures/dispatchable.png b/docs/control/system_level_control/figures/dispatchable.png index d0441a611a8a0eb48ad10e22a8e12b3a1d76d8a9..d0968c77787fea16e3c9b3aca42c0f2f28c93181 100644 GIT binary patch literal 156428 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ૢIawv7xiG@on( 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%0Aa>@iNK}#(&Jw^ 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≉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 A1^@s6 literal 123613 zcmeFZc|4Tu`!_BTn+GcExiyTDfs&a;%Fg$cla{&2OveA~o?MH(1$ zvas(u#Ik$)7T^!dEn4}hlbn#?0oLd z+x26{Jl5}bvt#pie;>1TZa?RehPnfM?7eg82AGBA_vY=tyH4M-8DU}3Wx0Iu+_lhM z-^Mr^Pv~W{OxRclIHYEQ51x2w;d|IHrPsABt4$91;W zb57#R$i=gEpHBW*)7q2fcTItBms0+j#au0_Zhp{d@#KG4Gq0TZruLWjrDor!|Mk8q z-h&Zk_HZx7f2Y^D^6munB3Fa5Fi+24gd%sIc`k>;XG5e>NJM;cBhzi@wiNutks#142|I0x7Aix8b8+`vxgt@}5 zcjU13n!!WAOuDmFcGhSjpLj|1FH`QwYyPD8rb8KH(B{YLfBu;lx&Q-NZ(aXR$j)D-_UQOH!WsCT^WDc!rxb8M;B?opNR zEA{#sNuAkC(9QBdGlpoy+UFbj4QX$GaYcESfCs9Y_l-Z<QSc~7O6 z->WQ(KL zkM?A#592E|lCg10*?em`H@sAez?b>z>3A*uwnyf=)xrxOF0`82uy;Hk$EraHR&^|(dpE%d z1yT`#Zk&u>7TG&U%`0ytwgvb$4OHcP-vM`ZL$)Ka=~7G9r{|p-_FJ08(DB+*te5jm z6de2p0%>mJPY&qJzF$lFz|6uOVW`^};(5f)%bUYwq|Ib)!?8;c_5AzCJwAY{bHyx)a@MTtg*%<|0V z4u!`kV-9k2`PD8U1J`}da3GTF)Xijg<4nwKL!&CUe(&q8hWI?@BPH9rdgRcWw(ivs zllbkO7=a&)1yV(>Qh�R>8PfehPYofM{(vu=4r+UO&A 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�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 diff --git a/docs/control/system_level_control/figures/flexible.png b/docs/control/system_level_control/figures/flexible.png new file mode 100644 index 0000000000000000000000000000000000000000..052a43d7a285dda761d74b52ee96563738b92d0b GIT binary patch literal 180539 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 Iw=vCyE!%sWX+OJ+#;VG|X=f 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 Nh3l%au&XAI{|`u}7}Nj& literal 109323 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ț<^?zrY{7vA0wyQt=*8>FrokUq1|KVk3 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 kfbm`1OL8rn}D;=8Q5yVhIC=SG^gGj|*6h$tiz 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 diff --git a/docs/control/system_level_control/figures/storage.png b/docs/control/system_level_control/figures/storage.png index 421982d26f93bbe3a96c8cdbb78724625d4ef7e4..c71e10e5d898ebe4d74865702a803ee93f83b3fe 100644 GIT binary patch literal 170580 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]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 literal 290437 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

ydI~b5-#O$l#GI&Jbl`OQ zACCTA8|gpgzLeVa-35M{*P*ZQ>(@6pDgL2g&=Q7My*YNizb`3QtNYcw&{AdVEd&W< zH7bVmYq}vp9}{j1jP_}?&t7a^u-57s6~aM#((4lyQR2%M*4@%(q{Yo@LH&#6z{>k*(BrBlF2eIe!; zWC;#36lg406Pne~{Gjmj=hk8(X6>W;M?KmYopA%hSj7?r!;dj5-5t#k&|%xqT|Ym)$K0zXq2O}x z@aIkb^O+S$3O(HQW5?JD0e-xO_mh0HW67z_S8Nc6Q*yL9fm(kp_wV$0n}8_6`$ne& z$g};EW``c~h;wzYR9$#qx)o`ET;`^cb-qacFY6Ca-TLm*BphhH>m{&l&ioE@PcTbI zIASBgM*HxH`LS2mA2JipZ-;E|9=Ghe-8M+Dgx!uN$1g&$VU>_RoaVgF0S(MKW-9{&;X9? z2SEj5^CLG3*X7e`%I72laL+Bu)@?vw|DE6x|C1w6ujEdMFNg(@2I(BMu`(zLJ zKMMCLu8-HTxpaiWA8yN}aB`-Kc&(Sl_hplke%-T%{qS*+YsvN8n;}(0zC{U8HTxp3 zpMYb%vYxsF_tRlyBy+u8o0jll4>|Y}seqO9z(vVzjq{6w3$qcPWG=y6cF5iROo)Hf zGw0SglCMz?^X9-}^Ut^M+q!&&SFlWNN)f@1{mBT+I4-YdpcUcyh#Y8=V)rl!>0!}YXRdz)k)ELX~0|C5~@5CvA8KjIj)Ey6z0;*eETTtN-y zCN*AC0QC))MZVu11M|!lQNWosKE?)_eqoxAlzXBEn8w-u_V<99{73x#_UozBVfc&d zPlrJb*(xJ|qj5@~11JF{_q^`)#Y_E(L3DOOXWKpQ9@`ew_bz2}bqDBxfXv6a1ZSRe;>iLrq7=JdR`|_sNd$(4h3H;Nm;nNpIyGa}%mAK}$!P92Tn`7KLf-*bzrsPG%u4uK7ZrUS`=fSH#DH@?4GJ(-PWeMk#wdDD|^& z@3$%)YM13TS?m6s%0~mm-D3K@p3U0SwwiHb2A~SPPi_l7?_7MEDER!!y9f6__X6l7 zp&=r1KN*$>5XVArLD|0-oj1+KL+2`{AqanHu`TtSusi^jel`AR+d`y<%~#6 zfrC%_W*@6?(<}}k{b6VDA;Ph?@dm1AZQY(6|3vI(8=P@sq2XPJw%Pc9H%Ff0L8`oK zO~51XRCga0L7FZojep{4-}~vC(-{}vvem~n}Aso3z?ilKwQ7l z^>%sbiMUdu4{=!cN_<&iP5b`(1L)fqS^KPBZYmk$;jwZf^SGI}M#O^!M1kk=OBOr5 z?3z75v+Uz0P}@{Ai7-{BOo2SD|9^iB0dxP(L^}*yQCR&!^f;YI3 zec6+@bILWb*Os{Wz3cotkQWEnK}}OhrZY~$OL{-VJuZt_d?0w6tnvy78yPwcED!~n zWBQ(!J=VM5V{Cd(aXqc#!K`{i+~CoI0-5ApE(x;PWo?V+iizSG5BRr0^zl(zsuKV6 z_V=!1h(ma{Gs~lgW;7}pW~P^L(_SCBo zV@*V#V}{3Nb-fy#rS%r$HcY0X5JMt&_|P}8p~Lz!u5QRyb|EsK&Ocp$+<=UY{15rO z&qA~oRvJEeLU@?5cpXt+XH!z{xTo>_Qfq7NLsq}cntF~3!Cjt|_`ye5^(-Vc^M~JN zs>19x?~u=Qz?&fOrOnM#YmNz*KBoFVp8)TF7yg$YphORp7*yTj#j~9)-GGZq@9EK zppB=OG7!yU=Xljt(ezzK;wA9ne ziKrLEd&Wvl#LxA*DmoaTz53%DY9bE|lktV`=btk((pa$|Rn7fKRp{*VtNW6h@hmCy zxP$Sm5nn7m7NnR)s0g%A5J9aN>-+%Mm^y<{@652DX3vWX|d#DQHWOe?5SmVV~&~v`T z{P+D#&`~W5;iXf*z3|M#j#c==y03DXW~K9ZWPEZbk*j#?m(`(Itn(rRLZX+D7lsh^Yj{0%N`jkWGQIL68ElJ?eU>`m zXfFfI6I~qXIf50KKdqy^5SPE4)hY?b>0p;&qDyaDmk`z1psi>^ln=Hh(9OqkqCSNx zJJ75%)q!Xb2vzmSYh@vpZ+Gq<@V`MQi=wYfR!0mEx#<%^WwH*UD(Phzol>H=M_ zUYV!J_RE;wzmbYv-$d*Z3ab(gv2ki}DWSJroIHWZ0_6!58k||31z}SBwKGML=p|WK zHDmNc7F5%<({{lBT4v0B!g7U_kUB#K!B@FY5AK@@y2a3Irz1b$;}!Fk5Ut|)9&G2d z7y`QGsv%J0R+*Z7Sh(N!dq-dH6SNw%>ip~Cp{;;DjfLC>oSjD(=yV6=Fy=waSzXJ9 zWcy}~LH0W=dCyM?{B-^e@Sq=|RTojMbUM}g3@D2M)(VSon-Kaf9w0+;uCQt#vDocacnpC+olvE^8!7}?$ z@%|Q5gNXXeSuvX#33B`%Mwy~D?%d$v*&p1v=4JwK;E|0iQtRk=`Neb5vVKfi9mbR; z(X6|^n$);;Ju?`SAt$kvd5r>JtxF<_Yp_r9&~VP<$NCaTigLOcKjfiBifx0gW=SP>Sz7LfwKQ6c`?B|Uab>do-W|0-3*8j}~t=h!5Ctc*@q3sHMj9Vpim{)M3f z4zckScuSQzfo-&sqv5U0S)!4w*Y|t_hJ>AH5|*=8PQ)B?(aesWA*#G{+&&?a$eO4V z!f06%eq}@{GsQrlf-9i%yhIPZAn$#$)w+2zm%Am$m`NYVC5ih#bm%qX?i}MXm2%-yk;}S+Bu7 zvuE^HfRh4Q5V*7dViOG^DewtpXwP=m@1{NGB%fcoSOYC~*RUk;xhn1jJw+uQ~5&KS#@3EAE|ih4wGi8!2Z&MGXAoAI=g><|_heE>;!L2>VGR;;|MNnBe# zEdJCK7qw!Xhf1ho%rNVtWOFQM>qKjGvbyUwt?<3>dm{?q5T-aa-m=P>OWL`q+M?RE zI4d+Ef`Tq_%yYN6xO#h#7DxAs1Sn)YhaXCPRi#);fcZA5vbWM&#a|z|3FmdR1cwwn zTw(F7+mbjxxYl`}pmg(5%9~Ymyc#TI>w3K@&u5l)rZM)f9`G3|!$lrJnqbT}{cB2H z7`<~R28bUFLVOOO4Yj-OT?H}4#UjkzgEk|0{I=-74JQl}{q8nl7aF=oVy^^IgcJu$-7Rol4>o4k%+NySv_A&4+SlqL5tlkgA{)8)w^a z*?1m*wYwWiQY|HHL=T|2FAJXU?S9rE>>|6i98upq8NvTzclNM3v_QR zb3z-1_#M%v2Q(>%+(0=v9RH11E?fgM*f?DQkrq2&u2zBcLB#JCTEOLb^JN z?Auey2w8|=K(gPD-S(S#U8LiPaU%y~o&R8rrydDY)^cExrAnDX^b^r*t! z;5e1@oA)?}=iTM%7Iu;MA1KJ{teNg~+G?bjM98x|V{COBC%6j9(Y_QZufhMp|` zoC!=wlJ|IMlLy7Li;^gzi0(yn3W#Br&1BaWMq4Yrx_(TLP<>AzM$nL5OU11Y36yzB z&kBl5^lzvbdDc>ix$An@%;@aj8kgVQGEJ>#Iw~rVpu)U(odyG&y8=DY9k=x0<9GYw zp^a8L^Raa2ap;U&EWL=@j}Yc3A;v=rTGw|PPxUpP%#c%9!nc+ot_vZ*gUJf=jA_!F z3%CSmMD%g}A!Gg@(_4tD&zWbA8)NR4KGh@C-nWzd zEetY#JYL>iYDaJuxx^90J>GT$*Kl3X7#G}RCD~7$i$f(L)uW&5kkH)jxrWsVy>Fa0 zN5y{Qf>Q0U=ZYtAb(}B1Hq7%cDrTQRAH?4H3hmbNngbuUrv89cv9obS27z;@tr3}? z5%!2F0?2O_C8@@DK*1EIG~nK5{3Qmxw5z1CXK8j)JJsToAK_P2aB zy{;6vqs%Rx)d_d|tH_q%j8=UkJWWqW#Jw|o;23@A!3q8LX4g&66MXK9!=^B@@fk6^ zE0tgwG~fW|-9K({alZP;*E9lO{gLotZrZOao*?_!a?l=w)C7Nw+33||FClsbn$tIo zGEv?1;9w`4lO4Sc>iaDv$Dg>~aTCvYN_c2z|J(FQYp-4WH20{ilE2;T?}GjKY#$_x zDxFn8B~TpC$v31cS?avzLl#8{ft#zzQASDcorW{ICVy7du~75~Z>50u3eq9%Fo}>} z4W3k!hn~KI0R~f?-FDPi`ndx5ESAeD-mnUk(T0TjHk(y^uq_~>o!ot^Fe(hP-vE<_ zGYZ-t>tMf%F&|6*L z?y@g50;*gF&uHzFhe*?Zvz@yY?m6Z# z6A+U1tN_XF*r!Ik{Ftk0D}D=Q3_tcK!$zxKlG- zYaJn)f;qsyyDD-l`Ir&9YQe9Bsv+?aZkfJXn{N z<^p3qI6IChn~g?2^~eDQa=9I`I!jwts+i|CZn|=$5_9YpVl7;-2O1&l!y=SVq)6Q$ zrz;f}H(FglC+MVNX!($zB?04{Q*Z0ij4j(%e+hDjRW!T2K`+KW&fekdG2U5 zt&=Jmbk^M4DrqdqTFc?#S*B!pT9LvhJ;u)gREBDJ-aPnV8x}4161#Fm#Urr$fL)6_ z1f|^G5)oi0i%O4T^`Own?kDCL<6+IuQP93-pPFYNEJIIc6ulWS70)Q!k13o~XG!yfJH!zbd|$k|`xtfn1)cZoIob))DPL@@XlJriYUm8W#Y9f(zNJDdq z59PT7uQRN9%+ICNQm5a&6I~gpRg61uP}QZn21e>tUl?6YOQcI^1?AJ{z1J}1cm3%o zMX6eHLl92oG)1z$xjNvv6l%;jTg7|a`|6$)K20jFUcg8HGP{-O_U0fXI}4Oa@C+uH z6!cEvc}Gf6oV!Euk%T6|zvO$;Q;)E>^6U~Sz_71JsNRGzPHL|NPoJC*Ftr(g(0U1u z?>7(L-1~_kf;m=}A31N@@gDm13lq;UOYzWo-nIHA%3j;(or0TGq{hMbAHMk;T^SZ| zbPl-i*8B@6OpM$lDj_C8m#ruU=`!pF&JN0=lq$?`$sWM!R|(ez=416MGg4}GYCeQG z!L!Ll4g#>6>E}*kRg`1-s?B7EF22ntgxhsZcJJ7E?)sh^veg}ds-5LH?@m5!6)b&C z-jaB0r4&^G%7&%nL)g*6(QocIc<&?UJ{f|JPxe_UO4opm&3{1JS1mrSpFXP9fQn@{ zuyiZZ7p)wav~k6#*E$S5FQtu4->pqDs&mI1lj!&v@IZcVfhE326ou20rv(t=g>!W? z%C2HQl-bhBN9C=MCgh_M7vGOvbkBG?tF8IT5j3$13!o2FHFiWr{K`!tSuNU%l+r=e zOD^{jkE1Y&_@y{S!7sy(|D=3M?Ks-r`{VgHQe0my4S}PzZ#G_Bdfw^>HrCiOn{q?2 z;OSU>I^#XbJI&nc3BCzbBUj@X&g=Fhkn-*of(xRpVGu*A0&(eJyLY>8s-NJ}G&ti2 zBkc);KyI)r@<1>$f`!btTq(3;Leooj(YPV33%YIn@yRboUE5@^n30m8r7i39P_Wb&ZZfE2rb6NM?LO zgU!C-YX$BX!~E<M`&8(GGg z^C~b}HP#?*AbhrwDsB#(vpuJgy)tG?p{+8V>8!jS37?l zLEd7pD=MkO$TjZ2b!m&|K5T5N>Jz!!(-(y6*n$YZl1fNGfbE{9GfVNUR^Z~h(AQ%U zx|~_gNT?VZ!oPbA~BD%8}RGNBc^u-Snh%7;qw`=2x zu398?x1ruD4dioxCoZuP8_0Dt*fa8QZU_Zc7WBC7n=O8(Pueh}7)7XpHi`4a_-kdp zhMkuXpLUmgS}#GO3a0j99L7!~WcdZvfmihmI@)!so&FTcu>g>FPjvGK#YX$Xax0w~ zN`h@h&p)clmbl$w{*M)nufShzc8DFtlf5=IRaS%ddH;}K1{4jh=B=&w7~0EB(lFMjX^oGR8SU7gO8uBt;Tanad^ zI%6sdOBE|3$BFq6B3plo3tYu)0>A5+t#}so_Amkpg_U3%2?M~e^{ha77If+|LJ=aC zQfp`9-N=*~zT-GlmJ_u(kFZQRMB7D=RH`g=J6IQx={D?dHzkAc$Z;cWB(x5Kh{t5} z=P|mZ1a~|;md-ExP^u`RBvex44$5ceP31HUsv->tR**Nq2pqrF6S=bz>IEy3-Ohel zvly6rjBSC0>dn-&k%ANFF*gljwrh^h?RIRaaDxv?rE&lGdP^OqH0G(Hd-A1b$0do5%wO2u7Y zxrQeLuL0`S#%le?zA9aB4=tc#?9OZgX#0vJSK$eTzDTW3TzFAG$nwh2al2$*l32i)^Q zZV&7mONS?~6fh=-Ej2FoAr5rtavoOHH%xiTMxd3Ti$(2RslNkRt^aLb1xHbaCz> zZcHf;J)0(KUGc^0jR+nM+Z~^rf#V#s-4>sC`|m9N$46bFIbfZa;Zh!h$Oq_$3xR>O z8|fofDI3~TA%;nMo2J!_SIChCO9K#GVAUuNQ7#cyFOfY}!EMe|avp!DRKn})?}eM_ zav1-9875qoMBsIG26WnOJ}aE~EzHOVG#Tc)IGoRYODNYg_=dJVuKH7y$_ozqcK6?r z;|qbTgTD8-^6SG8s-!tx9<|WQ2Zd!7S>B|<#vigrkwSlXLB)~$jNN+wwAD}YN+@dS zm;Yd!@&I#{l;Dgn+*N&LvVUBgElBaISJC=|q5mJEyDm2;7m9suSInRa*w+V*1THv- z?JR%EkWys&li2u5!#{)?OfCY4It|||ya)dP{GXhP-*;c?7AETu*(>F&Ea#&`cE4oc zDD=U2l+e?Cl3ia=1o{%ID18W=mJ&W>EAamT{I8?J+LB||Zj~tIybxcXN0U8OC<(6B zTl2;^xbtZ;)3nTyU(7(5!1qtEn1_&|(}%t+^*eBX{y;wB?>xM5tztMt-#sJV>T&3Z z2;UvQ$I_g|=95o~%QPy6!O8W1B$tLzA4{Vp=49r}Gk<>5*HEF!e>XPbgz~Af^a;38 z&G6X))?hAmH5Uc7mfV$|9I2Ew+Lxqd`6tj11E6O^hJV-&=yHnA1`)zYYti<=)F@W> zcljym7Pcv;ow&cia^$A9x8Ej*)~LZBNcpc=`J|ydzqv_*MXk)8`#MR!a(e$v1nV8U z`Dx;l>XM)09sls?Uw<+=2=G~_$4TC8NZDWhSL7LRzS^zil&krdAO7CrecoB;=~D%8 z`JSw-ZQ|zhM(_P6Z1+cQy9eox`=2pvEe}M2#M=VAzyCt8&j9_)H>LLg$vOHVJL%%T zO5&bb>0-X`4o zRMqfj%KbNgwLAeN^z`A7FRKV1m2>RsQ+~Zl-lpWW)NwSVn(P1WNF_Rk?X&lErwE#~ zzpq)OOF4>v=vY`TK#bR0vN0%SaV^|HV=Cv$wzS`OfMkg6{3KB=Hs4^^s~^-CLl?sNP%Lq-{AD|f{pFdKT+W*$q7;;S8;#-fD<(12G1j4{JFZm-8Y(dJ3Dg$-Cuo*fvD<` zmYm!~K;NSV+$-q5nh`1R5=Q-r%H7k-qmGJ1=oO5iWHb;xzcm$x*a^zA)$|Fk0Kv3? ziloL?b%g7ATzd!nNv+1zMFcCMkhCXSA57J5l#}R@d~77jl)y~}3Em;RgJODgE|#JQ zx}(a-2jFS%p=;f6J40Mw8R8vCTr*fk0@XEThW~key!PGDr-ad8G5=>GT0h@~w<~&- zT-*Lx1{K1fx#;&ZMCdAlKSqAU@ z^I3UW(KD#Xd~MW7&4nAR{XviZksJR2FF-u&*BoT6z?7xcg{V&tmF8X&kODxieNUGx zU&wAv0Lp)WG)FW>&?EBsqn#nqTExeos)^d=2O=hv`DMSJ<)abi0h|o>`8Mz911F75 zd8Oah`}Nk=K*Z`hHoVGRs$lB*D`uR_71}ZA^B9OnZ=uUGtoVK`nx`w%@=Fl!pEmLDlr;JP1o#7r`|2)f_vuv~f*9+c?NT zEC#B4s2Ri%o)5C9yK@8^yA}=|KlXtO$O{6Y@bt#es%y;qEnp*jfPBrC)g5+Xe%;#i zgZYh>+!dPww&~zWLxMzBb6^Q=wqWdeO4reWQ0=LaRvZW!VTDP)dvnSd98zbjKyq58 zQjSVdn)KniHggV-!2|5LRtZFXdsYm6U1RKmF6t`omU0Qk?O1@HjZqG&w|Yw|(ijq@ zks6b4TO!Bq5>PhXhWg_$4J zWL=$Sbhq}_+artF?bif;Vrxy6UNaZk!FE8H!7YG@;KH!zmK&Z+v$2Y-s!ZucwQ?`h z3tN4_S$eXEm1K1p3-0{+0Y*UbE}$7mefyAJKe{gDqkZzJe?TTv-~o6r6qf1svwz6c z8lpMQP+-gW3hP#Z&-!tb4>7Au-KnGF<*@^(e6N)!t&hQqg81cfDOB2q2SNTp;3y#E zwuRi+@Sff$)c9G#y0TG~)0dr;#B^nMMs!G_a!fJQ8*Nj6IDq}VT5TENT&VO`dw=gY z!3?8lO&-~~cWYpk1_)0nMyoBH(NpQJ+$T$_4-l&1mQKb&_2ABfCksPW($=*jLZz*x zW&{hy+_5IhIKG(;lEY)@O?NPz@DgRWO1FRDSD7YEgQ74?m*75@%DOt6)XtOvU7ac_ zn9lI<>E2Q&Caq0_t5_nPPNSpaAfL!JPG(j>ummzM@KET_ zokY4G0j9Q2?ttJYH`V1q%d0)ZO$(P`L_?iAI1E_Oeh>YICDLUg!7umSP{?fJ+R{9{ zr=|SCUV1!GoXFFc1}&ALuI7<1>gsp*-m9t{BCbk)JzPI<8&Vl`@ z)0+kStoo&ola}u!>u7D&3R%`&!KL5uil;U>brEH@2XEv@c;ycZe&RltTa$5Nw39K- zLoq9AMZsr~;D(LW+izRQynE^C5`8sh#sX36(?TI_plYsOi4bevHd=oKv#Vu;z_n_K z8{bQZ#Wu(8r5lq2J6c|F=eV=OSWe#K=ee1a54ly8-)SE^W{wfNK)Lu4r_rz0wgsb0 z0RW@ubdA?1%M0Gc3bN)l)+9QD;mBHS%d##GldWe<@Nd8U!@8L)r$qy~D36JY+(AB% z+&`{r*|dgPAa+`np3Fv;iSwGw?wKd#kckiq*)L=$n0<+8X33UtXz4q^Yx|>{{<=EZ zB4{r65p%dMGID>$5X0@PSH-_aX86G;ApJ{ywgJ3S}a%x z8hmaksx=6d0Zm1kxYv!fe5;s?j_JagH)k9c8!N61B2_VIg5I(zi44*xcj8-*on&k` zSHjKUB2yVL1hca{QN75=tvMw>q|$zFtERK25J=gpKBjI|1QK15Ma<8}`5%p3Vp59; zDAd9Cg739Y#w~$^_MXuukS;khC(OCkg3Ldydb3ejSDodqZosk5KOF;v`2955feq-G z!}0P3@TQZ}EV8XpA-4=Zo23zXyyj^(3y)0zh3K(!+7@h!8gvMmoL!`ln(N_?HQTcY zkX!0*-+s~(*8RKFQ+E3MPeH&uZ>~$uOtv0EparawYTax~E{YYvOK5_Y&D89jHCZ0S zV_wBbEHVChHY>yNQW`Nb4oaeSHVV?#S5obRj!+v+PezCQd&~!baRdao-{vpe@_vK2 z<@;S$ajsUPOEInd?M&%M%}0S5T-uO z*+XD8V=ywMGGMu-g>~b8*lB`2u9E0S5GZ``*@gWlKWn6Um+xrvL0tbQI%PBt2$Z-GQ>%58i2c3#r2yf?^p!X{&Fh_*L0&x6VD7=;Io*W{ey_)pQkEUf3(^ zo%Kqm;lU!IYQttcktP*B%&WjAkIr0-PMcx4C5`iN|Gh%~Vy?nqfWPZ^`V+*R=WcP1 zsFhp`A=ar+tqFTD8y6Fg3GK~WNo-X;D6%zt38t*hy1bKFFQaBnlt|h1#j(3lmfepb zLh@|Jkcnd*sb%AN$o~BVR737kGXZs(S7{qSw5**j9bEHBjEeaUu92wSJzZt+3ri1M z4}cT2c#`M9F9&Iz%lTVg=jP$(3NSG};prq6#(cTg_3(&$*B))4B%w#^Kpj-pZD8h> z9$Qw>acs|0gWxC=g*;%^TVAD^Y+y^LK5@3@c0qPSJlr2t!n4F4Tg4 z5tr;^4}~?8>emukL-pc`kAkEM_Li6D_r&=qJBt_09pkm? z$v$pkvKQ`-sqFbt%nlcb&RJ8IZLjAJA&Tt6}R9t*s z(cr)EFm_A*^|-XI`c%kqC<&F#5?|dp*gWx3&$)Nr4NXs+1%mdP(4)#YsO>z5F;|mcEH&Quq*vzjoZ>PCT4&< zX$0NjJ@zY>N5po~A=S9c><)#f#`KdcTG-ONm=vPIg|+Cxn$An?S`_pc=5kGGbL;_u zn3|U)!H3iuUSXQX{?%?*(OY;bVo?ulE#a{j-_Nm_n+ge-6suQ!-*Ba~>CUz1w zr~qA0K+j>Ibm21ifM?tO#y2gK;s;l0mas*|fs@c+zGKzXmbjk%LQA1IP6s`rF59!K z_BprkojITqlBv*AOWE(rGMaDfY`LGcmwu$l+5A@z>Bu;KYg^W@SO|z-8J^tt+rwe< zN97!>Ly>muu`t$i)ZSb#;64RAn^}T#$8K2*QBMLcl4CAQQ7g!TR&ILteank_g!SCf zo%H9hdBuUyn>GU}$MzUyIN{vw+{Lwu*NS!p*#!v9v5hjtecrunWAq@`!dK}1VfOI! zX4MmO)CN+*4pMGps2k0IadhoL!m}n(+sJZ7ElilK?YxdWrFJ{>BU^ zcWZZDhTooSVP6Ol*RXK4HubSQx0K(iYLq3+H;)fli5~R0fvfYvqct1(J*M4ErOETF z(s??9YwD}h^C4}CYkh-5?kQzdP3)R`TK@ahpP8T)lTh(k1sPp5Mf`}xX-bgbL`JQ% zO+Hp4U9!?ThkZFfImCK%WpEvhpdSubal)XU*7r{)Ub8$JvN`CTiuDt_90bq>?6p-9 zN)+8ucXeAan+qbP=X88{)0?b51rS;eDsH)brxHIGI}KFxhasQ?Y`x6%hZwafPXzQK z=5D5VUQQOM#aI~D_2MN6jyq7;$_l&_N~w6Anz#{=x#ov#y$-&b6O#o~th9cH1`TFh z=z|xn8dgptoRkVEiCJ`M$%F)S*DNETX=IldV>Tjydg7f*#P+s)b(1;Ob52XbfCB~M)V*`{f>SC-))Ah7z51D*u+Z+tc zbe2FiagAt(kI0B z?4F3b>KkG{4Pg>$XJ9{;-~#zuzCi1No)oM&Cr$+&;=AuLooD-oPe(S2U`8p zyamUqmAJrU#vx&kg2t$|Iv7b+3#%1}^k-JJ=7Aj{GFibQ+yy3;%bS|DAR6D(THVZ4 zvE+>#Hn>&uV#uTTGQ=&q;bT;7ZEhiPJ5m;Z^I1Ai(LZ^Ff2V}ZPfY^e>OHs5 zcRIq3e`5h*_?z0)oTrj$qpaAxMy{0YhQ$XyhBfi}H$C<@;Lx( z0d>y&v<%$U$Dg>cRD?sdBaEj>WbZqig z39~;u;$+Iz7QO)WFaHd10FZa36!`q_EC3)bhCa*OpTzgi zX!!~RA|F#5Im%TBf2-HrCb#}d{+WX(RW5(-1z-te7aKE9uWU=%{V^mPmh-W=pfYbb z?0?2~OXEjtur6sAx@{zX=G)TBk2%;itipx=nN1V@0B>w1^hcm;?f;7Hcq0Hy1L#r#rN1bse_ZCzh_s#nShAOK{G#grjHSOEU`~}@=fIiR zVizA`6Jsb?iYsvG)-jHu+dS+<9iweW5&6y-k9PqgkixrRjye|FoW%?x3Ti&O5p8E+uF7JdTa z|KjQv!e#rX3*>+5mo`VsTK)JSxx&`}`ivxZ_tIBecN-ntcpAWrMg}%nh%V)} z4i!E1>}_pEpbc$*%$f06ae%{alL}YF@1ixA&<##1=O}O;o~8k~zZG!QGC-wvtbj2R zq>+a>f*p5_YxPP2w$}|`_*nF=K`solOLzKSt2CH0dxIu!6A&QC+-TJnj%7DA4p$Ys zq+ha>#kt9>lMCRDPVSWo;&5Ata&wmFv(Al^q}~kb_f2o6Drct|ty4cGo&N`h0t{;e z=!8S5aKq<~i{!LWJPmr)BS3WFy3Lo}PZyukxj|VES!Sz<*50Db?@Yp5Y9WuKLyrS> zfCQk;K`xi3{j9Dn*os{}dc%^6=BNmq@Ak`a49@P<0=Ob1c&ZEs2>j8F7djjL_2i>&j0k zb`y^`WPL}8R|)MoHLKzBTtrCx$7{OJ0`_Jjxr&Iy95u*DeTnYI~KeQg^e35PlQdYY7iX+?2YwS^9?*Jv*(_^ z-f9}I3kU^Mx{nogSG(;3Zq-+Se3Y3UHm1<=(ms_EOz5L$ZU(wD`qsMa*J3L{w^h*J zSD2w&l!7x%sHu_v}?Mx>Z{uhWK3YhOP<5j5->Z{oCE7gyX2B z+MbB$_qE87=4t}9EoCiD9}TIjnbvnQxW85%-{7#*C#xgB@hq}8`h-<4q|^}CzA0GV z6SZ!)bs0f_6i&QZDJzsy_hI_c_#q$w?1PHi1m9-=C^kSGv4?YY6OrY$lK4Ul*qj++ z5Mr%x2sCMc^S%Yx{+hWGcDE6 zh}$`>qHJg;w1mt4NA_UXa$o@;7GRsJ*2h_|#mE4LQBPi_y=vS_8|k2e9|x^pB@UdA}PztXVAs)aaGqPo|ibdzIc)z7A=S;wWhQ1qXiPZLm>${|6>X-&LO&c7hOB8Ac+#RlMD5_yKr$c?gv_rm z$#GMt)dxZZA>gWRyqYqSbrzV;D5EEqh(tZDbpR)*GaC?rq%9m6>2JkI%pMbbfEw5z z3@1sq300w&>&-Gj!_BdC85c58D{&V~xFtGjW(;TN%n`{r1}Iu{m6JK2oWB)#V_ZlV z^ZphpNRTwfmy$2fcAQE;}G06BeR_iP#;dYHa#>(SG$FjN=D)};||3I)Q z-qAb6)vKbHEL^b!kx{HQC&5$Y^5zM{B!|?&(1Xmnq*si>sCN?xG6eM`pIkh_fIypG_nAT8U9eFk&kHMuHxf9JhT-jbh1NH% zGxqZMeo*1^ACQ0PG17mPEMf{1AQ*Do=F4!6ssJrAria{OK`C!%3ykz^1P0R6j^S?* zj1i%jG?Su6p`Cb|Rekx3$Q62+o2ep-lm|Hp(akK1i0TF1X$+XM+{P^Tvt=i) z5l5U(!rB>EE@uHLIB@x5c*3JA5f~igWZ+3(A@p#Pqq}RN3r(+1yz}c^c7)*HnY$t%JNzIZ zV`LB#<2k;+a4D95t%gtpS)UNs^(xAHudR27kDZkNzM970Y^=BP3vibi%T@-_qC ziasd1K=;*Q%p(-`8dKt{x}ovP&N=VQ1468)1cWL58spb)<$x|n-^7+N&yM_O0 zG(waiDGTzn<|^xaWPjE8n$Ak&aHvY(q6jU>ml7!@%Sc5@hdVW)*SeyJasD_BNEW`(! z_@T<}zKMIlHKTlPh_;#iE2jXQSYALHcFl3~WC8O4l6uew)o)Dg4djdH$kD6Q%8ZG? z3HkNhV^xsfgduYStkfD9w}hfkNG}Jjx6W~nYpvH8R;c6+2EvBq3%sNaNGnU&Yia9g z#(S`{FA0EO+}e@p8kqE&IFj7g$OG%17C<~G96$~Noi=)#lWJ|I=!ojEbCH4KMpriP zOs`km?Z@bM(L;Q2iI%ectjLqc*NNwIH~nnPG9H+3hSP1On12 z7UxT#ES0>+T-la71DIPj1_y8Eq~8IW3h}}a_Y$=CBTo>cT*<`F@;pHlK=U2cjEx7^ z1P)ifD`ZWz-kE-FI)YxItr{-B)gJ#DIT_@i$;WPXvmjVd1Sy=fw7R}1$q}nq4`f zoOfcCuL5c>Yqv1^=o|7nzz7V9aiLim;#i5S_q!gcUUD5+efr|K1<9Y}<&$N9Vzx3v z1MY_RDmA4RDLUj)eAQ^UJPfGa50->=3n=OBX03QjHCyr3T=Y%1a_|Ud2Ao)DnT{c&PLL z@lB;fsT4^llFC^^Zf%Z@BKLhn$esJ1Nw&kCb>AZQG33f%Mq42=?sH;VhG7Q7Fpe2B z^LxA6+Rtvg-``)&L+|(N{dzs``?YICZv}wvumK`aBE66PAL5Wrv_osr3p#bj$C64{ z7y^jr$J8>;7#wMT3`*yZV*kv4I%=RemHu)JxWM#WdQi_Fp*Q!Y!r1cUN4y&|G7ND%5+tUYYj=b<`G4j2sqK#WIAmG$+;I10~6`*4V@p`dOGYUD8M zW_=&NeO$>8YRzz_(pNMmIg@Y8wAg8g*12IGR6CZIU=!&_f+(Gr$tiiO*C4Uduk7Kf z4&3?YjoT0CV)o@K_}papDAMXZ;%qSfkP-$^$Z;beZD5A~W3RyNrG}OIVq9^0CuDW+ zKzGImskzRM2lJ`xFp`s%M;@_egRoH8EKGRyrE zYIce#cC5g5f%0AgR|@a0-5?m(qlxjjTw!lNB$+wF*QEP=oX}u@}w7ZSLVSHEKzBxX2Sq! zs2WrXz&fMf8FJk8Sy{Dx0C!)9b!Ay>w{7jX+|`j)+Xk*~=T{kP;KVYB>zDxNTyG0F z!#hZ#%4P&pJ!;UeFzB^B=wIvGKc%1E+YxACc1hJYeg2}tZz~q(H-Vg%fT-u+oZ^Ha zP0g)61+kCk7bgXYwPOQoCsmwt3Psv|!b<%u?hw+)vzqIRQi(oR1DPSC_a6Mn%syML zM|YFqs);xod8fVgpi?JZ{L%V=0}HcNEqvNhPc!1%>Qy4+2L(Lm+&Wh6-i{uRkE=6Y zSE_xOSS5laR(G^lNA@Z7RzFK=VfLIC>yqpve)JrZahvM;y$n*DeBY(T3ppJPVMWPz zgKDY3cqhny$2k1`_4fKJ26H1Oqq8jOWToj_Q<5{)D~m4H@%zT`@Ta$t0mg$Lrx!?$ z4}QZvG#TT~p|}j-@?XF7ANMnvM@rCRS8*ilpcJT!c!%8JU5|V@26i@@^C;z%)J27P zK!@?gD6Z?}B$+CGsVjSr+)Aq+Xc97)cWqfE?uowHTZ>er72s|b_8kW2T(_yp3NTB+ zp8&ElDa$e+s;C;DNFL?&p4a|?$G0`_(B)vY);}BJYRtbhxf}x6G2RUIX3C@TOOov$ zY$+s%e*Z(X^S6?2-U>-XKrJ{c7oX+R9(TN^IbkP?@@;R7ns$}>1iOXQQ`KB#8-WQ> zPPG=+APE=CUW+9Mb$Fz)cd@r3){FQ3@aD1=qmPR{=SrOh;3CVC22SYE&#~r?{LE*Z z_=wG40|lr1sJ4wSBE z9;+JN;p)^2<*GHFnD@5e=tBNVkXx^99rdu@Z-FMTwC2uDQ;Xl$=tEVTB)vpKuOg}d zm!y>&Pss30aoBXgU|ji$J;cmlbP@LOxJ>(XJ`59EZ32 zay75XSw8l%6-R3icSnsPNauT97A3^t^5rXC)e_Eldo%u=cff$j8FS1Zay@tKot83R zquE2XekPO^q6C0Wc#HX7uR!rRDw~Q!YgMPCWaQH5qjDiltU?}YO)Y>6G4l#vOr_6& zpif<>TXg*NveRs}fzx92)5>clzOvfMHv2R2Ys%v}p{wUFzom%*4au(q^RL@}+SB=t z>|hM$x1~s3e`+ZCKgQg*c3vfGlJa<8N%TkRc0?k0lC>aT4sLts+1hibrEs00`B$kW z=$V@3k5+T9jRtG^3YS=uXDP>t{vAr0XEVx@6FR*Eiu1!Q&S_~ja9xf+Wh5C>HTkBd zLK}X6&?lw}k0Ra~DRBmB24Zg+B#pn3uUkl)Ee0uD8Qb(YI**L?LN%U#o|==pdadOp z%%2C$cbfaNV1q06<}C`5y$iU6Vy#QW=r*~b#-qR=9HItpT%F)|?nFwZF9-GWHx72N zwd+nTu5odGA#r%N?3spYO*O?|zXoaHkJ4z6aC5S%ejS0jG&L6_Ub;<3bJDMWn0*Ll zKg1+Qbbnf3E3m6Of=>p^hdNHrtcCyTMY+Ag8OnT~E8&g4RWS=m>W{w#ocZGTV%tAhj?>b8t*xq4?~*#_UGHyXC-?; z=2xAI=#`DzIz0Pu$5O!kYc03TQOP%m*H$U|^n(FZ`Oy55D%>RKPGb?bT3{iLV^gB2 zlGz&vB4wP{y^)4?LF|Z`&U$N@<)HcUR09`ED!7#6{$=ciq<{{CFx2~^#p$mG*r*c$0Y&yF~IumXDB0xY*W7$D_?myyRKw?A4V_Ukq^r-o_XuDgj?bJg1*?&XfAPjb2~S4 z6$B^~ z>JsZ8LE@2H(qLAY^V_!Z|BcDkr~yed{f|hI9k%(>K*yh1Tla2%FD!8URT;RzFVPbQ zGrIdR(1iHwq}sT1`=Y&U&D_wqe=_KLH~$hyDoEkB>3JXl6-?k_H2lryNK%MWl(@HU3aWah4$&VyOl;vu3rbEY|9C z(dsX>IQ&$ciw;r1h#V9el2ZCvlBkA-Tl5Q4P}ErCm~&p=Y%XphqaLoqTE4Fz5* z-1PQ!q~u(x&!sNpH5wBKD;Lh)*-*yD7f6ZZy0|=0&pbFPoT?YJrAgZC^zkwBAAM3V zbI<4BbMMT#0vIRA12BkD7JQ|(HaWK_mD2fhrukZ6&Dw6#nSi^4l4X80!GipRPLJf; ziQ@cOh1a1b8jmEGxv&uU$fv7;`P0!rQm0zvg&$46V&&MWA9b}_%CG_{X3osOXFL5! zpW>Sih^0cj#EQ`K)fsQ#n$5abZA`E;YbJUm{x^8}w@O?uuEc+m3CHKfH=q*2^WB1L ztV4*Jc8xkvFJ?_LbaUd;ycveUKC_$XY*VS}2_xxi*xI0aS26~?w0krA172lhp%N_Y zIZ{m_{0oC3W)W?m!oJ@3t7p8>#P>j7On)0-T-4)9#881+&cap6a?kJ<2|F*177fc- zR^6Te8jc720=6Q1WDd(U6KG^Lmf5#yqkTNGWNQ{sP&cTENd)>G{*d|50EgrOK0rcd z$lk=L9~WKJs9Cax>X>*rt?Z^F4bKOATpecfVu3vv!K=@rh|wv;6Uf2yr1vx|vdCS# zc7mK2lv@UImOmHC%TiyJu2TYjgIw|G1;*)Y2p}}hq_1J#Z_X2umDbXngZ}~yZ8WSc zcX{9on2(0?WwJbs^F2a=0fS@MsX-{i=LSbtJ&%;J-Uba@BG(K{5I&B@EB#V>Nv2Ib z1%n8I1~tmg`A3)P0nr*{(BPdTG7_A??5fli{~~}qaLK(Y%>$9_t~mV$tC4sng=KZ- zNdtJ>LeYC!3iOveF+;##lJD*yytH41yL2BO{$tUsCAvqx449~8*0~vC8$%iNZpgS9 z`e-Chl9hZ6cLqa$YkGYnd8_Cu)iNAb3wLPd=vh(0g(^>)_qa;Oxc~84HWnb>Ij_W* zWpI^7WMNkC>&-)IYleeukXI&1GOyt>*T^O7{VXAwNo&zcd}rrVuZu1&yzghJ6jZgb zW4>)#F>Ie&0=FhHyChWi_xAXzkADbVtzp#1s-lT+LsKQ%%ToOL3!;_fY9$i^iDcBMiuK45@=7;2j(v9A z>rO^;0f)p9O(&JYC9TX`H*=3iSO5bOvs_aEoiz%niR{A_&g6Rs#cq-we|l$4M1ZM& zS?9uNO62G3M1r5k_?nW`T;|&7`zn_cAM^6Hr)JiuLaJ+MB|ayELb!sLj?w5@9ftK5 zKCH^GjQrR$8~1=YUBHZQ(rgXjsshnwKd=SoN!+HY@5fkr)D`^LOYH|zgta85A%$Jp zPTP0+;|eTvm0y?w9);g7D|ufL*54LgxiBB9#)K+zzwfI7HGfL2t*k_VdV(Wv^41aNat_Rk5k?PF^Qb= zo8zle@5*O5pGkeQ(o_?53&pUPa?`9=7BWXILrQ2vekDdG7^U|{B3$KgL6<@Vx;Ji( zs*&@}BzYnQG7*m(SrR!UEj37(nKdj$8$5{1YveQt^zLv3<~3>M!q_6ncnMVNYp9fq zsnIh2#1a*jGKC5?3OW*1@4ft^oaNc_{d6+UZ{_E9s{VoY#s)>cGv*?0pVrQWs5>+w z`LXtGCPtv&(hYh7<>Y*SBlI$n(v|qaL9V}@tZ}=|mrlKD6&*YmC>eATrI{vQ9@wY% zF)`lB7pJAV0*UCk>amx{^xHa?bKo?G& z(`1*QG|b?@c;|7uh&}9yT^4v8N%;v&ONk`b9K8jL5t&w)W<=RF$Tuvzn?wB5XmF|o ztS09RRXgyq>=--uLdfb!d&QRX}>?OYIi$())B4JlE;2<#5l0fH zl=Rf)=ZUDGYb6T&K>^pwz-IVreVl8}s$f|x5WrI@!)s0&9M`Y3 zIVdQgYQ77nkh{b-`k18rY|tkt7RW|4)Q}srPA9rbV-sbfoJTkc5#wnqm~7YR)K!%+ z1I>@kF7XBM8*_F(_0hm+Ow;kQ&`hAJ)G+R9#{{lZ9W@_$M6-n&%FhprH7pI3XXK6< zQdqPAQk*>C{G`FvenF~6UtKzo-#b4Tb>)X(|8&>xlDTj?!}jGFgzDSP7Y`irqo6zr8jIdoztOB4=>522NgC~#JfzA( z%WRYhj(t_ce860+p0WP3`}0R%iVhxp%=7qS_QZ{&k=e&j9*g&FK7XP6`~?->tXtQv zJUe}7qebcN1ZU*x4PDlgnkRI1g>9tvJ=t$IZ#}$D16B4q-noP7?d@$@UG(#8G=LPD z2NgqoYEck#U|44eyI~SssjGu&wzA%^D)EWG$cLb-7x6L5^%v!a7Jr5~)-krkGgfSb zs@1W5(1PZzA2piNx)b6FVt=2>oMwaQ{QTjUcN;!oH~cK*VD9&TWCUIIFF&$m6)|*D zjA?&Hi7n6U^Dauek4Qn?8ma5?O$u2S$nVi#EREOiER0jlot9^h7cip99*M#d_DW$? z)=Nlt`T^aORrW}MAN#uChc`f2o}+tAV#~JMakYSg(0j+{xsM0Zz5zXWqajsuIg=T9(dbu&9;7INSSiX2#Ajz`|bpi!wQ= z@>+?v_;#h??&rP(eEPwISiF+@H-~3k``MFP8P75#-Uf-@SZbA2HRo7oi-AN2+M)3( z)OW2&<+9v*t3QllI!pB;x^XSzrkw)mct$I~K3kkmW}NWCb0L^C!p>+WjS8)D+T6_C zp*4?evrBW|vdI6$5FeN*-UTCdPk*%;A|5rlxgFtleaK~^Oljn?%c3D-a1=ACz0^#$ zx^8)^{$KKEuGbGHARdMrg7kn!gYfxSt-9afQqe%AS}6PyVneNkJ@>UT;6i)yeCZ6; zsH)lxhyOiZaupjDa}zl1|J<78FZ*4>K?>r89A5BM0)(eF77?n_8Jc#3hIh0JIp(rd zc)b=Mhrkb4m}XEKsvI7$jq=|Nm^tmev1VA=P_-hSYZDHL&S_nMEYid5zs)-R4^|X) zg5B@l?0u^L6#z$1oeLIs6HeymK`9XS#MGvCuxC-*TNOkmQ>~0hkxhS87zQX_x5LA6 zlEo?x_IJ|m*sk6>%jD;ObD74ihADr!4gJwWC83AK$R0dLe>~z0%67C5)tD~yHA4Q> z;_TiYux#oxniI)~o@3%}atmLb=2My)M*Kvp!p2}X`_WUnd%zk@*!XUdABDGW^4v`| z^Y{f?occpO^0!#A^xU_P7>%g*yzqa1SM)x>+0SMl&+Lq^{}Zp@vB2N08xi#=i`re6 zfcW)qx#sU)+1>rq+lqH-FU&+oe@JY9w}asBV@LZGqz8MFch~wM!|WDWZa&=fg5e;R z`!!=;{g1Zxx66r215i@M7)!JK2!(&U?5V4OB)jST)-&<{3?&s+07}!Q>UO(x9KJox zk5{{S;cNl8RXAz>Pe%EVFE>pC(vCabapv~lLgGjCVc80hA@lJ5-v8DR^DVeeaRN}v z@eoSiZs_}ud)(k&f35SA=pMuNwjj@;nIZJ@W&6#lyA`<^$xDeB$Cc>WS z5aC@)^uM(5W@uO|mlGtJAeqp{ie$Skm%=5B48;46DiDrUPMX8gxMXlGZvMjQ|FJn(a#pYdDJ(TQ_N5Kp?WT0S_n|>I_O$M!BC#= zdafbj%ZhDb>cll9>TGF%ndj76YxMzp+JywRiNquHGik)H^;3Vx?q9bSd}P1F9u-cP zJgJ>OS)Sd0^*J=bJ%P%Uod9K93mIB2Y4uU2x}y~$J`3iqBGu|P9w}GONy}+e1|9B! z242jTH33t5Zpi!c{Kt*~%gRT|BuO2^9f&+N{c@?Bc2f_3c+2F7u22I%^hlJ z=vm;6e{Ho&M>(X3A9RBzP6xJETE}L_OUPVL$XDCaoBxEaZ%`Uh2XM$0_?|TRE!dqp z7MwmI8+9?gJ-uS%qxLXQaPINe11HB!q}K4dZDHTM_yh8bsAwWwk@v~pi3LSOHL*Vt0&z9=0rs&?4Z~5f#h)QeM*CPa!j!kQ*O#O<8aR6(VHKig5i_V+QM8O+maU zF#;mS^?BeOG$RjKnBc?f6EJIzg7-Vp=7y;s+Hd$Al6f;c57~VjhfLyCh&X z8K;x?TJgglG|X8b`H`siwsqey!>@SBk<5|ko*+Um}NaDhNIEdTCcsYy|X3Z zK<^LP<}3ef|0pj2#?1lKZGEI>yn2aCh1}+SA)P2cdVkv&?n3Yfpjba~yhwHD9M!Gn zL+~OgwhcN0a)huOZZx;H^VFttaUJfAFh#0X4l=<&pn91M=UV3m+spxFmm0ijVsIBE zJg~O413-~nd^7Fnq<%|L8O_*++sMf~jj46)R9!=6En0>171I|H*UTFTV%exzHnl+w zN${?oL}qsgaLn=+;qpAPYifdE3BY`=d3sKLF4j5tnK}nOd0Xf8><6ppBdc)3RafE& z98_bWvq(yBt(G4QXuLY0z~e48dGkPK=;u#=Oc~PB2r7pY4%E3$3M&X4VqY`wEHL(Q zscK&-)z0zgd?pAxUI#_FuMZf~e$zitP?8xzxD>NgS=a!<62vR0t*yx*V6)UtI|m%i z^@=<_S!9qil@S5dRzjF``+7!zDjHl=S!S+BJ>J~Hn|Y?LKSZTo zDRm

r)Vc-1Q!{706*u4)}Vke8C6?kHOEg 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 z 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 HJb(W$LBSmP From 74ebb58456eb2401cef9a1dee3c7ff600c7cfa4f Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 11 Jun 2026 07:30:22 -0500 Subject: [PATCH 130/132] PR feedback --- docs/control/system_level_control/slc_cost_min.md | 4 ++-- docs/control/system_level_control/slc_profit_max.md | 4 ++-- .../complex_profit_max/run_complex_profit_max.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/control/system_level_control/slc_cost_min.md b/docs/control/system_level_control/slc_cost_min.md index 5691faeed..dd4832020 100644 --- a/docs/control/system_level_control/slc_cost_min.md +++ b/docs/control/system_level_control/slc_cost_min.md @@ -21,7 +21,7 @@ Unlike the {ref}`demand following controller `, which spli The controller follows a three-step dispatch process: -1. **Curtailable technologies** run at their available capacity (assumed zero marginal cost). Their output is subtracted from the demand. +1. **Flexible technologies** run at their available capacity (assumed zero marginal cost). Their output is subtracted from the demand. 2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging). Residual demand is split evenly across storage technologies producing the demanded commodity. 3. **Dispatchable technologies** are dispatched by cheapest marginal cost first, each up to its rated capacity, until the remaining demand is met. @@ -54,7 +54,7 @@ system_level_control: In addition to the standard inputs inherited from `SystemLevelControlBase`, the cost minimization controller adds marginal cost inputs based on the `cost_per_tech` configuration (see above). -The base inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: +The base inputs for technologies classified as `flexible`, `dispatchable`, and `storage` are: - `f"{tech_name}_{tech_output_commodity}_out"` - `f"{tech_name}_rated_{tech_output_commodity}_production"` diff --git a/docs/control/system_level_control/slc_profit_max.md b/docs/control/system_level_control/slc_profit_max.md index 777475084..15a87657e 100644 --- a/docs/control/system_level_control/slc_profit_max.md +++ b/docs/control/system_level_control/slc_profit_max.md @@ -58,7 +58,7 @@ display( The controller follows a three-step dispatch process: -1. **Curtailable technologies** run at available capacity - they are always profitable to produce (zero marginal cost). +1. **Flexible technologies** run at available capacity - they are always profitable to produce (zero marginal cost). 2. **Storage technologies** absorb any surplus (charging) or provide the deficit (discharging), split evenly across storage technologies producing the demanded commodity. 3. **Dispatchable technologies** are dispatched in merit order (cheapest first), but **only at timesteps where their marginal cost is below the sell price**. At each timestep, the dispatch is the minimum of the remaining demand and the rated capacity, gated by the profitability check. @@ -104,7 +104,7 @@ In addition to the standard inputs inherited from `SystemLevelControlBase`, this - `commodity_sell_price` - the sell price per unit of the demanded commodity, shape `(n_timesteps,)` - Marginal cost inputs per dispatchable technology based on `cost_per_tech` configuration -The base inputs for technologies classified as `curtailable`, `dispatchable`, and `storage` are: +The base inputs for technologies classified as `flexible`, `dispatchable`, and `storage` are: - `f"{tech_name}_{tech_output_commodity}_out"` - `f"{tech_name}_rated_{tech_output_commodity}_production"` diff --git a/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py index bc14cf238..fadfbf92a 100644 --- a/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py +++ b/examples/35_system_level_control/complex_profit_max/run_complex_profit_max.py @@ -2,7 +2,7 @@ Complex profit-maximization example with wind, solar, battery, NG, and grid. This example demonstrates profit-driven dispatch with: - - Wind + solar (curtailable) combined into a single renewable stream + - Wind + solar (flexible) combined into a single renewable stream - Battery storage (200 MWh) for renewable energy shifting - Natural gas turbine with marginal cost of $0.05/kWh (dispatchable) - Grid buying with time-varying marginal cost (dispatchable) @@ -189,7 +189,7 @@ axes[4].plot(hours, solar_out / 1000, color="gold", label="Solar (MW)") axes[4].set_ylabel("Power (MW)") axes[4].set_xlabel("Hour") -axes[4].set_title("Curtailable Renewable Generation") +axes[4].set_title("Flexible Renewable Generation") axes[4].legend(loc="upper right") for ax in axes: From 5a11de078eb00223a1a68972cf9d47d515c27b8c Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 11 Jun 2026 11:41:24 -0600 Subject: [PATCH 131/132] Reverting errant storage control logic --- .../system_level/system_level_control_base.py | 24 +++++++++++++++---- .../system_level/test/test_slc_controllers.py | 7 ++++++ .../system_level/test/test_slc_examples.py | 6 ++++- h2integrate/core/h2integrate_model.py | 18 ++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/h2integrate/control/control_strategies/system_level/system_level_control_base.py b/h2integrate/control/control_strategies/system_level/system_level_control_base.py index 45a2350e6..d1b8c0348 100644 --- a/h2integrate/control/control_strategies/system_level/system_level_control_base.py +++ b/h2integrate/control/control_strategies/system_level/system_level_control_base.py @@ -29,6 +29,9 @@ class SystemLevelControlBase(om.ExplicitComponent): - ``demand_commodity``: the commodity being controlled (e.g. "electricity") - ``demand_commodity_rate_units``: units string (or None) of the demand commodity - ``demand_tech``: name of the demand technology + - ``storage_techs_to_control``: dictionary with keys of the technology names. The value is True + if the technology is classified as "storage" and has an attached controller. + Otherwise the value is False. - ``technology_graph``: directional graph object representation of the technology_interconnections found in the ``plant_config`` - ``tech_to_commodity``: set of tuples formatted as (tech_name, tech_output_commodity) @@ -71,6 +74,7 @@ def setup(self): self.commodity = slc_config["demand_commodity"] self.commodity_rate_units = slc_config.get("demand_commodity_rate_units", None) self.demand_tech = slc_config["demand_tech"] + self.storage_techs_to_control = slc_config.get("storage_techs_to_control", {}) self.technology_graph = slc_config["technology_graph"] self.fixed_techs = [ @@ -472,11 +476,21 @@ def _dispatch_storage(self, storage_tech, remaining_demand, commodity, inputs, o if set_point_name not in outputs: return - # Emit a signed charge/discharge set-point signal: charge when remaining - # demand is negative, discharge when positive. The storage tech's - # controller (passthrough by default) forwards this to the performance - # model, which interprets the sign as charge or discharge. - outputs[set_point_name] = remaining_demand + if self.storage_techs_to_control.get(storage_tech, False): + # Storage tech has its own sub-controller: emit a combined demand + # signal (always positive) equal to the commodity flowing into + # storage from upstream techs plus any remaining demand. + upstream_techs = self.get_upstream_techs_for_commodity(storage_tech, commodity) + commodity_into_storage = np.zeros(self.n_timesteps) + for tech_name in upstream_techs: + commodity_into_storage += inputs[f"{tech_name}_{commodity}_out"] + + outputs[set_point_name] = commodity_into_storage + remaining_demand + else: + # Storage without a sub-controller: emit a charge/discharge + # command directly. Charge when remaining demand is negative, + # discharge when positive. + outputs[set_point_name] = remaining_demand remaining_demand -= inputs[f"{storage_tech}_{commodity}_out"] return remaining_demand diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py index f30ef906a..91cd39e9d 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py @@ -66,6 +66,7 @@ def _build_slc_config( demand_tech: str = "demand", demand_commodity: str = "electricity", demand_commodity_rate_units: str = "kW", + storage_techs_with_control: list = [], ): sources_to_commodities = { (e[0], e[-1]) for e in technology_graph.edges(data="commodity") if e[-1] is not None @@ -75,11 +76,17 @@ def _build_slc_config( (e[0], e[-1]) for e in sources_to_commodities if e[0] in tech_control_classifiers } + storage_techs = [k for k, v in tech_control_classifiers.items() if v == "storage"] + storage_techs_to_control = { + k: True if k in storage_techs_with_control else False for k in storage_techs + } + slc_config = { "demand_commodity": demand_commodity, "demand_commodity_rate_units": demand_commodity_rate_units, "demand_tech": demand_tech, "tech_to_commodity": tech_to_commodities, + "storage_techs_to_control": storage_techs_to_control, "technology_graph": technology_graph, "tech_control_classifiers": tech_control_classifiers, } diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 210eebae5..95718d7e6 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -207,13 +207,17 @@ def test_slc_battery_with_controller(subtests, temp_copy_of_example): with subtests.test("wind farm generates power"): assert wind_out.sum() > 0 + with subtests.test("natural gas not dispatched when wind+battery cover demand"): + demand = model.prob.get_val("electrical_load_demand.electricity_demand_out", units="kW") + battery_out = model.prob.get_val("battery.electricity_out", units="kW") + assert np.all(battery_out[wind_out < demand] >= 0) with subtests.test("lcoe"): assert ( pytest.approx( model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), rel=1e-6, ) - == 0.10710679575878151 + == 0.10902004 ) diff --git a/h2integrate/core/h2integrate_model.py b/h2integrate/core/h2integrate_model.py index 2a79ec7cc..43865c5bd 100644 --- a/h2integrate/core/h2integrate_model.py +++ b/h2integrate/core/h2integrate_model.py @@ -576,6 +576,21 @@ def _classify_slc_technologies(self): if e[-1] is not None } + # Check if storage models have a controller + storage_tech_to_control = {} + for tech, classifier in self.tech_control_classifiers.items(): + if classifier == "storage": + control_model = ( + self.technology_config["technologies"][tech] + .get("control_strategy", {}) + .get("model", None) + ) + if control_model is None: + storage_tech_to_control[tech] = False + else: + # storage model does use a controller + storage_tech_to_control[tech] = True + # Remove feedstocks and connectors control_classifiers_to_connect = [ "fixed", @@ -595,6 +610,7 @@ def _classify_slc_technologies(self): slc_config["demand_commodity"] = demand_commodity slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units slc_config["tech_to_commodity"] = tech_to_commodity + slc_config["storage_techs_to_control"] = storage_tech_to_control slc_config["technology_graph"] = self.technology_graph slc_config["tech_control_classifiers"] = self.tech_control_classifiers @@ -676,6 +692,8 @@ def add_system_level_controller(self, slc_config): - ``"tech_control_classifiers"`` (dict[str, str]): Mapping of tech name to classifier (``"fixed"``, ``"flexible"``, ``"dispatchable"``, ``"storage"``, ``"feedstock"``). + - ``"storage_techs_to_control"`` (dict[str, bool]): Whether each storage tech + has its own sub-controller. - ``"technology_graph"`` (nx.DiGraph): Directed graph of technology interconnections. From 34c4903e31ed9c6fdf933514838c1dc92efff8f5 Mon Sep 17 00:00:00 2001 From: John Jasa Date: Thu, 11 Jun 2026 11:47:33 -0600 Subject: [PATCH 132/132] inconsequential change to trigger CI --- .../control_strategies/system_level/test/test_slc_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py index 95718d7e6..275d78b96 100644 --- a/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py +++ b/h2integrate/control/control_strategies/system_level/test/test_slc_examples.py @@ -217,7 +217,7 @@ def test_slc_battery_with_controller(subtests, temp_copy_of_example): model.prob.get_val("finance_subgroup_electricity.LCOE", units="USD/(kW*h)"), rel=1e-6, ) - == 0.10902004 + == 0.109020041 )