Skip to content

Commit ebb9abb

Browse files
committed
Refactoring some SLC base methods
1 parent df47e4f commit ebb9abb

3 files changed

Lines changed: 62 additions & 90 deletions

File tree

h2integrate/control/control_strategies/system_level/demand_following_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def compute(self, inputs, outputs):
2121
commodity = self.commodity
2222
demand = inputs[self.demand_input_name].copy()
2323

24-
# 1. Curtailable techs: full production
24+
# 1. Curtailable techs: operate at full production
2525
for curtailable_tech in self.curtailable_techs:
2626
commodity_from_tech = self._get_commodity_for_tech(curtailable_tech)
2727
# check that this tech produces the commodity demanded

h2integrate/control/control_strategies/system_level/system_level_control_base.py

Lines changed: 59 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -94,121 +94,93 @@ def setup(self):
9494
self._setup_tech_category("storage", self.storage_techs)
9595
self._setup_feedstock_category(self.feedstock_comps)
9696

97-
def _setup_commodity_for_given_units(
98-
self, tech_name, commodity, commodity_units, add_in_name=True, initial_set_point=1.0
97+
def _setup_commodity(
98+
self,
99+
tech_name,
100+
commodity,
101+
commodity_units=None,
102+
commodity_reference_var=None,
103+
add_in_name=True,
104+
initial_set_point=1.0,
99105
):
100-
"""Adds inputs and outputs for a commodity when the units are known.
101-
The inputs and outputs that are added have the below naming convention:
106+
"""Register OpenMDAO inputs and outputs for a single (tech, commodity) pair.
102107
103-
- ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name
104-
- ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production
105-
capacity of tech_name
106-
- ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name
108+
This method handles unit specification in two mutually exclusive ways:
107109
108-
Args:
109-
tech_name (str): name of technology
110-
commodity (str): commodity of the technology described by `tech_name`
111-
commodity_units (str): units of commodity
112-
add_in_name (bool, optional): If True, add the input for the in_name variable.
113-
Defaults to True.
114-
initial_set_point (float, optional): Add as the initial value for the
115-
set_point variable. Defaults to 1.0.
116-
Returns:
117-
tuple(str, str, str): tuple of in_name, set_point_name, and rated_name
118-
"""
119-
in_name = f"{tech_name}_{commodity}_out"
120-
rated_name = f"{tech_name}_rated_{commodity}_production"
110+
1. **Explicit units** - pass ``commodity_units`` (e.g. ``"kW"``).
111+
Each variable is created with ``units=commodity_units``.
112+
2. **Copied units** - pass ``commodity_reference_var`` (the name of an
113+
already-registered input whose units should be reused).
114+
Each variable is created with ``units=None, copy_units=commodity_reference_var``.
121115
122-
if self.storage_techs_to_control.get(tech_name, False):
123-
# tech_name is storage and does have an attached controller
124-
set_point_name = f"{tech_name}_{commodity}_demand"
125-
else:
126-
# if tech_name is not in storage_techs_to_control
127-
# or storage tech does not have an attached controller
128-
set_point_name = f"{tech_name}_{commodity}_set_point"
116+
Exactly one of ``commodity_units`` or ``commodity_reference_var`` must be
117+
provided.
129118
130-
if add_in_name:
131-
self.add_input(
132-
in_name,
133-
val=0.0,
134-
shape=self.n_timesteps,
135-
units=commodity_units,
136-
desc=f"{commodity} output from {tech_name}",
137-
)
138-
self.add_input(
139-
rated_name,
140-
val=0.0,
141-
units=commodity_units,
142-
desc=f"Rated {commodity} production for {tech_name}",
143-
)
144-
self.add_output(
145-
set_point_name,
146-
val=initial_set_point,
147-
shape=self.n_timesteps,
148-
units=commodity_units,
149-
desc=f"Set point for {tech_name} {commodity} curtailment",
150-
)
151-
152-
return in_name, set_point_name, rated_name
153-
154-
def _setup_commodity_for_copy_units(
155-
self, tech_name, commodity, commodity_reference_var, add_in_name=True, initial_set_point=1.0
156-
):
157-
"""Adds inputs and outputs for a commodity where the units are based on a reference
158-
input variable. The inputs and outputs that are added have the below
159-
naming convention:
119+
The following OpenMDAO variables are created:
160120
161-
- ``f"{tech_name}_{commodity}_out"``: input commodity produced by tech_name
162-
- ``f"{tech_name}_rated_{commodity}_production"``: input rated commodity production
163-
capacity of tech_name
164-
- ``f"{tech_name}_{commodity}_set_point"``: output control setpoint for tech_name
121+
- Input ``"{tech_name}_{commodity}_out"`` - commodity produced by the tech
122+
(only if ``add_in_name=True``).
123+
- Input ``"{tech_name}_rated_{commodity}_production"`` - rated production
124+
capacity of the tech.
125+
- Output ``"{tech_name}_{commodity}_set_point"`` (or
126+
``"{tech_name}_{commodity}_demand"`` for storage techs with an attached
127+
controller) - control set-point sent to the tech.
165128
166129
Args:
167-
tech_name (str): name of technology
168-
commodity (str): commodity of the technology described by `tech_name`
169-
commodity_reference_var (str): name of input to copy units from
170-
add_in_name (bool, optional): If True, add the input for the in_name variable.
171-
Defaults to True.
172-
initial_set_point (float, optional): Add as the initial value for the
173-
set_point variable. Defaults to 1.0.
130+
tech_name (str): Name of the technology.
131+
commodity (str): Commodity produced by ``tech_name``.
132+
commodity_units (str | None): Explicit unit string for the commodity.
133+
Mutually exclusive with ``commodity_reference_var``.
134+
commodity_reference_var (str | None): Name of an existing input
135+
variable whose units should be copied. Mutually exclusive with
136+
``commodity_units``.
137+
add_in_name (bool, optional): If True, register the
138+
``"{tech_name}_{commodity}_out"`` input. Defaults to True.
139+
initial_set_point (float, optional): Initial value for the
140+
set-point output. Defaults to 1.0.
174141
175142
Returns:
176-
tuple(str, str, str): tuple of in_name, set_point_name, and rated_name
143+
tuple[str, str, str]: ``(in_name, set_point_name, rated_name)``
177144
"""
145+
# --- Determine unit kwargs for add_input / add_output ---------
146+
# Either explicit units or copy_units from a reference variable.
147+
if commodity_units is not None:
148+
unit_kwargs = {"units": commodity_units}
149+
else:
150+
unit_kwargs = {"units": None, "copy_units": commodity_reference_var}
151+
152+
# --- Build variable names -------------------------------------
178153
in_name = f"{tech_name}_{commodity}_out"
179154
rated_name = f"{tech_name}_rated_{commodity}_production"
180155

156+
# Storage techs with an attached controller receive a "demand"
157+
# output instead of a "set_point" output.
181158
if self.storage_techs_to_control.get(tech_name, False):
182-
# tech_name is storage and does have an attached controller
183159
set_point_name = f"{tech_name}_{commodity}_demand"
184160
else:
185-
# if tech_name is not in storage_techs_to_control
186-
# or storage tech does not have an attached controller
187161
set_point_name = f"{tech_name}_{commodity}_set_point"
188162

163+
# --- Register inputs and output -------------------------------
189164
if add_in_name:
190165
self.add_input(
191166
in_name,
192167
val=0.0,
193168
shape=self.n_timesteps,
194-
units=None,
195-
copy_units=commodity_reference_var,
196169
desc=f"{commodity} output from {tech_name}",
170+
**unit_kwargs,
197171
)
198172
self.add_input(
199173
rated_name,
200174
val=0.0,
201-
units=None,
202-
copy_units=commodity_reference_var,
203175
desc=f"Rated {commodity} production for {tech_name}",
176+
**unit_kwargs,
204177
)
205178
self.add_output(
206179
set_point_name,
207180
val=initial_set_point,
208181
shape=self.n_timesteps,
209-
units=None,
210-
copy_units=commodity_reference_var,
211182
desc=f"Set point for {tech_name} {commodity} curtailment",
183+
**unit_kwargs,
212184
)
213185

214186
return in_name, set_point_name, rated_name
@@ -256,19 +228,19 @@ def _setup_tech_category(self, category, tech_list):
256228
for commodity in tech_commodities:
257229
if commodity in self.commodities_to_units:
258230
# Units are already known explicitly
259-
in_name, set_point_name, rated_name = self._setup_commodity_for_given_units(
231+
in_name, set_point_name, rated_name = self._setup_commodity(
260232
tech_name,
261233
commodity,
262-
self.commodities_to_units[commodity],
234+
commodity_units=self.commodities_to_units[commodity],
263235
add_in_name=True,
264236
initial_set_point=initial_set_point,
265237
)
266238
elif commodity in self.commodities_to_ref_var:
267239
# Units are inferred from a previously-registered reference variable
268-
in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units(
240+
in_name, set_point_name, rated_name = self._setup_commodity(
269241
tech_name,
270242
commodity,
271-
self.commodities_to_ref_var[commodity],
243+
commodity_reference_var=self.commodities_to_ref_var[commodity],
272244
add_in_name=True,
273245
initial_set_point=initial_set_point,
274246
)
@@ -288,20 +260,20 @@ def _setup_tech_category(self, category, tech_list):
288260
# variable so later techs with this commodity can
289261
# copy its units.
290262
self.commodities_to_ref_var[commodity] = in_name
291-
in_name, set_point_name, rated_name = self._setup_commodity_for_copy_units(
263+
in_name, set_point_name, rated_name = self._setup_commodity(
292264
tech_name,
293265
commodity,
294-
self.commodities_to_ref_var[commodity],
266+
commodity_reference_var=self.commodities_to_ref_var[commodity],
295267
add_in_name=False,
296268
initial_set_point=initial_set_point,
297269
)
298270
else:
299271
# Connection provided units — record them for future use
300272
self.commodities_to_units[commodity] = meta_data["units"]
301-
in_name, set_point_name, rated_name = self._setup_commodity_for_given_units(
273+
in_name, set_point_name, rated_name = self._setup_commodity(
302274
tech_name,
303275
commodity,
304-
self.commodities_to_units[commodity],
276+
commodity_units=self.commodities_to_units[commodity],
305277
add_in_name=False,
306278
initial_set_point=initial_set_point,
307279
)

h2integrate/core/h2integrate_model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ def _classify_slc_technologies(self):
562562

563563
# Remove feedstocks and connectors
564564
control_classifiers_to_connect = ["curtailable", "dispatchable", "storage", "feedstock"]
565-
tech_to_commodities = {
565+
tech_to_commodity = {
566566
(e[0], e[-1])
567567
for e in sources_to_commodities
568568
if self.tech_control_classifiers[e[0]] in control_classifiers_to_connect
@@ -572,7 +572,7 @@ def _classify_slc_technologies(self):
572572
slc_config["demand_tech"] = demand_tech
573573
slc_config["demand_commodity"] = demand_commodity
574574
slc_config["demand_commodity_rate_units"] = demand_commodity_rate_units
575-
slc_config["tech_to_commodity"] = tech_to_commodities
575+
slc_config["tech_to_commodity"] = tech_to_commodity
576576
slc_config["storage_techs_to_control"] = storage_tech_to_control
577577
slc_config["technology_graph"] = self.technology_graph
578578

0 commit comments

Comments
 (0)