Skip to content

Commit f46e7c8

Browse files
committed
updated _find_feedstock_techs to use self.feedstock_comps
1 parent b6b1415 commit f46e7c8

2 files changed

Lines changed: 30 additions & 55 deletions

File tree

h2integrate/control/control_strategies/system_level/system_level_control_base.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -606,20 +606,19 @@ def _find_feedstock_techs(self, tech_name):
606606
Returns:
607607
list[str]: names of upstream feedstock technologies.
608608
"""
609-
tech_config = self.options["tech_config"]
610-
technologies = tech_config.get("technologies", {})
611609
interconnections = self.options["plant_config"].get("technology_interconnections", [])
612610

613611
# Upstream tech names for this dispatchable tech
612+
# NOTE: could getting upstream_techs be replaced with the two lines below
613+
# comds = self._get_commodity_for_tech(tech_name)
614+
# upstream_techs = list(
615+
# set([self.get_upstream_techs_for_commodity(tech_name, c) for c in comds])
616+
# )
614617
upstream_techs = [conn[0] for conn in interconnections if conn[1] == tech_name]
615618

616-
feedstock_names = []
617-
for upstream in upstream_techs:
618-
tech_def = technologies.get(upstream, {})
619-
perf_model = tech_def.get("performance_model", {}).get("model", "")
620-
cost_model = tech_def.get("cost_model", {}).get("model", "")
621-
if "Feedstock" in perf_model or "Feedstock" in cost_model:
622-
feedstock_names.append(upstream)
619+
feedstock_names = [
620+
upstream for upstream in upstream_techs if upstream in self.feedstock_comps
621+
]
623622

624623
return feedstock_names
625624

h2integrate/control/control_strategies/system_level/test/test_slc_controllers.py

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ def _make_plant_config(
2222
curtailable=None,
2323
dispatchable=None,
2424
storage=None,
25+
feedstock=None,
2526
sell_price=0.06,
2627
cost_per_tech=None,
2728
technology_interconnections=None,
2829
):
2930
"""Build a minimal plant_config dict for controller tests."""
30-
all_techs = (curtailable or []) + (dispatchable or []) + (storage or [])
31+
all_techs = (curtailable or []) + (dispatchable or []) + (storage or []) + (feedstock or [])
32+
3133
tech_to_commodity = {(t, "electricity") for t in all_techs}
34+
3235
config = {
3336
"plant": {"simulation": {"n_timesteps": n_timesteps, "dt": 3600}, "plant_life": 30},
3437
"system_level_control": {
@@ -39,6 +42,7 @@ def _make_plant_config(
3942
"curtailable_techs": curtailable or [],
4043
"dispatchable_techs": dispatchable or [],
4144
"storage_techs": storage or [],
45+
"feedstock_techs": feedstock or [],
4246
"tech_to_commodity": tech_to_commodity,
4347
"commodity_sell_price": sell_price,
4448
"cost_per_tech": cost_per_tech or {},
@@ -56,7 +60,8 @@ def _make_slc_config(plant_config):
5660
curtailable = slc.get("curtailable_techs", [])
5761
dispatchable = slc.get("dispatchable_techs", [])
5862
storage = slc.get("storage_techs", [])
59-
all_techs = curtailable + dispatchable + storage
63+
feedstock = slc.get("feedstock_techs", [])
64+
all_techs = curtailable + dispatchable + storage + feedstock
6065

6166
# Build technology graph
6267
tech_graph = nx.DiGraph()
@@ -79,6 +84,8 @@ def _make_slc_config(plant_config):
7984
classifiers[t] = "dispatchable"
8085
for t in storage:
8186
classifiers[t] = "storage"
87+
for t in feedstock:
88+
classifiers[t] = "feedstock"
8289

8390
return {
8491
"demand_commodity": slc["demand_commodity"],
@@ -91,7 +98,7 @@ def _make_slc_config(plant_config):
9198
}
9299

93100

94-
def _build_problem(slc_cls, plant_config, tech_config=None):
101+
def _build_problem(slc_cls, plant_config):
95102
"""Create and setup an OpenMDAO Problem with the given controller."""
96103
slc_config = _make_slc_config(plant_config)
97104
prob = om.Problem()
@@ -100,7 +107,7 @@ def _build_problem(slc_cls, plant_config, tech_config=None):
100107
slc_cls(
101108
driver_config={},
102109
plant_config=plant_config,
103-
tech_config=tech_config or {},
110+
tech_config={},
104111
slc_config=slc_config,
105112
),
106113
)
@@ -482,22 +489,16 @@ def test_feedstock_single(self):
482489
"""feedstock mode: single upstream feedstock drives marginal cost."""
483490
pc = _make_plant_config(
484491
dispatchable=["ng_plant"],
492+
feedstock=["ng_feed"],
485493
demand=50000,
486494
sell_price=0.10,
487495
cost_per_tech={"ng_plant": "feedstock"},
488496
technology_interconnections=[
489497
["ng_feed", "ng_plant", "natural_gas", "pipe"],
490498
],
491499
)
492-
tech_config = {
493-
"technologies": {
494-
"ng_feed": {
495-
"performance_model": {"model": "FeedstockPerformanceModel"},
496-
"cost_model": {"model": "FeedstockCostModel"},
497-
},
498-
}
499-
}
500-
prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config)
500+
501+
prob = _build_problem(CostMinimizationControl, pc)
501502
prob.set_val("slc.ng_plant_rated_electricity_production", 100000)
502503
# Feedstock VarOpEx: $1M/yr; production: 100 MW * 4 h = 400 MWh
503504
prob.set_val("slc.ng_feed_VarOpEx", np.full(30, 1_000_000.0))
@@ -513,6 +514,7 @@ def test_feedstock_multiple(self):
513514
"""feedstock mode: multiple upstream feedstocks are summed."""
514515
pc = _make_plant_config(
515516
dispatchable=["plant"],
517+
feedstock=["feed_a", "feed_b"],
516518
demand=50000,
517519
sell_price=0.10,
518520
cost_per_tech={"plant": "feedstock"},
@@ -522,22 +524,8 @@ def test_feedstock_multiple(self):
522524
["other_tech", "plant", "something", "cable"],
523525
],
524526
)
525-
tech_config = {
526-
"technologies": {
527-
"feed_a": {
528-
"performance_model": {"model": "FeedstockPerformanceModel"},
529-
"cost_model": {"model": "FeedstockCostModel"},
530-
},
531-
"feed_b": {
532-
"performance_model": {"model": "FeedstockPerformanceModel"},
533-
"cost_model": {"model": "FeedstockCostModel"},
534-
},
535-
"other_tech": {
536-
"performance_model": {"model": "SomePerformanceModel"},
537-
},
538-
}
539-
}
540-
prob = _build_problem(CostMinimizationControl, pc, tech_config=tech_config)
527+
528+
prob = _build_problem(CostMinimizationControl, pc)
541529
prob.set_val("slc.plant_rated_electricity_production", 100000)
542530
# Two feedstocks: $500k and $300k → total $800k/yr
543531
prob.set_val("slc.feed_a_VarOpEx", np.full(30, 500_000.0))
@@ -554,22 +542,16 @@ def test_feedstock_profit_max_unprofitable(self):
554542
"""feedstock mode in profit max: unprofitable when feedstock costs exceed sell price."""
555543
pc = _make_plant_config(
556544
dispatchable=["ng_plant"],
545+
feedstock=["ng_feed"],
557546
demand=50000,
558547
sell_price=0.01, # very low sell price
559548
cost_per_tech={"ng_plant": "feedstock"},
560549
technology_interconnections=[
561550
["ng_feed", "ng_plant", "natural_gas", "pipe"],
562551
],
563552
)
564-
tech_config = {
565-
"technologies": {
566-
"ng_feed": {
567-
"performance_model": {"model": "FeedstockPerformanceModel"},
568-
"cost_model": {"model": "FeedstockCostModel"},
569-
},
570-
}
571-
}
572-
prob = _build_problem(ProfitMaximizationControl, pc, tech_config=tech_config)
553+
554+
prob = _build_problem(ProfitMaximizationControl, pc)
573555
prob.set_val("slc.ng_plant_rated_electricity_production", 100000)
574556
prob.set_val("slc.commodity_sell_price", 0.01)
575557
# Very expensive feedstock: $100M/yr → high marginal cost
@@ -591,12 +573,6 @@ def test_feedstock_no_feedstock_raises(self):
591573
["some_tech", "ng_plant", "electricity", "cable"],
592574
],
593575
)
594-
tech_config = {
595-
"technologies": {
596-
"some_tech": {
597-
"performance_model": {"model": "SomePerformanceModel"},
598-
},
599-
}
600-
}
576+
601577
with pytest.raises(ValueError, match="at least one feedstock"):
602-
_build_problem(CostMinimizationControl, pc, tech_config=tech_config)
578+
_build_problem(CostMinimizationControl, pc)

0 commit comments

Comments
 (0)