From 66136091d16f6777c3cab2e6e3f54f36de44ddd6 Mon Sep 17 00:00:00 2001 From: CAMUS Benjamin Date: Thu, 31 Oct 2024 17:39:32 +0100 Subject: [PATCH] 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)