From 66136091d16f6777c3cab2e6e3f54f36de44ddd6 Mon Sep 17 00:00:00 2001 From: CAMUS Benjamin Date: Thu, 31 Oct 2024 17:39:32 +0100 Subject: [PATCH 01/15] first version of the implementation de reserve lot 3 --- src/libs/antares/study/area/list.cpp | 68 +--- .../antares/study/area/capacityReservation.h | 4 +- src/solver/optimisation/CMakeLists.txt | 4 + .../LTSockLevelReserveParticipation.h | 26 ++ .../LTStockLevelReserveParticipation.cpp | 115 +++++++ .../constraints/ReserveParticipationGroup.cpp | 10 + .../STSockLevelReserveParticipation.h | 1 + .../STStockLevelReserveParticipation.cpp | 117 +++++++ .../LTStockLevelReserveParticipation.h | 25 ++ .../STStockLevelReserveParticipation.h | 25 ++ .../solver/optimisation/opt_rename_problem.h | 5 + .../opt_gestion_second_membre_reserves.cpp | 46 ++- .../optimisation/opt_rename_problem.cpp | 20 ++ .../sim_structure_probleme_economique.h | 10 +- .../simulation/sim_alloc_probleme_hebdo.cpp | 10 + .../simulation/sim_calcul_economique.cpp | 4 + src/solver/variable/CMakeLists.txt | 2 + .../antares/solver/variable/economy/all.h | 4 +- .../reserveParticipationMarginalCost.h | 310 ++++++++++++++++++ .../vCardReserveParticipationMarginalCost.h | 109 ++++++ .../include/antares/solver/variable/info.h | 11 + 21 files changed, 858 insertions(+), 68 deletions(-) create mode 100644 src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h create mode 100644 src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp create mode 100644 src/solver/optimisation/constraints/STSockLevelReserveParticipation.h create mode 100644 src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/reserveParticipationMarginalCost.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/vCardReserveParticipationMarginalCost.h diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index 64a33cea07..5f26fc925d 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -954,77 +954,21 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << section.name; } } - else if (tmp == "type") - { - if (p->value == "up") - type = 0; - else if (p->value == "down") - type = 1; - else - logs.warning() - << area.name << ": invalid type for reserve " << section.name; - } - else - logs.warning() - << area.name << ": invalid key " << tmp << " in file " << buffer; - } - fs::path filePath = study.folderInput / "reserves" / area.id.to() - / (file_name + ".txt"); - ret = tmpCapacityReservation.need.loadFromFile(filePath, false) && ret; - if (type == 0) - area.allCapacityReservations.areaCapacityReservationsUp.emplace( - section.name, tmpCapacityReservation); - else if (type == 1) - area.allCapacityReservations.areaCapacityReservationsDown.emplace( - section.name, tmpCapacityReservation); - else - logs.warning() - << area.name << ": invalid type for reserve " << section.name; - } - }); - } - } - - // Reserves - { - buffer.clear() << study.folderInput << SEP << "reserves" << SEP << area.id << SEP - << "reserves.ini"; - if (ini.open(buffer, false)) - { - ini.each( - [&](const IniFile::Section& section) - { - if (area.allCapacityReservations.contains(section.name)) - { - logs.warning() << area.name << ": reserve name already exists for reserve " - << section.name; - } - else - { - CapacityReservation tmpCapacityReservation; - std::string file_name = AllCapacityReservations::toFilename(section.name); - int type = -1; - for (auto* p = section.firstProperty; p; p = p->next) - { - CString<30, false> tmp; - tmp = p->key; - tmp.toLower(); - - if (tmp == "failure-cost") + else if (tmp == "max-activation-ratio") { - if (!p->value.to(tmpCapacityReservation.failureCost)) + if (!p->value.to(tmpCapacityReservation.maxActivationRatio)) { logs.warning() - << area.name << ": invalid failure cost for reserve " + << area.name << ": invalid maximum activation ratio for reserve " << section.name; } } - else if (tmp == "spillage-cost") + else if (tmp == "max-activation-duration") { - if (!p->value.to(tmpCapacityReservation.spillageCost)) + if (!p->value.to(tmpCapacityReservation.maxActivationHours)) { logs.warning() - << area.name << ": invalid spillage cost for reserve " + << area.name << ": invalid maximum activation duration for reserve " << section.name; } } diff --git a/src/libs/antares/study/include/antares/study/area/capacityReservation.h b/src/libs/antares/study/include/antares/study/area/capacityReservation.h index 53bc789b9d..5c4056fc4c 100644 --- a/src/libs/antares/study/include/antares/study/area/capacityReservation.h +++ b/src/libs/antares/study/include/antares/study/area/capacityReservation.h @@ -33,9 +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) {} + CapacityReservation() : failureCost(0), spillageCost(0), need(timeseriesNumbers), maxActivationRatio(1.), maxActivationHours(0) {} float failureCost; float spillageCost; + float maxActivationRatio; + int maxActivationHours; Antares::Data::TimeSeries need; private: diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index c6c9c4cdcb..f855534522 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -150,6 +150,8 @@ set(RTESOLVER_OPT constraints/STReserveUpParticipation.cpp include/antares/solver/optimisation/constraints/STReserveDownParticipation.h constraints/STReserveDownParticipation.cpp + include/antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h + constraints/STStockLevelReserveParticipation.cpp include/antares/solver/optimisation/constraints/LTTurbiningMaxReserve.h constraints/LTTurbiningMaxReserve.cpp include/antares/solver/optimisation/constraints/LTPumpingMaxReserve.h @@ -162,6 +164,8 @@ set(RTESOLVER_OPT constraints/LTTurbiningCapacityThreasholds.cpp include/antares/solver/optimisation/constraints/LTPumpingCapacityThreasholds.h constraints/LTPumpingCapacityThreasholds.cpp + include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h + constraints/LTStockLevelReserveParticipation.cpp include/antares/solver/optimisation/ProblemMatrixEssential.h ProblemMatrixEssential.cpp include/antares/solver/optimisation/LinearProblemMatrixStartUpCosts.h diff --git a/src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h b/src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h new file mode 100644 index 0000000000..014fcc7b0f --- /dev/null +++ b/src/solver/optimisation/constraints/LTSockLevelReserveParticipation.h @@ -0,0 +1,26 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'LTPumpingCapacityThreasholds' Constraint type + */ +class LTPumpingCapacityThreasholds : private ConstraintFactory +{ +public: + LTPumpingCapacityThreasholds(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 + */ + void add(int pays, int cluster, int pdt); + +private: + ReserveData& data; +}; + diff --git a/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp new file mode 100644 index 0000000000..6577e8f6b0 --- /dev/null +++ b/src/solver/optimisation/constraints/LTStockLevelReserveParticipation.cpp @@ -0,0 +1,115 @@ +#include "antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h" + +void LTStockLevelReserveParticipation::add(int pays, int cluster, int pdt) +{ + int globalClusterIdx = data.longTermStorageOfArea[pays].GlobalHydroIndex; + + if (!data.Simulation) + { + // 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 : 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 + { + builder.updateHourWithinWeek(pdt).HydroLevel(pays, 1.); + + for (const 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++) + { + builder.updateHourWithinWeek(t); + for (const auto& reserveParticipations : capacityReservation.AllLTStorageReservesParticipation) + { + 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(); + } + + // 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 : stock level at time t + // P_{res,t_st} : power participation for reserve up res at time t_st + // R_{min,res} : max power participation ratio + // R_down : min stock level + { + builder.updateHourWithinWeek(pdt).HydroLevel(pays, 1.); + + for (const 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++) + { + builder.updateHourWithinWeek(t); + for (const auto& reserveParticipations : capacityReservation.AllLTStorageReservesParticipation) + { + 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(); + } + } + else + { + // Lambda that count the number of reserveParticipations + auto countReservesParticipations = [](const std::vector& reservations, int time, int time_max) + { + 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; + } + return counter; + }; + + int nbTermsUp = countReservesParticipations( + data.areaReserves[pays].areaCapacityReservationsUp, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); + int nbTermsDown = countReservesParticipations( + data.areaReserves[pays].areaCapacityReservationsDown, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); + + builder.data.NbTermesContraintesPourLesReserves += (nbTermsUp + 1) + (nbTermsDown + 1); + builder.data.nombreDeContraintes += 2; + } +} \ No newline at end of file diff --git a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp index 3eb7477b28..5fc3d96d0d 100644 --- a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp +++ b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp @@ -40,6 +40,9 @@ #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" + ReserveParticipationGroup::ReserveParticipationGroup(PROBLEME_HEBDO* problemeHebdo, @@ -281,6 +284,8 @@ void ReserveParticipationGroup::BuildConstraints() STPumpingCapacityThreasholds STPumpingCapacityThreasholds(builder_, data); LTTurbiningCapacityThreasholds LTTurbiningCapacityThreasholds(builder_, data); LTPumpingCapacityThreasholds LTPumpingCapacityThreasholds(builder_, data); + LTStockLevelReserveParticipation LTStockLevelReserveParticipation(builder_, data); + STStockLevelReserveParticipation STStockLevelReserveParticipation(builder_, data); for (int pdt = 0; pdt < problemeHebdo_->NombreDePasDeTempsPourUneOptimisation; pdt++) { @@ -307,6 +312,8 @@ void ReserveParticipationGroup::BuildConstraints() STTurbiningCapacityThreasholds.add(pays, cluster, pdt); // 15 (n) STPumpingCapacityThreasholds.add(pays, cluster, pdt); + // 15 (r) + STStockLevelReserveParticipation.add(pays, cluster, pdt); } // Long Term Storage Clusters @@ -328,6 +335,9 @@ void ReserveParticipationGroup::BuildConstraints() LTTurbiningCapacityThreasholds.add(pays, 0, pdt); // 15 (d) LTPumpingCapacityThreasholds.add(pays, 0, pdt); + // 15 (r) + LTStockLevelReserveParticipation.add(pays, 0, pdt); + } } } diff --git a/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h b/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/src/solver/optimisation/constraints/STSockLevelReserveParticipation.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp new file mode 100644 index 0000000000..f93d5d9cf2 --- /dev/null +++ b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp @@ -0,0 +1,117 @@ +#include "antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h" + +void STStockLevelReserveParticipation::add(int pays, int cluster, int pdt) +{ + int globalClusterIdx = data.shortTermStorageOfArea[pays][cluster].clusterGlobalIndex; + + if (!data.Simulation) + { + // 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 : 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 + { + builder.updateHourWithinWeek(pdt).ShortTermStorageLevel(globalClusterIdx, 1.); + + for (const 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++) + { + builder.updateHourWithinWeek(t); + for (const auto& [clusterId, reserveParticipations] : capacityReservation.AllSTStorageReservesParticipation) + { + if (cluster == clusterId) + builder.STStorageClusterReserveDownParticipation( + reserveParticipations.globalIndexClusterParticipation, + capacityReservation.maxActivationRatio); + } + } + } + builder.lessThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown + [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.STStockLevelReserveParticipationDown(builder.data.nombreDeContraintes, + "ShortTermStorage"); + 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 : stock level at time t + // P_{res,t_st} : power participation for reserve up res at time t_st + // R_{min,res} : max power participation ratio + // R_down : min stock level + { + builder.updateHourWithinWeek(pdt).ShortTermStorageLevel(globalClusterIdx, 1.); + + for (const 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++) + { + builder.updateHourWithinWeek(t); + for (const auto& [clusterId, reserveParticipations] : capacityReservation.AllSTStorageReservesParticipation) + { + if (cluster == clusterId) + builder.STStorageClusterReserveUpParticipation( + reserveParticipations.globalIndexClusterParticipation, + -capacityReservation.maxActivationRatio); + } + } + } + builder.greaterThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp + [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.STStockLevelReserveParticipationUp(builder.data.nombreDeContraintes, + "ShortTermStorage"); + builder.build(); + } + } + else + { + // Lambda that count the number of reserveParticipations + auto countReservesParticipations = [cluster](const std::vector& reservations, int time, int time_max) + { + 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.AllSTStorageReservesParticipation.count(cluster) * n_t; + } + return counter; + }; + + int nbTermsUp = countReservesParticipations( + data.areaReserves[pays].areaCapacityReservationsUp, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); + int nbTermsDown = countReservesParticipations( + data.areaReserves[pays].areaCapacityReservationsDown, pdt, builder.data.NombreDePasDeTempsPourUneOptimisation); + + builder.data.NbTermesContraintesPourLesReserves += (nbTermsUp + 1) + (nbTermsDown + 1); + builder.data.nombreDeContraintes += 2; + } +} \ No newline at end of file diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h new file mode 100644 index 0000000000..1f30f13b57 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/LTStockLevelReserveParticipation.h @@ -0,0 +1,25 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'LTStockLevelReserveParticipation' Constraint type + */ +class LTStockLevelReserveParticipation : private ConstraintFactory +{ +public: + LTStockLevelReserveParticipation(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 + */ + void add(int pays, int cluster, int pdt); + +private: + ReserveData& data; +}; \ No newline at end of file diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h new file mode 100644 index 0000000000..95c4d17c06 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockLevelReserveParticipation.h @@ -0,0 +1,25 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'STStockLevelReserveParticipation' Constraint type + */ +class STStockLevelReserveParticipation : private ConstraintFactory +{ +public: + STStockLevelReserveParticipation(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 + */ + void add(int pays, int cluster, int pdt); + +private: + ReserveData& data; +}; \ No newline at end of file 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 cc2e63d016..228fc376f6 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 @@ -230,6 +230,9 @@ class ConstraintNamer: public Namer void STTurbiningCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); void STPumpingCapacityThreasholdsUp(unsigned int constraint, const std::string& clusterName); void STPumpingCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); + void STStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); + void STStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); + void LTReserveUpParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName); @@ -246,6 +249,8 @@ class ConstraintNamer: public Namer void LTTurbiningCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); void LTPumpingCapacityThreasholdsUp(unsigned int constraint, const std::string& clusterName); 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 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 dc5143b9c7..f4a1378834 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -68,7 +68,8 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro if (cnt >= 0) { SecondMembre[cnt] = areaReserveUp.need.at(pdtGlobal); - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays].Reserves[pdtHebdo].CoutsMarginauxHoraires[areaReserveUp.areaReserveIndex]); + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = adresseDuResultat; } for (const auto& [clusterId, reserveParticipation]: @@ -100,7 +101,8 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro if (cnt >= 0) { SecondMembre[cnt] = areaReserveDown.need.at(pdtGlobal); - AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays].Reserves[pdtHebdo].CoutsMarginauxHoraires[areaReserveDown.areaReserveIndex]); + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = adresseDuResultat; } } @@ -227,6 +229,26 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro * cluster.injectionNominalCapacity; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown + [globalClusterIdx]; + if (cnt >= 0) + { + SecondMembre[cnt] = cluster.reservoirCapacity + * cluster.series->upperRuleCurve[pdtJour]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } + + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp + [globalClusterIdx]; + if (cnt >= 0) + { + SecondMembre[cnt] = cluster.reservoirCapacity + * cluster.series->lowerRuleCurve[pdtJour]; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } } } @@ -338,6 +360,26 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro .ContrainteDePmaxPompageHoraire[pdtJour]; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt3] = nullptr; } + + int cnt4 + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown + [globalClusterIdx]; + if (cnt4 >= 0) + { + SecondMembre[cnt4] = hydroCluster.NiveauHoraireSup[pdtHebdo];; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt4] = nullptr; + } + + int cnt5 + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp + [globalClusterIdx]; + if (cnt5 >= 0) + { + SecondMembre[cnt5] = hydroCluster.NiveauHoraireInf[pdtHebdo];; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt5] = nullptr; + } } } } diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index f11aa9098b..cba9f668b6 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -639,6 +639,16 @@ void ConstraintNamer::STPumpingCapacityThreasholdsDown(unsigned int constraint, SetSTStorageClusterElementName(constraint, "STPumpingCapacityThreasholdsDown", clusterName); } +void ConstraintNamer::STStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "STStockLevelReserveParticipationUp", clusterName); +} + +void ConstraintNamer::STStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "STStockLevelReserveParticipationDown", clusterName); +} + void ConstraintNamer::LTReserveUpParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName) @@ -695,6 +705,16 @@ void ConstraintNamer::LTPumpingCapacityThreasholdsDown(unsigned int constraint, SetLTStorageClusterElementName(constraint, "LTPumpingCapacityThreasholdsDown", clusterName); } +void ConstraintNamer::LTStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "LTStockLevelReserveParticipationUp", clusterName); +} + +void ConstraintNamer::LTStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) +{ + SetLTStorageClusterElementName(constraint, "LTStockLevelReserveParticipationDown", 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 c883c8d026..5e3bd29139 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 @@ -119,12 +119,17 @@ struct CORRESPONDANCES_DES_CONTRAINTES std::vector NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMax; std::vector NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMin; std::vector NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds; + std::vector NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp; + std::vector NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown; std::vector NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation; std::vector NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation; std::vector NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax; std::vector NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin; std::vector NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds; + std::vector NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp; + std::vector NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown; + std::vector NumeroDeContrainteDesNiveauxPays; @@ -327,6 +332,8 @@ struct CAPACITY_RESERVATION std::vector need; //!< Vector size is number of hours in year float failureCost = 0; float spillageCost = 0; + float maxActivationRatio = 0; + int maxActivationDuration = 0; std::string reserveName; int globalReserveIndex; int areaReserveIndex; @@ -513,6 +520,7 @@ struct RESERVES { std::vector ValeursHorairesInternalUnsatisfied; std::vector ValeursHorairesInternalExcessReserve; + std::vector CoutsMarginauxHoraires; }; struct RESULTATS_HORAIRES @@ -525,8 +533,6 @@ struct RESULTATS_HORAIRES std::vector ValeursHorairesDeDefaillanceNegative; - - std::vector CoutsMarginauxHoraires; std::vector ProductionThermique; // index is pdtHebdo std::vector HydroUsage; // index is pdtHebdo diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 7d8a3d8b6c..e6bc2f4203 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -268,6 +268,10 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds.assign( study.runtime.shortTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown.assign(study.runtime.longTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp.assign(study.runtime.longTermStorageCount, -1); problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation.assign( @@ -284,6 +288,11 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds.assign( study.runtime.longTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown.assign(study.runtime.longTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp.assign(study.runtime.longTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeLaDeuxiemeContrainteDesContraintesDesGroupesQuiTombentEnPanne.assign( @@ -518,6 +527,7 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, nbReserves, 0.); problem.ResultatsHoraires[k].Reserves[j].ValeursHorairesInternalExcessReserve.assign( nbReserves, 0.); + problem.ResultatsHoraires[k].Reserves[j].CoutsMarginauxHoraires.assign(nbReserves, 0.); problem.ResultatsHoraires[k].HydroUsage[j].reserveParticipationOfCluster.assign( 1, // For the moment only one hydro cluster per area 0.); diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index d9f7c12b70..fb5837f456 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -49,6 +49,8 @@ static void importCapacityReservations(AreaList& areas, PROBLEME_HEBDO& problem) CAPACITY_RESERVATION areaCapacityReservationsUp; areaCapacityReservationsUp.failureCost = reserveCapacity.failureCost; areaCapacityReservationsUp.spillageCost = reserveCapacity.spillageCost; + areaCapacityReservationsUp.maxActivationRatio = reserveCapacity.maxActivationRatio; + areaCapacityReservationsUp.maxActivationDuration = reserveCapacity.maxActivationHours; areaCapacityReservationsUp.reserveName = reserveName; areaCapacityReservationsUp.globalReserveIndex = globalReserveIndex; areaCapacityReservationsUp.areaReserveIndex = areaReserveIndex; @@ -72,6 +74,8 @@ static void importCapacityReservations(AreaList& areas, PROBLEME_HEBDO& problem) CAPACITY_RESERVATION areaCapacityReservationsDown; areaCapacityReservationsDown.failureCost = reserveCapacity.failureCost; areaCapacityReservationsDown.spillageCost = reserveCapacity.spillageCost; + areaCapacityReservationsDown.maxActivationRatio = reserveCapacity.maxActivationRatio; + areaCapacityReservationsDown.maxActivationDuration = reserveCapacity.maxActivationHours; areaCapacityReservationsDown.reserveName = reserveName; areaCapacityReservationsDown.globalReserveIndex = globalReserveIndex; areaCapacityReservationsDown.areaReserveIndex = areaReserveIndex; diff --git a/src/solver/variable/CMakeLists.txt b/src/solver/variable/CMakeLists.txt index 18c37935de..1ea44d9fca 100644 --- a/src/solver/variable/CMakeLists.txt +++ b/src/solver/variable/CMakeLists.txt @@ -117,6 +117,7 @@ set(SRC_VARIABLE_ECONOMY include/antares/solver/variable/economy/avail-dispatchable-generation.h include/antares/solver/variable/economy/dispatchable-generation-margin.h include/antares/solver/variable/economy/reserveParticipationCost.h + include/antares/solver/variable/economy/reserveParticipationMarginalCost.h include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h include/antares/solver/variable/economy/vCardReserveParticipationByDispatchableOnUnitsPlant.h include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h @@ -131,6 +132,7 @@ set(SRC_VARIABLE_ECONOMY include/antares/solver/variable/economy/vCardReserveParticipationBySTStorageGroup.h include/antares/solver/variable/economy/reserveParticipationByLTStorage.h include/antares/solver/variable/economy/vCardReserveParticipationByLTStorage.h + include/antares/solver/variable/economy/vCardReserveParticipationMarginalCost.h # Links include/antares/solver/variable/economy/links/flowLinear.h diff --git a/src/solver/variable/include/antares/solver/variable/economy/all.h b/src/solver/variable/include/antares/solver/variable/economy/all.h index 931615e8de..8f986063aa 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/all.h +++ b/src/solver/variable/include/antares/solver/variable/economy/all.h @@ -46,6 +46,7 @@ #include "dtgMarginAfterCsr.h" #include "spilledEnergy.h" #include "reserveParticipationCost.h" +#include "reserveParticipationMarginalCost.h" #include "reserveParticipationByThermalGroup.h" #include "reserveParticipationUnsuppliedSpilled.h" #include "hydroCost.h" @@ -156,6 +157,7 @@ typedef // Prices // by plant >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VariablesPerArea; /*! diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationMarginalCost.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationMarginalCost.h new file mode 100644 index 0000000000..fc372ef6a3 --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationMarginalCost.h @@ -0,0 +1,310 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** Antares_Simulator is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#ifndef __SOLVER_VARIABLE_ECONOMY_ReserveParticipationMarginalCost_H__ +#define __SOLVER_VARIABLE_ECONOMY_ReserveParticipationMarginalCost_H__ + +#include "../variable.h" +#include "./vCardReserveParticipationMarginalCost.h" + +namespace Antares +{ +namespace Solver +{ +namespace Variable +{ +namespace Economy +{ + +/*! +** \brief Reserve participation unsupplied and spilled volumes for an area +*/ +template +class ReserveParticipationMarginalCost : public Variable::IVariable, + NextT, + VCardReserveParticipationMarginalCost> +{ +public: + //! Type of the next static variable + typedef NextT NextType; + //! VCard + typedef VCardReserveParticipationMarginalCost VCardType; + //! Ancestor + typedef Variable::IVariable, NextT, VCardType> AncestorType; + + //! List of expected results + typedef typename VCardType::ResultsType ResultsType; + + typedef VariableAccessor VariableAccessorType; + + enum + { + //! How many items have we got + count = 1 + NextT::count, + }; + + template + struct Statistics + { + enum + { + count + = ((VCardType::categoryDataLevel & CDataLevel && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), + }; + }; + +public: + ReserveParticipationMarginalCost() : pValuesForTheCurrentYear(NULL), pSize(0) + { + } + + ~ReserveParticipationMarginalCost() + { + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + delete[] pValuesForTheCurrentYear[numSpace]; + delete[] pValuesForTheCurrentYear; + } + + void initializeFromStudy(Data::Study& study) + { + // Next + NextType::initializeFromStudy(study); + } + + void initializeFromArea(Data::Study* study, Data::Area* area) + { + // Get the number of years in parallel + pNbYearsParallel = study->maxNbYearsInParallel; + pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; + + // Get the area + pSize = 0; + for (auto res : area->allCapacityReservations.areaCapacityReservationsUp) + { + pSize += 1; + } + for (auto res : area->allCapacityReservations.areaCapacityReservationsDown) + { + pSize += 1; + } + if (pSize) + { + AncestorType::pResults.resize(pSize); + + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + pValuesForTheCurrentYear[numSpace] + = new VCardType::IntermediateValuesDeepType[pSize]; + + // Minimum power values of the cluster for the whole year - from the solver in the + // accurate mode not to be displayed in the output \todo think of a better place like + // the DispatchableMarginForAllAreas done at the beginning of the year + + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + for (unsigned int i = 0; i != pSize; ++i) + pValuesForTheCurrentYear[numSpace][i].initializeFromStudy(*study); + + for (unsigned int i = 0; i != pSize; ++i) + { + AncestorType::pResults[i].initializeFromStudy(*study); + AncestorType::pResults[i].reset(); + } + } + else + { + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace] = nullptr; + } + AncestorType::pResults.clear(); + } + // Next + NextType::initializeFromArea(study, area); + } + + size_t getMaxNumberColumns() const + { + return pSize * ResultsType::count; + } + + void initializeFromLink(Data::Study* study, Data::AreaLink* link) + { + // Next + NextType::initializeFromAreaLink(study, link); + } + + void simulationBegin() + { + // Next + NextType::simulationBegin(); + } + + void simulationEnd() + { + NextType::simulationEnd(); + } + + void yearBegin(unsigned int year, unsigned int numSpace) + { + // Reset the values for the current year + for (unsigned int i = 0; i != pSize; ++i) + pValuesForTheCurrentYear[numSpace][i].reset(); + + // Next variable + NextType::yearBegin(year, numSpace); + } + + void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) + { + // Next variable + NextType::yearEndBuildForEachThermalCluster(state, year, numSpace); + } + + void yearEndBuild(State& state, unsigned int year) + { + // Next variable + NextType::yearEndBuild(state, year); + } + + void yearEnd(unsigned int year, unsigned int numSpace) + { + // Merge all results for all thermal clusters + { + for (unsigned int i = 0; i < pSize; ++i) + { + // Compute all statistics for the current year (daily,weekly,monthly) + pValuesForTheCurrentYear[numSpace][i].computeStatisticsForTheCurrentYear(); + } + } + // Next variable + NextType::yearEnd(year, numSpace); + } + + void computeSummary(std::map& numSpaceToYear, + unsigned int nbYearsForCurrentSummary) + { + for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace) + { + for (unsigned int i = 0; i < pSize; ++i) + { + // Merge all those values with the global results + AncestorType::pResults[i].merge(numSpaceToYear[numSpace], + pValuesForTheCurrentYear[numSpace][i]); + } + } + + // Next variable + NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary); + } + + void hourBegin(unsigned int hourInTheYear) + { + // Next variable + NextType::hourBegin(hourInTheYear); + } + + void hourForEachArea(State& state, unsigned int numSpace) + { + auto& area = state.area; + int column = 0; + + auto reserves = state.problemeHebdo->allReserves[area->index]; + for (const auto& reserveUp : reserves.areaCapacityReservationsUp) + { + pValuesForTheCurrentYear[numSpace][column++].hour[state.hourInTheYear] + += state.hourlyResults->Reserves[state.hourInTheWeek] + .CoutsMarginauxHoraires[reserveUp.areaReserveIndex]; + } + for (const auto& reserveDown : reserves.areaCapacityReservationsDown) + { + pValuesForTheCurrentYear[numSpace][column++].hour[state.hourInTheYear] + += state.hourlyResults->Reserves[state.hourInTheWeek] + .CoutsMarginauxHoraires[reserveDown.areaReserveIndex]; + } + + // Next variable + NextType::hourForEachArea(state, numSpace); + } + + Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear( + unsigned int, + unsigned int numSpace) const + { + return pValuesForTheCurrentYear[numSpace]->hour; + } + + void localBuildAnnualSurveyReport(SurveyResults& results, + int fileLevel, + int precision, + unsigned int numSpace) const + { + // Initializing external pointer on current variable non applicable status + results.isCurrentVarNA = AncestorType::isNonApplicable; + + if (AncestorType::isPrinted[0]) + { + assert(NULL != results.data.area); + const auto& thermal = results.data.area->thermal; + results.variableUnit = VCardType::Unit(); + // Write the data for the current year + int column = 0; + for (const auto& reserveUp : results.data.area->allCapacityReservations.areaCapacityReservationsUp) + { + // Write the data for the current year + Yuni::String caption = reserveUp.first; + caption << "_MRG.COST"; + results.variableCaption = caption; // VCardType::Caption(); + pValuesForTheCurrentYear[numSpace][column++].template buildAnnualSurveyReport( + results, fileLevel, precision); + } + for (const auto& reserveDown : results.data.area->allCapacityReservations.areaCapacityReservationsDown) + { + // Write the data for the current year + Yuni::String caption = reserveDown.first; + caption << "_MRG.COST"; + results.variableCaption = caption; // VCardType::Caption(); + pValuesForTheCurrentYear[numSpace][column++].template buildAnnualSurveyReport( + results, fileLevel, precision); + } + } + } + +private: + //! Intermediate values for each year + typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; + size_t pSize; + unsigned int pNbYearsParallel; + +}; // class ReserveParticipationMarginalCost + +} // namespace Economy +} // namespace Variable +} // namespace Solver +} // namespace Antares + +#endif // __SOLVER_VARIABLE_ECONOMY_MarginalCost_H__ \ No newline at end of file diff --git a/src/solver/variable/include/antares/solver/variable/economy/vCardReserveParticipationMarginalCost.h b/src/solver/variable/include/antares/solver/variable/economy/vCardReserveParticipationMarginalCost.h new file mode 100644 index 0000000000..5722bd15f3 --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/vCardReserveParticipationMarginalCost.h @@ -0,0 +1,109 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditi96ons of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** Antares_Simulator is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#ifndef __SOLVER_VARIABLE_ECONOMY_VCardReserveParticipationMarginalCost_H__ +#define __SOLVER_VARIABLE_ECONOMY_VCardReserveParticipationMarginalCost_H__ + +#include "../storage/results.h" + +namespace Antares +{ +namespace Solver +{ +namespace Variable +{ +namespace Economy +{ +struct VCardReserveParticipationMarginalCost +{ + //! Caption + static std::string Caption() + { + return "RESERVE PARTICIPATION MARGINAL COST"; + } + //! Unit + static std::string Unit() + { + return "Euro"; + } + + //! The short description of the variable + static std::string Description() + { + return "Reserve participation marginal cost"; + } + + //! The expected results + typedef Results> + ResultsType; + + //! The VCard to look for for calculating spatial aggregates + typedef VCardReserveParticipationUnsuppliedSpilled VCardForSpatialAggregate; + + enum + { + //! Data Level + categoryDataLevel = Category::DataLevel::area, + //! File level (provided by the type of the results) + categoryFileLevel = ResultsType::categoryFile & (Category::FileLevel::id | Category::FileLevel::va), + //! Precision (views) + precision = Category::all, + //! Indentation (GUI) + nodeDepthForGUI = +0, + //! Decimal precision + decimal = 0, + //! Number of columns used by the variable + columnCount = Category::dynamicColumns, + //! The Spatial aggregation + spatialAggregate = Category::spatialAggregateSum, + spatialAggregateMode = Category::spatialAggregateEachYear, + spatialAggregatePostProcessing = 0, + //! Intermediate values + hasIntermediateValues = 1, + //! Can this variable be non applicable (0 : no, 1 : yes) + isPossiblyNonApplicable = 0, + }; + + typedef IntermediateValues IntermediateValuesDeepType; + typedef IntermediateValues* IntermediateValuesBaseType; + typedef IntermediateValuesBaseType* IntermediateValuesType; + + // typedef IntermediateValues IntermediateValuesType; + +}; // class VCard + +static std::string marginalCostToString() +{ + return "MRG.COST"; +} + +} // namespace Economy +} // namespace Variable +} // namespace Solver +} // namespace Antares + +#endif //__SOLVER_VARIABLE_ECONOMY_VCardReserveParticipationMarginalCost_H__ \ No newline at end of file diff --git a/src/solver/variable/include/antares/solver/variable/info.h b/src/solver/variable/include/antares/solver/variable/info.h index 26419b9468..77729bb16e 100644 --- a/src/solver/variable/include/antares/solver/variable/info.h +++ b/src/solver/variable/include/antares/solver/variable/info.h @@ -29,6 +29,7 @@ #include "./economy/vCardReserveParticipationBySTStorageGroup.h" #include "./economy/vCardReserveParticipationByThermalGroup.h" #include "./economy/vCardReserveParticipationUnsuppliedSpilled.h" +#include "./economy/vCardReserveParticipationMarginalCost.h" #include "antares/solver/variable/surveyresults.h" #include "antares/study/fwd.h" @@ -618,6 +619,16 @@ struct VariableAccessor unsuppliedOrSpilled); res = true; } + else if constexpr (std::is_same_v< + VCardType, + Economy::VCardReserveParticipationMarginalCost>) + { + auto [unsuppliedOrSpilled, reserveName] + = thermal.list.reserveParticipationUnsuppliedSpilledAt(results.data.area, i); + results.variableCaption = reserveName + "_" + + Economy::marginalCostToString(); + res = true; + } else res = setClusterCaption(results, fileLevel, i); if (!res) From 1a3fe6ed0d50f49c52b08624c37a59b306661e8d Mon Sep 17 00:00:00 2001 From: CAMUS Benjamin Date: Thu, 28 Nov 2024 16:44:54 +0100 Subject: [PATCH 02/15] first version of the implementation of the reserve equations v.2 for part 3 --- src/libs/antares/study/area/list.cpp | 53 +++++++- .../antares/study/area/capacityReservation.h | 8 +- src/solver/optimisation/CMakeLists.txt | 4 + .../constraints/ReserveParticipationGroup.cpp | 16 ++- ...STStockEnergyLevelReserveParticipation.cpp | 59 +++++++++ ...kGlobalEnergyLevelReserveParticipation.cpp | 123 ++++++++++++++++++ .../STStockLevelReserveParticipation.cpp | 121 ++++++++--------- .../STStockEnergyLevelReserveParticipation.h | 26 ++++ ...ockGlobalEnergyLevelReserveParticipation.h | 25 ++++ .../solver/optimisation/opt_rename_problem.h | 4 + .../opt_gestion_second_membre_reserves.cpp | 61 ++++++++- .../optimisation/opt_rename_problem.cpp | 19 ++- .../sim_structure_probleme_economique.h | 8 ++ .../simulation/sim_alloc_probleme_hebdo.cpp | 11 +- .../simulation/sim_calcul_economique.cpp | 7 + 15 files changed, 465 insertions(+), 80 deletions(-) create mode 100644 src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp create mode 100644 src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index 5f26fc925d..6c915b7d0f 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -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(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(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(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(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; @@ -963,6 +1005,15 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << section.name; } } + else if (tmp == "max-energy-activation-ratio") + { + if (!p->value.to(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(tmpCapacityReservation.maxActivationHours)) diff --git a/src/libs/antares/study/include/antares/study/area/capacityReservation.h b/src/libs/antares/study/include/antares/study/area/capacityReservation.h index 5c4056fc4c..df06f50c5e 100644 --- a/src/libs/antares/study/include/antares/study/area/capacityReservation.h +++ b/src/libs/antares/study/include/antares/study/area/capacityReservation.h @@ -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; @@ -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 areaCapacityReservationsUp; std::map areaCapacityReservationsDown; diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index f855534522..90c37a2652 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -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 diff --git a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp index 5fc3d96d0d..49e8c51e01 100644 --- a/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp +++ b/src/solver/optimisation/constraints/ReserveParticipationGroup.cpp @@ -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, @@ -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); @@ -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++; } @@ -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++; } @@ -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++) { @@ -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 @@ -337,7 +348,6 @@ void ReserveParticipationGroup::BuildConstraints() LTPumpingCapacityThreasholds.add(pays, 0, pdt); // 15 (r) LTStockLevelReserveParticipation.add(pays, 0, pdt); - } } } diff --git a/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp new file mode 100644 index 0000000000..df111f3e81 --- /dev/null +++ b/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp @@ -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; + } +} \ No newline at end of file diff --git a/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp new file mode 100644 index 0000000000..3e1fbe7c18 --- /dev/null +++ b/src/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.cpp @@ -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& 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); + } +} \ No newline at end of file diff --git a/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp index f93d5d9cf2..0bb982a088 100644 --- a/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp +++ b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp @@ -6,112 +6,99 @@ void STStockLevelReserveParticipation::add(int pays, int cluster, int pdt) if (!data.Simulation) { - // 15 (r) (1) + // 15 (g) (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).ShortTermStorageLevel(globalClusterIdx, 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.AllSTStorageReservesParticipation.contains(cluster)) { - builder.updateHourWithinWeek(t); - for (const auto& [clusterId, reserveParticipations] : capacityReservation.AllSTStorageReservesParticipation) - { - if (cluster == clusterId) - builder.STStorageClusterReserveDownParticipation( + RESERVE_PARTICIPATION_STSTORAGE reserveParticipations = capacityReservation.AllSTStorageReservesParticipation[cluster]; + builder.STStorageClusterReserveDownParticipation( reserveParticipations.globalIndexClusterParticipation, capacityReservation.maxActivationRatio); - } } } - builder.lessThan(); - data.CorrespondanceCntNativesCntOptim[pdt] - .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown - [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.STStockLevelReserveParticipationDown(builder.data.nombreDeContraintes, - "ShortTermStorage"); - builder.build(); + if (builder.NumberOfVariables() > 0) + { + builder.ShortTermStorageLevel(globalClusterIdx, 1.); + builder.lessThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown + [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.STStockLevelReserveParticipationDown(builder.data.nombreDeContraintes, + "ShortTermStorage"); + builder.build(); + } } - // 15 (r) (2) + // 15 (g) (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).ShortTermStorageLevel(globalClusterIdx, 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.AllSTStorageReservesParticipation.contains(cluster)) { - builder.updateHourWithinWeek(t); - for (const auto& [clusterId, reserveParticipations] : capacityReservation.AllSTStorageReservesParticipation) - { - if (cluster == clusterId) - builder.STStorageClusterReserveUpParticipation( + RESERVE_PARTICIPATION_STSTORAGE reserveParticipations = capacityReservation.AllSTStorageReservesParticipation[cluster]; + builder.STStorageClusterReserveUpParticipation( reserveParticipations.globalIndexClusterParticipation, -capacityReservation.maxActivationRatio); - } } } - builder.greaterThan(); - data.CorrespondanceCntNativesCntOptim[pdt] - .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp - [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.STStockLevelReserveParticipationUp(builder.data.nombreDeContraintes, - "ShortTermStorage"); - builder.build(); + if (builder.NumberOfVariables() > 0) + { + builder.ShortTermStorageLevel(globalClusterIdx, -1.); + builder.lessThan(); + data.CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp + [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.STStockLevelReserveParticipationUp(builder.data.nombreDeContraintes, + "ShortTermStorage"); + builder.build(); + } } } else { // Lambda that count the number of reserveParticipations - auto countReservesParticipations = [cluster](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.AllSTStorageReservesParticipation.count(cluster) * n_t; + counter += capacityReservation.AllSTStorageReservesParticipation.count(cluster); } 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/include/antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h new file mode 100644 index 0000000000..6e2c7b624a --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.h @@ -0,0 +1,26 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'STStockLevelReserveParticipation' Constraint type + */ +class STStockEnergyLevelReserveParticipation : private ConstraintFactory +{ +public: + STStockEnergyLevelReserveParticipation(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/include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h new file mode 100644 index 0000000000..e797389722 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/STStockGlobalEnergyLevelReserveParticipation.h @@ -0,0 +1,25 @@ +#pragma once +#include "ConstraintBuilder.h" + +/* + * represent 'STStockLevelReserveParticipation' Constraint type + */ +class STStockGlobalEnergyLevelReserveParticipation : private ConstraintFactory +{ +public: + STStockGlobalEnergyLevelReserveParticipation(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 + */ + void add(int pays, int cluster, int pdt); + +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 228fc376f6..6da8f953da 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 @@ -232,6 +232,10 @@ class ConstraintNamer: public Namer void STPumpingCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); void STStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); void STStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); + void STEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName, const std::string& reserveName); + void STGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); + void STGlobalEnergyStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); + void LTReserveUpParticipation(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 f4a1378834..53d5d842fa 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -165,6 +165,21 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro SecondMembre[cnt] = reserveParticipation.maxPumping; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation + [reserveParticipation.globalIndexClusterParticipation]; + if (cnt >= 0) + { + auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); + std::vector& Xmin = problemeHebdo->ProblemeAResoudre->Xmin; + int clusterGlobalIndex = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea].clusterGlobalIndex; + int varLevel = variableManager.ShortTermStorageLevel(clusterGlobalIndex, pdtJour); + double level_min = Xmin[varLevel]; + SecondMembre[cnt] = -areaReserveUp.maxEnergyActivationRatio * areaReserveUp.maxActivationDuration * level_min; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } } } auto& areaReservesDown @@ -192,6 +207,21 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro SecondMembre[cnt] = reserveParticipation.maxPumping; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + + cnt + = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation + [reserveParticipation.globalIndexClusterParticipation]; + if (cnt >= 0) + { + auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); + std::vector& Xmax = problemeHebdo->ProblemeAResoudre->Xmax; + int clusterGlobalIndex = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea].clusterGlobalIndex; + int varLevel = variableManager.ShortTermStorageLevel(clusterGlobalIndex, pdtJour); + double level_max = Xmax[varLevel]; + SecondMembre[cnt] = areaReserveDown.maxEnergyActivationRatio * areaReserveDown.maxActivationDuration * level_max; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } } } for (const auto& cluster : problemeHebdo->ShortTermStorage[pays]) @@ -230,13 +260,19 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); + int varLevel = variableManager.ShortTermStorageLevel(globalClusterIdx, pdtJour); + std::vector& Xmax = problemeHebdo->ProblemeAResoudre->Xmax; + double level_max = Xmax[varLevel]; + std::vector& Xmin = problemeHebdo->ProblemeAResoudre->Xmin; + double level_min = Xmin[varLevel]; + cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown [globalClusterIdx]; if (cnt >= 0) { - SecondMembre[cnt] = cluster.reservoirCapacity - * cluster.series->upperRuleCurve[pdtJour]; + SecondMembre[cnt] = level_max; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -245,10 +281,27 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [globalClusterIdx]; if (cnt >= 0) { - SecondMembre[cnt] = cluster.reservoirCapacity - * cluster.series->lowerRuleCurve[pdtJour]; + SecondMembre[cnt] = -level_min; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } + + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown + [globalClusterIdx]; + if (cnt >= 0) + { + SecondMembre[cnt] = areaReserves[pays].maxGlobalActivationDurationDown * areaReserves[pays].maxGlobalEnergyActivationRatioDown * level_max; + AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; + } + + cnt = CorrespondanceCntNativesCntOptim + .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp + [globalClusterIdx]; + if (cnt >= 0) + { + 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 cba9f668b6..3c271c86cf 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -641,12 +641,27 @@ void ConstraintNamer::STPumpingCapacityThreasholdsDown(unsigned int constraint, void ConstraintNamer::STStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName) { - SetLTStorageClusterElementName(constraint, "STStockLevelReserveParticipationUp", clusterName); + SetSTStorageClusterElementName(constraint, "STStockLevelReserveParticipationUp", clusterName); } void ConstraintNamer::STStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) { - SetLTStorageClusterElementName(constraint, "STStockLevelReserveParticipationDown", clusterName); + SetSTStorageClusterElementName(constraint, "STStockLevelReserveParticipationDown", clusterName); +} + +void ConstraintNamer::STEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName, const std::string& reserveName) +{ + SetSTStorageClusterAndReserveElementName(constraint, "STEnergyStockLevelReserveParticipationDown", clusterName, reserveName); +} + +void ConstraintNamer::STGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) +{ + SetSTStorageClusterElementName(constraint, "STGlobalEnergyStockLevelReserveParticipationDown", clusterName); +} + +void ConstraintNamer::STGlobalEnergyStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName) +{ + SetSTStorageClusterElementName(constraint, "STGlobalEnergyStockLevelReserveParticipationUp", clusterName); } void ConstraintNamer::LTReserveUpParticipation(unsigned int constraint, 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 5e3bd29139..20f398259d 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 @@ -121,6 +121,9 @@ struct CORRESPONDANCES_DES_CONTRAINTES std::vector NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds; std::vector NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp; std::vector NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown; + std::vector NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation; + std::vector NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp; + std::vector NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown; std::vector NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation; std::vector NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation; @@ -333,6 +336,7 @@ struct CAPACITY_RESERVATION float failureCost = 0; float spillageCost = 0; float maxActivationRatio = 0; + float maxEnergyActivationRatio = 1; int maxActivationDuration = 0; std::string reserveName; int globalReserveIndex; @@ -342,6 +346,10 @@ struct CAPACITY_RESERVATION // Vector size is number of reserves up or down struct AREA_RESERVES_VECTOR { + float maxGlobalEnergyActivationRatioUp = 1.; + float maxGlobalEnergyActivationRatioDown = 1.; + int maxGlobalActivationDurationUp = 0; + int maxGlobalActivationDurationDown = 0; std::vector areaCapacityReservationsUp; std::vector areaCapacityReservationsDown; }; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index e6bc2f4203..93e745697f 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -269,9 +269,16 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, .NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds.assign( study.runtime.shortTermStorageCount, -1); problem.CorrespondanceCntNativesCntOptim[k] - .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown.assign(study.runtime.longTermStorageCount, -1); + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown.assign(study.runtime.shortTermStorageCount, -1); problem.CorrespondanceCntNativesCntOptim[k] - .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp.assign(study.runtime.longTermStorageCount, -1); + .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp.assign(study.runtime.shortTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation.assign(study.runtime.shortTermStorageCount * study.runtime.capacityReservationCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp.assign(study.runtime.shortTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] + .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown.assign(study.runtime.shortTermStorageCount, -1); + problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation.assign( diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index fb5837f456..598ca73df9 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -43,6 +43,11 @@ static void importCapacityReservations(AreaList& areas, PROBLEME_HEBDO& problem) auto area = areas[areaIndex]; auto& areaReserves = problem.allReserves[areaIndex]; + areaReserves.maxGlobalActivationDurationDown = area->allCapacityReservations.maxGlobalActivationDurationDown; + areaReserves.maxGlobalActivationDurationUp = area->allCapacityReservations.maxGlobalActivationDurationUp; + areaReserves.maxGlobalEnergyActivationRatioDown = area->allCapacityReservations.maxGlobalEnergyActivationRatioDown; + areaReserves.maxGlobalEnergyActivationRatioUp = area->allCapacityReservations.maxGlobalEnergyActivationRatioUp; + for (auto const& [reserveName, reserveCapacity] : area->allCapacityReservations.areaCapacityReservationsUp) { @@ -50,6 +55,7 @@ static void importCapacityReservations(AreaList& areas, PROBLEME_HEBDO& problem) areaCapacityReservationsUp.failureCost = reserveCapacity.failureCost; areaCapacityReservationsUp.spillageCost = reserveCapacity.spillageCost; areaCapacityReservationsUp.maxActivationRatio = reserveCapacity.maxActivationRatio; + areaCapacityReservationsUp.maxEnergyActivationRatio = reserveCapacity.maxEnergyActivationRatio; areaCapacityReservationsUp.maxActivationDuration = reserveCapacity.maxActivationHours; areaCapacityReservationsUp.reserveName = reserveName; areaCapacityReservationsUp.globalReserveIndex = globalReserveIndex; @@ -76,6 +82,7 @@ static void importCapacityReservations(AreaList& areas, PROBLEME_HEBDO& problem) areaCapacityReservationsDown.spillageCost = reserveCapacity.spillageCost; areaCapacityReservationsDown.maxActivationRatio = reserveCapacity.maxActivationRatio; areaCapacityReservationsDown.maxActivationDuration = reserveCapacity.maxActivationHours; + areaCapacityReservationsDown.maxEnergyActivationRatio = reserveCapacity.maxEnergyActivationRatio; areaCapacityReservationsDown.reserveName = reserveName; areaCapacityReservationsDown.globalReserveIndex = globalReserveIndex; areaCapacityReservationsDown.areaReserveIndex = areaReserveIndex; From b4e646f6efac7d37803064eafc6d7122ef43b0e6 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 29 Nov 2024 15:27:58 +0100 Subject: [PATCH 03/15] Fix pdt issue --- .../opt_gestion_second_membre_reserves.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp index dc5143b9c7..8456b031dd 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -51,10 +51,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - int pdtGlobal = problemeHebdo->weekInTheYear - * problemeHebdo->NombreDePasDeTempsDUneJournee - * problemeHebdo->NombreDeJours - + pdtJour; + int hourInTheYear = problemeHebdo->weekInTheYear * 168 + pdtHebdo; // Thermal clusters { @@ -67,7 +64,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [areaReserveUp.globalReserveIndex]; if (cnt >= 0) { - SecondMembre[cnt] = areaReserveUp.need.at(pdtGlobal); + SecondMembre[cnt] = areaReserveUp.need.at(hourInTheYear); AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -99,7 +96,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [areaReserveDown.globalReserveIndex]; if (cnt >= 0) { - SecondMembre[cnt] = areaReserveDown.need.at(pdtGlobal); + SecondMembre[cnt] = areaReserveDown.need.at(hourInTheYear); AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } } @@ -201,7 +198,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [globalClusterIdx]; if (cnt >= 0) { - SecondMembre[cnt] = cluster.series.get()->maxWithdrawalModulation[pdtJour] + SecondMembre[cnt] = cluster.series.get()->maxWithdrawalModulation[hourInTheYear] * cluster.withdrawalNominalCapacity; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -212,7 +209,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [globalClusterIdx]; if (cnt >= 0) { - SecondMembre[cnt] = cluster.series.get()->lowerRuleCurve[pdtJour] + SecondMembre[cnt] = cluster.series.get()->lowerRuleCurve[hourInTheYear] * cluster.withdrawalNominalCapacity; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -223,7 +220,7 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [globalClusterIdx]; if (cnt >= 0) { - SecondMembre[cnt] = cluster.series.get()->maxInjectionModulation[pdtJour] + SecondMembre[cnt] = cluster.series.get()->maxInjectionModulation[hourInTheYear] * cluster.injectionNominalCapacity; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } From 9c3a50aed38a7f59ab0848d9bc9dc5f4c988ce66 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 29 Nov 2024 15:43:39 +0100 Subject: [PATCH 04/15] Typo Fix pdt issue --- src/solver/optimisation/opt_gestion_second_membre_reserves.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp index 8456b031dd..1a6cd0e45b 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -46,12 +46,12 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro for (int pdtJour = 0, pdtHebdo = PremierPdtDeLIntervalle; pdtHebdo < DernierPdtDeLIntervalle; pdtHebdo++, pdtJour++) { + int hourInTheYear = problemeHebdo->weekInTheYear * 168 + pdtHebdo; const CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim = problemeHebdo->CorrespondanceCntNativesCntOptim[pdtJour]; for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - int hourInTheYear = problemeHebdo->weekInTheYear * 168 + pdtHebdo; // Thermal clusters { From c0ec60a8ad19ca73a6353926e2e192ef0d305868 Mon Sep 17 00:00:00 2001 From: CAMUS Benjamin Date: Fri, 29 Nov 2024 17:57:44 +0100 Subject: [PATCH 05/15] fix bugs related to the implementation of reserves lot 3 v2 --- src/libs/antares/study/area/list.cpp | 10 +- ...STStockEnergyLevelReserveParticipation.cpp | 95 +++++++++++-------- .../STStockLevelReserveParticipation.cpp | 4 +- .../solver/optimisation/opt_rename_problem.h | 2 +- .../opt_gestion_second_membre_reserves.cpp | 33 +++---- .../optimisation/opt_rename_problem.cpp | 4 +- 6 files changed, 81 insertions(+), 67 deletions(-) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index bcbb60c4ac..f572b99449 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -927,7 +927,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, tmp = p->key; tmp.toLower(); - if (tmp == "max_activation_ratio_up") + if (tmp == "max-energy-activation-ratio-up") { if (!p->value.to(area.allCapacityReservations.maxGlobalEnergyActivationRatioUp)) { @@ -935,7 +935,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << area.name << ": invalid maximum energy activation ratio for UP reserves"; } } - else if (tmp == "max_activation_ratio_down") + else if (tmp == "max-energy-activation-ratio-down") { if (!p->value.to(area.allCapacityReservations.maxGlobalEnergyActivationRatioDown)) { @@ -943,7 +943,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << area.name << ": invalid maximum energy activation ratio for DOWN reserves"; } } - else if (tmp == "max_activation_duration_up") + else if (tmp == "max-activation-duration-up") { if (!p->value.to(area.allCapacityReservations.maxGlobalActivationDurationUp)) { @@ -951,7 +951,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << area.name << ": invalid maximum energy activation duration for UP reserves"; } } - else if (tmp == "max_activation_duration_down") + else if (tmp == "max-activation-duration-down") { if (!p->value.to(area.allCapacityReservations.maxGlobalActivationDurationDown)) { @@ -995,7 +995,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, << section.name; } } - else if (tmp == "max-activation-ratio") + else if (tmp == "max-power-activation-ratio") { if (!p->value.to(tmpCapacityReservation.maxActivationRatio)) { diff --git a/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp index df111f3e81..066e844671 100644 --- a/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp +++ b/src/solver/optimisation/constraints/STStockEnergyLevelReserveParticipation.cpp @@ -7,53 +7,66 @@ void STStockEnergyLevelReserveParticipation::add(int pays, int cluster, int rese = isUpReserve ? data.areaReserves[pays].areaCapacityReservationsUp[reserve] : data.areaReserves[pays].areaCapacityReservationsDown[reserve]; - if (!data.Simulation) + if (capacityReservation.maxActivationDuration > 0) { - // 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 + if (!data.Simulation) { - float sign = isUpReserve ? -1. : 1.; + // 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]; + RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation + = capacityReservation.AllSTStorageReservesParticipation[cluster]; - builder.updateHourWithinWeek(pdt); + 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); - } + for (int t=0; t < capacityReservation.maxActivationDuration; t++) + { + if (isUpReserve) + { + builder.STStorageClusterReserveUpParticipation( + reserveParticipation.globalIndexClusterParticipation, + capacityReservation.maxActivationRatio, + t, builder.data.NombreDePasDeTempsPourUneOptimisation); + } + else + { + 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; - 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(); + ConstraintNamer namer(builder.data.NomDesContraintes); + const int hourInTheYear = builder.data.weekInTheYear * 168 + pdt; + namer.UpdateTimeStep(hourInTheYear); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.STEnergyStockLevelReserveParticipation(builder.data.nombreDeContraintes, + reserveParticipation.clusterName, + capacityReservation.reserveName); + builder.build(); + } + } + else + { + builder.data.NbTermesContraintesPourLesReserves += 2 * capacityReservation.maxActivationDuration; + builder.data.nombreDeContraintes += 1; } - } - else - { - builder.data.NbTermesContraintesPourLesReserves += 2 * capacityReservation.maxActivationDuration; - builder.data.nombreDeContraintes += 1; } } \ No newline at end of file diff --git a/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp index 0bb982a088..a4ebd46fd0 100644 --- a/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp +++ b/src/solver/optimisation/constraints/STStockLevelReserveParticipation.cpp @@ -46,7 +46,7 @@ void STStockLevelReserveParticipation::add(int pays, int cluster, int pdt) // 15 (g) (2) // Participation of up reserves requires a sufficient level of stock - // R_t - Sum(P_{res} * R_{min,res}) >= R_down + // -R_t + Sum(P_{res} * R_{min,res}) <= -R_down // R_t : stock level at time t // P_{res} : power participation for reserve up res // R_{min,res} : max power participation ratio @@ -61,7 +61,7 @@ void STStockLevelReserveParticipation::add(int pays, int cluster, int pdt) RESERVE_PARTICIPATION_STSTORAGE reserveParticipations = capacityReservation.AllSTStorageReservesParticipation[cluster]; builder.STStorageClusterReserveUpParticipation( reserveParticipations.globalIndexClusterParticipation, - -capacityReservation.maxActivationRatio); + capacityReservation.maxActivationRatio); } } if (builder.NumberOfVariables() > 0) 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 6da8f953da..72d8a5fe84 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 @@ -232,7 +232,7 @@ class ConstraintNamer: public Namer void STPumpingCapacityThreasholdsDown(unsigned int constraint, const std::string& clusterName); void STStockLevelReserveParticipationUp(unsigned int constraint, const std::string& clusterName); void STStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); - void STEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName, const std::string& reserveName); + void STEnergyStockLevelReserveParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName); void STGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName); void STGlobalEnergyStockLevelReserveParticipationUp(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 53d5d842fa..a0f6ffa8d7 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp @@ -172,11 +172,12 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [reserveParticipation.globalIndexClusterParticipation]; if (cnt >= 0) { - auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); - std::vector& Xmin = problemeHebdo->ProblemeAResoudre->Xmin; - int clusterGlobalIndex = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea].clusterGlobalIndex; - int varLevel = variableManager.ShortTermStorageLevel(clusterGlobalIndex, pdtJour); - double level_min = Xmin[varLevel]; + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + auto& cluster = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea]; + int hourInTheYear = weekFirstHour + pdtHebdo; + double level_min = cluster.reservoirCapacity + * cluster.series->lowerRuleCurve[hourInTheYear]; + SecondMembre[cnt] = -areaReserveUp.maxEnergyActivationRatio * areaReserveUp.maxActivationDuration * level_min; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -214,11 +215,11 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro [reserveParticipation.globalIndexClusterParticipation]; if (cnt >= 0) { - auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); - std::vector& Xmax = problemeHebdo->ProblemeAResoudre->Xmax; - int clusterGlobalIndex = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea].clusterGlobalIndex; - int varLevel = variableManager.ShortTermStorageLevel(clusterGlobalIndex, pdtJour); - double level_max = Xmax[varLevel]; + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + auto& cluster = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea]; + int hourInTheYear = weekFirstHour + pdtHebdo; + double level_max = cluster.reservoirCapacity + * cluster.series->upperRuleCurve[hourInTheYear]; SecondMembre[cnt] = areaReserveDown.maxEnergyActivationRatio * areaReserveDown.maxActivationDuration * level_max; AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } @@ -260,12 +261,12 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr; } - auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo); - int varLevel = variableManager.ShortTermStorageLevel(globalClusterIdx, pdtJour); - std::vector& Xmax = problemeHebdo->ProblemeAResoudre->Xmax; - double level_max = Xmax[varLevel]; - std::vector& Xmin = problemeHebdo->ProblemeAResoudre->Xmin; - double level_min = Xmin[varLevel]; + int weekFirstHour = problemeHebdo->weekInTheYear * 168; + int hourInTheYear = weekFirstHour + pdtHebdo; + double level_max = cluster.reservoirCapacity + * cluster.series->upperRuleCurve[hourInTheYear]; + double level_min = cluster.reservoirCapacity + * cluster.series->lowerRuleCurve[hourInTheYear]; cnt = CorrespondanceCntNativesCntOptim .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index 15749cd488..ba5940c751 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -648,9 +648,9 @@ void ConstraintNamer::STStockLevelReserveParticipationDown(unsigned int constrai SetSTStorageClusterElementName(constraint, "STStockLevelReserveParticipationDown", clusterName); } -void ConstraintNamer::STEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName, const std::string& reserveName) +void ConstraintNamer::STEnergyStockLevelReserveParticipation(unsigned int constraint, const std::string& clusterName, const std::string& reserveName) { - SetSTStorageClusterAndReserveElementName(constraint, "STEnergyStockLevelReserveParticipationDown", clusterName, reserveName); + SetSTStorageClusterAndReserveElementName(constraint, "STEnergyStockLevelReserveParticipation", clusterName, reserveName); } void ConstraintNamer::STGlobalEnergyStockLevelReserveParticipationDown(unsigned int constraint, const std::string& clusterName) From f3edc0eb83714c4a73d74954b26d184064e30632 Mon Sep 17 00:00:00 2001 From: sylvmara Date: Wed, 4 Dec 2024 15:23:20 +0100 Subject: [PATCH 06/15] Corrected a bug where part of the reserves were transmitted from one area to another, creating segfaults --- src/solver/variable/include/antares/solver/variable/state.hxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/variable/include/antares/solver/variable/state.hxx b/src/solver/variable/include/antares/solver/variable/state.hxx index dadb3f82d6..9c16d562fe 100644 --- a/src/solver/variable/include/antares/solver/variable/state.hxx +++ b/src/solver/variable/include/antares/solver/variable/state.hxx @@ -95,7 +95,8 @@ inline void State::initFromAreaIndex(const unsigned int areaIndex, uint numSpace for (int h=0 ; h< HOURS_PER_YEAR; h++) { reserveParticipationPerLTStorageClusterForYear[hourInTheYear].clear(); - + reserveParticipationPerSTStorageClusterForYear[hourInTheYear].clear(); + reserveParticipationPerThermalClusterForYear[hourInTheYear].clear(); } } switch (simulationMode) From d05df33b75f71f7e98a64bb8c721d866d2d78a88 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Mon, 9 Dec 2024 15:40:07 +0100 Subject: [PATCH 07/15] Fix issue with multiple areas when exporting results with participations to reserves --- ...reserveParticipationByDispatchableOffUnitsPlant.h | 2 +- .../reserveParticipationByDispatchableOnUnitsPlant.h | 2 +- .../reserveParticipationByDispatchablePlant.h | 12 ++---------- .../economy/reserveParticipationByLTStorage.h | 7 ++----- .../economy/reserveParticipationBySTStorage.h | 12 ++---------- 5 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h index 6e20d3afa7..3310663ad2 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h @@ -106,7 +106,7 @@ class ReserveParticipationByDispatchableOffUnitsPlant pNbYearsParallel = study->maxNbYearsInParallel; pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; - // Get the area + // Get the number of Onthermal reserveParticipations pSize = area->thermal.list.reserveParticipationsCount(); if (pSize) diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h index 7fd761806f..ba377ffae1 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h @@ -106,7 +106,7 @@ class ReserveParticipationByDispatchableOnUnitsPlant pNbYearsParallel = study->maxNbYearsInParallel; pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; - // Get the area + // Get the number of Onthermal reserveParticipations pSize = area->thermal.list.reserveParticipationsCount(); if (pSize) diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchablePlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchablePlant.h index d184239ccf..863e203898 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchablePlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchablePlant.h @@ -106,16 +106,8 @@ class ReserveParticipationByDispatchableOnUnitsPlant pNbYearsParallel = study->maxNbYearsInParallel; pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; - // Get the area - pSize = 0; - for (int areaIndex = 0; areaIndex < study->areas.size(); areaIndex++) - { - if (study->areas[areaIndex]->allCapacityReservations.size() > 0) - { - pSize = area->thermal.list.reserveParticipationsCount(); - break; - } - } + // Get the number of thermal reserveParticipations + pSize = area->thermal.list.reserveParticipationsCount(); if (pSize) { AncestorType::pResults.resize(pSize); diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h index bf7e14a412..9f2bec9ebc 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h @@ -67,11 +67,8 @@ class ReserveParticipationByLTStorage pNbYearsParallel = study->maxNbYearsInParallel; pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; - pSize = 0; - for (int areaIndex = 0; areaIndex < study->areas.size(); areaIndex++) - { - pSize += study->areas[areaIndex]->hydro.reserveParticipationsCount(); - } + // Get the number of LTStorage reserveParticipations + pSize = area->hydro.reserveParticipationsCount; if (pSize) { AncestorType::pResults.resize(pSize); diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h index 14794d4929..343df31000 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h @@ -105,16 +105,8 @@ class ReserveParticipationBySTStorage pNbYearsParallel = study->maxNbYearsInParallel; pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; - // Get the area - pSize = 0; - for (int areaIndex = 0; areaIndex < study->areas.size(); areaIndex++) - { - if (study->areas[areaIndex]->allCapacityReservations.size() > 0) - { - pSize = area->shortTermStorage.reserveParticipationsCount(); - break; - } - } + // Get the number of STStorage reserveParticipations + pSize = area->shortTermStorage.reserveParticipationsCount(); if (pSize) { AncestorType::pResults.resize(pSize); From 45073bfff319eceef30be939d14571fad9baa943 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Mon, 9 Dec 2024 15:57:15 +0100 Subject: [PATCH 08/15] typo --- .../solver/variable/economy/reserveParticipationByLTStorage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h index 9f2bec9ebc..cc7a74de38 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h @@ -68,7 +68,7 @@ class ReserveParticipationByLTStorage pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; // Get the number of LTStorage reserveParticipations - pSize = area->hydro.reserveParticipationsCount; + pSize = area->hydro.reserveParticipationsCount(); if (pSize) { AncestorType::pResults.resize(pSize); From b16f18d626955a1da0447bd4e5605c7ee02b299c Mon Sep 17 00:00:00 2001 From: sylvmara Date: Wed, 11 Dec 2024 12:31:12 +0100 Subject: [PATCH 09/15] Logs warnings instead of crashing when the bimap is empty when in shouldn't (the solver did not find a solution) --- .../study/include/antares/study/area/area.h | 2 +- ...ParticipationByDispatchableOffUnitsPlant.h | 42 +++++++++++++------ ...eParticipationByDispatchableOnUnitsPlant.h | 20 ++++++--- .../economy/reserveParticipationBySTStorage.h | 22 ++++++---- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/libs/antares/study/include/antares/study/area/area.h b/src/libs/antares/study/include/antares/study/area/area.h index 81cb81c006..59eaf54ecf 100644 --- a/src/libs/antares/study/include/antares/study/area/area.h +++ b/src/libs/antares/study/include/antares/study/area/area.h @@ -87,7 +87,7 @@ class BiMap } // Function to return the size of the bimap - int size() + int size() const { return key_to_value.size(); } diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h index 3310663ad2..0e6acda125 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h @@ -179,15 +179,23 @@ class ReserveParticipationByDispatchableOffUnitsPlant i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { - for (auto const& [reserveName, reserveParticipation] : - state.reserveParticipationPerThermalClusterForYear[i][state.thermalCluster->name()]) + /*if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap in empty { - pValuesForTheCurrentYear - [numSpace][state.area->reserveParticipationThermalClustersIndexMap.get( - std::make_pair(reserveName, state.thermalCluster->name()))] - .hour[i] - = reserveParticipation.offUnitsParticipation; + logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; + break; } + else + {*/ + for (auto const& [reserveName, reserveParticipation] : + state.reserveParticipationPerThermalClusterForYear[i][state.thermalCluster->name()]) + { + pValuesForTheCurrentYear + [numSpace][state.area->reserveParticipationThermalClustersIndexMap.get( + std::make_pair(reserveName, state.thermalCluster->name()))] + .hour[i] + = reserveParticipation.offUnitsParticipation; + } + //} } } // Next variable @@ -266,12 +274,20 @@ class ReserveParticipationByDispatchableOffUnitsPlant // Write the data for the current year for (uint i = 0; i < pSize; ++i) { - auto [clusterName, reserveName] - = results.data.area->reserveParticipationThermalClustersIndexMap.get(i); - results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); - results.variableUnit = VCardType::Unit(); - pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( - results, fileLevel, precision); + if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap is empty + { + logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; + break; + } + else + { + auto [clusterName, reserveName] + = results.data.area->reserveParticipationThermalClustersIndexMap.get(i); + results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( + results, fileLevel, precision); + } } } } diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h index ba377ffae1..044a804641 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h @@ -266,12 +266,20 @@ class ReserveParticipationByDispatchableOnUnitsPlant // Write the data for the current year for (uint i = 0; i < pSize; ++i) { - auto [clusterName, reserveName] - = results.data.area->reserveParticipationThermalClustersIndexMap.get(i); - results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); - results.variableUnit = VCardType::Unit(); - pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( - results, fileLevel, precision); + if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap is empty + { + logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; + break; + } + else + { + auto [clusterName, reserveName] + = results.data.area->reserveParticipationThermalClustersIndexMap.get(i); + results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( + results, fileLevel, precision); + } } } } diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h index 343df31000..bdbe3329d7 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h @@ -258,13 +258,21 @@ class ReserveParticipationBySTStorage // Write the data for the current year for (uint i = 0; i < pSize; ++i) { - auto [clusterName, reserveName] - = results.data.area->reserveParticipationSTStorageClustersIndexMap.get(i); - // Write the data for the current year - results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); - results.variableUnit = VCardType::Unit(); - pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( - results, fileLevel, precision); + if (results.data.area->reserveParticipationSTStorageClustersIndexMap.size() == 0) //Bimap in empty + { + logs.warning() << "Problem during the solver run, the STS bimap is empty for area " << results.data.area->name; + break; + } + else + { + auto [clusterName, reserveName] + = results.data.area->reserveParticipationSTStorageClustersIndexMap.get(i); + // Write the data for the current year + results.variableCaption = clusterName + "_" + reserveName; // VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace][i].template buildAnnualSurveyReport( + results, fileLevel, precision); + } } } } From 80e6f34cf3d9bdd0671fb30ad6d3e9e46d013996 Mon Sep 17 00:00:00 2001 From: sylvmara Date: Wed, 11 Dec 2024 14:58:20 +0100 Subject: [PATCH 10/15] Added failsafe for hydro reserves bimap --- ...ParticipationByDispatchableOffUnitsPlant.h | 24 +++++++------------ ...eParticipationByDispatchableOnUnitsPlant.h | 2 +- .../economy/reserveParticipationByLTStorage.h | 18 ++++++++++---- .../economy/reserveParticipationBySTStorage.h | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h index 0e6acda125..8013e799a0 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOffUnitsPlant.h @@ -179,23 +179,15 @@ class ReserveParticipationByDispatchableOffUnitsPlant i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { - /*if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap in empty + for (auto const& [reserveName, reserveParticipation] : + state.reserveParticipationPerThermalClusterForYear[i][state.thermalCluster->name()]) { - logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; - break; + pValuesForTheCurrentYear + [numSpace][state.area->reserveParticipationThermalClustersIndexMap.get( + std::make_pair(reserveName, state.thermalCluster->name()))] + .hour[i] + = reserveParticipation.offUnitsParticipation; } - else - {*/ - for (auto const& [reserveName, reserveParticipation] : - state.reserveParticipationPerThermalClusterForYear[i][state.thermalCluster->name()]) - { - pValuesForTheCurrentYear - [numSpace][state.area->reserveParticipationThermalClustersIndexMap.get( - std::make_pair(reserveName, state.thermalCluster->name()))] - .hour[i] - = reserveParticipation.offUnitsParticipation; - } - //} } } // Next variable @@ -276,7 +268,7 @@ class ReserveParticipationByDispatchableOffUnitsPlant { if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap is empty { - logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; + logs.warning() << "Problem during the results export, the thermal bimap is empty for area " << results.data.area->name; break; } else diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h index 044a804641..7a7ca8e4f9 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByDispatchableOnUnitsPlant.h @@ -268,7 +268,7 @@ class ReserveParticipationByDispatchableOnUnitsPlant { if (results.data.area->reserveParticipationThermalClustersIndexMap.size() == 0) //Bimap is empty { - logs.warning() << "Problem during the solver run, the thermal bimap is empty for area " << results.data.area->name; + logs.warning() << "Problem during the results export, the thermal bimap is empty for area " << results.data.area->name; break; } else diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h index cc7a74de38..3801d606f6 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationByLTStorage.h @@ -199,11 +199,19 @@ void localBuildAnnualSurveyReport(SurveyResults& results, assert(NULL != results.data.area); for (uint i = 0; i < pSize; ++i) { - auto reserveName = results.data.area->reserveParticipationLTStorageIndexMap.get(i); - results.variableCaption = "LongTermStorage_" + reserveName; // VCardType::Caption(); - results.variableUnit = VCardType::Unit(); - pValuesForTheCurrentYear[numSpace][0].template buildAnnualSurveyReport( - results, fileLevel, precision); + if (results.data.area->reserveParticipationLTStorageIndexMap.size() == 0) //Bimap in empty + { + logs.warning() << "Problem during the results export, the LTS bimap is empty for area " << results.data.area->name; + break; + } + else + { + auto reserveName = results.data.area->reserveParticipationLTStorageIndexMap.get(i); + results.variableCaption = "LongTermStorage_" + reserveName; // VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace][0].template buildAnnualSurveyReport( + results, fileLevel, precision); + } } } } diff --git a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h index bdbe3329d7..3950885e7c 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h +++ b/src/solver/variable/include/antares/solver/variable/economy/reserveParticipationBySTStorage.h @@ -260,7 +260,7 @@ class ReserveParticipationBySTStorage { if (results.data.area->reserveParticipationSTStorageClustersIndexMap.size() == 0) //Bimap in empty { - logs.warning() << "Problem during the solver run, the STS bimap is empty for area " << results.data.area->name; + logs.warning() << "Problem during the results export, the STS bimap is empty for area " << results.data.area->name; break; } else From 55a216c2f802817702e2afd6f4d195892b71fada Mon Sep 17 00:00:00 2001 From: sylvmara Date: Wed, 11 Dec 2024 17:50:46 +0100 Subject: [PATCH 11/15] Ignores reserves when thermal cluster is mustrun, but puts a warning --- .../study/parts/common/cluster_list.cpp | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/libs/antares/study/parts/common/cluster_list.cpp b/src/libs/antares/study/parts/common/cluster_list.cpp index 801bfe11ad..3fe23f9fc9 100644 --- a/src/libs/antares/study/parts/common/cluster_list.cpp +++ b/src/libs/antares/study/parts/common/cluster_list.cpp @@ -437,12 +437,30 @@ bool ClusterList::loadReserveParticipations(Area& area, const std::fil auto cluster = area.thermal.list.getClusterByName(tmpClusterName); if (reserve && cluster) { - ThermalClusterReserveParticipation tmpReserveParticipation{reserve.value(), - tmpMaxPower, - tmpParticipationCost, - tmpMaxPowerOff, - tmpParticipationCostOff}; - cluster.value().get()->addReserveParticipation(section.name, tmpReserveParticipation); + bool isClusterMustRun = false; + for (const auto& clusterMustRun : area.thermal.list.each_mustrun_and_enabled()) + { + if (clusterMustRun->id() == cluster.value().get()->id()) + { + isClusterMustRun = true; + break; + } + } + if (!isClusterMustRun) + { + ThermalClusterReserveParticipation tmpReserveParticipation{ reserve.value(), + tmpMaxPower, + tmpParticipationCost, + tmpMaxPowerOff, + tmpParticipationCostOff }; + + + cluster.value().get()->addReserveParticipation(section.name, tmpReserveParticipation); + } + else + { + logs.warning() << area.name << " : " << tmpClusterName << " is mustrun and is participating in capacity reservation " << section.name << ", ignored."; + } } else { From 57ca4b41a3dba1c3fad0b9f3fe6d1c3ea3632fcb Mon Sep 17 00:00:00 2001 From: CAMUS Benjamin Date: Thu, 12 Dec 2024 15:23:23 +0100 Subject: [PATCH 12/15] fix bug to read the reserve parameters whose names are more than 30 caracters long --- src/libs/antares/study/area/list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index f572b99449..30a6c44760 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -923,7 +923,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, { for (auto* p = section.firstProperty; p; p = p->next) { - CString<30, false> tmp; + CString<32, false> tmp; tmp = p->key; tmp.toLower(); From 2b826987c8c8c8f32529183efe7d197cc3225738 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 13 Dec 2024 08:31:20 +0100 Subject: [PATCH 13/15] 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(); From 5600547e14de4228d497926d44bd70ac2496b6d3 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 13 Dec 2024 12:00:05 +0100 Subject: [PATCH 14/15] upload archive CentOS --- .github/workflows/centos7.yml | 226 +++++++++++++++------------------- src/antares-deps | 1 + 2 files changed, 99 insertions(+), 128 deletions(-) create mode 160000 src/antares-deps diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 330df8e719..4bcc0e70c6 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -2,11 +2,13 @@ name: Centos7 CI (push and/or release) on: release: - types: [created] + types: [ created ] push: branches: - develop - dependabot/* + - feature/reserve_model_lot2_scalian + - feature/reserve_model_lot3_scalian schedule: - cron: '21 2 * * *' workflow_call: @@ -29,135 +31,103 @@ jobs: build: name: Build - env: - ORTOOLSDIR: ${{ github.workspace }}/or-tools runs-on: ubuntu-latest - container: 'antaresrte/rte-antares:centos7-simulator-no-deps' steps: - - name: Checkout - run: | - git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b ${{ env.REF }} . - - - name: Install gcc 10 - run: | - # update mirrors, official centos7 is deprecated - sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo &&\ - sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo &&\ - sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo &&\ - yum update -y - - # not a typo, centos-release-scl is needed to install devtoolset-10 but introduce deprecated mirror - sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo &&\ - sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo &&\ - sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo - - yum install -y centos-release-scl - yum install -y devtoolset-11-gcc* - - - name: Install cmake 3.28 - run: pip3 install cmake==3.28.4 - - - name: Install VCPKG - # Note: we need to use environment variables instead of workflow variables - # because github messes up path variables when running in container, - # see https://github.com/actions/runner/issues/2058 - run: | - git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.sh -disableMetrics - echo "VCPKG_ROOT=$GITHUB_WORKSPACE/vcpkg" >> $GITHUB_ENV - echo "VCPKG_CACHE_DIR=$GITHUB_WORKSPACE/vcpkg_cache" >> $GITHUB_ENV - echo "VCPKG_BINARY_SOURCES=clear;files,$GITHUB_WORKSPACE/vcpkg_cache,readwrite" >> $GITHUB_ENV - - - name: Restore vcpkg binary dir from cache - id: cache-vcpkg-binary - # Note: we are stuck with v3, because v4 is not compatible with oracle8 image - uses: actions/cache/restore@v3 - with: - path: ${{ env.VCPKG_CACHE_DIR }} - key: vcpkg-cache-centos7-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} - # Allows to restore a cache when deps have only partially changed (like adding a dependency) - restore-keys: vcpkg-cache-centos7- - - - name: Init submodule - run: | - git submodule update --init --remote src/tests/resources/Antares_Simulator_Tests - - - name: Config OR-Tools URL - run: | - echo "URL_ORTOOLS=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_centos7_static_sirius.zip" >> $GITHUB_ENV - - - name: Download OR-Tools - id: ortools - run: | - mkdir -p ${{ env.ORTOOLSDIR }} && cd ${{ env.ORTOOLSDIR }} - wget -q -O ortools.zip ${{ env.URL_ORTOOLS }} - unzip -q ortools.zip - rm ortools.zip - - - name: Install gh if needed - if: ${{ env.IS_RELEASE == 'true' }} - run: | - wget https://github.com/cli/cli/releases/download/v2.52.0/gh_2.52.0_linux_amd64.rpm - rpm -i gh_2.52.0_linux_amd64.rpm - gh --version - - - name: Configure - run: | - source /opt/rh/devtoolset-11/enable - source /opt/rh/rh-git227/enable - cmake -B _build -S src \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/vcpkg/scripts/buildsystems/vcpkg.cmake \ - -DVCPKG_TARGET_TRIPLET=x64-linux-release \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON \ - -DBUILD_TOOLS=ON \ - -DBUILD_UI=OFF \ - -DCMAKE_PREFIX_PATH=${{ env.ORTOOLSDIR }}/install \ - - - - name: Build - run: | - source /opt/rh/devtoolset-11/enable - source /opt/rh/rh-git227/enable - cmake --build _build --config Release -j$(nproc) - ccache -s - - - name: Installer .rpm creation - run: | - cd _build - cpack -G RPM - - - name: Solver archive creation - run: | - cd _build - cmake --install . --prefix install - pushd . - cd install/bin - tar czf ../../antares-solver_centos7.tar.gz antares-solver libsirius_solver.so - popd - rm -rf install - - - name: .tar.gz creation - run: | - cd _build - cpack -G TGZ - - - name: Publish assets - if: ${{ env.IS_RELEASE == 'true' }} - env: - GITHUB_TOKEN: ${{ github.token }} - tag: ${{ github.event.inputs.release_tag }} - run: | - gh release upload "$tag" _build/*.tar.gz _build/*.rpm - - - name: Cache vcpkg binary dir - if: always() - id: save-cache-vcpkg-binary - uses: actions/cache/save@v3 - with: - path: ${{ env.VCPKG_CACHE_DIR }} - key: vcpkg-cache-centos7-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} + + #sparse checkout -- only needed files + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + sparse-checkout: | + docker + src/vcpkg.json + ref: ${{ env.REF }} + + - name: set env variables -- DockerFiles + run: | + echo "DOCKERFILE=$(pwd)/docker/Dockerfile" >> $GITHUB_ENV + echo "DOCKERDIR=$(pwd)/docker" >> $GITHUB_ENV + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v45 + with: + files: | + docker/AntaresDeps + - name: Docker file push + id: docker_push + + if: steps.changed-files.outputs.any_changed == 'true' + uses: elgohr/Publish-Docker-Github-Action@main + with: + name: antaresrte/antaressystemdeps + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + workdir: ${{ env.DOCKERDIR }} + dockerfile: ${{ env.DOCKERDIR }}/AntaresDeps + cache: false + tags: latest + + - name: create vcpkg cache dir + run: | + echo "VCPKG_CACHE_DIR=$GITHUB_WORKSPACE/vcpkg_cache" >> $GITHUB_ENV + mkdir -p ${{ github.workspace }}/vcpkg_cache + - name: Restore vcpkg binary dir from cache + id: cache-vcpkg-binary + uses: actions/cache/restore@v4 + with: + path: ${{ github.workspace }}/vcpkg_cache + key: vcpkg-cache-centos7-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} + # Allows to restore a cache when deps have only partially changed (like adding a dependency) + restore-keys: vcpkg-cache-centos7- + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: centos7-on-${{ runner.os }} + + + - name: Build the image and Antares + run: | + ls -latr .ccache/ && \ + docker build \ + -t antares:centos7 \ + --build-arg="BRANCH=${{ env.REF }}" \ + --build-arg="NPROC=$(nproc)" \ + --build-arg="VCPKG_CACHE_DIR=./vcpkg_cache" \ + --build-arg CCACHE_DIR=./.ccache \ + --build-arg CCACHE_KEY=centos7-on-${{ runner.os }} \ + -f ${{ env.DOCKERFILE }} . + - name: create a container without starting it && retrieve the .tgz + run: | + container_id=$(docker create antares:centos7) + docker cp $container_id:/workspace/Antares_Simulator/_build/archive archive + docker cp $container_id:/workspace/vcpkg_cache ${{ env.VCPKG_CACHE_DIR }} + docker cp $container_id:/workspace/.ccache/. .ccache + ls -la .ccache + docker rm $container_id + - name: Publish assets + if: ${{ env.IS_RELEASE == 'true' }} + env: + GITHUB_TOKEN: ${{ github.token }} + tag: ${{ github.event.inputs.release_tag }} + run: | + gh release upload "$tag" archive/*.tar.gz archive/*.rpm + + + - name: Upload .tar.gz + uses: actions/upload-artifact@v4 + with: + path: archive/*.tar.gz + name: antares-9.2.0-rc4-CentOS-7.9.2009.tar.gz + + + - name: Cache vcpkg binary dir + if: always() + id: save-cache-vcpkg-binary + uses: actions/cache/save@v4 + with: + path: ${{ github.workspace }}/vcpkg_cache + key: vcpkg-cache-centos7-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} \ No newline at end of file diff --git a/src/antares-deps b/src/antares-deps new file mode 160000 index 0000000000..0d6bebfb90 --- /dev/null +++ b/src/antares-deps @@ -0,0 +1 @@ +Subproject commit 0d6bebfb901e47ec6ac1c73cb61a522803c81b98 From 64918d76b50a27428fe91b30471dbe97197b8366 Mon Sep 17 00:00:00 2001 From: h-fournier Date: Fri, 13 Dec 2024 14:42:43 +0100 Subject: [PATCH 15/15] Add missing files for CentOs --- docker/AntaresDeps | 37 ++++++++++++++++++ docker/Dockerfile | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 docker/AntaresDeps create mode 100644 docker/Dockerfile diff --git a/docker/AntaresDeps b/docker/AntaresDeps new file mode 100644 index 0000000000..bfe47cb44e --- /dev/null +++ b/docker/AntaresDeps @@ -0,0 +1,37 @@ +FROM centos:7 + +ENV LANG=en_US.UTF-8 \ + LC_ALL=en_US.UTF-8 \ + DEBIAN_FRONTEND=noninteractive \ + VCPKG_ROOT=/vcpkg \ + ORTOOLS_DIR=ortools + +CMD ["/bin/bash"] + +# Install requirements : update repo +RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo &&\ + sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo &&\ + sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo &&\ + yum install -y epel-release &&\ + yum install -y git redhat-lsb-core make wget centos-release-scl scl-utils python3 &&\ + sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo &&\ + sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo &&\ + sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo + +RUN yum update -y +RUN yum install -y epel-release +RUN yum install -y git redhat-lsb-core make wget centos-release-scl scl-utils rpm-build && \ + yum install -y devtoolset-11 && \ + yum install -y rh-git227-git ccache +RUN yum install -y unzip libuuid-devel wxGTK3-devel +RUN yum install -y python3-pip && python3 -m pip install --upgrade pip && pip3 install pytest numpy pandas + +# Install requirements +RUN rm -rf /var/cache/yum + +RUN echo "source /opt/rh/devtoolset-11/enable" >> /etc/bashrc +SHELL ["/bin/bash", "--login", "-c"] + +# Install CMake +RUN pip3 install cmake==3.28.4 + diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..17a21b3063 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,95 @@ +FROM antaresrte/antaressystemdeps:latest + + + +CMD ["/bin/bash"] + +RUN mkdir /workspace + +RUN echo "source /opt/rh/devtoolset-11/enable" >> /etc/bashrc +SHELL ["/bin/bash", "--login", "-c"] + + +RUN mkdir -p /workspace/vcpkg_cache +ARG VCPKG_CACHE_DIR +COPY $VCPKG_CACHE_DIR /workspace/ + + +ARG BRANCH=develop +RUN cd /workspace && \ + git clone https://github.com/AntaresSimulatorTeam/Antares_Simulator.git --branch $BRANCH && \ + cd Antares_Simulator && \ + git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.sh -disableMetrics && \ + export VCPKG_ROOT=/workspace/Antares_Simulator/vcpkg + + + + + +RUN ORTOOLS_TAG=$(cat /workspace/Antares_Simulator/ortools_tag) && \ + echo "ORTOOLS_TAG=$ORTOOLS_TAG" && \ + URL_ORTOOLS=https://github.com/rte-france/or-tools-rte/releases/download/$ORTOOLS_TAG/ortools_cxx_centos7_static_sirius.zip && \ + mkdir -p ortools && cd ortools && \ + wget -q -O ortools.zip $URL_ORTOOLS && \ + unzip -q ortools.zip && \ + rm ortools.zip + +WORKDIR /workspace/Antares_Simulator +# Accept build arguments for ccache +ARG CCACHE_DIR +ARG CCACHE_KEY + +# Copy ccache directory into the container +COPY ${CCACHE_DIR:-/dev/null} /workspace/.ccache + +# Configure ccache environment variables +ENV CCACHE_DIR=/workspace/.ccache +ENV CCACHE_BASEDIR=/workspace +ENV CCACHE_COMPRESS=1 +ENV PATH="/usr/lib/ccache:$PATH" + +RUN source /opt/rh/devtoolset-11/enable && \ + source /opt/rh/rh-git227/enable && \ + export VCPKG_BINARY_SOURCES="clear;files,/workspace/vcpkg_cache,readwrite" && \ + cmake -B _build -S src \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_TOOLCHAIN_FILE=/workspace/Antares_Simulator/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=x64-linux-release \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=OFF \ + -DBUILD_TOOLS=ON \ + -DBUILD_UI=OFF \ + -DCMAKE_PREFIX_PATH=/ortools/install + +ARG NPROC=2 +RUN source /opt/rh/devtoolset-11/enable && \ + source /opt/rh/rh-git227/enable && \ + export VCPKG_BINARY_SOURCES="clear;files,/workspace/vcpkg_cache,readwrite" && \ + cmake --build _build --config Release -j${NPROC} &&\ + ccache -s + +#Installer .rpm creation +RUN cd _build && \ + cpack -G RPM + +#Solver archive creation +RUN cd _build && \ + cpack -G RPM + +RUN cd _build && \ + cmake --install . --prefix install && \ + pushd . && \ + cd install/bin && \ + tar czf ../../antares-solver_centos7.tar.gz antares-solver libsirius_solver.so && \ + popd && \ + rm -rf install + +#.tar.gz creation +RUN cd _build && \ + cpack -G TGZ +#mv .rpm and .tar.gz +RUN cd _build && \ + mkdir archive && \ + mv *.tar.gz archive && \ + mv *.rpm archive