66from __future__ import annotations
77
88import logging
9+ import warnings
910from typing import TYPE_CHECKING
1011
1112from .config import CONFIG
@@ -655,9 +656,10 @@ class InvestParameters(Interface):
655656 maximum_size: Upper bound for continuous sizing decisions. Defaults to a large
656657 value (CONFIG.modeling.BIG) representing unlimited capacity.
657658 Ignored when fixed_size is specified.
658- optional: Controls whether investment is required. When True (default),
659- optimization can choose not to invest. When False, forces investment
659+ mandatory: Controls whether investment is required. When True, forces investment
660660 to occur (useful for mandatory upgrades or replacement decisions).
661+ When False (default), optimization can choose not to invest.
662+ optional: DEPRECATED. Use `mandatory` instead. Opposite of `mandatory`.
661663 fix_effects: Fixed costs incurred once if investment is made, regardless
662664 of size. Dictionary mapping effect names to values
663665 (e.g., {'cost': 10000, 'CO2_construction': 500}).
@@ -687,7 +689,7 @@ class InvestParameters(Interface):
687689 ```python
688690 solar_investment = InvestParameters(
689691 fixed_size=100, # 100 kW system (binary decision)
690- optional=True,
692+ mandatory=False, # Investment is optional
691693 fix_effects={
692694 'cost': 25000, # Installation and permitting costs
693695 'CO2': -50000, # Avoided emissions over lifetime
@@ -705,7 +707,7 @@ class InvestParameters(Interface):
705707 battery_investment = InvestParameters(
706708 minimum_size=10, # Minimum viable system size (kWh)
707709 maximum_size=1000, # Maximum installable capacity
708- optional=True,
710+ mandatory=False, # Investment is optional
709711 fix_effects={
710712 'cost': 5000, # Grid connection and control system
711713 'installation_time': 2, # Days for fixed components
@@ -737,7 +739,7 @@ class InvestParameters(Interface):
737739 boiler_replacement = InvestParameters(
738740 minimum_size=50,
739741 maximum_size=200,
740- optional=True , # Can choose not to replace
742+ mandatory=False , # Can choose not to replace
741743 fix_effects={
742744 'cost': 15000, # Installation costs
743745 'disruption': 3, # Days of downtime
@@ -821,26 +823,46 @@ def __init__(
821823 fixed_size : int | float | None = None ,
822824 minimum_size : int | float | None = None ,
823825 maximum_size : int | float | None = None ,
824- optional : bool = True , # Investition ist weglassbar
826+ mandatory : bool = False ,
825827 fix_effects : EffectValuesUserScalar | None = None ,
826828 specific_effects : EffectValuesUserScalar | None = None , # costs per Flow-Unit/Storage-Size/...
827829 piecewise_effects : PiecewiseEffects | None = None ,
828830 divest_effects : EffectValuesUserScalar | None = None ,
831+ # Backwards compatibility - deprecated parameter
832+ optional : bool | None = None ,
829833 ):
830834 self .fix_effects : EffectValuesUserScalar = fix_effects or {}
831835 self .divest_effects : EffectValuesUserScalar = divest_effects or {}
832836 self .fixed_size = fixed_size
833- self .optional = optional
834837 self .specific_effects : EffectValuesUserScalar = specific_effects or {}
835838 self .piecewise_effects = piecewise_effects
836839 self ._minimum_size = minimum_size if minimum_size is not None else CONFIG .modeling .EPSILON
837840 self ._maximum_size = maximum_size if maximum_size is not None else CONFIG .modeling .BIG # default maximum
841+ self .mandatory = mandatory
842+
843+ # Handle backwards compatibility for optional parameter
844+ if optional is not None :
845+ self .optional = optional
838846
839847 def transform_data (self , flow_system : FlowSystem ):
840848 self .fix_effects = flow_system .effects .create_effect_values_dict (self .fix_effects )
841849 self .divest_effects = flow_system .effects .create_effect_values_dict (self .divest_effects )
842850 self .specific_effects = flow_system .effects .create_effect_values_dict (self .specific_effects )
843851
852+ @property
853+ def optional (self ) -> bool :
854+ """DEPRECATED: Use 'mandatory' property instead. Returns the opposite of 'mandatory'."""
855+ import warnings
856+
857+ warnings .warn ("Property 'optional' is deprecated. Use 'mandatory' instead." , DeprecationWarning , stacklevel = 2 )
858+ return not self .mandatory
859+
860+ @optional .setter
861+ def optional (self , value : bool ):
862+ """DEPRECATED: Use 'mandatory' property instead. Sets the opposite of the given value to 'mandatory'."""
863+ warnings .warn ("Property 'optional' is deprecated. Use 'mandatory' instead." , DeprecationWarning , stacklevel = 2 )
864+ self .mandatory = not value
865+
844866 @property
845867 def minimum_size (self ):
846868 return self .fixed_size or self ._minimum_size
0 commit comments