@@ -86,8 +86,8 @@ def _plausibility_checks(self) -> None:
8686 if self .piecewise_conversion :
8787 for flow in self .flows .values ():
8888 if isinstance (flow .size , InvestParameters ) and flow .size .fixed_size is None :
89- raise PlausibilityError (
90- f'piecewise_conversion (in { self .label_full } ) and variable size '
89+ logger . warning (
90+ f'Piecewise_conversion (in { self .label_full } ) and variable size '
9191 f'(in flow { flow .label_full } ) do not make sense together!'
9292 )
9393
@@ -138,6 +138,7 @@ def __init__(
138138 eta_discharge : TimestepData = 1 ,
139139 relative_loss_per_hour : TimestepData = 0 ,
140140 prevent_simultaneous_charge_and_discharge : bool = True ,
141+ balanced : bool = False ,
141142 meta_data : Optional [Dict ] = None ,
142143 ):
143144 """
@@ -163,6 +164,7 @@ def __init__(
163164 relative_loss_per_hour: loss per chargeState-Unit per hour. The default is 0.
164165 prevent_simultaneous_charge_and_discharge: If True, loading and unloading at the same time is not possible.
165166 Increases the number of binary variables, but is recommended for easier evaluation. The default is True.
167+ balanced: Wether to equate the size of the charging and discharging flow. Only if not fixed.
166168 meta_data: used to store more information about the Element. Is not used internally, but saved in the results. Only use python native types.
167169 """
168170 # TODO: fixed_relative_chargeState implementieren
@@ -188,6 +190,7 @@ def __init__(
188190 self .eta_discharge : TimestepData = eta_discharge
189191 self .relative_loss_per_hour : TimestepData = relative_loss_per_hour
190192 self .prevent_simultaneous_charge_and_discharge = prevent_simultaneous_charge_and_discharge
193+ self .balanced = balanced
191194
192195 def create_model (self , model : SystemModel ) -> 'StorageModel' :
193196 self ._plausibility_checks ()
@@ -261,6 +264,18 @@ def _plausibility_checks(self) -> None:
261264 f'is below allowed minimum charge_state { minimum_inital_capacity } '
262265 )
263266
267+ if self .balanced :
268+ if not isinstance (self .charging .size , InvestParameters ) or not isinstance (self .discharging .size , InvestParameters ):
269+ raise PlausibilityError (
270+ f'Balancing charging and discharging Flows in { self .label_full } '
271+ f'is only possible with Investments.' )
272+ if (self .charging .size .minimum_size > self .discharging .size .maximum_size or
273+ self .charging .size .maximum_size < self .discharging .size .minimum_size ):
274+ raise PlausibilityError (
275+ f'Balancing charging and discharging Flows in { self .label_full } need compatible minimum and maximum sizes.'
276+ f'Got: { self .charging .size .minimum_size = } , { self .charging .size .maximum_size = } and '
277+ f'{ self .charging .size .minimum_size = } , { self .charging .size .maximum_size = } .' )
278+
264279
265280@register_class_for_io
266281class Transmission (Component ):
@@ -531,6 +546,15 @@ def do_modeling(self):
531546 # Initial charge state
532547 self ._initial_and_final_charge_state ()
533548
549+ if self .element .balanced :
550+ self .add (
551+ self ._model .add_constraints (
552+ self .element .charging .model ._investment .size * 1 == self .element .discharging .model ._investment .size * 1 ,
553+ name = f'{ self .label_full } |balanced_sizes' ,
554+ ),
555+ 'balanced_sizes'
556+ )
557+
534558 def _initial_and_final_charge_state (self ):
535559 if self .element .initial_charge_state is not None :
536560 name_short = 'initial_charge_state'
0 commit comments