Esempio n. 1
0
    def __init__(self,
                 esM,
                 name,
                 commodity,
                 reactances,
                 losses=0,
                 distances=None,
                 hasCapacityVariable=True,
                 capacityVariableDomain='continuous',
                 capacityPerPlantUnit=1,
                 hasIsBuiltBinaryVariable=False,
                 bigM=None,
                 operationRateMax=None,
                 operationRateFix=None,
                 tsaWeight=1,
                 locationalEligibility=None,
                 capacityMin=None,
                 capacityMax=None,
                 sharedPotentialID=None,
                 capacityFix=None,
                 isBuiltFix=None,
                 investPerCapacity=0,
                 investIfBuilt=0,
                 opexPerOperation=0,
                 opexPerCapacity=0,
                 opexIfBuilt=0,
                 QPcostScale=0,
                 interestRate=0.08,
                 economicLifetime=10,
                 technicalLifetime=None):
        """
        Constructor for creating an LinearOptimalPowerFlow class instance.
        The LinearOptimalPowerFlow component specific input arguments are described below. The Transmission
        component specific input arguments are described in the Transmission class and the general component
        input arguments are described in the Component class.

        **Required arguments:**

        :param reactances: reactances for DC power flow modeling (of AC lines).
        :type reactances: Pandas DataFrame. The row and column indices of the DataFrame have to equal
            the in the energy system model specified locations.
        """
        Transmission.__init__(
            self, esM, name, commodity, losses, distances, hasCapacityVariable,
            capacityVariableDomain, capacityPerPlantUnit,
            hasIsBuiltBinaryVariable, bigM, operationRateMax, operationRateFix,
            tsaWeight, locationalEligibility, capacityMin, capacityMax,
            sharedPotentialID, capacityFix, isBuiltFix, investPerCapacity,
            investIfBuilt, opexPerOperation, opexPerCapacity, opexIfBuilt,
            QPcostScale, interestRate, economicLifetime, technicalLifetime)

        self.modelingClass = LOPFModel

        self.reactances2dim = reactances
        try:
            self.reactances = pd.Series(self._mapC).apply(
                lambda loc: self.reactances2dim[loc[0]][loc[1]])
        except:
            self.reactances = utils.preprocess2dimData(self.reactances2dim)
Esempio n. 2
0
def getStock(esM, mileStoneYear, nbOfRepresentedYears):
    '''
    Function for determining the stock of all considered technologies for the next optimization period. 
    If the technical lifetime is expired, the fixed capacities of the concerned components are set to 0.

    :param mileStoneYear: Last year of the optimization period
    :type mileStoneYear: int

    :param nbOfRepresentativeYears: Number of years within one optimization period.
    :type nbOfRepresentativeYears: int

    :return esM: EnergySystemModel instance including the installed capacities of the previous optimization runs. 
    :rtype: EnergySystemModel instance

    Last edited: February 11, 2020
    |br| @author: Theresa Gross, Felix Kullmann
    '''
    for mdl in esM.componentModelingDict.keys():
        compValues = esM.componentModelingDict[mdl].getOptimalValues(
            'capacityVariablesOptimum')['values']
        if compValues is not None:
            for comp in compValues.index.get_level_values(0).unique():
                if 'stock' not in esM.componentModelingDict[
                        mdl].componentsDict[comp].name:
                    stockName = comp + '_stock' + '_' + str(mileStoneYear)
                    stockComp = copy.deepcopy(
                        esM.componentModelingDict[mdl].componentsDict[comp])
                    stockComp.name = stockName
                    stockComp.lifetime = esM.componentModelingDict[
                        mdl].componentsDict[
                            comp].technicalLifetime - nbOfRepresentedYears
                    # If lifetime is shorter than number of represented years, skip component
                    if any(getattr(stockComp, 'lifetime') <= 0):
                        continue

                    # If capacities are installed, set the values as capacityFix.
                    if getattr(stockComp, 'capacityFix') is None:
                        if isinstance(compValues.loc[comp], pd.DataFrame):
                            stockComp.capacityFix = utils.preprocess2dimData(
                                compValues.loc[comp].fillna(value=-1),
                                discard=False)
                        else:
                            # NOTE: Values of capacityMin and capacityMax are not overwritten.
                            # CapacityFix values set the capacity fix and fulfills the boundary constraints (capacityMin <= capacityFix <= capacityMax)
                            stockComp.capacityFix = compValues.loc[comp]
                    esM.add(stockComp)

                elif 'stock' in esM.componentModelingDict[mdl].componentsDict[
                        comp].name:
                    esM.componentModelingDict[mdl].componentsDict[
                        comp].lifetime -= nbOfRepresentedYears
                    # If lifetime is exceeded, remove component from the energySystemModel instance
                    if any(
                            getattr(
                                esM.componentModelingDict[mdl].
                                componentsDict[comp], 'lifetime') <= 0):
                        esM.removeComponent(comp)

    return esM
Esempio n. 3
0
def fixBinaryVariables(esM):
    """
    Search for the optimized binary variables and set them as fixed.

    :param esM: energy system model to which the component should be added. Used for unit checks.
    :type esM: EnergySystemModel instance from the FINE package
    """
    for mdl in esM.componentModelingDict.keys():
        compValues = esM.componentModelingDict[mdl].getOptimalValues(
            "isBuiltVariablesOptimum")["values"]
        if compValues is not None:
            for comp in compValues.index.get_level_values(0).unique():
                values = utils.preprocess2dimData(
                    compValues.loc[comp].fillna(value=-1).round(
                        decimals=0).astype(np.int64),
                    discard=False,
                )
                esM.componentModelingDict[mdl].componentsDict[
                    comp].isBuiltFix = values
Esempio n. 4
0
    def __init__(self, esM, name, commodity, losses=0, distances=None,
                 hasCapacityVariable=True, capacityVariableDomain='continuous', capacityPerPlantUnit=1,
                 hasIsBuiltBinaryVariable=False, bigM=None,
                 operationRateMax=None, operationRateFix=None, tsaWeight=1,
                 locationalEligibility=None, capacityMin=None, capacityMax=None, sharedPotentialID=None,
                 capacityFix=None, isBuiltFix=None,
                 investPerCapacity=0, investIfBuilt=0, opexPerOperation=0, opexPerCapacity=0,
                 opexIfBuilt=0, interestRate=0.08, economicLifetime=10):
        """
        Constructor for creating an Transmission class instance.
        The Transmission component specific input arguments are described below. The general component
        input arguments are described in the Component class.

        **Required arguments:**

        :param commodity: to the component related commodity.
        :type commodity: string

        **Default arguments:**

        :param losses: relative losses per lengthUnit (lengthUnit as specified in the energy system model) in
            percentage of the commodity flow. This loss factor can capture simple linear losses
            trans_in_ij=(1-losses*distance)*trans_out_ij (with trans being the commodity flow at a certain point in
            time and i and j being locations in the energy system). The losses can either be given as a float or a
            Pandas DataFrame with location specific values.
            |br| * the default value is 0
        :type losses: positive float (0 <= float <= 1) or Pandas DataFrame with positive values
            (0 <= float <= 1). The row and column indices of the DataFrame have to equal the in the energy
            system model specified locations.

        :param distances: distances between locations given in the lengthUnit (lengthUnit as specified in
            the energy system model).
            |br| * the default value is None
        :type distances: positive float (>= 0) or Pandas DataFrame with positive values (>= 0). The row and
            column indices of the DataFrame have to equal the in the energy system model specified locations.

        :param operationRateMax: if specified, indicates a maximum operation rate for all possible connections
            (both directions) of the transmission component at each time step by a positive float. If
            hasCapacityVariable is set to True, the values are given relative to the installed capacities (i.e.
            a value of 1 indicates a utilization of 100% of the capacity). If hasCapacityVariable
            is set to False, the values are given as absolute values in form of the commodityUnit,
            referring to the transmitted commodity (before considering losses) during one time step.
            |br| * the default value is None
        :type operationRateMax: None or Pandas DataFrame with positive (>= 0) entries. The row indices have
            to match the in the energy system model specified time steps. The column indices are combinations
            of locations (as defined in the energy system model), separated by a underscore (e.g.
            "location1_location2"). The first location indicates where the commodity is coming from. The second
            one location indicates where the commodity is going too. If a flow is specified from location i to
            location j, it also has to be specified from j to i.

        :param operationRateFix: if specified, indicates a fixed operation rate for all possible connections
            (both directions) of the transmission component at each time step by a positive float. If
            hasCapacityVariable is set to True, the values are given relative to the installed capacities (i.e.
            a value of 1 indicates a utilization of 100% of the capacity). If hasCapacityVariable
            is set to False, the values are given as absolute values in form of the commodityUnit,
            referring to the transmitted commodity (before considering losses) during one time step.
            |br| * the default value is None
        :type operationRateFix: None or Pandas DataFrame with positive (>= 0) entries. The row indices have
            to match the in the energy system model specified time steps. The column indices are combinations
            of locations (as defined in the energy system model), separated by a underscore (e.g.
            "location1_location2"). The first location indicates where the commodity is coming from. The second
            one location indicates where the commodity is going too. If a flow is specified from location i to
            location j, it also has to be specified from j to i.

        :param tsaWeight: weight with which the time series of the component should be considered when applying
            time series aggregation.
            |br| * the default value is 1
        :type tsaWeight: positive (>= 0) float

        :param opexPerOperation: describes the cost for one unit of the operation.
            The cost which is directly proportional to the operation of the component is obtained by multiplying
            the opexPerOperation parameter with the annual sum of the operational time series of the components.
            The opexPerOperation can either be given as a float or a Pandas DataFrame with location specific values.
            The cost unit in which the parameter is given has to match the one specified in the energy
            system model (e.g. Euro, Dollar, 1e6 Euro).
            |br| * the default value is 0
        :type opexPerOperation: positive (>=0) float or Pandas DataFrame with positive (>=0) values.
            The row and column indices of the DataFrame have to equal the in the energy system model
            specified locations.
        """
        # TODO add unit checks
        # Preprocess two-dimensional data
        self.locationalEligibility = utils.preprocess2dimData(locationalEligibility)
        self.capacityMax = utils.preprocess2dimData(capacityMax)
        self.capacityFix = utils.preprocess2dimData(capacityFix)
        self.isBuiltFix = utils.preprocess2dimData(isBuiltFix)

        # Set locational eligibility
        operationTimeSeries = operationRateFix if operationRateFix is not None else operationRateMax
        self.locationalEligibility = \
            utils.setLocationalEligibility(esM, self.locationalEligibility, self.capacityMax, self.capacityFix,
                                           self.isBuiltFix, hasCapacityVariable, operationTimeSeries, '2dim')

        self._mapC, self._mapL, self._mapI = {}, {}, {}
        for loc1 in esM.locations:
            for loc2 in esM.locations:
                if loc1 + '_' + loc2 in self.locationalEligibility.index:
                    if self.locationalEligibility[loc1 + '_' + loc2] == 0:
                        self.locationalEligibility[loc1 + '_' + loc2].drop(inplace=True)
                    self._mapC.update({loc1 + '_' + loc2: (loc1, loc2)})
                    self._mapL.setdefault(loc1, {}).update({loc2: loc1 + '_' + loc2})
                    self._mapI.update({loc1 + '_' + loc2: loc2 + '_' + loc1})

        self.capacityMin = utils.preprocess2dimData(capacityMin, self._mapC)
        self.investPerCapacity = utils.preprocess2dimData(investPerCapacity, self._mapC)
        self.investIfBuilt = utils.preprocess2dimData(investIfBuilt, self._mapC)
        self.opexPerCapacity = utils.preprocess2dimData(opexPerCapacity, self._mapC)
        self.opexIfBuilt = utils.preprocess2dimData(opexIfBuilt, self._mapC)
        self.interestRate = utils.preprocess2dimData(interestRate, self._mapC)
        self.economicLifetime = utils.preprocess2dimData(economicLifetime, self._mapC)

        Component. __init__(self, esM, name, dimension='2dim', hasCapacityVariable=hasCapacityVariable,
                            capacityVariableDomain=capacityVariableDomain, capacityPerPlantUnit=capacityPerPlantUnit,
                            hasIsBuiltBinaryVariable=hasIsBuiltBinaryVariable, bigM=bigM,
                            locationalEligibility=self.locationalEligibility, capacityMin=self.capacityMin,
                            capacityMax=self.capacityMax, sharedPotentialID=sharedPotentialID,
                            capacityFix=self.capacityFix, isBuiltFix=self.isBuiltFix,
                            investPerCapacity=self.investPerCapacity, investIfBuilt=self.investIfBuilt,
                            opexPerCapacity=self.opexPerCapacity, opexIfBuilt=self.opexIfBuilt,
                            interestRate=self.interestRate, economicLifetime=self.economicLifetime)

        # Set general component data
        utils.checkCommodities(esM, {commodity})
        self.commodity, self.commodityUnit = commodity, esM.commodityUnitsDict[commodity]
        self.distances = utils.preprocess2dimData(distances, self._mapC)
        self.losses = utils.preprocess2dimData(losses, self._mapC)
        self.distances = utils.checkAndSetDistances(self.distances, self.locationalEligibility, esM)
        self.losses = utils.checkAndSetTransmissionLosses(self.losses, self.distances, self.locationalEligibility)
        self.modelingClass = TransmissionModel

        # Set additional economic data
        self.opexPerOperation = utils.checkAndSetCostParameter(esM, name, opexPerOperation, '2dim',
                                                               self.locationalEligibility)

        # Set location-specific operation parameters
        if operationRateMax is not None and operationRateFix is not None:
            operationRateMax = None
            if esM.verbose < 2:
                warnings.warn('If operationRateFix is specified, the operationRateMax parameter is not required.\n' +
                              'The operationRateMax time series was set to None.')

        self.fullOperationRateMax = utils.checkAndSetTimeSeries(esM, operationRateMax, self.locationalEligibility)
        self.aggregatedOperationRateMax, self.operationRateMax = None, None

        self.fullOperationRateFix = utils.checkAndSetTimeSeries(esM, operationRateFix, self.locationalEligibility)
        self.aggregatedOperationRateFix, self.operationRateFix = None, None

        utils.isPositiveNumber(tsaWeight)
        self.tsaWeight = tsaWeight
Esempio n. 5
0
    def __init__(
        self,
        esM,
        name,
        commodity,
        losses=0,
        distances=None,
        hasCapacityVariable=True,
        capacityVariableDomain="continuous",
        capacityPerPlantUnit=1,
        hasIsBuiltBinaryVariable=False,
        bigM=None,
        operationRateMax=None,
        operationRateFix=None,
        tsaWeight=1,
        locationalEligibility=None,
        capacityMin=None,
        capacityMax=None,
        partLoadMin=None,
        sharedPotentialID=None,
        linkedQuantityID=None,
        capacityFix=None,
        isBuiltFix=None,
        investPerCapacity=0,
        investIfBuilt=0,
        opexPerOperation=0,
        opexPerCapacity=0,
        opexIfBuilt=0,
        QPcostScale=0,
        interestRate=0.08,
        economicLifetime=10,
        technicalLifetime=None,
        balanceLimitID=None,
    ):
        """
        Constructor for creating an Transmission class instance.
        The Transmission component specific input arguments are described below. The general component
        input arguments are described in the Component class.

        **Required arguments:**

        :param commodity: to the component related commodity.
        :type commodity: string

        **Default arguments:**

        :param losses: relative losses per lengthUnit (lengthUnit as specified in the energy system model) in
            percentage of the commodity flow. This loss factor can capture simple linear losses

            .. math::
                trans_{in, ij} = (1 - \\text{losses} \\cdot \\text{distances}) \\cdot trans_{out, ij}

            (with trans being the commodity flow at a certain point in
            time and i and j being locations in the energy system). The losses can either be given as a float or a
            Pandas DataFrame with location specific values.
            |br| * the default value is 0
        :type losses: positive float (0 <= float <= 1) or Pandas DataFrame with positive values
            (0 <= float <= 1). The row and column indices of the DataFrame have to equal the in the energy
            system model specified locations.

        :param distances: distances between locations given in the lengthUnit (lengthUnit as specified in
            the energy system model).
            |br| * the default value is None
        :type distances: positive float (>= 0) or Pandas DataFrame with positive values (>= 0). The row and
            column indices of the DataFrame have to equal the in the energy system model specified locations.

        :param operationRateMax: if specified, indicates a maximum operation rate for all possible connections
            (both directions) of the transmission component at each time step by a positive float. If
            hasCapacityVariable is set to True, the values are given relative to the installed capacities (i.e.
            a value of 1 indicates a utilization of 100% of the capacity). If hasCapacityVariable
            is set to False, the values are given as absolute values in form of the commodityUnit,
            referring to the transmitted commodity (before considering losses) during one time step.
            |br| * the default value is None
        :type operationRateMax: None or Pandas DataFrame with positive (>= 0) entries. The row indices have
            to match the in the energy system model specified time steps. The column indices are combinations
            of locations (as defined in the energy system model), separated by a underscore (e.g.
            "location1_location2"). The first location indicates where the commodity is coming from. The second
            location indicates where the commodity is going too. If a flow is specified from location i to
            location j, it also has to be specified from j to i.

        :param operationRateFix: if specified, indicates a fixed operation rate for all possible connections
            (both directions) of the transmission component at each time step by a positive float. If
            hasCapacityVariable is set to True, the values are given relative to the installed capacities (i.e.
            a value of 1 indicates a utilization of 100% of the capacity). If hasCapacityVariable
            is set to False, the values are given as absolute values in form of the commodityUnit,
            referring to the transmitted commodity (before considering losses) during one time step.
            |br| * the default value is None
        :type operationRateFix: None or Pandas DataFrame with positive (>= 0) entries. The row indices have
            to match the in the energy system model specified time steps. The column indices are combinations
            of locations (as defined in the energy system model), separated by a underscore (e.g.
            "location1_location2"). The first location indicates where the commodity is coming from. The second
            one location indicates where the commodity is going too. If a flow is specified from location i to
            location j, it also has to be specified from j to i.

        :param tsaWeight: weight with which the time series of the component should be considered when applying
            time series aggregation.
            |br| * the default value is 1
        :type tsaWeight: positive (>= 0) float

        :param opexPerOperation: describes the cost for one unit of the operation.
            The cost which is directly proportional to the operation of the component is obtained by multiplying
            the opexPerOperation parameter with the annual sum of the operational time series of the components.
            The opexPerOperation can either be given as a float or a Pandas DataFrame with location specific values.
            The cost unit in which the parameter is given has to match the one specified in the energy
            system model (e.g. Euro, Dollar, 1e6 Euro). The value has to match the unit costUnit/operationUnit
            (e.g. Euro/kWh, Dollar/kWh).
            |br| * the default value is 0
        :type opexPerOperation: positive (>=0) float or Pandas DataFrame with positive (>=0) values.
            The row and column indices of the DataFrame have to equal the in the energy system model
            specified locations.

        :param balanceLimitID: ID for the respective balance limit (out of the balance limits introduced in the esM).
            Should be specified if the respective component of the TransmissionModel is supposed to be included in
            the balance analysis. If the commodity is transported out of the region, it is counted as a negative, if
            it is imported into the region it is considered positive.
            |br| * the default value is None
        :type balanceLimitID: string
        """
        # TODO add unit checks
        # Preprocess two-dimensional data
        self.locationalEligibility = utils.preprocess2dimData(
            locationalEligibility)
        self.capacityMax = utils.preprocess2dimData(
            capacityMax, locationalEligibility=locationalEligibility)
        self.capacityFix = utils.preprocess2dimData(
            capacityFix, locationalEligibility=locationalEligibility)
        self.isBuiltFix = utils.preprocess2dimData(
            isBuiltFix, locationalEligibility=locationalEligibility)

        # Set locational eligibility
        operationTimeSeries = (operationRateFix if operationRateFix is not None
                               else operationRateMax)
        self.locationalEligibility = utils.setLocationalEligibility(
            esM,
            self.locationalEligibility,
            self.capacityMax,
            self.capacityFix,
            self.isBuiltFix,
            hasCapacityVariable,
            operationTimeSeries,
            "2dim",
        )

        self._mapC, self._mapL, self._mapI = {}, {}, {}
        for loc1 in esM.locations:
            for loc2 in esM.locations:
                if loc1 + "_" + loc2 in self.locationalEligibility.index:
                    if self.locationalEligibility[loc1 + "_" + loc2] == 0:
                        self.locationalEligibility.drop(labels=loc1 + "_" +
                                                        loc2,
                                                        inplace=True)
                    self._mapC.update({loc1 + "_" + loc2: (loc1, loc2)})
                    self._mapL.setdefault(loc1,
                                          {}).update({loc2: loc1 + "_" + loc2})
                    self._mapI.update({loc1 + "_" + loc2: loc2 + "_" + loc1})

        self.capacityMax = utils.preprocess2dimData(
            capacityMax,
            self._mapC,
            locationalEligibility=self.locationalEligibility)
        self.capacityFix = utils.preprocess2dimData(
            capacityFix,
            self._mapC,
            locationalEligibility=self.locationalEligibility)
        self.capacityMin = utils.preprocess2dimData(
            capacityMin,
            self._mapC,
            locationalEligibility=self.locationalEligibility)
        self.investPerCapacity = utils.preprocess2dimData(
            investPerCapacity, self._mapC)
        self.investIfBuilt = utils.preprocess2dimData(investIfBuilt,
                                                      self._mapC)
        self.isBuiltFix = utils.preprocess2dimData(
            isBuiltFix,
            self._mapC,
            locationalEligibility=self.locationalEligibility)
        self.opexPerCapacity = utils.preprocess2dimData(
            opexPerCapacity, self._mapC)
        self.opexIfBuilt = utils.preprocess2dimData(opexIfBuilt, self._mapC)
        self.interestRate = utils.preprocess2dimData(interestRate, self._mapC)
        self.economicLifetime = utils.preprocess2dimData(
            economicLifetime, self._mapC)
        self.technicalLifetime = utils.preprocess2dimData(
            technicalLifetime, self._mapC)
        self.balanceLimitID = balanceLimitID

        Component.__init__(
            self,
            esM,
            name,
            dimension="2dim",
            hasCapacityVariable=hasCapacityVariable,
            capacityVariableDomain=capacityVariableDomain,
            capacityPerPlantUnit=capacityPerPlantUnit,
            hasIsBuiltBinaryVariable=hasIsBuiltBinaryVariable,
            bigM=bigM,
            locationalEligibility=self.locationalEligibility,
            capacityMin=self.capacityMin,
            capacityMax=self.capacityMax,
            partLoadMin=partLoadMin,
            sharedPotentialID=sharedPotentialID,
            linkedQuantityID=linkedQuantityID,
            capacityFix=self.capacityFix,
            isBuiltFix=self.isBuiltFix,
            investPerCapacity=self.investPerCapacity,
            investIfBuilt=self.investIfBuilt,
            opexPerCapacity=self.opexPerCapacity,
            opexIfBuilt=self.opexIfBuilt,
            interestRate=self.interestRate,
            QPcostScale=QPcostScale,
            economicLifetime=self.economicLifetime,
            technicalLifetime=self.technicalLifetime,
        )

        # Set general component data
        utils.checkCommodities(esM, {commodity})
        self.commodity, self.commodityUnit = (
            commodity,
            esM.commodityUnitsDict[commodity],
        )
        self.distances = utils.preprocess2dimData(
            distances,
            self._mapC,
            locationalEligibility=self.locationalEligibility)
        self.losses = utils.preprocess2dimData(losses, self._mapC)
        self.distances = utils.checkAndSetDistances(self.distances,
                                                    self.locationalEligibility,
                                                    esM)
        self.losses = utils.checkAndSetTransmissionLosses(
            self.losses, self.distances, self.locationalEligibility)
        self.modelingClass = TransmissionModel

        # Set distance related costs data
        self.processedInvestPerCapacity = self.investPerCapacity * self.distances * 0.5
        self.processedInvestIfBuilt = self.investIfBuilt * self.distances * 0.5
        self.processedOpexPerCapacity = self.opexPerCapacity * self.distances * 0.5
        self.processedOpexIfBuilt = self.opexIfBuilt * self.distances * 0.5

        # Set additional economic data
        self.opexPerOperation = utils.preprocess2dimData(
            opexPerOperation, self._mapC)
        self.opexPerOperation = utils.checkAndSetCostParameter(
            esM, name, self.opexPerOperation, "2dim",
            self.locationalEligibility)

        self.operationRateMax = operationRateMax
        self.operationRateFix = operationRateFix

        self.fullOperationRateMax = utils.checkAndSetTimeSeries(
            esM, name, operationRateMax, self.locationalEligibility,
            self.dimension)
        self.aggregatedOperationRateMax, self.processedOperationRateMax = None, None

        self.fullOperationRateFix = utils.checkAndSetTimeSeries(
            esM, name, operationRateFix, self.locationalEligibility,
            self.dimension)
        self.aggregatedOperationRateFix, self.processedOperationRateFix = None, None

        # Set location-specific operation parameters
        if (self.fullOperationRateMax is not None
                and self.fullOperationRateFix is not None):
            self.fullOperationRateMax = None
            if esM.verbose < 2:
                warnings.warn(
                    "If operationRateFix is specified, the operationRateMax parameter is not required.\n"
                    + "The operationRateMax time series was set to None.")

        if self.partLoadMin is not None:
            if self.fullOperationRateMax is not None:
                if (((self.fullOperationRateMax > 0)
                     & (self.fullOperationRateMax < self.partLoadMin)
                     ).any().any()):
                    raise ValueError(
                        '"fullOperationRateMax" needs to be higher than "partLoadMin" or 0 for component '
                        + name)
            if self.fullOperationRateFix is not None:
                if (((self.fullOperationRateFix > 0)
                     & (self.fullOperationRateFix < self.partLoadMin)
                     ).any().any()):
                    raise ValueError(
                        '"fullOperationRateFix" needs to be higher than "partLoadMin" or 0 for component '
                        + name)

        utils.isPositiveNumber(tsaWeight)
        self.tsaWeight = tsaWeight