Skip to content

Commit

Permalink
first version of the implementation of the reserve equations v.2 for …
Browse files Browse the repository at this point in the history
…part 3
  • Loading branch information
bencamus committed Nov 28, 2024
1 parent 6613609 commit 1a3fe6e
Show file tree
Hide file tree
Showing 15 changed files with 465 additions and 80 deletions.
53 changes: 52 additions & 1 deletion src/libs/antares/study/area/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,49 @@ static bool AreaListLoadFromFolderSingleArea(Study& study,
ini.each(
[&](const IniFile::Section& section)
{
if (area.allCapacityReservations.contains(section.name))
if (section.name == "globalparameters" && section.firstProperty)
{
for (auto* p = section.firstProperty; p; p = p->next)
{
CString<30, false> tmp;
tmp = p->key;
tmp.toLower();

if (tmp == "max_activation_ratio_up")
{
if (!p->value.to<float>(area.allCapacityReservations.maxGlobalEnergyActivationRatioUp))
{
logs.warning()
<< area.name << ": invalid maximum energy activation ratio for UP reserves";
}
}
else if (tmp == "max_activation_ratio_down")
{
if (!p->value.to<float>(area.allCapacityReservations.maxGlobalEnergyActivationRatioDown))
{
logs.warning()
<< area.name << ": invalid maximum energy activation ratio for DOWN reserves";
}
}
else if (tmp == "max_activation_duration_up")
{
if (!p->value.to<int>(area.allCapacityReservations.maxGlobalActivationDurationUp))
{
logs.warning()
<< area.name << ": invalid maximum energy activation duration for UP reserves";
}
}
else if (tmp == "max_activation_duration_down")
{
if (!p->value.to<int>(area.allCapacityReservations.maxGlobalActivationDurationDown))
{
logs.warning()
<< area.name << ": invalid maximum energy activation duration for DOWN reserves";
}
}
}
}
else if (area.allCapacityReservations.contains(section.name))
{
logs.warning() << area.name << ": reserve name already exists for reserve "
<< section.name;
Expand Down Expand Up @@ -963,6 +1005,15 @@ static bool AreaListLoadFromFolderSingleArea(Study& study,
<< section.name;
}
}
else if (tmp == "max-energy-activation-ratio")
{
if (!p->value.to<float>(tmpCapacityReservation.maxEnergyActivationRatio))
{
logs.warning()
<< area.name << ": invalid maximum energy activation ratio for reserve "
<< section.name;
}
}
else if (tmp == "max-activation-duration")
{
if (!p->value.to<int>(tmpCapacityReservation.maxActivationHours))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@
/// @brief Represents an area capacity reservation using it's name, it's failure cost and it's spillage cost
struct CapacityReservation
{
CapacityReservation() : failureCost(0), spillageCost(0), need(timeseriesNumbers), maxActivationRatio(1.), maxActivationHours(0) {}
CapacityReservation() : failureCost(0), spillageCost(0), need(timeseriesNumbers), maxActivationRatio(0.), maxEnergyActivationRatio(1.), maxActivationHours(1.) {}
float failureCost;
float spillageCost;
float maxActivationRatio;
float maxEnergyActivationRatio;
int maxActivationHours;
Antares::Data::TimeSeries need;

Expand All @@ -47,6 +48,11 @@ struct CapacityReservation
/// @brief Stores all the Capacity reservations in two vectors for the up and down reserves
struct AllCapacityReservations
{
float maxGlobalEnergyActivationRatioUp = 1.;
float maxGlobalEnergyActivationRatioDown = 1.;
int maxGlobalActivationDurationUp = 1;
int maxGlobalActivationDurationDown = 1;

std::map<Data::ReserveName, CapacityReservation> areaCapacityReservationsUp;
std::map<Data::ReserveName, CapacityReservation> areaCapacityReservationsDown;

Expand Down
4 changes: 4 additions & 0 deletions src/solver/optimisation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ set(RTESOLVER_OPT
constraints/LTPumpingCapacityThreasholds.cpp
include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h
constraints/LTStockLevelReserveParticipation.cpp
include/antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h
constraints/STStockEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h
constraints/STStockGlobalEnergyLevelReserveParticipation.cpp
include/antares/solver/optimisation/ProblemMatrixEssential.h
ProblemMatrixEssential.cpp
include/antares/solver/optimisation/LinearProblemMatrixStartUpCosts.h
Expand Down
16 changes: 13 additions & 3 deletions src/solver/optimisation/constraints/ReserveParticipationGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
#include "antares/solver/optimisation/constraints/LTPumpingCapacityThreasholds.h"
#include "antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h"
#include "antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h"

#include "antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h"
#include "antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h"


ReserveParticipationGroup::ReserveParticipationGroup(PROBLEME_HEBDO* problemeHebdo,
Expand Down Expand Up @@ -80,6 +81,7 @@ void ReserveParticipationGroup::BuildConstraints()
STPumpingMaxReserve STPumpingMaxReserve(builder_, data);
STReserveUpParticipation STReserveUpParticipation(builder_, data);
STReserveDownParticipation STReserveDownParticipation(builder_, data);
STStockEnergyLevelReserveParticipation STStockEnergyLevelReserveParticipation(builder_, data);
LTTurbiningMaxReserve LTTurbiningMaxReserve(builder_, data);
LTPumpingMaxReserve LTPumpingMaxReserve(builder_, data);
LTReserveUpParticipation LTReserveUpParticipation(builder_, data);
Expand Down Expand Up @@ -188,6 +190,9 @@ void ReserveParticipationGroup::BuildConstraints()
// 15 (o)
STReserveUpParticipation
.add(pays, reserve, clusterReserveParticipation.clusterIdInArea, pdt);

// 15 (h)
STStockEnergyLevelReserveParticipation.add(pays, clusterReserveParticipation.clusterIdInArea, reserve, pdt, true);
}
reserve++;
}
Expand All @@ -214,6 +219,9 @@ void ReserveParticipationGroup::BuildConstraints()
// 15 (p)
STReserveDownParticipation
.add(pays, reserve, clusterReserveParticipation.clusterIdInArea, pdt);

// 15 (h)
STStockEnergyLevelReserveParticipation.add(pays, clusterReserveParticipation.clusterIdInArea, reserve, pdt, false);
}
reserve++;
}
Expand Down Expand Up @@ -286,6 +294,7 @@ void ReserveParticipationGroup::BuildConstraints()
LTPumpingCapacityThreasholds LTPumpingCapacityThreasholds(builder_, data);
LTStockLevelReserveParticipation LTStockLevelReserveParticipation(builder_, data);
STStockLevelReserveParticipation STStockLevelReserveParticipation(builder_, data);
STStockGlobalEnergyLevelReserveParticipation STStockGlobalEnergyLevelReserveParticipation(builder_, data);

for (int pdt = 0; pdt < problemeHebdo_->NombreDePasDeTempsPourUneOptimisation; pdt++)
{
Expand All @@ -312,8 +321,10 @@ void ReserveParticipationGroup::BuildConstraints()
STTurbiningCapacityThreasholds.add(pays, cluster, pdt);
// 15 (n)
STPumpingCapacityThreasholds.add(pays, cluster, pdt);
// 15 (r)
// 15 (g)
STStockLevelReserveParticipation.add(pays, cluster, pdt);
// 15 (i)
STStockGlobalEnergyLevelReserveParticipation.add(pays, cluster, pdt);
}

// Long Term Storage Clusters
Expand All @@ -337,7 +348,6 @@ void ReserveParticipationGroup::BuildConstraints()
LTPumpingCapacityThreasholds.add(pays, 0, pdt);
// 15 (r)
LTStockLevelReserveParticipation.add(pays, 0, pdt);

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

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

if (!data.Simulation)
{
// 15 (h) (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_STSTORAGE& reserveParticipation
= capacityReservation.AllSTStorageReservesParticipation[cluster];

builder.updateHourWithinWeek(pdt);

for (int t=0; t < capacityReservation.maxActivationDuration; t++)
{
builder.STStorageClusterReserveDownParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
builder.ShortTermStorageLevel(globalClusterIdx, sign * capacityReservation.maxEnergyActivationRatio,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
}

builder.lessThan();

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation
[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.STEnergyStockLevelReserveParticipationDown(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,123 @@
#include "antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h"

void STStockGlobalEnergyLevelReserveParticipation::add(int pays, int cluster, int pdt)
{
int globalClusterIdx = data.shortTermStorageOfArea[pays][cluster].clusterGlobalIndex;


if (!data.Simulation)
{
// 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.AllSTStorageReservesParticipation.contains(cluster))
{
RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation = capacityReservation.AllSTStorageReservesParticipation[cluster];
builder.STStorageClusterReserveDownParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}
if (builder.NumberOfVariables() > 0)
{
builder.ShortTermStorageLevel(globalClusterIdx, data.areaReserves[pays].maxGlobalEnergyActivationRatioDown,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}

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

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown
[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.STGlobalEnergyStockLevelReserveParticipationDown(builder.data.nombreDeContraintes,
"ShortTermStorage");
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.AllSTStorageReservesParticipation.contains(cluster))
{
RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation = capacityReservation.AllSTStorageReservesParticipation[cluster];
builder.STStorageClusterReserveUpParticipation(
reserveParticipation.globalIndexClusterParticipation,
capacityReservation.maxActivationRatio,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}
if (builder.NumberOfVariables() > 0)
{
builder.ShortTermStorageLevel(globalClusterIdx, -data.areaReserves[pays].maxGlobalEnergyActivationRatioUp,
t, builder.data.NombreDePasDeTempsPourUneOptimisation);
}
}

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

data.CorrespondanceCntNativesCntOptim[pdt]
.NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp
[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.STGlobalEnergyStockLevelReserveParticipationUp(builder.data.nombreDeContraintes,
"ShortTermStorage");
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.AllSTStorageReservesParticipation.count(cluster) * 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 1a3fe6e

Please sign in to comment.