diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index e7336d020c..dd82930032 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -102,9 +102,9 @@ set(SRC_STUDY_PART_SHORT_TERM_STORAGE parts/short-term-storage/series.cpp include/antares/study/parts/short-term-storage/series.h include/antares/study/parts/short-term-storage/cluster.h - include/antares/study/parts/short-term-storage/AdditionalConstraint.h + include/antares/study/parts/short-term-storage/AdditionalConstraints.h parts/short-term-storage/cluster.cpp - parts/short-term-storage/AdditionalConstraint.cpp + parts/short-term-storage/AdditionalConstraints.cpp ) source_group("study\\part\\short-term-storage" FILES ${SRC_STUDY_PART_SHORT_TERM_SOTRAGE}) diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraints.h similarity index 81% rename from src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h rename to src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraints.h index e16b991a05..7e27c9a60f 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraints.h @@ -22,20 +22,30 @@ #pragma once #include #include +#include namespace Antares::Data::ShortTermStorage { +struct SingleAdditionalConstraint +{ + std::set hours; + unsigned int globalIndex = 0; + unsigned int localIndex = 0; + + bool isValidHoursRange() const; +}; -struct AdditionalConstraint +struct AdditionalConstraints { std::string name; std::string cluster_id; std::string variable; std::string operatorType; - std::set hours; - double rhs; + // TODO a lot unused entries + //std::array rhs = {}; + std::vector rhs = {}; - unsigned int globalIndex = 0; + std::vector constraints = {}; struct ValidateResult { @@ -48,6 +58,7 @@ struct AdditionalConstraint private: bool isValidVariable() const; bool isValidOperatorType() const; - bool isValidHoursRange() const; + + bool isValidHours() const; }; } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h index df74a350b0..c117111efe 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h @@ -26,7 +26,7 @@ #include -#include "AdditionalConstraint.h" +#include "AdditionalConstraints.h" #include "properties.h" #include "series.h" @@ -51,6 +51,6 @@ class STStorageCluster std::shared_ptr series = std::make_shared(); mutable Properties properties; - std::vector additional_constraints; + std::vector additional_constraints; }; } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h index d4e0233b5c..65dc8145bc 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h @@ -23,7 +23,6 @@ #include #include -#include "AdditionalConstraint.h" #include "cluster.h" namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/series.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/series.h index 80f90b94f2..1f53a220fe 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/series.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/series.h @@ -63,5 +63,5 @@ class Series bool loadFile(const std::filesystem::path& folder, std::vector& vect); bool writeVectorToFile(const std::string& path, const std::vector& vect); - +void fillIfEmpty(std::vector& v, double value); } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp b/src/libs/antares/study/parts/short-term-storage/AdditionalConstraints.cpp similarity index 67% rename from src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp rename to src/libs/antares/study/parts/short-term-storage/AdditionalConstraints.cpp index 2ca904041c..8775ffe561 100644 --- a/src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp +++ b/src/libs/antares/study/parts/short-term-storage/AdditionalConstraints.cpp @@ -18,11 +18,12 @@ ** You should have received a copy of the Mozilla Public Licence 2.0 ** along with Antares_Simulator. If not, see . */ -#include "antares/study/parts/short-term-storage/AdditionalConstraint.h" +#include "antares/study/parts/short-term-storage/AdditionalConstraints.h" +#include namespace Antares::Data::ShortTermStorage { -AdditionalConstraint::ValidateResult AdditionalConstraint::validate() const +AdditionalConstraints::ValidateResult AdditionalConstraints::validate() const { if (cluster_id.empty()) { @@ -39,26 +40,38 @@ AdditionalConstraint::ValidateResult AdditionalConstraint::validate() const return {false, "Invalid operator type. Must be 'less', 'equal', or 'greater'."}; } - if (!isValidHoursRange()) + if (!isValidHours()) { - return {false, "Hours set contains invalid values. Must be between 1 and 168."}; + return {false, "Hours sets contains invalid values. Must be between 1 and 168."}; } return {true, ""}; } - -bool AdditionalConstraint::isValidHoursRange() const +bool SingleAdditionalConstraint::isValidHoursRange() const { // `hours` is a sorted set; begin() gives the smallest and prev(end()) gives the largest. - return !hours.empty() && *hours.begin() >= 1 && *std::prev(hours.end()) <= 168; + return !hours.empty() && *hours.begin() + >= 1 && *std::prev( + hours.end()) <= 168; } -bool AdditionalConstraint::isValidVariable() const +bool AdditionalConstraints::isValidHours() const +{ + return std::ranges::all_of(constraints.begin(), + constraints.end(), + [](const auto& constraint) + { + return constraint.isValidHoursRange(); + }); +} + + +bool AdditionalConstraints::isValidVariable() const { return variable == "injection" || variable == "withdrawal" || variable == "netting"; } -bool AdditionalConstraint::isValidOperatorType() const +bool AdditionalConstraints::isValidOperatorType() const { return operatorType == "less" || operatorType == "equal" || operatorType == "greater"; } diff --git a/src/libs/antares/study/parts/short-term-storage/container.cpp b/src/libs/antares/study/parts/short-term-storage/container.cpp index 39a958c5c7..897c234550 100644 --- a/src/libs/antares/study/parts/short-term-storage/container.cpp +++ b/src/libs/antares/study/parts/short-term-storage/container.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -87,7 +88,7 @@ bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path) for (auto* section = ini.firstSection; section; section = section->next) { - AdditionalConstraint constraint; + AdditionalConstraints constraint; constraint.name = section->name.c_str(); for (auto* property = section->firstProperty; property; property = property->next) { @@ -111,24 +112,50 @@ bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path) } else if (key == "hours") { - std::stringstream ss(value.c_str()); - std::string hour; - while (std::getline(ss, hour, ',')) + // + // std::stringstream ss(value.c_str()); + // std::string hour; + // while (std::getline(ss, hour, ',')) + // { + // int hourVal = std::stoi(hour); + // constraint.hours.insert(hourVal); + // } + + // Split the `hours` field into multiple groups + std::string hoursStr = value.c_str(); + std::regex groupRegex(R"(\[(.*?)\])"); + // Match each group enclosed in square brackets + auto groupsBegin = std::sregex_iterator(hoursStr.begin(), + hoursStr.end(), + groupRegex); + auto groupsEnd = std::sregex_iterator(); + for (auto it = groupsBegin; it != groupsEnd; ++it) { - int hourVal = std::stoi(hour); - constraint.hours.insert(hourVal); + // Extract the contents of the square brackets + std::string group = (*it)[1].str(); + std::stringstream ss(group); + std::string hour; + std::set hourSet; + + while (std::getline(ss, hour, ',')) + { + int hourVal = std::stoi(hour); + hourSet.insert(hourVal); + } + + constraint.hours.push_back(hourSet); // Add this group to the `hours` vector } } - else if (key == "rhs") - { - property->value.to(constraint.rhs); - } + + // try to read the rhs + loadFile(parent_path / ("rhs_" + constraint.name + ".txt"), constraint.rhs); + fillIfEmpty(constraint.rhs, 0.0); } - if (auto ret = constraint.validate(); !ret.ok) + if (auto [ok, error_msg] = constraint.validate(); !ok) { logs.error() << "Invalid constraint in section: " << section->name; - logs.error() << ret.error_msg; + logs.error() << error_msg; return false; } diff --git a/src/libs/antares/study/parts/short-term-storage/series.cpp b/src/libs/antares/study/parts/short-term-storage/series.cpp index 6c341c948d..4ee93d8a73 100644 --- a/src/libs/antares/study/parts/short-term-storage/series.cpp +++ b/src/libs/antares/study/parts/short-term-storage/series.cpp @@ -107,16 +107,16 @@ bool loadFile(const fs::path& path, std::vector& vect) return true; } -void Series::fillDefaultSeriesIfEmpty() +void fillIfEmpty(std::vector& v, double value) { - auto fillIfEmpty = [](std::vector& v, double value) + if (v.empty()) { - if (v.empty()) - { - v.resize(HOURS_PER_YEAR, value); - } - }; + v.resize(HOURS_PER_YEAR, value); + } +}; +void Series::fillDefaultSeriesIfEmpty() +{ fillIfEmpty(maxInjectionModulation, 1.0); fillIfEmpty(maxWithdrawalModulation, 1.0); fillIfEmpty(inflows, 0.0); diff --git a/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp b/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp index f6e684db83..f00d39d56e 100644 --- a/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp +++ b/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp @@ -130,28 +130,32 @@ void ShortTermStorageCumulation::add(int pays) for (const auto& storage: data.ShortTermStorage[pays]) { - for (const auto& constraint: storage.additional_constraints) + for (const auto& additional_constraints: storage.additional_constraints) { // sum (var[h]) sign rhs, h in list provided by user where: // var = injection for InjectionCumulationConstraint // var = withdrawal for WithdrawalCumulationConstraint // var = injectionEfficiency * injection - withdrawalEfficiency * withdrawal for Netting - auto constraintHelper = cumulationConstraintFromVariable(constraint.variable); - namer.ShortTermStorageCumulation(constraintHelper->name(), - builder.data.nombreDeContraintes, - storage.name, - constraint.name); - const auto index = storage.clusterGlobalIndex; - data.CorrespondanceCntNativesCntOptimHebdomadaires - .ShortTermStorageCumulation[constraint.globalIndex] - = builder.data.nombreDeContraintes; - - for (const auto& hour: constraint.hours) + auto constraintHelper = cumulationConstraintFromVariable( + additional_constraints.variable); + for (auto& constraint: additional_constraints.constraints) { - builder.updateHourWithinWeek(hour - 1); - constraintHelper->build(builder, index, storage); + namer.ShortTermStorageCumulation(constraintHelper->name() +, + builder.data.nombreDeContraintes, + storage.name, + additional_constraints.name); + const auto index = storage.clusterGlobalIndex; + data.CorrespondanceCntNativesCntOptimHebdomadaires + .ShortTermStorageCumulation[additional_constraints.globalIndex] + = builder.data.nombreDeContraintes; + + for (const auto& hour: additional_constraints.hours) + { + builder.updateHourWithinWeek(hour - 1); + constraintHelper->build(builder, index, storage); + } + builder.SetOperator(ConvertSense(additional_constraints.operatorType)).build(); } - builder.SetOperator(ConvertSense(constraint.operatorType)).build(); } } } 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 35051ba2d5..52b7e8dc0d 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 @@ -183,7 +183,7 @@ struct PROPERTIES bool penalizeVariationInjection; std::shared_ptr series; - std::vector additional_constraints; + std::vector additional_constraints; int clusterGlobalIndex; std::string name; }; diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 786b1b5aa6..cdecaaa1cd 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -61,10 +61,13 @@ static void importShortTermStorages( toInsert.penalizeVariationWithdrawal = st.properties.penalizeVariationWithdrawal; toInsert.name = st.properties.name; toInsert.additional_constraints = st.additional_constraints; - for (auto& constraint: toInsert.additional_constraints) + for (auto& additional_constraints: toInsert.additional_constraints) { - constraint.globalIndex = clusterCumulativeConstraintGlobalIndex; - ++clusterCumulativeConstraintGlobalIndex; + for (auto& [_, globalIndex]: additional_constraints.constraints) + { + globalIndex = clusterCumulativeConstraintGlobalIndex; + ++clusterCumulativeConstraintGlobalIndex; + } } toInsert.series = st.series;