Skip to content

Commit

Permalink
Implementation of LTStorage reserves v2
Browse files Browse the repository at this point in the history
  • Loading branch information
h-fournier committed Dec 13, 2024
1 parent 57ca4b4 commit 2b82698
Show file tree
Hide file tree
Showing 17 changed files with 499 additions and 122 deletions.
4 changes: 4 additions & 0 deletions src/solver/optimisation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ set(RTESOLVER_OPT
constraints/STStockEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h
constraints/STStockGlobalEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h
constraints/LTStockEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h
constraints/LTStockGlobalEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/ProblemMatrixEssential.h
ProblemMatrixEssential.cpp
include/antares/solver/optimisation/LinearProblemMatrixStartUpCosts.h
Expand Down
7 changes: 5 additions & 2 deletions src/solver/optimisation/constraints/ConstraintBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,12 @@ ConstraintBuilder& ConstraintBuilder::Pumping(unsigned int index, double coeff)
return *this;
}

ConstraintBuilder& ConstraintBuilder::HydroLevel(unsigned int index, double coeff)
ConstraintBuilder& ConstraintBuilder::HydroLevel(unsigned int index,
double coeff,
int offset,
int delta)
{
AddVariable(variableManager_.HydroLevel(index, hourInWeek_), coeff);
AddVariable(variableManager_.HydroLevel(index, hourInWeek_, offset, delta), coeff);
return *this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h"

void LTStockEnergyLevelReserveParticipation::add(int pays,
int cluster,
int reserve,
int pdt,
bool isUpReserve)
{
int globalClusterIdx = data.longTermStorageOfArea[pays].GlobalHydroIndex;
CAPACITY_RESERVATION& capacityReservation = isUpReserve
? data.areaReserves[pays]
.areaCapacityReservationsUp[reserve]
: data.areaReserves[pays]
.areaCapacityReservationsDown[reserve];

if (capacityReservation.maxActivationDuration > 0)
{
if (!data.Simulation)
{
// 15 (s) (1)
// Participation of down reserves requires a sufficient level of stock
// Sum(P_{res,t_st} * R_{min,res} +/- J_res * R_{lambda,t_st}) <= n_min * R_up
// R_t : stock level at time t
// P_{res,t_st} : power participation for reserve down res at time t_st
// R_{min,res} : max power participation ratio
// R_up : max stock level
{
float sign = isUpReserve ? -1. : 1.;

RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation
= capacityReservation.AllLTStorageReservesParticipation[cluster];

builder.updateHourWithinWeek(pdt);

for (int t = 0; t < capacityReservation.maxActivationDuration; t++)
{
if (isUpReserve)
{
builder.LTStorageClusterReserveUpParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
else
{
builder.LTStorageClusterReserveDownParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
builder.HydroLevel(
globalClusterIdx,
sign * capacityReservation.maxEnergyActivationRatio,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}

builder.lessThan();

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation
[reserveParticipation.globalIndexClusterParticipation]
= builder.data.nombreDeContraintes;

ConstraintNamer namer(builder.data.NomDesContraintes);
const int hourInTheYear = builder.data.weekInTheYear * 168 + pdt;
namer.UpdateTimeStep(hourInTheYear);
namer.UpdateArea(builder.data.NomsDesPays[pays]);
namer.LTEnergyStockLevelReserveParticipation(builder.data.nombreDeContraintes,
reserveParticipation.clusterName,
capacityReservation.reserveName);
builder.build();
}
}
else
{
builder.data.NbTermesContraintesPourLesReserves += 2
* capacityReservation
.maxActivationDuration;
builder.data.nombreDeContraintes += 1;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#include "antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h"

void LTStockGlobalEnergyLevelReserveParticipation::add(int pays, int cluster, int pdt)
{
int globalClusterIdx = data.longTermStorageOfArea[pays].GlobalHydroIndex;

if (!data.Simulation)
{
// 15 (t)
// Stock participation is energy constrained (optional constraints)
// Sum(P_{res,t_st} * R_{min,res} +/- J_down/up * R_{lambda,t_st}) <= n_min * R_up
// R_t : stock level at time t
// P_{res,t_st} : power participation for reserve down res at time t_st
// R_{min,res} : max power participation ratio
// R_up : max stock level

// DOWN reserves
{
builder.updateHourWithinWeek(pdt);

for (int t = 0; t < data.areaReserves[pays].maxGlobalActivationDurationDown; t++)
{
for (auto& capacityReservation:
data.areaReserves[pays].areaCapacityReservationsDown)
{
if (capacityReservation.AllLTStorageReservesParticipation.size())
{
RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation
= capacityReservation.AllLTStorageReservesParticipation[cluster];
builder.LTStorageClusterReserveDownParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}
if (builder.NumberOfVariables() > 0)
{
builder.HydroLevel(
globalClusterIdx,
data.areaReserves[pays].maxGlobalEnergyActivationRatioDown,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}

if (builder.NumberOfVariables() > 0)
{
builder.lessThan();

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown
[globalClusterIdx]
= builder.data.nombreDeContraintes;

ConstraintNamer namer(builder.data.NomDesContraintes);
const int hourInTheYear = builder.data.weekInTheYear * 168 + pdt;
namer.UpdateTimeStep(hourInTheYear);
namer.UpdateArea(builder.data.NomsDesPays[pays]);
namer.LTGlobalEnergyStockLevelReserveParticipationDown(
builder.data.nombreDeContraintes,
"LongTermStorage");
builder.build();
}
}

// UP reserves
{
builder.updateHourWithinWeek(pdt);

for (int t = 0; t < data.areaReserves[pays].maxGlobalActivationDurationUp; t++)
{
for (auto& capacityReservation: data.areaReserves[pays].areaCapacityReservationsUp)
{
if (capacityReservation.AllLTStorageReservesParticipation.size())
{
RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation
= capacityReservation.AllLTStorageReservesParticipation[cluster];
builder.LTStorageClusterReserveUpParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}
if (builder.NumberOfVariables() > 0)
{
builder.HydroLevel(
globalClusterIdx,
-data.areaReserves[pays].maxGlobalEnergyActivationRatioUp,
t,
builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}

if (builder.NumberOfVariables() > 0)
{
builder.lessThan();

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp
[globalClusterIdx]
= builder.data.nombreDeContraintes;

ConstraintNamer namer(builder.data.NomDesContraintes);
const int hourInTheYear = builder.data.weekInTheYear * 168 + pdt;
namer.UpdateTimeStep(hourInTheYear);
namer.UpdateArea(builder.data.NomsDesPays[pays]);
namer.LTGlobalEnergyStockLevelReserveParticipationUp(
builder.data.nombreDeContraintes,
"LongTermStorage");
builder.build();
}
}
}
else
{
// Lambda that count the number of reserveParticipations
auto countReservesParticipations =
[cluster](const std::vector<CAPACITY_RESERVATION>& reservations, int t_max)
{
int counter = 0;
for (const auto& capacityReservation: reservations)
{
counter += capacityReservation.AllLTStorageReservesParticipation.size()
* t_max;
}
return counter;
};

int nbTermsUp = countReservesParticipations(
data.areaReserves[pays].areaCapacityReservationsUp,
data.areaReserves[pays].maxGlobalActivationDurationUp);
int nbTermsDown = countReservesParticipations(
data.areaReserves[pays].areaCapacityReservationsDown,
data.areaReserves[pays].maxGlobalActivationDurationDown);

builder.data.NbTermesContraintesPourLesReserves += (nbTermsUp
+ data.areaReserves[pays]
.maxGlobalActivationDurationUp)
* (nbTermsUp > 0)
+ (nbTermsDown
+ data.areaReserves[pays]
.maxGlobalActivationDurationDown)
* (nbTermsDown > 0);
builder.data.nombreDeContraintes += (nbTermsUp > 0) + (nbTermsDown > 0);
}
}
Loading

0 comments on commit 2b82698

Please sign in to comment.