@@ -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 )
0 commit comments