From 2b826987c8c8c8f32529183efe7d197cc3225738 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 13 Dec 2024 08:31:20 +0100 Subject: [PATCH] Implementation of LTStorage reserves v2 --- src/solver/optimisation/CMakeLists.txt | 4 + .../constraints/ConstraintBuilder.cpp | 7 +- ...LTStockEnergyLevelReserveParticipation.cpp | 85 ++++++++++ ...kGlobalEnergyLevelReserveParticipation.cpp | 148 ++++++++++++++++++ .../LTStockLevelReserveParticipation.cpp | 123 +++++++-------- .../constraints/ReserveParticipationGroup.cpp | 55 +++++-- .../STSockLevelReserveParticipation.h | 1 - ...kGlobalEnergyLevelReserveParticipation.cpp | 1 + .../constraints/ConstraintBuilder.h | 5 +- .../LTStockEnergyLevelReserveParticipation.h | 26 +++ ...ckGlobalEnergyLevelReserveParticipation.h} | 7 +- .../solver/optimisation/opt_rename_problem.h | 3 + .../opt_gestion_second_membre_reserves.cpp | 118 ++++++++++---- .../optimisation/opt_rename_problem.cpp | 15 ++ .../sim_structure_probleme_economique.h | 4 +- .../simulation/sim_alloc_probleme_hebdo.cpp | 10 +- .../include/antares/solver/variable/info.h | 9 ++ 17 files changed, 499 insertions(+), 122 deletions(-) create mode 100644 src/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.cpp create mode 100644 src/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.cpp delete mode 100644 src/solver/optimisation/constraints/STSockLevelReserveParticipation.h create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h rename src/solver/optimisation/{constraints/LTSockLevelReserveParticipation.h => include/antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h} (62%) diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index 90c37a2652..cc44045e9d 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -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 diff --git a/src/solver/optimisation/constraints/ConstraintBuilder.cpp b/src/solver/optimisation/constraints/ConstraintBuilder.cpp index ceea511507..7cb329ccd9 100644 --- a/src/solver/optimisation/constraints/ConstraintBuilder.cpp +++ b/src/solver/optimisation/constraints/ConstraintBuilder.cpp @@ -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; } diff --git a/src/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.cpp new file mode 100644 index 0000000000..6faca090eb --- /dev/null +++ b/src/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.cpp @@ -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; + } + } +} diff --git a/src/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.cpp new file mode 100644 index 0000000000..c5fa7376fa --- /dev/null +++ b/src/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.cpp @@ -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& 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); + } +} diff --git a/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp index 6577e8f6b0..e152bdf4dc 100644 --- a/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp +++ b/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp @@ -8,108 +8,97 @@ void LTStockLevelReserveParticipation::add(int pays, int cluster, int pdt) { // 15 (r) (1) // Participation of down reserves requires a sufficient level of stock - // R_t + Sum(P_{res,t_st} * R_{min,res}) <= R_up + // R_t + Sum(P_{res} * R_{min,res}) <= R_up // R_t : stock level at time t - // P_{res,t_st} : power participation for reserve down res at time t_st + // P_{res} : power participation for reserve down res // R_{min,res} : max power participation ratio // R_up : max stock level { - builder.updateHourWithinWeek(pdt).HydroLevel(pays, 1.); + builder.updateHourWithinWeek(pdt); - for (const auto& capacityReservation : data.areaReserves[pays].areaCapacityReservationsDown) + for (auto& capacityReservation : data.areaReserves[pays].areaCapacityReservationsDown) { - int t_max = pdt + capacityReservation.maxActivationDuration; - if (t_max > builder.data.NombreDePasDeTempsPourUneOptimisation) - t_max = builder.data.NombreDePasDeTempsPourUneOptimisation; - - for (int t=pdt; t < t_max; t++) + if (capacityReservation.AllLTStorageReservesParticipation.size()) { - builder.updateHourWithinWeek(t); - for (const auto& reserveParticipations : capacityReservation.AllLTStorageReservesParticipation) - { - builder.LTStorageClusterReserveDownParticipation( - reserveParticipations.globalIndexClusterParticipation, - capacityReservation.maxActivationRatio); - } + RESERVE_PARTICIPATION_LTSTORAGE reserveParticipations = capacityReservation.AllLTStorageReservesParticipation[cluster]; + builder.LTStorageClusterReserveDownParticipation( + reserveParticipations.globalIndexClusterParticipation, + capacityReservation.maxActivationRatio); } } - builder.lessThan(); - data.CorrespondanceCntNativesCntOptim[pdt] - .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown - [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.LTStockLevelReserveParticipationDown(builder.data.nombreDeContraintes, - "LongTermStorage"); - builder.build(); + if (builder.NumberOfVariables() > 0) + { + builder.HydroLevel(globalClusterIdx, 1.); + builder.lessThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown + [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.LTStockLevelReserveParticipationDown(builder.data.nombreDeContraintes, + "LongTermStorage"); + builder.build(); + } } // 15 (r) (2) // Participation of up reserves requires a sufficient level of stock - // R_t - Sum(P_{res,t_st} * R_{min,res}) >= R_down + // -R_t + Sum(P_{res} * R_{min,res}) <= -R_down // R_t : stock level at time t - // P_{res,t_st} : power participation for reserve up res at time t_st + // P_{res} : power participation for reserve up res // R_{min,res} : max power participation ratio // R_down : min stock level { - builder.updateHourWithinWeek(pdt).HydroLevel(pays, 1.); + builder.updateHourWithinWeek(pdt); - for (const auto& capacityReservation : data.areaReserves[pays].areaCapacityReservationsUp) + for (auto& capacityReservation : data.areaReserves[pays].areaCapacityReservationsUp) { - int t_max = pdt + capacityReservation.maxActivationDuration; - if (t_max > builder.data.NombreDePasDeTempsPourUneOptimisation) - t_max = builder.data.NombreDePasDeTempsPourUneOptimisation; - - for (int t=pdt; t < t_max; t++) + if (capacityReservation.AllLTStorageReservesParticipation.size()) { - builder.updateHourWithinWeek(t); - for (const auto& reserveParticipations : capacityReservation.AllLTStorageReservesParticipation) - { - builder.LTStorageClusterReserveUpParticipation( - reserveParticipations.globalIndexClusterParticipation, - -capacityReservation.maxActivationRatio); - } + RESERVE_PARTICIPATION_LTSTORAGE reserveParticipations = capacityReservation.AllLTStorageReservesParticipation[cluster]; + builder.LTStorageClusterReserveUpParticipation( + reserveParticipations.globalIndexClusterParticipation, + capacityReservation.maxActivationRatio); } } - builder.greaterThan(); - data.CorrespondanceCntNativesCntOptim[pdt] - .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp - [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.LTStockLevelReserveParticipationUp(builder.data.nombreDeContraintes, - "LongTermStorage"); - builder.build(); + if (builder.NumberOfVariables() > 0) + { + builder.HydroLevel(globalClusterIdx, -1.); + builder.lessThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp + [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.LTStockLevelReserveParticipationUp(builder.data.nombreDeContraintes, + "LongTermStorage"); + builder.build(); + } } } else { // Lambda that count the number of reserveParticipations - auto countReservesParticipations = [](const std::vector& reservations, int time, int time_max) + auto countReservesParticipations = [cluster](const std::vector& reservations) { int counter = 0; for (const auto& capacityReservation: reservations) { - int n_t = capacityReservation.maxActivationDuration; - if (time + n_t > time_max) - n_t = time_max - time; - counter += capacityReservation.AllLTStorageReservesParticipation.size() * n_t; + counter += capacityReservation.AllLTStorageReservesParticipation.size(); } return counter; }; - int nbTermsUp = countReservesParticipations( - data.areaReserves[pays].areaCapacityReservationsUp, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); - int nbTermsDown = countReservesParticipations( - data.areaReserves[pays].areaCapacityReservationsDown, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); + int nbTermsUp = countReservesParticipations(data.areaReserves[pays].areaCapacityReservationsUp); + int nbTermsDown = countReservesParticipations(data.areaReserves[pays].areaCapacityReservationsDown); - builder.data.NbTermesContraintesPourLesReserves += (nbTermsUp + 1) + (nbTermsDown + 1); - builder.data.nombreDeContraintes += 2; + builder.data.NbTermesContraintesPourLesReserves += (nbTermsUp + 1) * (nbTermsUp > 0) + (nbTermsDown + 1) * (nbTermsDown > 0); + builder.data.nombreDeContraintes += (nbTermsUp > 0) + (nbTermsDown > 0); } } \ No newline at end of file diff --git a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp index 49e8c51e01..bdfe448ba0 100644 --- a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp +++ b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp @@ -20,31 +20,33 @@ */ #include "antares/solver/optimisation/constraints/ReserveParticipationGroup.h" + #include "antares/solver/optimisation/constraints/ConstraintGroup.h" -#include "antares/solver/optimisation/constraints/PMaxReserve.h" +#include "antares/solver/optimisation/constraints/LTPumpingCapacityThreasholds.h" +#include "antares/solver/optimisation/constraints/LTPumpingMaxReserve.h" +#include "antares/solver/optimisation/constraints/LTReserveDownParticipation.h" +#include "antares/solver/optimisation/constraints/LTReserveUpParticipation.h" +#include "antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h" +#include "antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h" +#include "antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h" +#include "antares/solver/optimisation/constraints/LTTurbiningCapacityThreasholds.h" +#include "antares/solver/optimisation/constraints/LTTurbiningMaxReserve.h" #include "antares/solver/optimisation/constraints/OffUnitsThermalParticipatingToReserves.h" +#include "antares/solver/optimisation/constraints/PMaxReserve.h" #include "antares/solver/optimisation/constraints/POffUnits.h" +#include "antares/solver/optimisation/constraints/POutBounds.h" #include "antares/solver/optimisation/constraints/POutCapacityThreasholds.h" -#include "antares/solver/optimisation/constraints/ThermalReserveParticipation.h" #include "antares/solver/optimisation/constraints/ReserveSatisfaction.h" -#include "antares/solver/optimisation/constraints/POutBounds.h" -#include "antares/solver/optimisation/constraints/STTurbiningMaxReserve.h" -#include "antares/solver/optimisation/constraints/STPumpingMaxReserve.h" -#include "antares/solver/optimisation/constraints/STTurbiningCapacityThreasholds.h" #include "antares/solver/optimisation/constraints/STPumpingCapacityThreasholds.h" -#include "antares/solver/optimisation/constraints/STReserveUpParticipation.h" +#include "antares/solver/optimisation/constraints/STPumpingMaxReserve.h" #include "antares/solver/optimisation/constraints/STReserveDownParticipation.h" -#include "antares/solver/optimisation/constraints/LTTurbiningMaxReserve.h" -#include "antares/solver/optimisation/constraints/LTPumpingMaxReserve.h" -#include "antares/solver/optimisation/constraints/LTReserveUpParticipation.h" -#include "antares/solver/optimisation/constraints/LTReserveDownParticipation.h" -#include "antares/solver/optimisation/constraints/LTTurbiningCapacityThreasholds.h" -#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/STReserveUpParticipation.h" #include "antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h" #include "antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h" - +#include "antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h" +#include "antares/solver/optimisation/constraints/STTurbiningCapacityThreasholds.h" +#include "antares/solver/optimisation/constraints/STTurbiningMaxReserve.h" +#include "antares/solver/optimisation/constraints/ThermalReserveParticipation.h" ReserveParticipationGroup::ReserveParticipationGroup(PROBLEME_HEBDO* problemeHebdo, bool simulation, @@ -82,6 +84,8 @@ void ReserveParticipationGroup::BuildConstraints() STReserveUpParticipation STReserveUpParticipation(builder_, data); STReserveDownParticipation STReserveDownParticipation(builder_, data); STStockEnergyLevelReserveParticipation STStockEnergyLevelReserveParticipation(builder_, data); + LTStockEnergyLevelReserveParticipation LTStockEnergyLevelReserveParticipation(builder_, + data); LTTurbiningMaxReserve LTTurbiningMaxReserve(builder_, data); LTPumpingMaxReserve LTPumpingMaxReserve(builder_, data); LTReserveUpParticipation LTReserveUpParticipation(builder_, data); @@ -251,6 +255,14 @@ void ReserveParticipationGroup::BuildConstraints() // 15 (e) LTReserveUpParticipation .add(pays, reserve, clusterReserveParticipation.clusterIdInArea, pdt); + + // 15 (s) + LTStockEnergyLevelReserveParticipation.add( + pays, + clusterReserveParticipation.clusterIdInArea, + reserve, + pdt, + true); } reserve++; } @@ -277,6 +289,14 @@ void ReserveParticipationGroup::BuildConstraints() // 15 (f) LTReserveDownParticipation .add(pays, reserve, clusterReserveParticipation.clusterIdInArea, pdt); + + // 15 (s) + LTStockEnergyLevelReserveParticipation.add( + pays, + clusterReserveParticipation.clusterIdInArea, + reserve, + pdt, + false); } reserve++; } @@ -295,6 +315,7 @@ void ReserveParticipationGroup::BuildConstraints() LTStockLevelReserveParticipation LTStockLevelReserveParticipation(builder_, data); STStockLevelReserveParticipation STStockLevelReserveParticipation(builder_, data); STStockGlobalEnergyLevelReserveParticipation STStockGlobalEnergyLevelReserveParticipation(builder_, data); + LTStockGlobalEnergyLevelReserveParticipation LTStockGlobalEnergyLevelReserveParticipation(builder_, data); for (int pdt = 0; pdt < problemeHebdo_->NombreDePasDeTempsPourUneOptimisation; pdt++) { @@ -348,6 +369,8 @@ void ReserveParticipationGroup::BuildConstraints() LTPumpingCapacityThreasholds.add(pays, 0, pdt); // 15 (r) LTStockLevelReserveParticipation.add(pays, 0, pdt); + // 15 (t) + LTStockGlobalEnergyLevelReserveParticipation.add(pays, 0, pdt); } } } diff --git a/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h b/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h deleted file mode 100644 index 6f70f09bee..0000000000 --- a/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp index 3e1fbe7c18..2221759732 100644 --- a/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp +++ b/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp @@ -7,6 +7,7 @@ void STStockGlobalEnergyLevelReserveParticipation::add(int pays, int cluster, in if (!data.Simulation) { + // 15 (i) // 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 diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h index 3d6aa610c2..7b4cbdd40b 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h @@ -201,7 +201,10 @@ class ConstraintBuilder ConstraintBuilder& Pumping(unsigned int index, double coeff); - ConstraintBuilder& HydroLevel(unsigned int index, double coeff); + ConstraintBuilder& HydroLevel(unsigned int index, + double coeff, + int offset = 0, + int delta = 0); ConstraintBuilder& Overflow(unsigned int index, double coeff); diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h new file mode 100644 index 0000000000..3901bc4754 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockEnergyLevelReserveParticipation.h @@ -0,0 +1,26 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'LTStockLevelReserveParticipation' Constraint type + */ +class LTStockEnergyLevelReserveParticipation : private ConstraintFactory +{ +public: + LTStockEnergyLevelReserveParticipation(ConstraintBuilder& builder, ReserveData& data) : + ConstraintFactory(builder), data(data) + { + } + + /*! + * @brief Add variables to the constraint and update constraints Matrix + * @param pays : area + * @param cluster : global index of the cluster + * @param pdt : timestep + * @param isUpReserve : true if ReserveUp, false if ReserveDown + */ + void add(int pays, int cluster, int reserve, int pdt, bool isUpReserve); + +private: + ReserveData& data; +}; diff --git a/src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h similarity index 62% rename from src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h rename to src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h index 014fcc7b0f..ce5415f9cd 100644 --- a/src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockGlobalEnergyLevelReserveParticipation.h @@ -2,12 +2,12 @@ #include "ConstraintBuilder.h" /* - * represent 'LTPumpingCapacityThreasholds' Constraint type + * represent 'LTStockLevelReserveParticipation' Constraint type */ -class LTPumpingCapacityThreasholds : private ConstraintFactory +class LTStockGlobalEnergyLevelReserveParticipation : private ConstraintFactory { public: - LTPumpingCapacityThreasholds(ConstraintBuilder& builder, ReserveData& data) : + LTStockGlobalEnergyLevelReserveParticipation(ConstraintBuilder& builder, ReserveData& data) : ConstraintFactory(builder), data(data) { } @@ -23,4 +23,3 @@ class LTPumpingCapacityThreasholds : private ConstraintFactory private: ReserveData& data; }; - diff --git a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h index 72d8a5fe84..f05d828555 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h @@ -255,6 +255,9 @@ class ConstraintNamer: public Namer void LTPumpingCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); void LTStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); void LTStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); + void LTEnergyStockLevelReserveParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName); + void LTGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); + void LTGlobalEnergyStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); void ReserveSatisfaction(unsigned int constraint, const std::string& reserveName); void PMaxDispatchableGeneration(unsigned int constraint, const std::string& clusterName); diff --git a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp index a0f6ffa8d7..7d8c150cff 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -144,7 +144,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro = areaReserves[pays].areaCapacityReservationsUp; for (const auto& areaReserveUp : areaReservesUp) { - for (const auto& [clusterId, reserveParticipation] : + for (const auto& [clusterId, reserveParticipation]: areaReserveUp.AllSTStorageReservesParticipation) { int cnt @@ -325,6 +325,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro SecondMembre[cnt] = reserveParticipation.maxTurbining; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation @@ -334,6 +335,24 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro SecondMembre[cnt] = reserveParticipation.maxPumping; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation + [reserveParticipation.globalIndexClusterParticipation]; + if (cnt >= 0) + { + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + auto& hydroCluster = problemeHebdo + ->CaracteristiquesHydrauliques[pays]; + int hourInTheYear = weekFirstHour + pdtHebdo; + double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo]; + + SecondMembre[cnt] = -areaReserveUp.maxEnergyActivationRatio + * areaReserveUp.maxActivationDuration + * level_min; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } } } auto& areaReservesDown = areaReserves[pays].areaCapacityReservationsDown; @@ -360,6 +379,22 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro SecondMembre[cnt] = reserveParticipation.maxPumping; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation + [reserveParticipation.globalIndexClusterParticipation]; + if (cnt >= 0) + { + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + auto& hydroCluster = problemeHebdo + ->CaracteristiquesHydrauliques[pays]; + int hourInTheYear = weekFirstHour + pdtHebdo; + double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo]; + SecondMembre[cnt] = areaReserveDown.maxEnergyActivationRatio + * areaReserveDown.maxActivationDuration + * level_max; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } } } @@ -379,60 +414,85 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro || isClusterParticipatingToReserves( problemeHebdo->allReserves[pays].areaCapacityReservationsUp)) { + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + int hourInTheYear = weekFirstHour + pdtHebdo; auto& hydroCluster = problemeHebdo->CaracteristiquesHydrauliques[pays]; + double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo]; + double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo]; int globalClusterIdx = hydroCluster.GlobalHydroIndex; - int cnt1 + int cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax [globalClusterIdx]; - if (cnt1 >= 0) + if (cnt >= 0) { - SecondMembre[cnt1] = hydroCluster - .ContrainteDePmaxHydrauliqueHoraire[pdtJour]; - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt1] = nullptr; + SecondMembre[cnt] = hydroCluster + .ContrainteDePmaxHydrauliqueHoraire[pdtJour]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } - - int cnt2 + + cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin [globalClusterIdx]; - if (cnt2 >= 0) + if (cnt >= 0) { - SecondMembre[cnt2] = hydroCluster - .MingenHoraire[pdtJour]; - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt2] = nullptr; + SecondMembre[cnt] = hydroCluster.MingenHoraire[pdtJour]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } - int cnt3 + cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds [globalClusterIdx]; - if (cnt3 >= 0) + if (cnt >= 0) { - SecondMembre[cnt3] = hydroCluster - .ContrainteDePmaxPompageHoraire[pdtJour]; - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt3] = nullptr; + SecondMembre[cnt] = hydroCluster.ContrainteDePmaxPompageHoraire[pdtJour]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } - int cnt4 - = CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown + [globalClusterIdx]; + if (cnt >= 0) + { + SecondMembre[cnt] = hydroCluster.NiveauHoraireSup[pdtHebdo]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } + + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp + [globalClusterIdx]; + if (cnt >= 0) + { + SecondMembre[cnt] = hydroCluster.NiveauHoraireInf[pdtHebdo]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } + + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown [globalClusterIdx]; - if (cnt4 >= 0) + if (cnt >= 0) { - SecondMembre[cnt4] = hydroCluster.NiveauHoraireSup[pdtHebdo];; - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt4] = nullptr; + SecondMembre[cnt] = areaReserves[pays].maxGlobalActivationDurationDown + * areaReserves[pays] + .maxGlobalEnergyActivationRatioDown + * level_max; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } - int cnt5 - = CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp [globalClusterIdx]; - if (cnt5 >= 0) + if (cnt >= 0) { - SecondMembre[cnt5] = hydroCluster.NiveauHoraireInf[pdtHebdo];; - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt5] = nullptr; + SecondMembre[cnt] = -areaReserves[pays].maxGlobalActivationDurationUp + * areaReserves[pays].maxGlobalEnergyActivationRatioUp + * level_min; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } } } diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index ba5940c751..262c8dd0ae 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -729,6 +729,21 @@ void ConstraintNamer::LTStockLevelReserveParticipationDown(unsigned int constrai SetLTStorageClusterElementName(constraint, "LTStockLevelReserveParticipationDown", clusterName); } +void ConstraintNamer::LTEnergyStockLevelReserveParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName) +{ + SetLTStorageClusterAndReserveElementName(constraint, "LTEnergyStockLevelReserveParticipation", clusterName, reserveName); +} + +void ConstraintNamer::LTGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "LTGlobalEnergyStockLevelReserveParticipationDown", clusterName); +} + +void ConstraintNamer::LTGlobalEnergyStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "LTGlobalEnergyStockLevelReserveParticipationUp", clusterName); +} + void ConstraintNamer::ReserveSatisfaction(unsigned int constraint, const std::string& reserveName) { SetThermalClusterReserveElementName(constraint, "ReserveSatisfaction", reserveName); diff --git a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h index 20f398259d..28bce2f5a3 100644 --- a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h +++ b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h @@ -132,7 +132,9 @@ struct CORRESPONDANCES_DES_CONTRAINTES std::vector NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds; std::vector NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp; std::vector NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown; - + std::vector NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation; + std::vector NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp; + std::vector NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown; std::vector NumeroDeContrainteDesNiveauxPays; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 7441fef6fc..12f9ab1c48 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -299,7 +299,15 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown.assign(study.runtime.longTermStorageCount, -1); problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp.assign(study.runtime.longTermStorageCount, -1); - + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation + .assign(study.runtime.longTermStorageCount * study.runtime.capacityReservationCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp + .assign(study.runtime.longTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown + .assign(study.runtime.longTermStorageCount, -1); problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeLaDeuxiemeContrainteDesContraintesDesGroupesQuiTombentEnPanne.assign( diff --git a/src/solver/variable/include/antares/solver/variable/info.h b/src/solver/variable/include/antares/solver/variable/info.h index 77729bb16e..b754e3874f 100644 --- a/src/solver/variable/include/antares/solver/variable/info.h +++ b/src/solver/variable/include/antares/solver/variable/info.h @@ -471,6 +471,15 @@ struct VariableAccessor results.variableCaption = reserveName + "_" + Economy::unsuppliedSpilledToString(unsuppliedOrSpilled); } + else if constexpr (std::is_same_v< + VCardT, + Economy::VCardReserveParticipationMarginalCost>) + { + auto [unsuppliedOrSpilled, reserveName] + = thermal.list.reserveParticipationUnsuppliedSpilledAt(results.data.area, i); + results.variableCaption = reserveName + "_" + + Economy::marginalCostToString(); + } else results.variableCaption = thermal.list.enabledClusterAt(i)->name();