API documentation

addCo2Production(asset, state, energyDelivery= 'PRODUCTION' , co2Delivery= 'CO2' , co2CapturedDelivery= 'CO2_CAPTURED_PRODUCTION' , fuelPickup= 'FUEL_CONSUMPTION' , co2Content= 'CO2_CONTENT' , co2ContentRunningBound= 'CO2_CONTENT_RUNNING_BOUND' , fuelCo2Content= 'FUEL_CO2_CONTENT' , ratioCC= 'RATIO_CC' )

Add CO2 production to an asset

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • co2Delivery (string) – name of the CO2 energy
  • co2CapturedDelivery (string) – name of the CO2 captured energy
  • fuelPickup (string) – name of the fuel pickup
  • co2Content (string or DataWrapper) – dataname of the yield between the electricity and the CO2 production
  • co2ContentRunningBound (string or DataWrapper) – dataname of the additional yield between the running bound and the CO2 production when using the cluster model
  • fuelCo2Content (string or DataWrapper) – dataname of the yield between the fuel consumption and the CO2 production
  • ratioCC (string or DataWrapper) – dataname of the percentage of captured carbon
Returns:

None

FUEL BEHAVIOR

If the behavior FUEL is active, fuelCo2Content is used to define the yield between the fuel consumption and the CO2 emissions.

\(\small co2emissions = \boldsymbol{fuelCo2Content} * fuelConsumption\)

WITHOUT FUEL BEHAVIOR

If the behavior FUEL is not active:

  • if the behavior CLUSTER is not active:

co2Content is used to define the yield between the energyDelivery production and the CO2 emissions.

\(\small co2emissions = \boldsymbol{co2Content} * energyDelivery\)

  • if the behavior CLUSTER is active:

CO2 emissions are the sum of the co2Content of the energyDelivery production and the co2ContentRunningBound of the running capacity.

\(\small co2emissions = \boldsymbol{co2Content} * energyDelivery + \boldsymbol{co2ContentRunningBound} * runningCapacity\)

CCS SPECIFIC

If the asset has a CO2 captured interface, the previous constraints are added twice:

  • for the co2Delivery interface, every co2content-like yield is multiplied by

\(\small co2content *= 1 - \boldsymbol{ratioCC}/100\)

  • for the co2CapturedDelivery interface, every co2content-like yield is multiplied by

\(\small co2content *= \boldsymbol{ratioCC}/100\)

addDSRReserveProduction(asset, state, pmax= 'PMAX' )

Add DSR (Demand Side Response) asset reserve production constraints

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
Returns:

None

NOTATIONS Two reserve lists activeReserveList and nonActiveReserveList are build according to the active behaviors of the asset.

Each reserve of the activeReserveList and the nonActiveReserveList has the following parameters:

  • reserve.energy : name of the reserve energy (ex : syncResUp). The variable associated to the procurement of the reserve reserve.energy for this asset is also named reserve.energy.
  • reserve.isUp : boolean that sets the reserve direction. True if it is an upward reserve, False otherwise
  • reserve.cost : reserve production cost (defined by parameter “MFRR_PROCUREMENT_COST” or “SYNC_RESERVE_PROCUREMENT_COST” according to the considered reserve)

Warning

Each reserve defined in the asset model needs to be included either in the activeReserveList or the nonActiveReserveList.

CONSTRAINTS for nonActiveReserveList

For each reserve in the nonActiveReserveList, the reserve procurement is set to 0.

\(\small reserve.energy = 0\)

CONSTRAINTS for activeReserveList

Reserve production costs

For each reserve a production cost is associated to the reserve production:

\(\small objectiveFunction += reserve.energy * \boldsymbol{reserve.cost}\)

Upper reserve procurement bounds

The total procurement of all the reserve in the same direction cannot exceed the installed capacity of the DSR asset.

\(\small \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy} \leq \boldsymbol{pmax}\)

\(\small \sum_{res \, | \, \{res.isUp = False\}}^{reserveList}{res.energy} \leq \boldsymbol{pmax}\)

addDischargeStock(asset, state, energyDelivery= 'PRODUCTION' , energyPickup= 'CONSUMPTION' , initialStorageLevel= 0 , minStorageLevel= None , inputEfficiency= 100.0 , outputEfficiency= 100.0 , storageCapacity= 'STORAGE_CAPACITY' , maxStorageCapacity= 'MAX_STORAGE_CAPACITY' , minStorageCapacity= 'MIN_STORAGE_CAPACITY' , storageCapex= 'STORAGE_CAPEX' , pmax= 'PMAX' , pmaxmax= 'PMAXMAX' , pmaxmin= 'PMAXMIN' , dischargeTime= 'DISCHARGE_TIME' , dischargeTimemax= 'MAX_DISCHARGE_TIME' , dischargeTimemin= 'MIN_DISCHARGE_TIME' , storageAvailability= 100.0 , storageLossRate= 'LOSS_RATE' , storageCost= 'STORAGE_COST' , boundedSupply= 'BOUNDED_SUPPLY' , prorataSupply= 'PRORATA_SUPPLY' , prorataSupplyCoef= 'PRORATA_SUPPLY_COEF' , fixedSupply= 'FIXED_SUPPLY' , fixedDemand= 'FIXED_DEMAND' , reserveList= 'DefaultReserveList' , addToModel= True , initialEqualsFinal= False )

Add a stock module to the asset, whose storage capacity can be implicitly defined with a dischargeTime parameter.

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • energyPickup (string) – name of the energy pickup parameter
  • initialStorageLevel (string or DataWrapper (or "None")) – dataname of the initial stock level
  • minStorageLevel (string or DataWrapper (or "None")) – dataname of the storage minimum level
  • inputEfficiency (string or DataWrapper (or Crystal.getOne())) – dataname of the input efficiency
  • outputEfficiency (string or DataWrapper (or Crystal.getOne())) – dataname of the output efficiency
  • storageCapacity (string or DataWrapper) – dataname of the storage capacity
  • maxStorageCapacity (string or DataWrapper) – dataname of the maximum storage capacity
  • minStorageCapacity (string or DataWrapper) – dataname of the minimum storage capacity
  • storageCapex (string or DataWrapper) – dataname of the investment cost for the stock capacity optimization
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • pmaxmin (string or DataWrapper) – dataname of the minimal Pmax of the asset in capacity optimization mode
  • dischargeTime (string or DataWrapper) – discharge time
  • dischargeTimemax (string or DataWrapper) – maximal discharge time
  • dischargeTimemin (string or DataWrapper) – minimal discharge time
  • storageAvailability (string or DataWrapper (or "None")) – dataname of the storage availability of the asset
  • storageLossRate (string or DataWrapper) – dataname of the loss rate applied on the asset storage
  • storageCost (string or DataWrapper) – dataname of the cost of storage
  • boundedSupply (string or DataWrapper) – dataname of the bounded supply to add to the asset storage
  • prorataSupply (string or DataWrapper (or "None")) – dataname of the prorata supply to add to the asset storage (type of bounded supply proportional to the production capacity)
  • prorataSupplyCoef (string or DataWrapper (or "None")) – dataname of the optionnal coefficient for the prorata supply to add to the asset storage (type of bounded supply proportional to the production capacity)
  • fixedSupply (string or DataWrapper (or "None")) – dataname of the fixed supply to add to the asset storage
  • fixedDemand (string or DataWrapper (or "None")) – dataname of the fixed demand to add to the asset storage
  • reserveList (List of Reserve object) – list of reserve procured by the asset
  • addToModel (boolean) – boolean that adds the storage module to the model if true. WARNING : the user MUST add the moduleStock to the model himself if false
  • initialEqualsFinal (boolean) – If we want the final storage value to be equal to the initial storage
Returns:

StockModule, in case the user wants to add user constraints in the asset xml

The function redefines some of the stockModule parameters if the behavior DISCHARGE_TIMES is active, before calling addStock :

\(\small storageCapacity = pmax * dischargeTime\)
addEnergyCogenerationProduction(asset, state, energyDelivery= 'PRODUCTION' , productionCost= 'PRODUCTION_COST' , variableCost= 'VARIABLE_COST' , minLoad= 'MIN_LOAD' , availability= 'AVAILABILITY' , pmax= 'PMAX' , pmaxmax= 'PMAXMAX' , pmaxmin= 'PMAXMIN' , capex= 'CAPEX' , foc= 'FOC' , heatDelivery= 'HEAT_PRODUCTION' , fuelYield= 'FUEL_YIELD' , fuelYieldHeat= 'FUEL_YIELD_HEAT' , heatOverElectricityRatio= 'HEAT_OVER_ELEC_RATIO' )

Add a combined heat and a other energy production.

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the produced energy
  • productionCost (string or DataWrapper (or "None")) – dataname of the production cost of the asset when BH_FUEL is inactive
  • variableCost (string or DataWrapper (or "None")) – dataname of the production cost of the asset when BH_FUEL is active
  • minLoad (string or DataWrapper (or "None")) – dataname of the minimal usage. Can be “None” if there is not one
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • pmaxmin (string or DataWrapper) – dataname of the minimal Pmax of the asset in capacity optimization mode
  • capex (string or DataWrapper) – dataname of the investment cost for the capacity optimization
  • foc (string or DataWrapper) – dataname of the fixed operating costs
  • heatDelivery (string) – name of the produced heat
  • fuelYield (string or DataWrapper) – dataname of the fuel yield w.r.t main production (energyDelivery)
  • fuelYieldHeat (string or DataWrapper) – dataname of the fuel yield w.r.t heat production (heatDelivery)
  • heatOverElectricityRatio (string or DataWrapper) – dataname of the heat over electricity ratio
Returns:

None

The principal energy production is energyDelivery and the secondary energy production is heatDelivery.

COMMON CONSTRAINTS

Variable and production costs

If the asset is consuming fuel, a variable cost which does not include the cost for fuel is associated to the energy production:

\(\small objectiveFunction += energyDelivery * \boldsymbol{variableCost}\)

If the asset is not consuming fuel , the production cost which includes the cost for fuel is associated to the energy production:

\(\small objectiveFunction += energyDelivery * \boldsymbol{productionCost}\)

FUEL (behavior FUEL is active)

energyDelivery and heatDelivery are linked by the following expression:

\(\small heatDelivery = energyDelivery * \frac{fuelYieldHeat}{fuelYield}\)

NO FUEL (behavior FUEL is inactive)

If fuelYield or fuelYieldHeat does not exist, we use heatOverElectricityRatio instead:

\(\small heatDelivery = energyDelivery * heatOverElectricityRatio\)

In the following parts, all the constraints are ONLY set on principal energy production. So, pmax refers to the pmax of the principal energy production, etc.

FLEET CONSTRAINTS

Lower and upper production bounds

If the asset is a must run fleet (behavior MUST_RUN is active), the energy production is equal to the installed capacity multiplied by the availability:

\(\small energyDelivery = \boldsymbol{pmax} * \boldsymbol{availability}\)

If the asset is not a must run fleet (behavior MUST_RUN is inactive), the energy production is bounded below and above as follow:

\(\small \boldsymbol{pmax} * \boldsymbol{availability} * \boldsymbol{minLoad} \leq energyDelivery \leq \boldsymbol{pmax} * \boldsymbol{availability}\)

CAPACITY OPTIMIZATION (behavior OPTIM_PMAX is active)

Installed capacity

When the installed capacity is optimized, pmax becomes a variable (optimPmax) which is bounded below and above as follow. The equations above involving pmax stay the same, aside from pmax which is replaced by the variable optimPmax

\(\small \boldsymbol{pmaxmin} \leq optimPmax \leq \boldsymbol{pmaxmax}\)

Investment cost

The cost to increase the variable optimPmax depends on the annualized capex and the foc for the given technology.

\(\small objectiveFunction += optimPmax * ( \boldsymbol{capex} + \boldsymbol{foc} )\)
addEnergyConsumption(asset, state, energyPickup= 'CONSUMPTION' , energyDelivery= 'PRODUCTION' , availability= 'AVAILABILITY' , pmax= 'PMAX' , pmaxIn= 'PMAX_IN' , consumptionCost= 'CONSUMPTION_COST' , pmaxInOutRatio= 100.0 , pmaxmax= 'PMAXMAX' , pmaxmin= 'PMAXMIN' , capex= 'CAPEX' , foc= 'FOC' )

Add an energy consumption

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyPickup (string) – name of the energy pickup parameter
  • energyDelivery (string) – name of the energy delivery parameter
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxIn (string or DataWrapper) – dataname of the PmaxIn of the asset in simulation mode (used if BH_USE_PMAX_IN is active)
  • consumptionCost (string or DataWrapper (or "None")) – dataname of the consumption cost of the asset
  • pmaxInOutRatio (string or DataWrapper (or "None")) – dataname of the ratio pmaxIn/pmaxOut in case of capacity optimization. If is None, pmaxIn is optimized independently
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • pmaxmin (string or DataWrapper) – dataname of the minimal Pmax of the asset in capacity optimization mode
  • capex (string or DataWrapper) – dataname of the investment cost for the capacity optimization
  • foc (string or DataWrapper) – dataname of the fixed operating costs
Returns:

None

COMMON CONSTRAINTS

Consumption cost

If the consumptionCost parameter is not None, a cost is added to the objective function, proportional to the consumption

\(\small objectiveFunction += energyPickup * \boldsymbol{consumptionCost}\)

Upper consumption bound

The energy consumption is bounded by the availability multiplied by the maximum power.

\(\small energyPickup \leq \boldsymbol{availability} * \boldsymbol{pmax}\) [1]

CAPACITY OPTIMIZATION (behavior OPTIM_PMAX is active)

Consumption capacity

If behavior OPTIM_PMAX is active, the consumption upper bound becomes a variable (optimPmaxIn):

\(\small energyPickup \leq \boldsymbol{availability} * \boldsymbol{optimPmaxIn}\)

If pmaxInOutRatio is not None, the consumption upper bound is optimized proportionally to the optimized pmax associated with the energyDelivery parameter, whose constraints should be set separately.

\(\small \boldsymbol{optimPmaxIn} = pmaxInOutRatio * \boldsymbol{optimizedPmax}\)

If pmaxInOutRatio is None, optimPmaxIn is optimized as an independent variable, which is bounded below and above as follows.

\(\small \boldsymbol{pmaxmin} \leq optimPmaxIn \leq \boldsymbol{pmaxmax}\)

Investment cost

The cost to increase the variable optimPmaxIn depends on the annualized capex and the foc for the given technology.

\(\small objectiveFunction += optimPmaxIn * ( \boldsymbol{capex} + \boldsymbol{foc} )\)
[1]If behavior USE_PMAX_IN is active, the parameter pmaxIn is used instead of the pmax parameter. This behavior enables to have different upper bounds for production and consumption.
addEnergyProduction(asset, state, energyDelivery= 'PRODUCTION' , productionCost= 'PRODUCTION_COST' , variableCost= 'VARIABLE_COST' , minLoad= 'MIN_LOAD' , runningCapacityMinLoad= 'RUNNING_CAPACITY_MIN_LOAD' , availability= 'AVAILABILITY' , pmax= 'PMAX' , pmaxmax= 'PMAXMAX' , pmaxmin= 'PMAXMIN' , capex= 'CAPEX' , foc= 'FOC' , minOffTime= 'MIN_OFF_TIME' , clusterStartingCost= 'CLUSTER_STARTING_COST' , runningCost= 'RUNNING_COST' )

Add energy production using either a fleet or a cluster model, and with or without capacity optimization, according to the active behaviors

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • productionCost (string or DataWrapper (or "None")) – dataname of the production cost of the asset when BH_FUEL is inactive
  • variableCost (string or DataWrapper (or "None")) – dataname of the production cost of the asset when BH_FUEL is active
  • minLoad (string or DataWrapper (or "None")) – dataname of the minimal usage. Can be “None” if there isn’t one
  • runningCapacityMinLoad (string or DataWrapper) – min stable production level as a % of Pmax for an asset in Unit Mode, as % of running capacity for cluster mode.
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • pmaxmin (string or DataWrapper) – dataname of the minimal Pmax of the asset in capacity optimization mode
  • capex (string or DataWrapper) – dataname of the investment cost for the capacity optimization
  • foc (string or DataWrapper) – dataname of the fixed operating costs
  • minOffTime (string or DataWrapper) – minimum off-state duration (in hours)
  • clusterStartingCost (string or DataWrapper) – starting costs for the cluster model
  • runningCost (string or DataWrapper) – costs on running capacity for the cluster model
Returns:

None

COMMON CONSTRAINTS

Variable and production costs

If the asset is consuming fuel (behavior FUEL is active), a variable cost which does not include the cost for fuel is associated to the energy production:

\(\small objectiveFunction += energyDelivery * \boldsymbol{variableCost}\)

If the asset is not consuming fuel (behavior FUEL is inactive), the production cost which includes the cost for fuel is associated to the energy production:

\(\small objectiveFunction += energyDelivery * \boldsymbol{productionCost}\)

FLEET CONSTRAINTS (behavior CLUSTER is inactive)

Lower and upper production bounds

If the asset is a must run fleet (behavior MUST_RUN is active), the energy production is equal to the installed capacity multiplied by the availability:

\(\small energyDelivery = \boldsymbol{pmax} * \boldsymbol{availability}\)

If the asset is not a must run fleet (behavior MUST_RUN is inactive), the energy production is bounded below and above as follow:

\(\small \boldsymbol{pmax} * \boldsymbol{availability} * \boldsymbol{minLoad} \leq energyDelivery \leq \boldsymbol{pmax} * \boldsymbol{availability}\)

CLUSTER CONSTRAINTS (behavior CLUSTER is active)

Running capacity

In cluster mode, a key element is the running capacity (noted runningCapacity). This variable represents the capacity that is running (and can be used instantaneously for production). The actual energy production is bounded below and above by bounds that depend on the running capacity

\(\small runningCapacity * \boldsymbol{runningCapacityMinLoad} \leq energyDelivery \leq runningCapacity\)

Running and starting costs

A running cost is associated to maintaining a certain running capacity. Increasing the running capacity also comes with a cost.

\(\small objectiveFunction += runningCapacity * \boldsymbol{runningCost}\) \(\small objectiveFunction_{(t)} += \max{(runningCapacity_{(t)} - runningCapacity_{(t-1)}},\,0) * \boldsymbol{clusterStartingCost}\)

Lower and upper bounds on the running capacity

The running capacity is bounded below and above as follow:

\(\small 0 \leq runningCapacity \leq \boldsymbol{pmax} * \boldsymbol{availability}\)

Minimum off-state duration

When a part of the running capacity is switched off, this part cannot be switched on before a duration equals to minOffTime.

Other running capacity constraints

More details over the equations to model running capacity and all of the variables and constraints used in Cluster behaviour can be found here.

CAPACITY OPTIMIZATION (behavior OPTIM_PMAX is active)

Installed capacity

When the installed capacity is optimized, pmax becomes a variable (optimPmax) which is bounded below and above as follow. The equations above involving pmax stay the same, aside from pmax which is replaced by the variable optimPmax

\(\small \boldsymbol{pmaxmin} \leq optimPmax \leq \boldsymbol{pmaxmax}\)

Investment cost

The cost to increase the variable optimPmax depends on the annualized capex and the foc for the given technology.

\(\small objectiveFunction += optimPmax * ( \boldsymbol{capex} + \boldsymbol{foc} )\)
addEnergyTransmission(asset, state, energyPickup= 'CONSUMPTION' , energyDelivery= 'PRODUCTION' , losses= 'LOSSES' , productionCost= 'PRODUCTION_COST' , consumptionCost= 'CONSUMPTION_COST' , availability= 'AVAILABILITY' , pmax= 'PMAX' , pmaxmax= 'PMAXMAX' , pmaxmin= 'PMAXMIN' , capex= 'CAPEX' , foc= 'FOC' )

Add energy transmission

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyPickup (string) – name of the energy pickup parameter
  • energyDelivery (string) – name of the energy delivery parameter
  • losses (string or DataWrapper) – dataname of the losses between the energy pickup and the energy delivery of the asset
  • productionCost (string or DataWrapper (or "None")) – dataname of the production cost of the asset
  • consumptionCost (string or DataWrapper (or "None")) – dataname of the consumption cost of the asset
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • pmaxmin (string or DataWrapper) – dataname of the minimal Pmax of the asset in capacity optimization mode
  • capex (string or DataWrapper) – dataname of the investment cost for the capacity optimization
  • foc (string or DataWrapper) – dataname of the fixed operating costs
Returns:

None

COMMON CONSTRAINTS Losses (behavior FLOW_BASED inactive) If the behavior FLOW_BASED is inactive and the parameter losses is not None, losses are taken into account to set the input and output flow of a transmission.

Consumption cost

If the consumptionCost parameter is not None, a cost is added to the objective function, proportional to the consumption

\(\small objectiveFunction += energyPickup * \boldsymbol{consumptionCost}\)

Production cost

If the productionCost parameter is not None, a cost is added to the objective function, proportional to the production

\(\small objectiveFunction += energyDelivery * \boldsymbol{productionCost}\)

Relation between the consumption and the production

To represent potential losses, a fraction of the consumed energy is lost when the energy is going through the transmission, which results to a production lower than the consumption.

\(\small energyDelivery = (1 - \boldsymbol{losses}) * energyPickup\)

``Upper consumption bound``(behavior FLOW_BASED inactive)

The energy consumption is bounded by the availability multiplied by the maximum power when the transmission is not in Flow-Based behavior. The constraints in this case are written in the api_flow_based.

\(\small energyPickup \leq \boldsymbol{availability} * \boldsymbol{pmax}\)

CAPACITY OPTIMIZATION (behavior OPTIM_PMAX is active)

Installed capacity

When the installed capacity is optimized, pmax becomes a variable (optimPmax) which is bounded below and above as follow. The equations above involving pmax stay the same, aside from pmax which is replaced by the variable optimPmax

\(\small \boldsymbol{pmaxmin} \leq optimPmax \leq \boldsymbol{pmaxmax}\)

Investment cost

The cost to increase the variable optimPmax depends on the annualized capex and the foc for the given technology.

\(\small objectiveFunction += optimPmax * ( \boldsymbol{capex} + \boldsymbol{foc} )\)
addFuelConsumption(asset, state, fuelPickup= 'FUEL_CONSUMPTION' , energyDelivery= 'PRODUCTION' , fuelYieldOrEfficiency= 'FUEL_YIELD' , pMax= 'PMAX' , runningCapacityMinLoad= 'RUNNING_CAPACITY_MIN_LOAD' , fuelYieldPmin= 'FUEL_YIELD_PMIN' )

Add fuel consumption if FUEL behavior is active.

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • fuelPickup (string) – name of the fuel energy pickup parameter
  • energyDelivery (string) – name of the produced energy
  • fuelYieldOrEfficiency (string) – fuel yield when the asset is running at pMax for cluster and unit mode. Overall fuel yield for fleet mode
  • pMax (string or DataWrapper) – maximum power output for Unit Mode fuel consumption
  • runningCapacityMinLoad (string or DataWrapper) – dataname of the minimal stable load for cluster or Unit Mode expressed as % of pMax
  • fuelYieldPmin (string) – yield when the asset is running at its min stable load ( runningCapacityMinLoad * pMax or runningCapacityMinLoad * pMax )
Returns:

None

Introduced variables:

  • fuelConsumption : fuel consumption for the given asset
  • runningCapacity: electricity generation capacity that is running (and can be used instantaneously for production)

NO FUEL CONSTRAINTS (behavior FUEL is inactive)

In this case, no fuel consumption is set for this asset.

FUEL CONSTRAINTS (behavior FUEL is active)

Fleet constraints

  • If the behavior CLUSTER is inactive, fuelYieldOrEfficiency is used to define the yield between the production and the fuel consumption.

\(\small energyDelivery = \boldsymbol{fuelYieldOrEfficiency} * fuelConsumption\)

Cluster and Unit constraints

  • If CLUSTER or UNIT behavior is active, the total fuel consumption is divided in two parts : the fuel used to keep the running capacity turned on
(equals to pMax in Unit Mode), and the fuel necessary to effectively produce the output energy.

\(\small fuelConsumption = powerOutputFuelConsumption * energyDelivery + runningCapacityFuelConsumption * runningCapacity\)

with

\(\ powerOutputFuelConsumption = (1 / fuelYieldPmax - runningCapacityMinLoad / fuelYieldPmin) / (1 - runningCapacityMinLoad)\) \(\ runningCapacityFuelConsumption = 1 / fuelYieldPmax - powerOutputFuelConsumption\)

addGradients(asset, state, energyDelivery= 'PRODUCTION' , energyPickup= 'CONSUMPTION' , availability= 'AVAILABILITY' , pmax= 'PMAX' , gradientUp= 'GRADIENT_UP' , gradientDown= 'GRADIENT_DOWN' , isInput= False )

Add gradients to an asset production if behavior GRADIENTS is active

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • energyPickup (string) – name of the energy pickup parameter
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset
  • gradientUp (string or DataWrapper) – dataname of the upper gradient bound (in %/min)
  • gradientDown (string or DataWrapper) – dataname of the lower gradient bound (in %/min)
  • isInput (bool) – if True, add gradient to pickup energy. If False, add it to delivery energy
Returns:

None

GRADIENT UNITS

gradientUp and gradientDown are expressed as a percentage of the available power per minute: %/min. They are automatically converted to fit the current time step duration (often an hour), to be expressed as %/timeStepDuration.

GRADIENT CONSTRAINTS

The upward variation of the asset production is bounded by the gradientUp coefficient, and the downward variation by the gradientDown coefficient.

\(\small{ energyDelivery_{(t)} - energyDelivery_{(t-1)}}\) [2] \(\small{~~~~~~\geq \boldsymbol{gradientDown} * \boldsymbol{pmax} * \min{(availability_{(t)}, availability_{(t-1)})}}\) \(\small{~~~~~~~~+ \boldsymbol{pmax} * \min{(availability_{(t)} - availability_{(t-1)}, 0)}}\) [3]

\(\small{ energyDelivery_{(t)} - energyDelivery_{(t-1)}}\) \(\small{~~~~~~\leq \boldsymbol{gradientUp} * \boldsymbol{pmax} * \min{(availability_{(t)}, availability_{(t-1)})}}\) \(\small{~~~~~~~~+ \boldsymbol{pmax} * \max{(availability_{(t)} - availability_{(t-1)}, 0)}}\) [4]

[2]If OPTIM_PMAX is active, the pmax variable is used instead of the pmax parameter.
[3]If the availability decreases between two time steps, the gradient term in the inequality might not allow enough flexibility to respect the constraint \(\small{energyDelivery_{(t)} \leq availability_{(t)}*pmax}\). To prevent any infeasibility, this term allows to decrease the energyDelivery according to the upper bound evolution of the previous constraint.
[4]If the availability increases between two time steps, the gradient term in the inequality might not allow enough flexibility to respect the constraint \(\small{energyDelivery_{(t)} \geq minLoad_{(t)}*pmax}\). To prevent any infeasibility, this term allows to increase the energyDelivery according to the lower bound evolution of the previous constraint. In our model, the minLoad is expressed as a percentage of the availability. Therefore, this term allows more flexibility than necessary but simplify the models by using only the availability and not the minLoad.
addInitialStorageLevelBounds(asset, moduleStock, storageCapacity= 'STORAGE_CAPACITY' , dischargeTime= 'DISCHARGE_TIME' , pmax= 'PMAX' , initialStorageLevel= 0 , minInitialStorageLevel= None , maxInitialStorageLevel= None )

Add an upper bound and a lower bound to the initial storage level

Parameters:
  • asset (Asset) – asset to configure
  • moduleStock (StockModule) – stock module to configure
  • storageCapacity (string or DataWrapper) – dataname of the storage capacity
  • dischargeTime (string or DataWrapper) – discharge time
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • initialStorageLevel (string or DataWrapper (or "None")) – dataname of the initial stock level
  • minInitialStorageLevel (string or DataWrapper (or "None")) – minimum initial storage level
  • maxInitialStorageLevel (string or DataWrapper (or "None")) – maximum initial storage level
addMinimumFlow(asset, state, energyPickup= 'CONSUMPTION' )
addMinimumFlowOptimCapa(MODEL, asset, state, energyPickup, availability, minimumFlow)
addReserveProduction(asset, state, energyDelivery= 'PRODUCTION' , pmax= 'PMAX' , availability= 'AVAILABILITY' , reserveList= 'DefaultReserveList' , minLoad= 'MIN_LOAD' , runningCapacityMinLoad= 'RUNNING_CAPACITY_MIN_LOAD' , isQuickStart= False , isFleetModeEnabled= False )

Add reserve production constraints to a production asset

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the main energy delivery parameter (not reserve delivery)
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • reserveList (List of Reserve objects (see: Reserve object definition in DefaultVar)) – list of the reserves this asset can produce
  • minLoad (string or DataWrapper (or "None")) – dataname of the minimal usage. Can be “None” if there isn’t one
  • runningCapacityMinLoad (string or DataWrapper (or "None")) – dataname of the minimal stable level of the asset. Expressed as percentage of P max in Unit mode or % of running capacity for cluster Mode. Can be “None” if there isn’t one
  • isQuickStart (boolean) – boolean that indicates if the asset can start fast enough to participate to manual reserve(s) with its not running capacity
  • isFleetModeEnabled (boolean) – boolean that indicates if the asset can run in fleet mode and provide reserve
Returns:

None

NOTATIONS

Each reserve of the reserveList has the following parameters:

  • reserve.energy: name of the reserve energy (ex : syncResUp)
  • reserve.isUp: boolean that sets the reserve direction. True if it is an upward reserve, False otherwise
  • reserve.isManual: boolean that sets how the reserve is activated. True if it is activated manually, False otherwise
  • reserve.maxShare: maximal share of the running capacity (respectively available capacity) that can be used to provide automatic (respectively manual) reserve
  • reserve.cost: reserve production cost
  • reserve.delay: activation delay in hour
  • reserve.notRunningCost: cost for starting non-running capacity to provide reserve

Introduced variables:

  • runningCapacity: electricity generation capacity that is running (and can be used instantaneously for production)
  • reserve.runningEnergy: reserve energy that can be called instantaneously since it only requires to start running capacity
  • reserve.notRunningEnergy: reserve energy that can not be called instantaneously since it requires starting non-running capacity

Warning

For clarity, the equations below describe the model in cluster mode (behavior CLUSTER is active). To obtain the equations for the fleet mode:

  • runningCapacity should be replaced by pmax * availability
  • runningCapacityMinLoad should be replaced by minLoad
  • an additional minimum generation constraint is added, using runningCapacityMinLoad if it still exists:

\(\small energyDelivery - \sum_{res \, | \, \{res.delay \leq reserve.delay \text{ and } res.isUp = False\}}^{reserveList}{res.energy} \geq \boldsymbol{runningCapacityMinLoad} * (\boldsymbol{energyDelivery + \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy}})\)

NO RESERVE PRODUCTION (behavior RESERVE is inactive)

If the behavior RESERVE is inactive, each reserve production is set to 0.

\(\small reserve.energy = 0\)

RESERVE PRODUCTION (behavior RESERVE is active)

Reserve production costs

For each reserve a production cost is associated to the reserve production:

\(\small objectiveFunction += reserve.energy * \boldsymbol{reserve.cost}\)

Maximal participation

A given unit can only allocate a part of its running capacity to produce reserve, since starting up/switching off more capacity would take longer than the available delay. This part is determined by the parameter reserve.maxShare. This parameter applies for the considered reserve and all the reserves in the same direction (up or down) which have a shorter activation delay than the considered reserve.

\(\small \sum_{res \, | \, \{res.delay \leq reserve.delay \text{ and } res.isUp = reserve.isUp\}}^{reserveList}{res.energy}\) \(\small ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\leq runningCapacity * \boldsymbol{reserve.maxShare}\)

Two additional constraints involving the electricity production also applies. A given unit cannot produce more than its running capacity and less than its minimum load:

  • \(\small energyDelivery + \sum_{res \, | \, \{res.delay \leq reserve.delay \text{ and } res.isUp = True\}}^{reserveList}{res.energy} \leq runningCapacity\)
  • \(\small energyDelivery - \sum_{res \, | \, \{res.delay \leq reserve.delay \text{ and } res.isUp = False\}}^{reserveList}{res.energy} \geq runningCapacity * \boldsymbol{runningCapacityMinLoad}\)

Tertiary reserve

For a manually (isManual is True) activated reserve (ex: mFRR) the equations above may slightly change for peaking and hydro units (isQuickStart is True). Indeed, tertiary reserve activation delay may be long enough for peaking or hydro units to start up non-running capacity (reserve.notRunningEnergy) and to generate power within this delay. In terms of equations, it leads to substitute the runningCapacity by pmax * availability and the runningCapacityMinLoad by 0 in the equations above.

Reserve production corresponding to non-running capacity comes with an additional cost:

\(\small reserve.energy = reserve.runningEnergy + reserve.notRunningEnergy\) \(\small objectiveFunction += reserve.notRunningEnergy * \boldsymbol{reserve.notRunningCost}\)
addReserveProductionStorage(asset, state, energyDelivery= 'PRODUCTION' , energyPickup= 'CONSUMPTION' , pmax= 'PMAX' , pmaxIn= 'PMAX_IN' , availability= 'AVAILABILITY' , reserveList= 'DefaultReserveList' )

Add reserve production constraints to a storage asset

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the main energy delivery parameter (not reserve delivery)
  • energyPickup (string) – name of the main energy pickup parameter (not reserve pickup)
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxIn (string or DataWrapper) – dataname of the PmaxIn of the asset in simulation mode
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • reserveList (List of Reserve objects (see: Reserve object definition in DefaultVar)) – list of the reserves this asset can produce
Returns:

None

NOTATIONS

Each reserve of the reserveList has the following parameters:

  • reserve.energy: name of the reserve energy (ex : syncResUp)
  • reserve.isUp: boolean that sets the reserve direction. True if it is an upward reserve, False otherwise
  • reserve.isManual: boolean that sets how the reserve is activated. True if it is activated manually, False otherwise
  • reserve.maxShare: maximal share of the running capacity (respectively available capacity) that can be used to provide automatic (respectively manual) reserve
  • reserve.cost: reserve production cost
  • reserve.delay: activation delay in hour
  • reserve.delivery_duration: duration during which the capacity must be reserved
  • reserve.notRunningCost: cost for starting non-running capacity to provide reserve

Introduced variables:

  • overallAvailableCapacity: maximum capacity available for upward/downward reserve \(\small overallAvailableCapacity = pmax + pmaxIn\)
  • limitedRunningCapacity: maximum capacity available for upward/downward reserve for STEPs, half of the overallAvailableCapacity

NO RESERVE PRODUCTION (behavior RESERVE is inactive)

If the behavior RESERVE is inactive, each reserve production is set to 0.

\(\small reserve.energy = 0\)

RESERVE PRODUCTION (behavior RESERVE is active)

Reserve production costs

For each reserve a production cost is associated to the reserve production:

\(\small objectiveFunction += reserve.energy * \boldsymbol{reserve.cost}\)

Maximal participation

A given unit can only allocate a part of its running capacity to produce reserve, since starting up/switching off more capacity would take longer than the available delay. This part is determined by the parameter reserve.maxShare. This parameter applies for the considered reserve and is relative to the overallAvailableCapacity for the STEPs and the overallAvailableCapacity for the others.

  • for STEPs : \(res.energy \leq limitedRunningCapacity * \boldsymbol{reserve.maxShare}\)
  • for other storages : \(res.energy \leq overallAvailableCapacity * \boldsymbol{reserve.maxShare}\)

Power constraints

Two constraints involving the electricity production and the energy delivery also apply (for STEPs, change overallAvailableCapacity to limitedRunningCapacity). A given unit cannot produce more upward reserve than its capacity :

  • \(\small energyDelivery - energyPickup + \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy} \leq pmax\)

A given unit cannot produce more downward reserve than its capacity too :

  • \(\small energyPickup - energyDelivery + \sum_{res \, | \, \{res.isUp = False\}}^{reserveList}{res.energy} \leq pmaxIn\)

Storage constraints

Two constraints involving the electricity production and the energy delivery also apply for storage(for STEPs, change overallAvailableCapacity to limitedRunningCapacity). A given unit must be able to reserve capacity for the delivery duration of the considered reserves :

  • \(\small energyDelivery - energyPickup + \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy*res.delivery_duration} \leq stock*efficiency_output\)
  • \(\small energyPickup - energyDelivery + \sum_{res \, | \, \{res.isUp = False\}}^{reserveList}{res.energy*res.delivery_duration} \leq (stock_max-stock)*efficiency_input\)
addStock(asset, state, energyDelivery= 'PRODUCTION' , energyPickup= 'CONSUMPTION' , initialStorageLevel= 0 , minStorageLevel= None , inputEfficiency= 100.0 , outputEfficiency= 100.0 , storageCapacity= 'STORAGE_CAPACITY' , maxStorageCapacity= 'MAX_STORAGE_CAPACITY' , minStorageCapacity= 'MIN_STORAGE_CAPACITY' , storageCapex= 'STORAGE_CAPEX' , pmax= 'PMAX' , pmaxmax= 'PMAXMAX' , dischargeTime= 'DISCHARGE_TIME' , storageAvailability= 100.0 , storageLossRate= 'LOSS_RATE' , storageCost= 'STORAGE_COST' , boundedSupply= 'BOUNDED_SUPPLY' , prorataSupply= 'PRORATA_SUPPLY' , prorataSupplyCoef= 'PRORATA_SUPPLY_COEF' , fixedSupply= 'FIXED_SUPPLY' , fixedDemand= 'FIXED_DEMAND' , reserveList= 'DefaultReserveList' , addToModel= True , initialEqualsFinal= False )

Add a stock module to the asset

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • energyPickup (string) – name of the energy pickup parameter
  • initialStorageLevel (string or DataWrapper (or "None")) – dataname of the initial stock level
  • minStorageLevel (string or DataWrapper (or "None")) – dataname of the storage minimum level
  • inputEfficiency (string or DataWrapper (or 100.0)) – dataname of the input efficiency
  • outputEfficiency (string or DataWrapper (or 100.0)) – dataname of the output efficiency
  • storageCapacity (string or DataWrapper) – dataname of the storage capacity
  • maxStorageCapacity (string or DataWrapper) – dataname of the maximum storage capacity in capacity optimization mode
  • minStorageCapacity (string or DataWrapper) – dataname of the minimum storage capacity in capacity optimization mode
  • storageCapex (string or DataWrapper) – dataname of the investment cost for the stock capacity optimization
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • pmaxmax (string or DataWrapper) – dataname of the maximal Pmax of the asset in capacity optimization mode
  • dischargeTime (string or DataWrapper) – discharge time (in case a fixed discharge time is used, and production capacity of the asset is optimized)
  • storageAvailability (string or DataWrapper (or "None")) – dataname of the storage availability of the asset
  • storageLossRate (string or DataWrapper) – dataname of the loss rate applied to the asset storage
  • storageCost (string or DataWrapper) – dataname of the cost of storage
  • boundedSupply (string or DataWrapper (or "None")) – dataname of the bounded supply to add to the asset storage
  • prorataSupply (string or DataWrapper (or "None")) – dataname of the prorata supply to add to the asset storage (type of bounded supply proportional to the production capacity)
  • prorataSupplyCoef (string or DataWrapper (or "None")) – dataname of the optionnal coefficient for the prorata supply to add to the asset storage (type of bounded supply proportional to the production capacity)
  • fixedSupply (string or DataWrapper (or "None")) – dataname of the fixed supply to add to the asset storage
  • fixedDemand (string or DataWrapper (or "None")) – dataname of the fixed demand to add to the asset storage
  • reserveList (list of Reserve object) – list of reserve procured by the asset
  • addToModel (boolean) – boolean that adds the storage module to the model when true. WARNING : the user MUST add the moduleStock to the model himself if false
  • initialEqualsFinal (boolean) – If we want the final storage value to be equal to the initial storage
Returns:

StockModule, in case the user wants to add user constraints in the asset xml

NOTATIONS

Each reserve of the reserveList has the following parameters:

  • reserve.energy: name of the reserve energy (ex : syncResUp)
  • reserve.isUp: boolean that sets the reserve direction. True if it is an upward reserve, false if it is a downward reserve

Introduced variables:

  • stock: level of the stock

COMMON CONSTRAINTS

Storage evolution

The stock is filled by the energyPickup and is discharged to the energyDelivery.

inputEfficiency fraction of the input energy that is effectively filling the stock, models the losses when filling the stock.

outputEfficiency fraction of the output energy that is effectively arriving to the delivery point, models the losses when discharging the stock.

Another supply can also be specified, whose hourly volume is defined in the boundedSupply parameter.

\(\small stock_{(t)} = l_{(t)} * [~stock_{(t-1)} ~+\) \(\small ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (\boldsymbol{energyPickup_{(t)}} * ~\boldsymbol{inputEfficiency} -\boldsymbol{energyDelivery_{(t)}} * 1 / ~\boldsymbol{outputEfficiency} ) * timeStepDuration\) \(\small ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (+ ~\boldsymbol{boundedSupply_{(t)}}) ]\)

where

\(\small l_{(t)} = exp(-lossRate * dt)\)

If you need a bounded supply proportional to the production capacity (which can be helpful when optimizing the capacity of some technologies), you can instead specify a prorata supply . This prorata supply is defined by a chronique, but can also easily be redimensionned by using the parameter prorataSupplyCoef.

\(\small stock_{(t)} = l_{(t)} * [~stock_{(t-1)} ~+\) \(\small ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (\boldsymbol{energyPickup_{(t)}} * ~\boldsymbol{inputEfficiency} -\boldsymbol{energyDelivery_{(t)}} * 1 / ~\boldsymbol{outputEfficiency} ) * timeStepDuration\) \(\small ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (+ ~\boldsymbol{prorataSupply_{(t)}} * \boldsymbol{productionCapacity} * \boldsymbol{prorataSupplyCoef} ) ]\)

Initial storage level

At at the first time step, the storage level is defined by initialStorageLevel, as a percentage of the storage capacity.

\(\small stock_{(0)} = \boldsymbol{initialStorageLevel} * \boldsymbol{storageCapacity}\)

Maximum storage level

The maximum storage level is bounded by storageCapacity.

\(\small stock \leq \boldsymbol{storageCapacity} * \boldsymbol{storageAvailability}\)

Minimum storage level

The minimum storage level is bounded by minStorageLevel. To handle long term storage plan, it is common to have a non zero value for the minStorageLevel only at the end of the tactical horizon. This value would have been defined according to yearly storage optimization.

\(\small stock \geq \boldsymbol{minStorageLevel} * \boldsymbol{storageCapacity}\)

Storage cost

Add a penalty to the global objective proportional to the storage. It is used to handle equivalent solutions, by favouring the storage discharge. The storageCost value needs to be very small regarding other operational costs.

\(\small objectiveFunction += stock * \boldsymbol{storageCost}\)

RESERVE CONSTRAINTS (behavior RESERVE is active)

Additional constraints on the storage evolution are necessary if the storage module can procure reserve. Indeed, it is necessary to make sure that the storage level is adequate if a reserve energy is used during the balancing time frame.

Upward reserve

If upward reserve is used, the storage level has to be high enough to face the higher energy demand:

\(\small \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy} \leq stock * \boldsymbol{outputEfficiency}\)

Downard reserve

If downward reserve is used, the storage level has to be low enough to face the lower energy demand:

\(\small \sum_{res \, | \, \{res.isUp = False\}}^{reserveList}{res.energy} \leq (\boldsymbol{storageCapacity} - stock) * \boldsymbol{outputEfficiency}\)

CAPACITY OPTIMIZATION

behavior DISCHARGE_TIMES and behavior OPTIM_PMAX are active

If these two behaviors are active, then only the _pmax parameter of the asset is optimized, and the storage capacity is implicitly redefined with the relation :

\(\small storageCapacity = \boldsymbol{dischargeTime} * pmax\)

Note

Use addDischargeStock if you want to use DISCHARGE_TIMES behavior

[5]If a storageLossRate is specified, a fraction of the storage volume is lost between two time steps. In the equation, \(\small stock_{(t-1)}\) is replaced by : \(\small stock_{(t-1)} * e^{(-~lossRate~*~dt)}\)

NB: in case of heuristic, the constraints are changed to take into account the weights of the represented weeks

** Initial storage level equals final storage level **

If initialEqualsFinal is set to True and minStorageLevel does not exist (or equals 0), the final storage level has to match the original storage level:

\(\small stock_{(0)} = stock_{(strategicHorizon-1)}\)

In order to avoid infeasibilities, this constraint is not used when minStorageLevel exists.

addTargetInVolume(asset, state, interfaceName, isInput, maxVolume, minVolume, maxProfile, minProfile)

Set a minimum and maximum target in volume for the given interface (where the volume is the cumulative of the interface production/consumption)

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • interfaceName (String) – name of the interface whose flow (production or consumption) must be limited in volume
  • isInput (Boolean) – boolean set to True if interfaceName is an energy pickup, False if it is an energy delivery
  • maxVolume (double) – max target in volume at the last time step of the simulation (strategic horizon)
  • minVolume (double) – min target in volume at the last time step of the simulation (strategic horizon)
  • maxProfile (DataWrapper) – maximal volume profile, expressed as a percentage of the maxVolume
  • minProfile (DataWrapper) – minimal volume profile, expressed as a percentage of the minVolume

NO TARGET IN VOLUME (behavior VOLUME_TARGET is not active)

In this case no constraints are set

TARGET IN VOLUME (behavior VOLUME_TARGET is active)

Total interface production/consumption must be at the end of the simulation between minVolume and maxVolume :

\(\small \boldsymbol{minVolume} \leq cumulativeInterface_{(t=strategic horizon)} \leq \boldsymbol{maxVolume}\)

Profiles (percentage) are used to limit cumulative interface production/consumption at each time-step t of the simulation :

\(\small \boldsymbol{minVolume} * \boldsymbol{minProfile_{(t)}} \leq cumulativeInterface_{(t)} \leq \boldsymbol{maxVolume} * \boldsymbol{maxProfile_{(t)}}\)

Warning

Please note that minProfile and maxProfile are guidelines to reach at the end of the simulation a volume between the minVolume and maxVolume. Then both minProfile and maxProfile should be increasing from 0 at t=0- to 1 at t=strategicHorizon to be consistent with the above defined constraints.

addTransmissionReserveProduction(asset, state, energyPickup= 'CONSUMPTION' , energyDelivery= 'PRODUCTION' , pmax= 'PMAX' , availability= 'AVAILABILITY' , losses= 'LOSSES' , reserveList= 'DefaultReserveList' )

Add reserve production constraints to a transmission asset

Parameters:
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • energyPickup (string) – name of the main energy pickup parameter
  • energyDelivery (string) – name of the main energy delivery parameter (not reserve delivery)
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
  • availability (string or DataWrapper) – dataname of the availability of the asset
  • losses (string or DataWrapper) – dataname of the losses between the energy pickup and the energy delivery of the asset
  • reserveList (List of Reserve objects (see: Reserve object definition in DefaultVar)) – list of all the reserves this asset can procure
Returns:

None

NOTATIONS

Each reserve of the reserveList has the following parameters:

  • reserve.energy: name of the reserve energy (ex : syncResUp)
  • reserve.isUp: boolean that determines the reserve direction. True if it is an upward reserve, False otherwise
  • reserve.cost: reserve production cost

NO RESERVE PRODUCTION (behavior RESERVE is inactive)

If the behavior RESERVE is inactive, each reserve production is set to 0.

\(\small reserve.energy = 0\)

RESERVE PRODUCTION (behavior RESERVE is active)

Upper reserve production bounds

The upper bound for each reserve production is set to pmax

\(\small reserve.energy \le \boldsymbol{pmax}\)

General production bounds

The total production (electricity + upward reserves) cannot exceed the available capacity (losses included) of the transmission line.

\(\small energyDelivery + \sum_{res \, | \, \{res.isUp = True\}}^{reserveList}{res.energy} \leq \boldsymbol{pmax} * \boldsymbol{availability} * ( 1 - \boldsymbol{losses})\)

General consumption bounds

The total consumption (electricity + downward reserves) cannot exceed the available capacity of the transmission line.

\(\small energyPickup + \sum_{res \, | \, \{res.isUp = False\}}^{reserveList}{res.energy} \leq \boldsymbol{pmax} * \boldsymbol{availability}\)

Reserve production costs

For each reserve a production cost is associated to the reserve production:

\(\small objectiveFunction += reserve.energy * \boldsymbol{reserve.cost}\)
addUnitMode(asset, stateON, energyDelivery= 'PRODUCTION' , co2Delivery= 'CO2' , fuelPickup= 'FUEL_CONSUMPTION' , fuelYieldOrEfficiency= 'FUEL_YIELD' , fuelYieldPmin= 'FUEL_YIELD_PMIN' , fuelCo2Content= 'FUEL_CO2_CONTENT' , co2Content= 'CO2_CONTENT' , co2ContentRunningBound= 'CO2_CONTENT_RUNNING_BOUND' , minOnTime= 'MIN_ON_TIME' , pMax= 'PMAX' , runningCapacityMinLoad= 'RUNNING_CAPACITY_MIN_LOAD' , minOffTime= 'MIN_OFF_TIME' , reserveList= 'DefaultReserveList' , startingCost= 'STARTING_COST' , stoppingCost= None , productionCost= 'PRODUCTION_COST' , stateOffName= 'OFF' , startUpTime= 'STARTUP_TIME' )

Create and update states for an asset for which Unit behavior is active

Parameters:
  • asset (Asset) – asset to configure
  • stateON (AssetState) – state to configure
  • energyDelivery (string) – name of the energy delivery parameter
  • co2Delivery (string) – name of the co2 delivery parameter
  • fuelPickup (string) – name of the fuel pickUp parameter
  • fuelYieldOrEfficiency (string) – fuel yield when the asset is running at pMax
  • fuelYieldPmin (string) – name of the yield when unit is running at runningCapacityMinLoad*Pmax parameter.
  • fuelCo2Content (string) – dataname of the yield between the fuel consumption and the CO2 production
  • co2Content (string or DataWrapper) – dataname of the yield between the electricity and the CO2 production (if behaviour fuel not activated)
  • co2ContentRunningBound (string or DataWrapper) – dataname of the yield between the running capacity (pmax) and the CO2 production (if behaviour fuel not activated)
  • minOnTime (string or DataWrapper) – dataname of the minimal duration of the state “stateON” in hours (or “None” if there isn’t one)
  • pMax (string) – dataname of the max capacity of the asset
  • runningCapacityMinLoad (percentage) – dataname of the min load of the asset
  • minOffTime (string or DataWrapper) – dataname of the minimal duration of the state “stateOFF” in hours (or “None” if there isn’t one)
  • reserveList (string) – default name of the reserveList
  • startingCost (string or DataWrapper) – dataname of the transition cost to “stateON” in euros (or “None” if there isn’t one)
  • stoppingCost (string or DataWrapper) – dataname of the transition cost to “stateOFF” in euros (or “None” if there isn’t one)
  • stateOffName (string) – name of the “stateOFF” state in case a state named “OFF” already exists
  • productionCost (string or DataWrapper) – dataname of the production cost in €/MWh for the asset (or “None” if there isn’t one)
  • startUpTime (string) – name of the transition’s duration between OFF and ON state parameter.
Returns:

None

State On

If the asset has a min On time greater than timeStepDuration:

\(\small minDuration(stateON) = minOnTime / timeStepDuration\)

If the asset has a startup cost greater than 0:

\(\small stateOn.setTransitionCost(startUpCost)\)

State Off

No electricity production:

\(\small energyDelivery_{stateOff} = 0\)

If the asset has a min Off time greater than timeStepDuration:

\(\small minDuration_{stateOff} = minOffTime / timeStepDuration\)

If the asset has a shutdown cost greater than 0:

\(\small stateOff.setTransitionCost(startUpCost)\)

State RampUp

If the asset has a startUp duration greater than timeStepDuration we define a rampUp state with the following constraint:

\(\small minDuration_{stateRampUp} = startUpTime / timeStepDuration\)

No electricity production during start up process:

\(\small energyDelivery_{stateRampUp} = 0\)

We force asset to produce at minLoad * Pmax at the end of the start up process thus at the first time step asset is in state On:

\(\small interStateGradientUpperBound_{stateRampUp \rightarrow stateOn} = runningCapacityMinLoad * pMax * availabilty_{t}\)

Co2 production and fuel consumption :

Add CO2 production and fuel consumption corresponding to a linear ramp between 0 and their values at first time step of state On
finalize(state)

Add the state to the model and runs post-treatment functions if necessary.

Returns:None
forceConstantInterface(MODEL, asset, interfaceName, isInput)

Force an interface production or consumption variable to be constant over time if CONSTANT_VAR behavior is active

Parameters:
  • MODEL (AssetModel) – asset model to configure
  • asset (Asset) – asset to configure
  • interfaceName (String) – name of the interface whose flow (production or consumption) must be equal
  • isInput (Boolean) – boolean set to True if interfaceName is an energy pickup, False if it is an energy delivery
Returns:

None

forceInitialEqualFinal(asset, moduleStock, minStorageLevel)

Force the final storage value to be equal to the initial storage value :param asset: asset to configure :type asset: Asset :param moduleStock: stock module to configure :type moduleStock: StockModule :param minStorageLevel: storage minimum level in percentage of the storage capacity (in [0,1]) :type minStorageLevel: DataWrapper (or “None”)

Note

Please note that the initial and final storage value are the ones at the beginning and at the end of each simulation, then if rolling horizons are used then the storage value will be equal to the initial storage value at the end of each tactical horizons

NB: in case of heuristic, the constraint is changed to take into account the weights of the represented weeks

nationalReserveProcurement()

Set the minimal reserve procurement constraint for each country, represented by a node, inside a reserve procurement cooperation node. Also set the constraints allowing transmissions to exchange reserve energy

Returns:None

INTRODUCTION

With regional cooperation, countries can share their imbalance risks to decrease global reserve sizing requirements by pooling part of it. Indeed, for a given level of security of supply, the total regional reserve requirement is lower.

Then each country can procure reserve locally from assets from its nodes, but also reserves a part of its transmission capacity to meet the total reserve requirements.

Modelling details can be found here (4.5.4 Reserve sharing)

NOTATIONS

-\(\small reserveAsset_{node}^{reserve}\) : reserve asset of type Reserve for the country \(\small node\) and the reserve energy \(\small reserve\). For each \(\small reserveAsset_{node}^{reserve}\), the two following parameters are used here :

  • \(\small totalReserve_{node}^{reserve}\) : from parameter _demand, it represents the total reserve requirement necessary for the country \(\small node\) and the reserve energy \(\small reserve\).
  • \(\small localReserve_{node}^{reserve}\) : from parameter _localReserve, it represents the fraction of the total reserve requirement that needs to be procured locally for the country \(\small node\) and the reserve energy \(\small reserve\).

-For a given asset from the model, the following variable is used :

  • asset.reserve : the variable associated to the procurement of the reserve named reserve for this asset

NATIONAL RESERVE PROCUREMENT CONSTRAINTS

For each node and for each reserve energy, a minimum share of the total requirement needs to be procured locally. Then, the sum of reserve procurement of all assets of the given node needs to be greater than the minimum share :

For each \(\small node\) and for each \(\small reserve\) energy in the model :

\(\small \sum_{asset \in node}{asset.reserve} \geq totalReserve_{node}^{reserve} * localReserve_{node}^{reserve}\)

CROSS-BORDER CAPACITY RESERVATION

For each node and for each reserve energy, if the total reserve requirement is not met only with local reserve procurement, then cross-border reservation needs to be done. For all transmissions within a cooperation region, the reserve procurement constraints needs to be set to satisfy this reservation. This is done with the method addTransmissionReserveProduction().

reserveSymmetryRequirement(activationPerNode)

Set reserve symmetry requirement constraints

Parameters:activationPerNode (dictionary) – for each node, an activation value is set. 1 stands for “activate symmetry requirement”, and 0 for “no symmetry requirement”
Returns:None

Warning

The symmetry requirement only applies to syncResUp and syncResDown energies. If these two reserve energies are not defined in the model, no additional constraints are set, even if nodes are listed in the activationPerZone dictionary.

NOTATIONS

For a given asset from the model, the following variable is used :

  • asset.reserve : the variable associated to the procurement of the reserve named reserve for this asset

CONSTRAINTS

For each node of the model, if the value from activationPerZone is set to 1, then symmetry requirement constraint is set for all assets from this node that can procure syncResUp and syncResDown.

For each \(\small asset\) with symmetry requirement :

\(\small asset.syncResUp = asset.syncResDown\)
getTransmissionFlowBasedConstraints(portfolio)
Parameters:portfolio – model portfolio
Returns:None

On a simulation that uses the flow-based model, each timestep is associated to a flow-based domain thanks to the flow-based domain map given by the model object.

CHECKS

  1. The model object instantiation of “TRANSMISSION_FLOW_BASED” needs to be unique, otherwise we do not know which one tu use to set the constraints.

  2. The model object is used because there are transmissions with the behavior flow-based activated and constraints need to be set, otherwise, the model stops there.

  3. On transmissions with the behavior flow-based activated, the model checks if:

    • the energy type for pick-up and delivery for one transmission is the same,
    • the energy type for all the flow-based transmission is the same.

One flow-based domain gives us information (PTDFs and RAM) on a certain number of critical network elements (CNECs) which will bind the possible flows on the interconnections with the flow-based behavior activated. Thus, on each timestep, for each CNEC of the given flow-based domain, the constraint is :

\(\small \sum_{transmission\, | \, \{transmission.BH = FLOW\_BASED\}}{(PTDF_{FB,A} - PTDF_{FB,B})*transmission(A \rightarrow B).getOutQtyVar(\boldsymbol{energyDelivery})\leq RAM}\)

To improve the model, two other coupling methods, derived from the flow-based, have been added: the Advanced Hybrid Coupling and Evolved Flow-Based.

The Advanced Hybrid Coupling (AHC) integrates to the model the NTC connections between the flow-based nodes (interface of at least one flow-based transmission) and neighbouring ones.

\(\small leftTerm ~+= \sum_{transmission(zoneAHC \rightarrow zoneFB)}{(PTDF_{AHC,transmission} - PTDF_{FB,zoneFB})*transmission(zoneAHC \rightarrow zoneFB).getOutQtyVar(\boldsymbol{energyDelivery})}\) \(\small ~+ \sum_{transmission(zoneFB \rightarrow zoneAHC)}{(PTDF_{FB,zoneFB} - PTDF_{AHC,transmission})*transmission(zoneFB \rightarrow zoneAHC).getOutQtyVar(\boldsymbol{energyDelivery})}\)

The Evolved Flow-Based (EvFB) integrates to the model the HVDC lines between two flow-based nodes.

\(\small leftTerm ~+= \sum_{transmission\, | \, \{transmissionEvFB\}}{(PTDF_{evFB,transmission})*transmission.getOutQtyVar(\boldsymbol{energyDelivery})}\)

CHECKS

  1. The Flow-Based Domain Map is correct and associates to each timestep a Flow-Based Domain with given data.

  2. A given Flow-Based Domain is complete, meaning for each CNEC of the domain:

    • PTDF data exists for all the nodes located from either side of all transmission with behavior Flow-Based activated,
    • RAM data is given.
setTransmissionEquality(portfolio, assetType)

Set a constraint imposing that the increase of installed capacity of all transmission or pipeline lines to be equal in the two ways. Only in capacity optimization mode.

Parameters:
  • portfolio (Portfolio) – model portfolio
  • assetType (String) – dataname of the asset type
Returns:

None

For instance, for a transmission line between a zone A and a zone B, when there is capacity optimization, the constraint is :

\(\small optimP_{max}(A \rightarrow B) - P_{maxmin}(A \rightarrow B) = optimP_{max}(B \rightarrow A) - P_{maxmin}(B \rightarrow A)\)

The difference between the optimized pmax \(optimP_{max}\) and the minimal pmax \(P_{maxmin}\) for each ways A to B or B to A must be equal.

setPipelineReverseFlowConstraints(portfolio)

Add a pipeline reverse flow constraint on all pipelines

Parameters:portfolio (Portfolio) – model portfolio
Returns:None

For two opposing pipelines between delivery points A and B such as \(\small capex(A \rightarrow B) + foc(A \rightarrow B) <= capex(B \rightarrow A) + foc(B \rightarrow A)\), we have :

\(\small optimPmax(A \rightarrow B) <= optimPmax(B \rightarrow A)\)

If \(\small capex(A \rightarrow B) + foc(A \rightarrow B) <= capex(B \rightarrow A) + foc(B \rightarrow A)\) and \(\small pmaxmin(A \rightarrow B) >= pmaxmin(B \rightarrow A)\), data is considered inconsistent and an error will be returned

Note: It is assumed that there is no more than one pipeline between two zones in one direction

variableStorageInjectionCapacity(MODEL, asset, state, moduleStock, energyPickup= 'CONSUMPTION' , energyDelivery= 'PRODUCTION' , pmax= 'PMAX' , pmaxIn= 'PMAX_IN' , storageCapacity= 'STORAGE_CAPACITY' , dischargeTime= 'DISCHARGE_TIME' , pmaxInOutRatio= 100.0 )

Set a constraint that limits the injection capacity depending on the storage level.

Parameters:
  • MODEL (AssetModel) – model to configure
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • moduleStock (StockModule) – stock module to configure
  • energyPickup (string) – name of the picked up energy
  • energyDelivery (string) – name of the delivered energy
  • pmax (DataWrapper) – pmaxOut of the asset
  • pmaxIn (DataWrapper) – pmaxIn of the asset
  • storageCapacity (DataWrapper) – dataname of the storage capacity
  • dischargeTime (DataWrapper) – dataname of the discharge time
  • pmaxInOutRatio (DataWrapper) – dataname of the discharge time
Returns:

None

This constraint was designed to work with a regular pmax upper bound constraint on the energyPickup, often set with addEnergyConsumption. For clarity reason, we assume that this constraint has already been set.

  • If the storage level is between 0% of the storage capacity and _injectionInflexionStorageLevel , the energyPickup is bounded by pmax
  • If the storage level is between _injectionInflexionStorageLevel and 100% of the storage capacity,
    the energyPickup upper bound limitation decreases linearly from pmax to _filledStorageRatioInjection (as % of pmax)

Warning

If behavior USE_PMAX_IN is active, the parameter pmaxIn is used instead of pmax for the Previous equations.

If behavior OPTIM_PMAX or OPTIM_PATHWAY is active:

  • DISCHARGE_TIMES behavior must be active to use this constraint

  • USE_PMAX_IN behavior value is ignored, and the storageCapacity and the pmax upper bound are defined as follows:

    \(\small pmax = pmaxInOutRatio * optimizedPmax\)

    \(\small storageCapacity = dischargeTime * optimizedPmax\)

variableStorageWithdrawalCapacity(MODEL, asset, state, moduleStock, energyDelivery= 'PRODUCTION' , pmax= 'PMAX' , storageCapacity= 'STORAGE_CAPACITY' , dischargeTime= 'DISCHARGE_TIME' )

Set a constraint that changes limits withdrawal capacity depending on the storage level.

Parameters:
  • MODEL (AssetModel) – model to configure
  • asset (Asset) – asset to configure
  • state (AssetState) – state to configure
  • moduleStock (StockModule) – stock module to configure
  • energyDelivery (string) – name of the delivered energy
  • pmax (DataWrapper) – pmaxOut of the asset
  • storageCapacity (DataWrapper) – dataname of the storage capacity
  • dischargeTime (DataWrapper or None) – dataname of the discharge time
Returns:

None

This constraint was designed to work with a regular pmax upper bound constraint on the energyDelivery, often set with addEnergyProduction. For clarity reason, we assume that this constraint has already been set.

  • If the storage level is between 0% of the storage capacity and _withdrawalInflexionStorageLevel ,
    the energyDelivery upper bound limitation increases linearly from _emptyStorageRatioWithdrawal % of pmax to pmax
  • If the storage level is between _withdrawalInflexionStorageLevel and 100% of the storage capacity,
    the energyDelivery is bounded by pmax

Warning

If behavior OPTIM_PMAX or OPTIM_PATHWAY is active:

  • DISCHARGE_TIMES behavior must be active to use this constraint

  • The storageCapacity is defined as follows:

    \(\small storageCapacity = dischargeTime * optimizedPmax\)

setDemandResponseModel(state, asset)

Set Demand response model constraints (this model typically represents the power demand of domestic hot water storage tank with an electric boiler)

INTRODUCED VARIABLES

  • electricityConsumption : electricty consumption of the asset

NON-FLEXIBLE DEMAND (behavior MUST_RUN is active)

The electricity consumption (input energy E) is equal to the given Raw demand timeseries :

\(\small \forall \text{ timesteps t : }\)

\(\small electricityConsumption(t) = \boldsymbol{\_demand}(t)\)

FLEXIBLE DEMAND (behavior MUST_RUN is inactive)

The model represent a useful demand that has to be satisfied periodically (_demandCycleDuration) at a given time (_demandFirstHour). This periodic demand is satisfied by a stock that can be recharged with the electricity consumption.

An example is the useful demand of sanitary hot water, satisfied by a water storage tank with an electric boiler. The hot water typically has to be produced daily and be ready during morning, but the water tank can be heated anytime before this moment. In this case, the asset parameters would have the following values:

  • \(\small \_demandCycleDuration = 24 h\)
  • \(\small \_demandFirstHour = 6 am\)

The periodic useful demand is calculated from a raw constant demand or a raw demand timeseries (parameter _demand). The power consumption is then jointly optimized with the power production during the simulation.

Equations

Let \(\small consumptionPeriod\) be the time span between two consecutive moments where the useful demand has to be satisfied. For the previous example, it would be the time span between 6am and 6am the day after.

The electricity consumption is optimized according to the following constraints :

\(\small \forall ~consumptionPeriod\)

\(\small \sum_{t \in consumptionPeriod}electricityConsumption(t) = \sum_{t \in consumptionPeriod} \boldsymbol{\_demand}(t)\)

\(\small \forall \text{ timesteps t : }\)

\(\small electricityConsumption(t) \leq \boldsymbol{\_pmaxIn}\)

Please note that if the \(\small consumptionPeriod\) is not reached at the end of the strategic horizon (=last time step of the simulation != _demandFirstHour), the last \(\small consumptionPeriod\) become the time span between the last moment where the useful demand has been satisfied (=last _demandFirstHour) and the last time step. The above constraints remain valid.

NB: in case of heuristic, the constraint is changed to take into account the weights of the represented weeks

setElectricVehiclesModel(state, asset)

Each electric vehicle asset represents a fleet of vehicles that can be recharged in a given location (e.g. at home, at work or on public). Vehicles are not modelled individually. Instead arrivals and departures timeseries are used to determine the evolution of vehicles connected to the charging location.

PARAMETERS

Parameters:
  • state (Asset) – asset to configure
  • asset (AssetState) – state to configure

Asset parameters :

Parameters:
  • totalEV – Total number of vehicles
  • initialConnectedEV – Percentage of connected EV at t=0
  • arrivals – Percentage of vehicles arriving at terminal
  • departures – Percentage of vehicles leaving from terminal
  • evStorageCapacity – EV storage capacity
  • evRecharge – Average journey discharge
  • evPmaxIn – Average charging capacity per vehicle and per time setp
  • inputEfficiency – EV charging efficiency
  • storageCost – Cost associated with storage
  • evPmaxOut – Average Vehicle-to-grid discharging capacity
  • outputEfficiency – EV discharging efficiency
  • productionCost – Production cost

Asset input and output :

Parameters:
  • energyPickup – electricty consumption
  • energyDelivery – electricity production (only in case of vehicle to grid)

Other :

Parameters:nbTimeSteps – Number of time step of the simulation (strategic horizon)

IMMEDIATE RECHARGE (behavior MUST_RUN is active)

Vehicles are charged immediately after arrival at the terminal location. The number of time steps necessary to recharge an electric vehicle after a typical journey is defined as follows :

\(\small nbTsRecharge = \left \lceil \frac{evRecharge}{evPmaxIn ~\cdot~ inputEfficiency} \right \rceil\)

The electricity consumption can then be expressed according to the arrivals timeseries, the average charging capacity per time step, and the number of time step of recharge :

\[\begin{split}\small energyPickup(t) &= \small \sum_{\substack{i=0 \\ t-i \geq 0}}^{nbTsRecharge-2} arrivals(t-i) \cdot totalEV \cdot evPmaxIn \cdot inputEfficiency \\ &~~~~~~+ \small \left ( evRecharge - inputEfficiency \cdot evPmaxIn \cdot (nbTsRecharge-1) \right )\end{split}\]

Please note that if the average journey discharge is not a multiple of the average charging capacity per time step (\(\small evPmaxIn \cdot inputEfficiency\)), the last time step of recharge of a electric vehicle cannot be made at full capacity, since the battery will be full already. Then, during this last hour of recharge (\(\small nbTsRecharge-1\) time steps after the arrival of the vehicle), the electric vehicle will only be recharged of the remaining battery capacity : \(\small evRecharge - inputEfficiency \cdot evPmaxIn \cdot (nbTsRecharge-1)\).

For example, with \(\small evRecharge = 5~kWh,~ inputEfficiency=1,~ evPmaxIn = 2~kW\):

If an electric vehicle arrives at the charging location at t, it will be recharged of 2 kWh at t, and 2 kWh at t+1, but only of \(\small 5-2 \times 2 = 1\) kWh at t+2.

OPTIMIZED RECHARGE (behavior MUST_RUN is inactive)

Recharge of all electric vehicles is jointly optimized with the electricity production during the simulation

A few hypotheses are taken for the charging process:

  • each vehicle must be totally charged before departure from terminal
  • the average journey discharge is the same for all vehicles, and is equal to evRecharge. Then, each vehicle arriving at the charging location have a level of recharge equal to \(\small evStorageCapacity - evRecharge\)

Notations

  • Number of connected vehicles at each time step t :

    \(\small connectedEV(t) = \left ( initialConnectedEV + \sum_{i=0}^{t} (arrivals(i) - departures(i)) \right ) * totalEV\)

  • Global storage capacity of all connected electric vehicles at each time step t :

    \(\small globalStorageCapacity(t) = connectedEV(t) * evStorageCapacity\)

  • Quantity of energy required by all electric vehicles leaving the charging location at each time step t :

    \(\small requiredDemandAtDepature(t) = evStorageCapacity * departures(t) * totalEV\)

Temporal variables

  • Energy stored by all electric vehicle in their batteries: \(\small stock\)

Equations

  • Evolution of the energy stored in all electric vehicles for all time steps t:

    \(\small stock(t) = stock(t-1) + energyPickup(t) * inputEfficiency + (evStorageCapacity - evRecharge) * arrivals(t) * totalEV - requiredDemandAtDepature(t)\)

    \(\small stock(t) \leq globalStorageCapacity(t)\)

    Storage cost : \(\small objectiveFunction += stock * storageCost\)

  • Charging limitation :

    \(\small energyPickup(t) \leq connectedEV(t) * evPmaxIn\)

VEHICLE TO GRID (behavior USE_ENERGY_PRODUCTION is active)

In the case of OPTIMIZED RECHARGE, electric vehicles can also inject electricity to the grid if the behavior USE_ENERGY_PRODUCTION (Vehicle to grid) is active. The full battery storage capacity (evStorageCapacity) of each connected electric vehicle can then be used to store electricity from the grid, and restitute it later in time.

Equations

The following equations are added to the previous ones defined in section OPTIMIZED RECHARGE:

  • The stock evolution constraint is modified in order to take into account the electric vehicle injection to the grid:

    \(\small stock(t) = stock(t-1) + energyPickup(t) * inputEfficiency - energyDelivery(t) * 1/outputEfficiency + (evStorageCapacity - evRecharge) * arrivals(t) * totalEV - requiredDemandAtDepature(t)\)

  • Injection limitation :

    \(\small energyDelivery(t) \leq connectedEV(t) * evPmaxOut(t)\)

  • Electricty production cost :

    \(\small objectiveFunction += energyDelivery * productionCost\)

buildHPcapacity(asset, state, temperature= 'TEMPERATURE' , bivalentTemp= 'BIVALENT_TEMP' , hpCapaAtBivalentTemp= 'BIVALENT_TEMP_PMAX' )

Heat pump capacities depend on the outside temperature (the colder, the less efficient). This function builds the HP capacity timeseries, according to the temperature timeseries.

Heat production split between the HP and the back-up heater

Heat production split between the HP and the back-up heater

For all timesteps t:

  • if \(\small temperature(t) >= bivalentTemp\) :

    \(\small heatPumpCapacity(t) = hpCapaAtBivalentTemp\)

  • if \(\small tempHpCapaEq0 < temperature(t) < bivalentTemp\):

    \(\small heatPumpCapacity(t) = hpCapaAtBivalentTemp * \frac{temperature(t) - tempHpCapaEq0}{bivalentTemp - tempHpCapaEq0}\)

  • if \(\small temperature(t) <= tempHpCapaEq0\):

    \(\small heatPumpCapacity(t) = 0\)

createHeatPumpConstraints(asset, state, heatPumpCapacity, temperature= 'TEMPERATURE' , copData= 'COP' , heatingDemand= 'HEATING_DEMAND' , energyPickup= 'CONSUMPTION' , fuelPickup= 'FUEL_CONSUMPTION' , co2Delivery= 'CO2' , backUpHeaterYield= 'BACKUP_HEATER_YIELD' , fuelCo2Content= 'FUEL_CO2_CONTENT' , dischargeTime= 'DISCHARGE_TIME' , storageCost= 'STORAGE_COST' , lossRate= 'LOSS_RATE' , backUpProductionCost= 0.001 )

Create the heat pump constraints

INTRODUCED VARIABLES

  • hpProduction : heat production of the heat pump
  • backUpProduction : heat production of the back-up heater
  • hpConsumption : energy consumption of the heat pump
  • backUpConsumption : energy consumption of the back-up heater

COMMON CONSTRAINTS

Heat pump upper production bound

\(\small \forall~timestep~t, hpProduction(t) \leq \boldsymbol{heatPumpCapacity}(t)\)

Back-up heater upper production bound

The back-up is sized in order to cover exactly the heat demand at the hour when the temperature is the lowest \(\small h_{T_{min}}\):

\(\small backUpCapacity = \boldsymbol{heatingDemand}(h_{T_{min}}) - \boldsymbol{heatPumpCapacity}(h_{T_{min}})\)

\(\small \forall~timestep~t, backUpProduction(t) \leq backUpCapacity\)

Heat pump and back-up heater efficiencies

\(\small \forall~timestep~t, hpProduction(t) = \boldsymbol{copData(temp}(t) \boldsymbol{)} * hpConsumption\)

\(\small \forall~timestep~t, backUpProduction(t) = \boldsymbol{backUpHeaterYield} * backUpConsumption(t)\)

Heating demand constraint

  • if the behavior MUST_RUN is active (no thermal storage):

    \(\small \forall~timestep~t, hpProduction(t) + backUpProduction(t) = \boldsymbol{heatingDemand}(t)\)

  • if the behavior MUST_RUN is inactive (thermal storage):

    Please refer to the below section THERMAL STORAGE

ELECTRIC BACK-UP HEATER (behavior GAS_BACKUP_HEATER is inactive)

Electricity consumption

\(\small \forall~timestep~t, \boldsymbol{energyPickup}(t) = \boldsymbol{hpConsumption}(t) + \boldsymbol{backUpConsumption}(t)\)

GAS BACK-UP HEATER (behavior GAS_BACKUP_HEATER is active)

Electricity consumption

\(\small \forall~timestep~t, \boldsymbol{energyPickup}(t) = \boldsymbol{hpConsumption}(t)\)

Gas consumption

\(\small \forall~timestep~t, \boldsymbol{energyFuel}(t) = \boldsymbol{backUpConsumption}(t)\)

THERMAL STORAGE (behavior MUST_RUN is inactive)

If the behavior MUST_RUN is inactive, a thermal storage is added to store the heat production of the heat pump and the back-up heater, in order to produce heat when the electricity/gas prices are lower, and restitute it later in time :

\(\small \forall~timesteps~t : storedHeat(t) = storedHeat(t-1) * (1 - \boldsymbol{lossRate}) + hpProduction(t) + backUpProduction(t) - \boldsymbol{heatingDemand}(t)\)

The thermal storage can store the equivalent of dischargeTime hours of heat production at full capacity :

\(\small storedHeat \leq \max_{t} (\boldsymbol{heatingDemand}(t)) * \boldsymbol{dischargeTime}\)

NB: in case of heuristic, the constraints are changed to take into account the weights of the represented weeks

addDcopfModel(asset, susceptance= 'SUSCEPTANCE' , phaseShiftMin= 'PHASE_SHIFT_MIN' , phaseShiftMax= 'PHASE_SHIFT_MAX' , energyPickup= 'CONSUMPTION' , reverseDirectionTransmission= 'REVERSE_DIRECTION_TRANSMISSION' )

Set DCOPF constraints if behavior DCOPF is active

Parameters:
  • asset (Asset) – asset to configure
  • susceptance (string or double) – name of the susceptance parameter or susceptance value. The susceptance should be normalised, and expressed in \(S.(kV)^{2}\)
  • phaseShiftMin (string or double) – name of the phaseShiftMin parameter, or phaseShiftMin value
  • phaseShiftMax (string or double) – name of the phaseShiftMax parameter, or phaseShiftMax value
  • energyPickup (string) – name of the energy pickup interface
  • reverseDirectionTransmission (string) – name of the transmission asset that represents the other flow direction of the current asset.
Returns:

None

If behavior DCOPF is active, set DCOPF (Direct Current Optimal power flow) constraints to a pair of transmissions/transformers (the asset itself and reverseDirectionTransmission asset). Please note that the equations above are only set once for the pair of the current asset and reverseDirectionTransmission.

ASSUMPTIONS FOR DCOPF

  • Resistances of lines is negligible compared to reactances. This assumption is typically valid in transmission systems (i.e. voltage superior to 200kV).
  • All the susceptances are normalized by the voltage value. It is then necessary to multiply the susceptance absolute value (in Siemens) by the Voltage of the input node and the voltage of the output node (both Voltage expressed in kV). The final susceptance parameter is then expressed in \(S.(kV)^{2}\)

NOTATIONS

  • Indices i,j refer to the input and output nodes of the asset.
  • \(\small \theta_k\) is the voltage angle of node k
  • \(\small \phi_{ij}\) is the phase shift angle of the asset. It can represent a constant offset, or a variable offset for phase shift transformers.
  • \(\small F_{ij}\) is the total energy flow from i to j, equal to the energy consumption from the current asset minus the energy consumption of reverseDirectionTransmission. The energy consumption is retrieved from energy interface energyPickup. Because of this definition, \(\small F_{ij}\) is positive if the flow is coming from i to j, and negative in the other direction.

DCOPF CONSTRAINTS

Active power constraint

\(\small F_{ij} = - susceptance * (\theta_j - \theta_i + \phi_{ij})\)

Phase shift angle

If phaseShiftMin or phaseShiftMax is None, we assume that there is no phase shift angle and then \(\small \phi_{ij} = 0\).

If \(\small phaseShiftMin \ne phaseShiftMax\), \(\small \phi_{ij}\) is a variable respecting :

\(\small phaseShiftMin \leq \phi_{ij} \leq phaseShiftMax\)
forceInitialStockEqualToFinalStock(MODEL, moduleStock)

Force the final stock level to be equal to the initial stock level

Parameters:
  • MODEL (AssetModel) – model to configure
  • moduleStock (StockModule) – stock module to configure
Returns:

None

addEnergyCost(state, energy, isInput, energyCost, asset= None , pmax= 'PMAX' )

Add a cost to the given energy (delivery or pickup depending on the isInput value)

Parameters:
  • state (AssetState) – state to configure
  • energy (string) – name of the energy as string
  • isInput (boolean) – cost of the energy
  • energyCost (DataWrapper) – cost of the energy
  • asset (Asset) – asset to configure
  • pmax (string or DataWrapper) – dataname of the Pmax of the asset in simulation mode
Returns:

None

Currently, linear costs are used :

  • If isInput = true :

\(\small objectiveFunction += energyPickup * energyCost\)

  • If isInput = false :

\(\small objectiveFunction += energyDelivery * energyCost\)

NB: in case of heuristic with a TS cost, the TS is changed to take into account the weights of the represented weeks

addEnergyYield(state, coef, energyA, energyB, isInputA= False , isInputB= False , offSet= 0 )

Add a linear yield function between two energies

Parameters:
  • state (AssetState) – state to configure
  • coef (DataWrapper or float) – yield between the two energies
  • energyA (string) – name of the energy as string
  • energyB (string) – name of the energy as string
  • isInputA (boolean) – indicate if energyA is an input or an output
  • isInputB (boolean) – indicate if energyB is an input or an output
  • offSet (DataWrapper or float) – offset of the affine relation we want between energy B and energy A
Returns:

None

The energy flows considered rely on the *isInput* values :

  • If isInputB = true and isInputA = true :

\(\small energyBpickup = coef * energyApickup\)

  • If isInputB = false and isInputA = true :

\(\small energyBdelivery = coef * energyApickup\)

  • If isInputB = true and isInputA = false :

\(\small energyBpickup = coef * energyAdelivery\)

  • If isInputB = false and isInputA = false :

\(\small energyBdelivery = coef * energyAdelivery\)

  • If offset != 0:

\(\small energyB = coef * energyA + offset\)

class Asset

Asset object

getData(dataName)

Get the data associated with dataName

Parameters:dataName (string) – data name
Returns:data
Return type:DataWrapper
getParameter(energyParameterName)

Get the energy name associated with energyParameterName

Parameters:energyParameterName (string) – energy parameter name
Returns:energy name
Return type:string
class AssetModel

Different models can be used for a same asset. An AssetModel represents one model

addState(state)

Add a state to an AssetModel

Parameters:state (AssetState) – the state to be added
class AssetState

Represents a possible state for an Asset

addLowerBound(energyName, isInput, lb)

Set a lower bound constraint on a given energy of the energy asset

Parameters:
  • energyName (string) – energy name
  • isInput (bool) – energy considered as an input or output
  • lb (DataWrapper) – lower bound
addUpperBound(energyName, isInput, ub)

Set an upper bound constraint on a given energy of the energy asset

Parameters:
  • energyName (string) – energy name
  • isInput (bool) – energy considered as an input or output
  • ub (DataWrapper) – upper bound
isActiveBehavior(behaviorName)

Test if the behavior associated to behaviorName is active

Parameters:behavior_name (string) – name of the behavior
Returns:boolean
setEquality(energyName, isInput, data)

Set an equality constraint on a given energy

Parameters:
  • energyName (string) – energy name
  • isInput (bool) – energy considered as an input or output
  • data (DataWrapper) – numerical value to be set
class DataWrapper

Data container used to hold different data types (float, timeSeries)

getValue(ts)

Get the value of a DataWrapper:

  • If ts is not provided : the DataWrapper must contain a float. the method returns the float value of the DataWrapper
  • If ts is provided : the DataWrapper must contain a TimeSeries. the method returns the value of the TimeSeries at time step ts
Parameters:ts (int) – time step
Returns:value
Return type:float
setValue(ts, val)

Set the value of a DataWrapper:

  • If ts is not provided : the value of the DataWrapper is set at val. If the DataWrapper contains a timeSeries, it is converted to a float
  • If ts is provided : the DataWrapper must contain a TimeSeries. the value of the TimeSeries at time step ts is set at val
Parameters:
  • ts (int) – time step
  • val (float) – value to set
TimeSeries(size)

Create a time serie with all its values at 0

Parameters:size (int) – size of the time serie
Returns:timeSeries
Return type:DataWrapper