From d0c90b5f6c74bcd61d864bb1a2db34593e42e097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Tue, 14 May 2024 15:28:15 +0200 Subject: [PATCH] Rationalize consistency checks on the number of columns (#2073) # Context This is a preliminary work to place `maxHydroPumping` & `maxHydroGen` under sc-builder prefix "h", and remove prefix "hgp" introduced in CR23 (see #2068). This should also fix #2069. # Description - Add homogeneity in the checks performed on the number of columns for - Links (direct & indirect) (prefix "ntc) - Hydro (ror, storage & mingen) (prefix "h") - Thermal (prefix "t", not useful for now, but we may use this mechanism for fuelCost & co2Cost, to replace the custom `checkFuelCostColumnNumber` and `checkCO2CostColumnNumber` functions) - Declare TSNumbers before series. Otherwise we get a segfault since data members are initialized in the order where they appear in the class declaration. - Remove `EqualizeGenerationTSsizes` mechanism for `{ror, storage}` and `{ror, mingen}`. If only one column is present, use it, which is more or less equivalent to the column duplication made by `EqualizeGenerationTSsizes`. # TODO - [x] Add unit tests, especially to check that errors are emitted when they should. # Related work [Improve logs](https://github.com/AntaresSimulatorTeam/Antares_Simulator/pull/2080) --- .../series/include/antares/series/series.h | 35 +++- src/libs/antares/series/series.cpp | 91 +++++++++- src/libs/antares/study/area/area.cpp | 12 +- src/libs/antares/study/area/links.cpp | 18 +- src/libs/antares/study/area/list.cpp | 40 +++-- .../study/area/store-timeseries-numbers.cpp | 20 +-- .../BindingConstraintGroupRepository.cpp | 6 +- .../study/include/antares/study/area/links.h | 6 +- .../BindingConstraintGroup.h | 2 +- .../antares/study/parts/common/cluster.h | 5 +- .../antares/study/parts/hydro/series.h | 11 +- .../antares/study/parts/load/container.h | 5 +- .../antares/study/parts/solar/container.h | 5 +- .../antares/study/parts/wind/container.h | 5 +- .../study/scenario-builder/applyToMatrix.hxx | 12 +- .../study/parts/common/cluster_list.cpp | 16 +- src/libs/antares/study/parts/hydro/series.cpp | 46 ++---- .../BindingConstraintsTSNumbersData.cpp | 7 +- .../simulation/TimeSeriesNumbersWriter.cpp | 21 +-- src/solver/simulation/common-eco-adq.cpp | 6 +- .../solver/simulation/common-eco-adq.h | 2 +- .../antares/solver/simulation/solver.hxx | 28 ++-- .../solver/simulation/timeseries-numbers.h | 2 + .../simulation/sim_calcul_economique.cpp | 2 +- src/solver/simulation/timeseries-numbers.cpp | 155 ++++++++++++------ .../solver/variable/economy/profitByPlant.h | 2 +- src/solver/variable/state.cpp | 4 +- .../end-to-end/simple_study/simple-study.cpp | 3 - .../test-sc-builder-file-read-line.cpp | 56 ++----- .../libs/antares/study/series/CMakeLists.txt | 1 + .../antares/study/series/timeseries-tests.cpp | 102 +++++++++++- .../test-store-timeseries-number.cpp | 37 ++--- .../solver/simulation/tests-ts-numbers.cpp | 80 ++++----- 33 files changed, 497 insertions(+), 346 deletions(-) diff --git a/src/libs/antares/series/include/antares/series/series.h b/src/libs/antares/series/include/antares/series/series.h index 3d0bf4f90f..d3dde6d092 100644 --- a/src/libs/antares/series/include/antares/series/series.h +++ b/src/libs/antares/series/include/antares/series/series.h @@ -21,6 +21,10 @@ #ifndef __ANTARES_LIBS_STUDY_PARTS_COMMON_TIMESERIES_H__ #define __ANTARES_LIBS_STUDY_PARTS_COMMON_TIMESERIES_H__ +#include +#include +#include + #include namespace Antares::Data @@ -32,13 +36,37 @@ namespace Antares::Data ** The goal is to handle indexing with the time series numbers: getCoefficient() ** and also providing a wrapper for all the Matrix<> functions such as resize() */ +class TimeSeries; + +class TimeSeriesNumbers +{ +public: + void registerSeries(const TimeSeries* s, std::string label); + // Return a description of the error in case of inconsistent number of columns, std::nullopt + // otherwis + std::optional checkSeriesNumberOfColumnsConsistency() const; + + uint32_t operator[](uint y) const; + uint32_t& operator[](uint y); + + void clear(); + void reset(uint h); + + uint height() const; + + void saveToBuffer(std::string& data) const; + +private: + Matrix tsNumbers; + std::map series; +}; + class TimeSeries { public: - using numbers = Matrix; using TS = Matrix; - explicit TimeSeries(numbers& tsNumbers); + explicit TimeSeries(TimeSeriesNumbers& tsNumbers); /*! ** \brief Load series from a file ** @@ -71,6 +99,7 @@ class TimeSeries void reset(); void reset(uint32_t width, uint32_t height); + uint32_t numberOfColumns() const; void unloadFromMemory() const; void roundAllEntries(); void resize(uint32_t timeSeriesCount, uint32_t timestepCount); @@ -82,7 +111,7 @@ class TimeSeries uint64_t memoryUsage() const; TS timeSeries; - numbers& timeseriesNumbers; + TimeSeriesNumbers& timeseriesNumbers; static const std::vector emptyColumn; ///< used in getColumn if timeSeries empty }; diff --git a/src/libs/antares/series/series.cpp b/src/libs/antares/series/series.cpp index 29ec499934..9116a5b5da 100644 --- a/src/libs/antares/series/series.cpp +++ b/src/libs/antares/series/series.cpp @@ -21,6 +21,10 @@ #include "antares/series/series.h" +#include +#include +#include + #include #include #include @@ -31,8 +35,80 @@ using namespace Yuni; namespace Antares::Data { +void TimeSeriesNumbers::registerSeries(const TimeSeries* s, std::string label) +{ + series[std::move(label)] = s; +} + +// TODO[FOM] Code duplication +static bool checkAllElementsIdenticalOrOne(std::vector w) +{ + auto first_one = std::remove(w.begin(), w.end(), 1); // Reject all 1 to the end + return std::adjacent_find(w.begin(), first_one, std::not_equal_to()) == first_one; +} + +static std::string errorMessage(const std::map& series) +{ + std::ostringstream msg; + auto isLast = [&series](std::size_t& idx) + { + idx++; + return idx == series.size(); + }; + for (std::size_t idx = 0; const auto& [label, s]: series) + { + msg << label << ": " << s->numberOfColumns() << (isLast(idx) ? "" : ", "); + } + return msg.str(); +} + +uint TimeSeriesNumbers::height() const +{ + return tsNumbers.height; +} + +uint32_t TimeSeriesNumbers::operator[](uint y) const +{ + return tsNumbers[0][y]; +} + +uint32_t& TimeSeriesNumbers::operator[](uint y) +{ + return tsNumbers[0][y]; +} + +void TimeSeriesNumbers::reset(uint h) +{ + tsNumbers.reset(1, h); +} + +void TimeSeriesNumbers::clear() +{ + tsNumbers.clear(); +} + +void TimeSeriesNumbers::saveToBuffer(std::string& data) const +{ + const auto add1 = [](uint32_t x) { return x + 1; }; + tsNumbers.saveToBuffer(data, 0, true, add1, true); +} + +std::optional TimeSeriesNumbers::checkSeriesNumberOfColumnsConsistency() const +{ + std::vector width; + for (const auto& [_, s]: series) + { + width.push_back(s->numberOfColumns()); + } + + if (!checkAllElementsIdenticalOrOne(width)) + { + return errorMessage(series); + } + return std::nullopt; +} -TimeSeries::TimeSeries(numbers& tsNumbers): +TimeSeries::TimeSeries(TimeSeriesNumbers& tsNumbers): timeseriesNumbers(tsNumbers) { } @@ -79,7 +155,13 @@ const double* TimeSeries::getColumn(uint32_t year) const uint32_t TimeSeries::getSeriesIndex(uint32_t year) const { - return timeseriesNumbers[0][year]; + // If the timeSeries only has one column, we have no choice but to use it. + if (numberOfColumns() == 1) + { + return 0; + } + + return timeseriesNumbers[year]; } double* TimeSeries::operator[](uint32_t index) @@ -101,6 +183,11 @@ void TimeSeries::reset(uint32_t width, uint32_t height) timeSeries.reset(width, height); } +uint32_t TimeSeries::numberOfColumns() const +{ + return timeSeries.width; +} + void TimeSeries::resize(uint32_t timeSeriesCount, uint32_t timestepCount) { timeSeries.resize(timeSeriesCount, timestepCount); diff --git a/src/libs/antares/study/area/area.cpp b/src/libs/antares/study/area/area.cpp index ace3a35008..ee46111120 100644 --- a/src/libs/antares/study/area/area.cpp +++ b/src/libs/antares/study/area/area.cpp @@ -291,15 +291,15 @@ void Area::resizeAllTimeseriesNumbers(uint nbYears) { assert(hydro.series and "series must not be nullptr !"); - load.series.timeseriesNumbers.reset(1, nbYears); - solar.series.timeseriesNumbers.reset(1, nbYears); - wind.series.timeseriesNumbers.reset(1, nbYears); - hydro.series->timeseriesNumbers.reset(1, nbYears); - hydro.series->timeseriesNumbersHydroMaxPower.reset(1, nbYears); + load.series.timeseriesNumbers.reset(nbYears); + solar.series.timeseriesNumbers.reset(nbYears); + wind.series.timeseriesNumbers.reset(nbYears); + hydro.series->timeseriesNumbers.reset(nbYears); + hydro.series->timeseriesNumbersHydroMaxPower.reset(nbYears); for (auto& namedLink: links) { AreaLink* link = namedLink.second; - link->timeseriesNumbers.reset(1, nbYears); + link->timeseriesNumbers.reset(nbYears); } thermal.resizeAllTimeseriesNumbers(nbYears); renewable.resizeAllTimeseriesNumbers(nbYears); diff --git a/src/libs/antares/study/area/links.cpp b/src/libs/antares/study/area/links.cpp index b89fa960dd..2203439d7b 100644 --- a/src/libs/antares/study/area/links.cpp +++ b/src/libs/antares/study/area/links.cpp @@ -34,17 +34,6 @@ using namespace Yuni; using namespace Antares; -namespace // anonymous -{ -struct TSNumbersPredicate -{ - uint32_t operator()(uint32_t value) const - { - return value + 1; - } -}; -} // namespace - #define SEP (IO::Separator) namespace @@ -76,6 +65,9 @@ AreaLink::AreaLink(): style(stPlain), linkWidth(1) { + timeseriesNumbers.registerSeries(&directCapacities, "direct-capacity"); + timeseriesNumbers.registerSeries(&indirectCapacities, "indirect-capacity"); + directCapacities.reset(); indirectCapacities.reset(); } @@ -194,13 +186,12 @@ bool AreaLink::loadTimeSeries(const StudyVersion& version, const AnyString& fold void AreaLink::storeTimeseriesNumbers(Solver::IResultWriter& writer) const { Clob path; - TSNumbersPredicate predicate; std::string buffer; path << "ts-numbers" << SEP << DIRECTORY_NAME_FOR_TRANSMISSION_CAPACITIES << SEP << from->id << SEP << with->id << ".txt"; - timeseriesNumbers.saveToBuffer(buffer, 0, true, predicate, true); + timeseriesNumbers.saveToBuffer(buffer); writer.addEntryFromBuffer(path.c_str(), buffer); } @@ -532,7 +523,6 @@ bool AreaLinksLoadFromFolder(Study& study, AreaList* l, Area* area, const AnyStr // Checks on loaded link's data if (study.usedByTheSolver) { - // Short names for link's properties const uint nbDirectTS = link.directCapacities.timeSeries.width; const uint nbIndirectTS = link.indirectCapacities.timeSeries.width; if (nbDirectTS != nbIndirectTS) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index bbcb3469fe..f79c61efd0 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -166,7 +166,7 @@ static bool AreaListSaveThermalDataToFile(const AreaList& list, const AnyString& IniFile::Section* s = ini.addSection("unserverdenergycost"); list.each( - [&](const Data::Area& area) + [&s](const Data::Area& area) { // 0 values are skipped if (!Utils::isZero(area.thermal.unsuppliedEnergyCost)) @@ -177,7 +177,7 @@ static bool AreaListSaveThermalDataToFile(const AreaList& list, const AnyString& s = ini.addSection("spilledenergycost"); list.each( - [&](const Data::Area& area) + [&s](const Data::Area& area) { // 0 values are skipped if (!Utils::isZero(area.thermal.spilledEnergyCost)) @@ -613,7 +613,7 @@ bool AreaList::loadListFromFile(const AnyString& filename) void AreaList::saveLinkListToBuffer(Yuni::Clob& buffer) const { each( - [&](const Data::Area& area) + [&buffer](const Data::Area& area) { buffer << area.id << '\n'; auto end = area.links.end(); @@ -669,7 +669,7 @@ bool AreaList::preloadAndMarkAsModifiedAllInvalidatedAreas(uint* invalidateCount bool ret = true; uint count = 0; each( - [&](const Data::Area& area) + [&ret, &count](const Data::Area& area) { if (area.invalidateJIT) { @@ -690,7 +690,7 @@ bool AreaList::preloadAndMarkAsModifiedAllInvalidatedAreas(uint* invalidateCount void AreaList::markAsModified() const { - each([&](const Data::Area& area) { area.markAsModified(); }); + each([](const Data::Area& area) { area.markAsModified(); }); } bool AreaList::saveToFolder(const AnyString& folder) const @@ -773,7 +773,7 @@ bool AreaList::saveToFolder(const AnyString& folder) const // Save all areas each( - [&](const Data::Area& area) + [&ret, &buffer, &folder, this](const Data::Area& area) { logs.info() << "Exporting the area " << (area.index + 1) << '/' << areas.size() << ": " << area.name; @@ -953,8 +953,6 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, { buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "series"; ret = hydroSeries->loadGenerationTS(area.id, buffer, studyVersion) && ret; - - hydroSeries->EqualizeGenerationTSsizes(area, study.usedByTheSolver); } if (studyVersion < StudyVersion(9, 1)) @@ -1048,7 +1046,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, } ini.each( - [&](const IniFile::Section& section) + [&area, &buffer](const IniFile::Section& section) { for (auto* p = section.firstProperty; p; p = p->next) { @@ -1243,7 +1241,7 @@ bool AreaList::loadFromFolder(const StudyLoadOptions& options) // Load all nodes uint indx = 0; each( - [&](Data::Area& area) + [&options, &ret, &buffer, &indx, this](Data::Area& area) { // Progression options.logMessage.clear() @@ -1358,7 +1356,7 @@ void AreaListEnsureDataSolarPrepro(AreaList* l) assert(l); l->each( - [&](Data::Area& area) + [](Data::Area& area) { if (!area.solar.prepro) { @@ -1373,7 +1371,7 @@ void AreaListEnsureDataWindPrepro(AreaList* l) assert(l); l->each( - [&](Data::Area& area) + [](Data::Area& area) { if (!area.wind.prepro) { @@ -1388,7 +1386,7 @@ void AreaListEnsureDataHydroTimeSeries(AreaList* l) assert(l); l->each( - [&](Data::Area& area) + [](Data::Area& area) { if (!area.hydro.series) { @@ -1403,7 +1401,7 @@ void AreaListEnsureDataHydroPrepro(AreaList* l) assert(l); l->each( - [&](Data::Area& area) + [](Data::Area& area) { if (!area.hydro.prepro) { @@ -1414,20 +1412,20 @@ void AreaListEnsureDataHydroPrepro(AreaList* l) void AreaListEnsureDataThermalPrepro(AreaList* l) { - l->each([&](Data::Area& area) { area.thermal.list.ensureDataPrepro(); }); + l->each([](Data::Area& area) { area.thermal.list.ensureDataPrepro(); }); } uint64_t AreaList::memoryUsage() const { uint64_t ret = sizeof(AreaList) + sizeof(Area**) * areas.size(); - each([&](const Data::Area& area) { ret += area.memoryUsage(); }); + each([&ret](const Data::Area& area) { ret += area.memoryUsage(); }); return ret; } uint AreaList::areaLinkCount() const { uint ret = 0; - each([&](const Data::Area& area) { ret += (uint)area.links.size(); }); + each([&ret](const Data::Area& area) { ret += (uint)area.links.size(); }); return ret; } @@ -1492,7 +1490,7 @@ bool AreaList::renameArea(const AreaName& oldid, const AreaName& newid, const Ar // We have to update all links connected to this area each( - [&](Data::Area& a) + [&oldid](Data::Area& a) { auto* link = a.findLinkByID(oldid); if (!link) @@ -1529,7 +1527,7 @@ void AreaListDeleteLinkFromAreaPtr(AreaList* list, const Area* a) } list->each( - [&](Data::Area& area) + [&a](Data::Area& area) { if (!area.links.empty()) { @@ -1570,14 +1568,14 @@ void AreaList::resizeAllTimeseriesNumbers(uint n) { // Ask to resize the matrices dedicated to the sampled timeseries numbers // for each area - each([&](Data::Area& area) { area.resizeAllTimeseriesNumbers(n); }); + each([n](Data::Area& area) { area.resizeAllTimeseriesNumbers(n); }); } void AreaList::fixOrientationForAllInterconnections( BindingConstraintsRepository& bindingconstraints) { each( - [&](Data::Area& area) + [&bindingconstraints](Data::Area& area) { bool mustLoop; // for each link from this area diff --git a/src/libs/antares/study/area/store-timeseries-numbers.cpp b/src/libs/antares/study/area/store-timeseries-numbers.cpp index ebd77f32d9..746fbf9101 100644 --- a/src/libs/antares/study/area/store-timeseries-numbers.cpp +++ b/src/libs/antares/study/area/store-timeseries-numbers.cpp @@ -31,32 +31,16 @@ using namespace Yuni; namespace Antares::Data { -namespace // anonymous -{ -struct TSNumbersPredicate -{ - uint32_t operator()(uint32_t value) const - { - return value + 1; - } -}; -} // anonymous namespace - static void storeTSnumbers(Solver::IResultWriter& writer, - const Matrix& timeseriesNumbers, + const TimeSeriesNumbers& timeseriesNumbers, const String& id, const String& directory) { - TSNumbersPredicate predicate; Clob path; path << "ts-numbers" << SEP << directory << SEP << id << ".txt"; std::string buffer; - timeseriesNumbers.saveToBuffer(buffer, - 0, // precision - true, // print_dimensions - predicate, // predicate - true); // save even if all coeffs are zero + timeseriesNumbers.saveToBuffer(buffer); writer.addEntryFromBuffer(path.c_str(), buffer); } diff --git a/src/libs/antares/study/binding_constraint/BindingConstraintGroupRepository.cpp b/src/libs/antares/study/binding_constraint/BindingConstraintGroupRepository.cpp index 14522479e4..ce168c7eef 100644 --- a/src/libs/antares/study/binding_constraint/BindingConstraintGroupRepository.cpp +++ b/src/libs/antares/study/binding_constraint/BindingConstraintGroupRepository.cpp @@ -96,11 +96,7 @@ void BindingConstraintGroupRepository::resizeAllTimeseriesNumbers(unsigned int n { std::for_each(groups_.begin(), groups_.end(), - [&](auto& group) - { - group->timeseriesNumbers.clear(); - group->timeseriesNumbers.reset(1, nb_years); - }); + [&](auto& group) { group->timeseriesNumbers.reset(nb_years); }); } BindingConstraintGroup* BindingConstraintGroupRepository::operator[](const std::string& name) const diff --git a/src/libs/antares/study/include/antares/study/area/links.h b/src/libs/antares/study/include/antares/study/area/links.h index 767cd89da8..fd4b8e69d8 100644 --- a/src/libs/antares/study/include/antares/study/area/links.h +++ b/src/libs/antares/study/include/antares/study/area/links.h @@ -134,6 +134,9 @@ class AreaLink final: public Yuni::NonCopyable Area* with; //@} + //! Monte-Carlo + TimeSeriesNumbers timeseriesNumbers; + //! \name Data //@{ /*! @@ -144,9 +147,6 @@ class AreaLink final: public Yuni::NonCopyable TimeSeries directCapacities; TimeSeries indirectCapacities; - //! Monte-Carlo - Matrix timeseriesNumbers; - //! Flag for using loop flow bool useLoopFlow; diff --git a/src/libs/antares/study/include/antares/study/binding_constraint/BindingConstraintGroup.h b/src/libs/antares/study/include/antares/study/binding_constraint/BindingConstraintGroup.h index c5ef46898a..64f5ae8bb0 100644 --- a/src/libs/antares/study/include/antares/study/binding_constraint/BindingConstraintGroup.h +++ b/src/libs/antares/study/include/antares/study/binding_constraint/BindingConstraintGroup.h @@ -48,7 +48,7 @@ class BindingConstraintGroup public: // Public data members - Matrix timeseriesNumbers; + TimeSeriesNumbers timeseriesNumbers; private: std::set> constraints_; diff --git a/src/libs/antares/study/include/antares/study/parts/common/cluster.h b/src/libs/antares/study/include/antares/study/parts/common/cluster.h index b481cdd5c4..53e5d115d6 100644 --- a/src/libs/antares/study/include/antares/study/parts/common/cluster.h +++ b/src/libs/antares/study/include/antares/study/parts/common/cluster.h @@ -127,11 +127,12 @@ class Cluster // (initialized in the same time that the runtime data) uint areaWideIndex = (uint)-1; + //! tsNumbers must be constructed before series + TimeSeriesNumbers tsNumbers; + //! Series TimeSeries series; - TimeSeries::numbers tsNumbers; - /*! ** \brief Modulation matrix ** diff --git a/src/libs/antares/study/include/antares/study/parts/hydro/series.h b/src/libs/antares/study/include/antares/study/parts/hydro/series.h index f2b6269c88..6402f52ee9 100644 --- a/src/libs/antares/study/include/antares/study/parts/hydro/series.h +++ b/src/libs/antares/study/include/antares/study/parts/hydro/series.h @@ -69,8 +69,6 @@ class DataSeriesHydro void markAsModified() const; //@} - void EqualizeGenerationTSsizes(Area& area, bool usedByTheSolver); - // Loading hydro time series collection // Returned boolean : reading from file failed bool loadGenerationTS(const AreaName& areaID, const AnyString& folder, StudyVersion version); @@ -105,10 +103,12 @@ class DataSeriesHydro //@} + TimeSeriesNumbers timeseriesNumbers; + TimeSeriesNumbers timeseriesNumbersHydroMaxPower; + /*! ** \brief Run-of-the-river - ROR (MW) ** - ** (it was DAYS_PER_YEAR before 3.9) */ TimeSeries ror; @@ -143,10 +143,6 @@ class DataSeriesHydro */ TimeSeries maxHourlyPumpPower; - // TS's number matrices for Generation and Maximum Power - Matrix timeseriesNumbers; - Matrix timeseriesNumbersHydroMaxPower; - // Equalizing max generation and max pumping numbers of TS's void EqualizeMaxPowerTSsizes(Area& area); @@ -155,6 +151,7 @@ class DataSeriesHydro // Getters for generation (ror, storage and mingen) and // max power (generation and pumping) number of TS uint TScount() const; + void computeTSCount(); uint maxPowerTScount() const; void setMaxPowerTScount(uint count) diff --git a/src/libs/antares/study/include/antares/study/parts/load/container.h b/src/libs/antares/study/include/antares/study/parts/load/container.h index 715088efd7..083dc6df7d 100644 --- a/src/libs/antares/study/include/antares/study/parts/load/container.h +++ b/src/libs/antares/study/include/antares/study/parts/load/container.h @@ -70,11 +70,12 @@ class Container final: private Yuni::NonCopyable public: //! Data for the pre-processor Data::Load::Prepro* prepro; + + TimeSeriesNumbers tsNumbers; + /*! Data for time-series */ TimeSeries series; - TimeSeries::numbers tsNumbers; - }; // class Container } // namespace Load diff --git a/src/libs/antares/study/include/antares/study/parts/solar/container.h b/src/libs/antares/study/include/antares/study/parts/solar/container.h index c9ecdaaf0c..a4ea96d55b 100644 --- a/src/libs/antares/study/include/antares/study/parts/solar/container.h +++ b/src/libs/antares/study/include/antares/study/parts/solar/container.h @@ -67,11 +67,12 @@ class Container public: //! Data for the pre-processor Data::Solar::Prepro* prepro; + + TimeSeriesNumbers tsNumbers; + /*! Data for time-series */ TimeSeries series; - TimeSeries::numbers tsNumbers; - }; // class Container } // namespace Solar diff --git a/src/libs/antares/study/include/antares/study/parts/wind/container.h b/src/libs/antares/study/include/antares/study/parts/wind/container.h index b89d2851ab..7e36522597 100644 --- a/src/libs/antares/study/include/antares/study/parts/wind/container.h +++ b/src/libs/antares/study/include/antares/study/parts/wind/container.h @@ -67,11 +67,12 @@ class Container public: //! Data for the pre-processor Data::Wind::Prepro* prepro; + + TimeSeriesNumbers tsNumbers; + /*! Data for time-series */ TimeSeries series; - TimeSeries::numbers tsNumbers; - }; // class Container } // namespace Wind diff --git a/src/libs/antares/study/include/antares/study/scenario-builder/applyToMatrix.hxx b/src/libs/antares/study/include/antares/study/scenario-builder/applyToMatrix.hxx index 2adb555582..5a210fd04d 100644 --- a/src/libs/antares/study/include/antares/study/scenario-builder/applyToMatrix.hxx +++ b/src/libs/antares/study/include/antares/study/scenario-builder/applyToMatrix.hxx @@ -89,17 +89,16 @@ bool ApplyToMatrix(uint& errors, bool ret = true; // In this case, m.height represents the total number of years - const uint nbYears = data.timeseriesNumbers.height; + const uint nbYears = data.timeseriesNumbers.height(); // The matrix m has only one column - assert(data.timeseriesNumbers.width == 1); - typename Matrix::ColumnType& target = data.timeseriesNumbers[0]; + auto& target = data.timeseriesNumbers; for (uint y = 0; y != nbYears; ++y) { if (years[y] != 0) { // The new TS number - uint tsNum = years[y] - 1; + uint32_t tsNum = years[y] - 1; // When the TS-Generators are not used if (!CheckValidity(tsNum, data, tsGenMax)) @@ -138,10 +137,9 @@ bool ApplyToMatrixMaxPower(uint& errors, bool ret = true; // In this case, m.height represents the total number of years - const uint nbYears = data.timeseriesNumbersHydroMaxPower.height; + const uint nbYears = data.timeseriesNumbersHydroMaxPower.height(); // The matrix m has only one column - assert(data.timeseriesNumbersHydroMaxPower.width == 1); - typename Matrix::ColumnType& target = data.timeseriesNumbersHydroMaxPower[0]; + auto& target = data.timeseriesNumbersHydroMaxPower; for (uint y = 0; y != nbYears; ++y) { diff --git a/src/libs/antares/study/parts/common/cluster_list.cpp b/src/libs/antares/study/parts/common/cluster_list.cpp index bee380ed41..25813bee79 100644 --- a/src/libs/antares/study/parts/common/cluster_list.cpp +++ b/src/libs/antares/study/parts/common/cluster_list.cpp @@ -30,17 +30,6 @@ using namespace Yuni; -namespace // anonymous -{ -struct TSNumbersPredicate -{ - uint32_t operator()(uint32_t value) const - { - return value + 1; - } -}; -} // namespace - namespace Antares::Data { using namespace Antares; @@ -95,7 +84,7 @@ void ClusterList::resizeAllTimeseriesNumbers(uint n) const { for (auto& c: allClusters_) { - c->series.timeseriesNumbers.reset(1, n); + c->series.timeseriesNumbers.reset(n); } } @@ -104,7 +93,6 @@ void ClusterList::resizeAllTimeseriesNumbers(uint n) const template void ClusterList::storeTimeseriesNumbers(Solver::IResultWriter& writer) const { - TSNumbersPredicate predicate; Clob path; std::string ts_content; @@ -113,7 +101,7 @@ void ClusterList::storeTimeseriesNumbers(Solver::IResultWriter& writer path.clear() << "ts-numbers" << SEP << typeID() << SEP << cluster->parentArea->id << SEP << cluster->id() << ".txt"; ts_content.clear(); // We must clear ts_content here, since saveToBuffer does not do it. - cluster->series.timeseriesNumbers.saveToBuffer(ts_content, 0, true, predicate, true); + cluster->series.timeseriesNumbers.saveToBuffer(ts_content); writer.addEntryFromBuffer(path.c_str(), ts_content); } } diff --git a/src/libs/antares/study/parts/hydro/series.cpp b/src/libs/antares/study/parts/hydro/series.cpp index 8f3228cffb..79cca5514a 100644 --- a/src/libs/antares/study/parts/hydro/series.cpp +++ b/src/libs/antares/study/parts/hydro/series.cpp @@ -128,6 +128,12 @@ DataSeriesHydro::DataSeriesHydro(): maxHourlyGenPower(timeseriesNumbersHydroMaxPower), maxHourlyPumpPower(timeseriesNumbersHydroMaxPower) { + timeseriesNumbers.registerSeries(&ror, "ror"); + timeseriesNumbers.registerSeries(&storage, "storage"); + timeseriesNumbers.registerSeries(&mingen, "mingen"); + timeseriesNumbersHydroMaxPower.registerSeries(&maxHourlyGenPower, "max-geneneration-power"); + timeseriesNumbersHydroMaxPower.registerSeries(&maxHourlyPumpPower, "max-pumping-power"); + // Pmin was introduced in v8.6 // The previous behavior was Pmin=0 // For compatibility reasons with existing studies, mingen, maxHourlyGenPower and @@ -167,11 +173,15 @@ void DataSeriesHydro::reset() resizeMaxPowerTS(1); } +void DataSeriesHydro::computeTSCount() +{ + generationTScount_ = std::max(storage.numberOfColumns(), ror.numberOfColumns()); +} + void DataSeriesHydro::resizeGenerationTS(uint nbSeries) { storage.reset(nbSeries, DAYS_PER_YEAR); ror.reset(nbSeries, HOURS_PER_YEAR); - mingen.reset(nbSeries, HOURS_PER_YEAR); generationTScount_ = nbSeries; } @@ -204,39 +214,6 @@ void DataSeriesHydro::markAsModified() const maxHourlyPumpPower.markAsModified(); } -void DataSeriesHydro::EqualizeGenerationTSsizes(Area& area, bool usedByTheSolver) -{ - if (!usedByTheSolver) // From GUI, no need to equalize TS collections sizes - { - return; - } - - // Equalize ROR and INFLOWS time series sizes - // ------------------------------------------ - std::string fatalErrorMsg = "Hydro : area `" + area.id.to() + "` : "; - fatalErrorMsg += "ROR and INFLOWS must have the same number of time series."; - - generationTScount_ = EqualizeTSsize(ror, - storage, - fatalErrorMsg, - area, - HOURS_PER_YEAR, - DAYS_PER_YEAR); - - logs.info() << " '" << area.id - << "': ROR and INFLOWS time series were both set to : " << generationTScount_; - - // Equalize ROR and MINGEN time series sizes - // ----------------------------------------- - fatalErrorMsg = "Hydro : area `" + area.id.to() + "` : "; - fatalErrorMsg += "ROR and MINGEN must have the same number of time series."; - - generationTScount_ = EqualizeTSsize(ror, mingen, fatalErrorMsg, area); - - logs.info() << " '" << area.id - << "': ROR and MINGEN time series were both set to : " << generationTScount_; -} - bool DataSeriesHydro::loadGenerationTS(const AreaName& areaID, const AnyString& folder, StudyVersion studyVersion) @@ -251,6 +228,7 @@ bool DataSeriesHydro::loadGenerationTS(const AreaName& areaID, && ret; } + computeTSCount(); return ret; } diff --git a/src/libs/antares/study/scenario-builder/BindingConstraintsTSNumbersData.cpp b/src/libs/antares/study/scenario-builder/BindingConstraintsTSNumbersData.cpp index 3b00b3c29c..24b5b8cb6b 100644 --- a/src/libs/antares/study/scenario-builder/BindingConstraintsTSNumbersData.cpp +++ b/src/libs/antares/study/scenario-builder/BindingConstraintsTSNumbersData.cpp @@ -62,7 +62,7 @@ bool BindingConstraintsTSNumberData::apply(Study& study) return std::all_of( rules_.begin(), rules_.end(), - [&study, this](const std::pair& args) + [&study, this](const auto& args) { const auto& [groupName, tsNumbers] = args; auto group = study.bindingConstraintsGroups[groupName]; @@ -84,9 +84,8 @@ bool BindingConstraintsTSNumberData::reset(const Study& study) study.bindingConstraintsGroups.end(), [&](const auto& group) { - MatrixType& ts_numbers = rules_[group->name()]; - ts_numbers.resize(1, nbYears); - ts_numbers.fillColumn(0, 0); + auto& ts_numbers = rules_[group->name()]; + ts_numbers.reset(1, nbYears); }); return true; } diff --git a/src/solver/simulation/TimeSeriesNumbersWriter.cpp b/src/solver/simulation/TimeSeriesNumbersWriter.cpp index 594c2d257a..31016bbc49 100644 --- a/src/solver/simulation/TimeSeriesNumbersWriter.cpp +++ b/src/solver/simulation/TimeSeriesNumbersWriter.cpp @@ -37,35 +37,18 @@ BindingConstraintsTimeSeriesNumbersWriter::BindingConstraintsTimeSeriesNumbersWr { } -namespace // anonymous -{ -struct TSNumbersPredicate -{ - uint32_t operator()(uint32_t value) const - { - return value + 1; - } -}; -} // anonymous namespace - // TODO : remove duplication static void genericStoreTimeseriesNumbers(Solver::IResultWriter& writer, - const Matrix& timeseriesNumbers, + const Data::TimeSeriesNumbers& timeseriesNumbers, const std::string& id, const std::string& directory) { - TSNumbersPredicate predicate; std::filesystem::path path = std::filesystem::path() / "ts-numbers" / directory.c_str() / id.c_str(); path.replace_extension("txt"); std::string buffer; - timeseriesNumbers.saveToBuffer(buffer, - 0, // precision - true, // print_dimensions - predicate, // predicate - true); // save even if all coeffs are zero - + timeseriesNumbers.saveToBuffer(buffer); writer.addEntryFromBuffer(path.string(), buffer); } diff --git a/src/solver/simulation/common-eco-adq.cpp b/src/solver/simulation/common-eco-adq.cpp index 34dc46f201..5b2909f4e6 100644 --- a/src/solver/simulation/common-eco-adq.cpp +++ b/src/solver/simulation/common-eco-adq.cpp @@ -240,7 +240,7 @@ void PrepareRandomNumbers(Data::Study& study, { uint indexArea = 0; study.areas.each( - [&](const Data::Area& area) + [&study, &problem, &randomForYear, &indexArea](const Data::Area& area) { double rnd = 0.; @@ -449,7 +449,7 @@ void BuildThermalPartOfWeeklyProblem(Data::Study& study, int retrieveAverageNTC(const Data::Study& study, const Matrix<>& capacities, - const Matrix& tsNumbers, + const Data::TimeSeriesNumbers& tsNumbers, std::vector& avg) { const auto& parameters = study.parameters; @@ -469,7 +469,7 @@ int retrieveAverageNTC(const Data::Study& study, continue; } - uint32_t tsIndex = (width == 1) ? 0 : tsNumbers[0][y]; + uint32_t tsIndex = (width == 1) ? 0 : tsNumbers[y]; weightOfTS[tsIndex] += yearsWeight[y]; } diff --git a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h index e197d315ac..2110c4cbe9 100644 --- a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h +++ b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h @@ -155,7 +155,7 @@ void updatingAnnualFinalHydroLevel(const Data::AreaList& areas, PROBLEME_HEBDO& */ int retrieveAverageNTC(const Data::Study& study, const Matrix<>& capacities, - const Matrix& tsNumbers, + const Data::TimeSeriesNumbers& tsNumbers, std::vector& avg); void finalizeOptimizationStatistics(PROBLEME_HEBDO& problem, diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index ef4245d5e6..70d88c47af 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -349,6 +349,12 @@ void ISimulation::run() // for a single simulation study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); // Now, we will prepare the time-series numbers + if (not TimeSeriesNumbers::CheckNumberOfColumns(study.areas)) + { + throw FatalError( + "Inconsistent number of time-series detected. Please check your input data."); + } + if (not TimeSeriesNumbers::Generate(study)) { throw FatalError("An unrecoverable error has occured. Can not continue."); @@ -375,14 +381,15 @@ void ISimulation::run() logs.info() << " Starting the simulation"; uint finalYear = 1 + study.runtime->rangeLimits.year[Data::rangeEnd]; { - pDurationCollector("mc_years") << [&] { loopThroughYears(0, finalYear, state); }; + pDurationCollector("mc_years") + << [finalYear, &state, this] { loopThroughYears(0, finalYear, state); }; } // Destroy the TS Generators if any // It will export the time-series into the output in the same time TSGenerator::DestroyAll(study); // Post operations - pDurationCollector("post_processing") << [&] { ImplementationType::simulationEnd(); }; + pDurationCollector("post_processing") << [this] { ImplementationType::simulationEnd(); }; ImplementationType::variables.simulationEnd(); @@ -462,31 +469,31 @@ void ISimulation::regenerateTimeSeries(uint year) if (pData.haveToRefreshTSLoad && (year % pData.refreshIntervalLoad == 0)) { pDurationCollector("tsgen_load") - << [&] { GenerateTimeSeries(study, year, pResultWriter); }; + << [year, this] { GenerateTimeSeries(study, year, pResultWriter); }; } // Solar if (pData.haveToRefreshTSSolar && (year % pData.refreshIntervalSolar == 0)) { - pDurationCollector("tsgen_solar") - << [&] { GenerateTimeSeries(study, year, pResultWriter); }; + pDurationCollector("tsgen_solar") << [year, this] + { GenerateTimeSeries(study, year, pResultWriter); }; } // Wind if (pData.haveToRefreshTSWind && (year % pData.refreshIntervalWind == 0)) { pDurationCollector("tsgen_wind") - << [&] { GenerateTimeSeries(study, year, pResultWriter); }; + << [year, this] { GenerateTimeSeries(study, year, pResultWriter); }; } // Hydro if (pData.haveToRefreshTSHydro && (year % pData.refreshIntervalHydro == 0)) { - pDurationCollector("tsgen_hydro") - << [&] { GenerateTimeSeries(study, year, pResultWriter); }; + pDurationCollector("tsgen_hydro") << [year, this] + { GenerateTimeSeries(study, year, pResultWriter); }; } // Thermal const bool refreshTSonCurrentYear = (year % pData.refreshIntervalThermal == 0); - pDurationCollector("tsgen_thermal") << [&] + pDurationCollector("tsgen_thermal") << [refreshTSonCurrentYear, year, this] { if (refreshTSonCurrentYear) { @@ -727,7 +734,8 @@ void ISimulation::computeRandomNumbers( // ... Reservoir levels ... uint areaIndex = 0; study.areas.each( - [&](Data::Area& area) + [&areaIndex, &indexYear, &randomForYears, &randomHydroGenerator, &y, &isPerformed, this]( + Data::Area& area) { // looking for the initial reservoir level (begining of the year) auto& min = area.hydro.reservoirLevel[Data::PartHydro::minimum]; diff --git a/src/solver/simulation/include/antares/solver/simulation/timeseries-numbers.h b/src/solver/simulation/include/antares/solver/simulation/timeseries-numbers.h index a46e3b3512..2b087b65e6 100644 --- a/src/solver/simulation/include/antares/solver/simulation/timeseries-numbers.h +++ b/src/solver/simulation/include/antares/solver/simulation/timeseries-numbers.h @@ -31,6 +31,8 @@ namespace Antares::Solver::TimeSeriesNumbers { +bool CheckNumberOfColumns(const Data::AreaList& areas); + /*! ** \brief Generate all time-series numbers for a given set */ diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 9ddb735072..fd3719d69d 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -349,7 +349,7 @@ static void prepareBindingConstraint(PROBLEME_HEBDO& problem, auto* group = bcgroups[bc->group()]; if (group) { - tsIndexForBc = group->timeseriesNumbers[0][problem.year]; + tsIndexForBc = group->timeseriesNumbers[problem.year]; } // If there is only one TS, always select it. diff --git a/src/solver/simulation/timeseries-numbers.cpp b/src/solver/simulation/timeseries-numbers.cpp index afe27f5f26..787d9d930b 100644 --- a/src/solver/simulation/timeseries-numbers.cpp +++ b/src/solver/simulation/timeseries-numbers.cpp @@ -350,7 +350,8 @@ bool checkInterModalConsistencyForArea(const Area& area, { logs.error() << "Inter-modal correlation: time-series numbers of inter-modal modes in area '" - << area.name << "'" << " are not identical"; + << area.name << "'" + << " are not identical"; return false; } @@ -390,62 +391,61 @@ void storeTSnumbersForIntraModal(const array& intramo AreaList& areas) { areas.each( - [&](Area& area) + [year, &isTSintramodal, &intramodal_draws](Area& area) { // ------------- // Load ... // ------------- - assert(year < area.load.series.timeseriesNumbers.height); + assert(year < area.load.series.timeseriesNumbers.height()); int indexTS = ts_to_tsIndex.at(timeSeriesLoad); if (isTSintramodal[indexTS] && area.load.series.timeSeries.width > 1) { - area.load.series.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + area.load.series.timeseriesNumbers[year] = intramodal_draws[indexTS]; } // ------------- // Solar ... // ------------- - assert(year < area.solar.series.timeseriesNumbers.height); + assert(year < area.solar.series.timeseriesNumbers.height()); indexTS = ts_to_tsIndex.at(timeSeriesSolar); if (isTSintramodal[indexTS] && area.solar.series.timeSeries.width > 1) { - area.solar.series.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + area.solar.series.timeseriesNumbers[year] = intramodal_draws[indexTS]; } // ------------- // Wind ... // ------------- - assert(year < area.wind.series.timeseriesNumbers.height); + assert(year < area.wind.series.timeseriesNumbers.height()); indexTS = ts_to_tsIndex.at(timeSeriesWind); if (isTSintramodal[indexTS] && area.wind.series.timeSeries.width > 1) { - area.wind.series.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + area.wind.series.timeseriesNumbers[year] = intramodal_draws[indexTS]; } // ------------- // Hydro ... // ------------- - assert(year < area.hydro.series->timeseriesNumbers.height); + assert(year < area.hydro.series->timeseriesNumbers.height()); indexTS = ts_to_tsIndex.at(timeSeriesHydro); if (isTSintramodal[indexTS] && area.hydro.series->TScount() > 1) { - area.hydro.series->timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + area.hydro.series->timeseriesNumbers[year] = intramodal_draws[indexTS]; } // ------------- // Hydro Max Power ... // ------------- - assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height); + assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height()); indexTS = ts_to_tsIndex.at(timeSeriesHydroMaxPower); if (isTSintramodal[indexTS]) { - area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = intramodal_draws - [indexTS]; + area.hydro.series->timeseriesNumbersHydroMaxPower[year] = intramodal_draws[indexTS]; } // ------------- @@ -457,7 +457,7 @@ void storeTSnumbersForIntraModal(const array& intramo { for (auto& cluster: area.thermal.list.each_enabled()) { - cluster->series.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + cluster->series.timeseriesNumbers[year] = intramodal_draws[indexTS]; } } @@ -470,7 +470,7 @@ void storeTSnumbersForIntraModal(const array& intramo { for (auto& cluster: area.renewable.list.each_enabled()) { - cluster->series.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + cluster->series.timeseriesNumbers[year] = intramodal_draws[indexTS]; } } @@ -486,7 +486,7 @@ void storeTSnumbersForIntraModal(const array& intramo auto& link = *(it->second); if (link.directCapacities.timeSeries.width > 1) { - link.timeseriesNumbers[0][year] = intramodal_draws[indexTS]; + link.timeseriesNumbers[year] = intramodal_draws[indexTS]; } } } @@ -498,7 +498,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i Study& study) { study.areas.each( - [&](Area& area) + [&study, &isTSintramodal, year](Area& area) { // ------------- // Load ... @@ -507,7 +507,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { - area.load.series.timeseriesNumbers[0][year] = (uint32_t)(floor( + area.load.series.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * area.load.series.timeSeries.width)); } @@ -519,7 +519,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { - area.solar.series.timeseriesNumbers[0][year] = (uint32_t)(floor( + area.solar.series.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * area.solar.series.timeSeries.width)); } @@ -531,7 +531,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { - area.wind.series.timeseriesNumbers[0][year] = (uint32_t)(floor( + area.wind.series.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * area.wind.series.timeSeries.width)); } @@ -543,7 +543,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { - area.hydro.series->timeseriesNumbers[0][year] = (uint32_t)(floor( + area.hydro.series->timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * area.hydro.series->TScount())); } @@ -558,8 +558,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i uint nbTimeSeries = area.hydro.series->maxPowerTScount(); if (nbTimeSeries != 1) { - area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = static_cast< - uint32_t>( + area.hydro.series->timeseriesNumbersHydroMaxPower[year] = static_cast( (floor(study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries))); } } @@ -579,7 +578,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i { if (!isTSintramodal[indexTS]) { - cluster->series.timeseriesNumbers[0][year] = (uint32_t)(floor( + cluster->series.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * cluster->series.timeSeries.width)); } @@ -597,7 +596,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i { // There is no TS generation for renewable clusters uint nbTimeSeries = cluster->series.timeSeries.width; - cluster->series.timeseriesNumbers[0][year] = (uint32_t)(floor( + cluster->series.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries)); } } @@ -615,7 +614,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i const uint nbTimeSeries = link.directCapacities.timeSeries.width; if (nbTimeSeries > 1) { - link.timeseriesNumbers[0][year] = (uint32_t)(floor( + link.timeseriesNumbers[year] = (uint32_t)(floor( study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries)); } } @@ -625,7 +624,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i for (auto& group: study.bindingConstraintsGroups) { const auto nbTimeSeries = group->numberOfTimeseries(); - auto& groupTsNumber = group->timeseriesNumbers[0][year]; + auto& groupTsNumber = group->timeseriesNumbers[year]; if (nbTimeSeries > 1) { groupTsNumber = (uint32_t)(floor(study.runtime->random[seedTimeseriesNumbers].next() @@ -634,11 +633,11 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i } } -Matrix* getFirstTSnumberInterModalMatrixFoundInArea( +Data::TimeSeriesNumbers* getFirstTSnumberInterModalMatrixFoundInArea( Area& area, const array& isTSintermodal) { - Matrix* tsNumbersMtx = nullptr; + Data::TimeSeriesNumbers* tsNumbersMtx = nullptr; if (isTSintermodal[ts_to_tsIndex.at(timeSeriesLoad)]) { tsNumbersMtx = &(area.load.series.timeseriesNumbers); @@ -680,60 +679,61 @@ Matrix* getFirstTSnumberInterModalMatrixFoundInArea( return tsNumbersMtx; } -void applyMatrixDrawsToInterModalModesInArea(Matrix* tsNumbersMtx, - Area& area, - const array& isTSintermodal, - const uint years) +static void applyMatrixDrawsToInterModalModesInArea( + Data::TimeSeriesNumbers& tsNumbersMtx, + Area& area, + const array& isTSintermodal, + const uint years) { for (uint year = 0; year < years; ++year) { - const uint draw = tsNumbersMtx->entry[0][year]; + const uint32_t draw = tsNumbersMtx[year]; assert(draw < 100000); - assert(year < area.load.series.timeseriesNumbers.height); + assert(year < area.load.series.timeseriesNumbers.height()); if (isTSintermodal[ts_to_tsIndex.at(timeSeriesLoad)]) { - area.load.series.timeseriesNumbers[0][year] = draw; + area.load.series.timeseriesNumbers[year] = draw; } - assert(year < area.solar.series.timeseriesNumbers.height); + assert(year < area.solar.series.timeseriesNumbers.height()); if (isTSintermodal[ts_to_tsIndex.at(timeSeriesSolar)]) { - area.solar.series.timeseriesNumbers[0][year] = draw; + area.solar.series.timeseriesNumbers[year] = draw; } - assert(year < area.wind.series.timeseriesNumbers.height); + assert(year < area.wind.series.timeseriesNumbers.height()); if (isTSintermodal[ts_to_tsIndex.at(timeSeriesWind)]) { - area.wind.series.timeseriesNumbers[0][year] = draw; + area.wind.series.timeseriesNumbers[year] = draw; } - assert(year < area.hydro.series->timeseriesNumbers.height); + assert(year < area.hydro.series->timeseriesNumbers.height()); if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydro)]) { - area.hydro.series->timeseriesNumbers[0][year] = draw; + area.hydro.series->timeseriesNumbers[year] = draw; } - assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height); + assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height()); if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydroMaxPower)]) { - area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = draw; + area.hydro.series->timeseriesNumbersHydroMaxPower[year] = draw; } if (isTSintermodal[ts_to_tsIndex.at(timeSeriesThermal)]) { for (auto& cluster: area.thermal.list.each_enabled()) { - assert(year < cluster->series.timeseriesNumbers.height); - cluster->series.timeseriesNumbers[0][year] = draw; + assert(year < cluster->series.timeseriesNumbers.height()); + cluster->series.timeseriesNumbers[year] = draw; } } if (isTSintermodal[ts_to_tsIndex.at(timeSeriesRenewable)]) { for (const auto& cluster: area.renewable.list.each_enabled()) { - assert(year < cluster->series.timeseriesNumbers.height); - cluster->series.timeseriesNumbers[0][year] = draw; + assert(year < cluster->series.timeseriesNumbers.height()); + cluster->series.timeseriesNumbers[year] = draw; } } } @@ -745,6 +745,61 @@ bool TimeSeriesNumbers::checkAllElementsIdenticalOrOne(std::vector w) return std::adjacent_find(w.begin(), first_one, std::not_equal_to()) == first_one; } +using Checks = std::vector>; + +static Checks buildChecksFromStudy(const AreaList& areas) +{ + Checks toCheck; + + // LINKS + for (const auto& [_, area]: areas) + { + const std::string areaID = area->id.to(); + for (const auto& [_, link]: area->links) + { + const std::string areaID2 = link->with->id.to(); + toCheck.push_back({&link->timeseriesNumbers, "link " + areaID + " / " + areaID2}); + } + } + + // HYDRO + for (const auto& [_, area]: areas) + { + const std::string areaID = area->id.to(); + toCheck.push_back({&area->hydro.series->timeseriesNumbers, "hydro " + areaID}); + } + + return toCheck; +} + +static bool performChecks(const Checks& toCheck) +{ + bool ret = true; + for (const auto& [tsNumber, context]: toCheck) + { + const auto errorMessageMaybe = tsNumber->checkSeriesNumberOfColumnsConsistency(); + if (errorMessageMaybe.has_value()) + { + logs.error() << "Inconsistent number of columns for " << context << " (" + << errorMessageMaybe.value() << ")"; + ret = false; + } + } + if (!ret) + { + logs.error() << "Please check that all series have the same number of columns or 1 column, " + "or a combination of 1 column and the same number of columns"; + } + + return ret; +} + +bool TimeSeriesNumbers::CheckNumberOfColumns(const AreaList& areas) +{ + Checks toCheck = buildChecksFromStudy(areas); + return performChecks(toCheck); +} + bool TimeSeriesNumbers::Generate(Study& study) { logs.info() << "Preparing time-series numbers..."; @@ -827,11 +882,11 @@ bool TimeSeriesNumbers::Generate(Study& study) return false; } - Matrix* tsNumbersMtx = getFirstTSnumberInterModalMatrixFoundInArea( + Data::TimeSeriesNumbers* tsNumbersMtx = getFirstTSnumberInterModalMatrixFoundInArea( area, isTSintermodal); - applyMatrixDrawsToInterModalModesInArea(tsNumbersMtx, area, isTSintermodal, years); + applyMatrixDrawsToInterModalModesInArea(*tsNumbersMtx, area, isTSintermodal, years); } } return true; diff --git a/src/solver/variable/include/antares/solver/variable/economy/profitByPlant.h b/src/solver/variable/include/antares/solver/variable/economy/profitByPlant.h index 9ff62bd68b..6d7791af16 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/profitByPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/profitByPlant.h @@ -285,7 +285,7 @@ class ProfitByPlant: public Variable::IVariable, NextT, VCa double hourlyClusterProduction = thermal[area->index] .thermalClustersProductions[cluster->areaWideIndex]; double pMin = thermal[area->index].PMinOfClusters[cluster->areaWideIndex]; - uint tsIndex = cluster->series.timeseriesNumbers[0][state.year]; + uint tsIndex = cluster->series.timeseriesNumbers[state.year]; // Thermal cluster profit pValuesForTheCurrentYear[numSpace][cluster->areaWideIndex].hour[hourInTheYear] diff --git a/src/solver/variable/state.cpp b/src/solver/variable/state.cpp index 73881c03c0..9318e49f21 100644 --- a/src/solver/variable/state.cpp +++ b/src/solver/variable/state.cpp @@ -150,7 +150,7 @@ void State::initFromThermalClusterIndex(const uint clusterAreaWideIndex) void State::initFromThermalClusterIndexProduction(const uint clusterAreaWideIndex) { - uint serieIndex = thermalCluster->series.timeseriesNumbers[0][this->year]; + uint serieIndex = thermalCluster->series.timeseriesNumbers[this->year]; if (thermal[area->index].thermalClustersProductions[clusterAreaWideIndex] > 0.) { @@ -295,7 +295,7 @@ void State::yearEndBuildFromThermalClusterIndex(const uint clusterAreaWideIndex) continue; } - uint serieIndex = currentCluster->series.timeseriesNumbers[0][this->year]; + uint serieIndex = currentCluster->series.timeseriesNumbers[this->year]; thermalClusterOperatingCostForYear[h] = thermalClusterProduction * currentCluster->getOperatingCost(serieIndex, h); diff --git a/src/tests/end-to-end/simple_study/simple-study.cpp b/src/tests/end-to-end/simple_study/simple-study.cpp index cd1a755603..4ea0f8db1c 100644 --- a/src/tests/end-to-end/simple_study/simple-study.cpp +++ b/src/tests/end-to-end/simple_study/simple-study.cpp @@ -391,9 +391,6 @@ BOOST_FIXTURE_TEST_CASE(scenario_builder, HydroMaxPowerStudy) double averageLoad = (4 * 300. + 3. * 200. + 2. * 100.) / weightSum; - BOOST_TEST(hydro->series->maxHourlyGenPower.timeseriesNumbers[0][0] == 2U); - BOOST_TEST(hydro->series->maxHourlyGenPower.timeseriesNumbers[0][1] == 1U); - BOOST_TEST(hydro->series->maxHourlyGenPower.timeseriesNumbers[0][2] == 0); BOOST_TEST(output.overallCost(area).hour(0) == loadInArea - averageLoad * area->thermal.unsuppliedEnergyCost, tt::tolerance(0.1)); diff --git a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp index 297a3b7d3b..da83ee9f4f 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp +++ b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp @@ -194,7 +194,7 @@ BOOST_FIXTURE_TEST_CASE(on_area2_and_on_year_18__load_TS_number_11_is_chosen__re tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(area_2->load.series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(area_2->load.series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -212,7 +212,7 @@ BOOST_FIXTURE_TEST_CASE(on_area3_and_on_year_7__wind_TS_number_5_is_chosen__read tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(area_3->wind.series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(area_3->wind.series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -230,7 +230,7 @@ BOOST_FIXTURE_TEST_CASE(on_area1_and_on_year_4__solar_TS_number_8_is_chosen__rea tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(area_1->solar.series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(area_1->solar.series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -248,31 +248,10 @@ BOOST_FIXTURE_TEST_CASE(on_area2_and_on_year_15__solar_TS_number_3_is_chosen__re tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(area_2->hydro.series->timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(area_2->hydro.series->timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } -// ================= -// Tests on Hydro Max Power -// ================= -BOOST_FIXTURE_TEST_CASE( - on_area3_and_on_year_10__hydro_power_credits_TS_number_6_is_chosen__reading_OK, - Fixture) -{ - AreaName yearNumber = "7"; - String tsNumber = "6"; - AreaName::Vector splitKey = {"hgp", "area 3", yearNumber}; - BOOST_CHECK(my_rule.readLine(splitKey, tsNumber, false)); - - BOOST_CHECK_EQUAL(my_rule.hydroMaxPower.get_value(yearNumber.to(), area_3->index), - tsNumber.to()); - - BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL( - area_3->hydro.series->timeseriesNumbersHydroMaxPower[0][yearNumber.to()], - tsNumber.to() - 1); -} - // =========================== // Tests on Thermal clusters // =========================== @@ -289,7 +268,7 @@ BOOST_FIXTURE_TEST_CASE( tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(thCluster_11->series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(thCluster_11->series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -306,7 +285,7 @@ BOOST_FIXTURE_TEST_CASE( tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -323,7 +302,7 @@ BOOST_FIXTURE_TEST_CASE( tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(thCluster_31->series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(thCluster_31->series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -346,7 +325,7 @@ BOOST_FIXTURE_TEST_CASE( tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -366,7 +345,7 @@ BOOST_FIXTURE_TEST_CASE( tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(rnCluster_32->series.timeseriesNumbers[0][yearNumber.to()], + BOOST_CHECK_EQUAL(rnCluster_32->series.timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } @@ -433,8 +412,7 @@ BOOST_FIXTURE_TEST_CASE(on_link_area1_area2_and_on_year_0__ntc_TS_number_10_is_c tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(link_12->timeseriesNumbers[0][yearNumber.to()], - tsNumber.to() - 1); + BOOST_CHECK_EQUAL(link_12->timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } BOOST_FIXTURE_TEST_CASE(on_link_area1_area3_and_on_year_15__ntc_TS_number_7_is_chosen__reading_OK, @@ -449,8 +427,7 @@ BOOST_FIXTURE_TEST_CASE(on_link_area1_area3_and_on_year_15__ntc_TS_number_7_is_c tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(link_13->timeseriesNumbers[0][yearNumber.to()], - tsNumber.to() - 1); + BOOST_CHECK_EQUAL(link_13->timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } BOOST_FIXTURE_TEST_CASE(on_link_area2_area3_and_on_year_19__ntc_TS_number_6_is_chosen__reading_OK, @@ -465,8 +442,7 @@ BOOST_FIXTURE_TEST_CASE(on_link_area2_area3_and_on_year_19__ntc_TS_number_6_is_c tsNumber.to()); BOOST_CHECK(my_rule.apply()); - BOOST_CHECK_EQUAL(link_23->timeseriesNumbers[0][yearNumber.to()], - tsNumber.to() - 1); + BOOST_CHECK_EQUAL(link_23->timeseriesNumbers[yearNumber.to()], tsNumber.to() - 1); } // ======================== @@ -476,14 +452,14 @@ BOOST_FIXTURE_TEST_CASE(binding_constraints_group_groupTest__Load_TS_4_for_year_ Fixture) { auto yearNumber = 3; - auto tsNumber = 4; + uint32_t tsNumber = 4; AreaName::Vector splitKey = {"bc", "groupTest", std::to_string(yearNumber)}; BOOST_CHECK(my_rule.readLine(splitKey, std::to_string(tsNumber))); BOOST_CHECK_EQUAL(my_rule.binding_constraints.get("groupTest", yearNumber), tsNumber); BOOST_CHECK(my_rule.apply()); - auto actual = study->bindingConstraintsGroups["groupTest"]->timeseriesNumbers[0][yearNumber]; + auto actual = study->bindingConstraintsGroups["groupTest"]->timeseriesNumbers[yearNumber]; BOOST_CHECK_EQUAL(actual, tsNumber - 1); } @@ -504,8 +480,8 @@ BOOST_FIXTURE_TEST_CASE(thermalTSNumberData, Fixture) tsdata.apply(*study); - BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][2], 21); - BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][5], 0); + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[2], 21); + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[5], 0); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/libs/antares/study/series/CMakeLists.txt b/src/tests/src/libs/antares/study/series/CMakeLists.txt index 0afbfe34ef..f525878822 100644 --- a/src/tests/src/libs/antares/study/series/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/series/CMakeLists.txt @@ -10,6 +10,7 @@ target_link_libraries(timeseries-tests PRIVATE Boost::unit_test_framework Antares::series + antares-solver-simulation ) # Storing timeseries-tests under the folder Unit-tests in the IDE diff --git a/src/tests/src/libs/antares/study/series/timeseries-tests.cpp b/src/tests/src/libs/antares/study/series/timeseries-tests.cpp index c5d5e01a4c..a2b928bf6a 100644 --- a/src/tests/src/libs/antares/study/series/timeseries-tests.cpp +++ b/src/tests/src/libs/antares/study/series/timeseries-tests.cpp @@ -23,9 +23,13 @@ #define WIN32_LEAN_AND_MEAN +#include +#include + #include #include +#include using namespace Antares::Data; @@ -43,12 +47,12 @@ struct Fixture ts(tsnum) { ts.reset(1, HOURS_PER_YEAR); - tsnum.resize(1, 1); - tsnum[0][0] = 0; + tsnum.reset(1); + tsnum[0] = 0; } + TimeSeriesNumbers tsnum; TimeSeries ts; - TimeSeries::numbers tsnum; std::string folder; void fillColumn(unsigned int idx); @@ -75,13 +79,37 @@ void Fixture::fillColumnReverse(unsigned int idx) void Fixture::fillTsnum() { - tsnum.resize(1, ts.timeSeries.width); + tsnum.reset(ts.timeSeries.width); for (unsigned int i = 0; i < ts.timeSeries.width; i++) { - tsnum[0][i] = i; + tsnum[i] = i; } } +class FixtureMultipleTS +{ +public: + void init(const std::vector& width) + { + const int height = 10; // Arbitrary + ts.resize(width.size()); + for (size_t idx = 0; int w: width) + { + // TimeSeries::TimeSeries does not exist, so we use pointers + ts[idx] = std::make_unique(tsnum); // ts[idx] is registered to tsnum here + tsnum.registerSeries(ts[idx].get(), std::to_string(idx)); + ts[idx]->reset(w, height); + idx++; + } + } + +public: + TimeSeriesNumbers tsnum; + +private: + std::vector> ts; +}; + // ================== // Tests section // ================== @@ -90,10 +118,10 @@ BOOST_AUTO_TEST_SUITE(timeseries_tests) BOOST_FIXTURE_TEST_CASE(getSeriesIndex, Fixture) { - tsnum.resize(1, 10); + tsnum.reset(10); for (unsigned int i = 0; i < 10; i++) { - tsnum[0][i] = i; + tsnum[i] = i; } ts.resize(2, HOURS_PER_YEAR); @@ -160,8 +188,8 @@ BOOST_FIXTURE_TEST_CASE(getCoefficientSpecificData, Fixture) { ts.resize(2, 2); fillTsnum(); - tsnum[0][0] = 1; - tsnum[0][1] = 0; + tsnum[0] = 1; + tsnum[1] = 0; ts.timeSeries[0][0] = 12.5; ts.timeSeries[0][1] = 74.74; ts.timeSeries[1][0] = -57; @@ -172,4 +200,60 @@ BOOST_FIXTURE_TEST_CASE(getCoefficientSpecificData, Fixture) BOOST_CHECK_EQUAL(ts.getCoefficient(1, 0), 12.5); } +// SINGLE COLUMN +BOOST_FIXTURE_TEST_CASE(getCoefficient_SingleColumn, Fixture) +{ + ts.resize(1, 2); + + // Here, we provide 2 time series numbers... + tsnum.reset(2); + for (unsigned int i = 0; i < 2; i++) + { + tsnum[i] = i; + } + + // ...but only one column + ts.timeSeries[0][0] = 12.5; + ts.timeSeries[0][1] = 74.74; + + // year=1 + BOOST_CHECK_EQUAL(ts.getCoefficient(0, 0), 12.5); + BOOST_CHECK_EQUAL(ts.getCoefficient(0, 1), 74.74); + + // year=2 + BOOST_CHECK_EQUAL(ts.getCoefficient(1, 0), 12.5); + BOOST_CHECK_EQUAL(ts.getCoefficient(1, 1), 74.74); +} + +// VALID CONFIGURATIONS +BOOST_FIXTURE_TEST_CASE(checkSizeOK_1TS, FixtureMultipleTS) +{ + init({11}); + BOOST_CHECK(!tsnum.checkSeriesNumberOfColumnsConsistency()); +} + +BOOST_FIXTURE_TEST_CASE(checkSizeOK_2TS, FixtureMultipleTS) +{ + init({12, 12}); + BOOST_CHECK(!tsnum.checkSeriesNumberOfColumnsConsistency()); +} + +BOOST_FIXTURE_TEST_CASE(checkSizeOK_4TS, FixtureMultipleTS) +{ + init({22, 22, 1, 22}); + BOOST_CHECK(!tsnum.checkSeriesNumberOfColumnsConsistency()); +} + +BOOST_FIXTURE_TEST_CASE(checkSizeKO_2TS, FixtureMultipleTS) +{ + init({11, 12}); + BOOST_CHECK(tsnum.checkSeriesNumberOfColumnsConsistency()); +} + +BOOST_FIXTURE_TEST_CASE(checkSizeKO_4TS, FixtureMultipleTS) +{ + init({22, 22, 1, 21}); + BOOST_CHECK(tsnum.checkSeriesNumberOfColumnsConsistency()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp index e155b7d091..72adfc718a 100644 --- a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp +++ b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(BC_group_TestGroup_has_output_file) study->parameters.storeTimeseriesNumbers = true; study->bindingConstraintsGroups.add("TestGroup"); - study->bindingConstraintsGroups["TestGroup"]->timeseriesNumbers.resize(1, 1); + study->bindingConstraintsGroups["TestGroup"]->timeseriesNumbers.reset(1); auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); @@ -75,8 +75,8 @@ BOOST_AUTO_TEST_CASE(BC_group_TestGroup_has_output_file) fs::path bc_path = working_tmp_dir / "ts-numbers" / "bindingconstraints" / "TestGroup.txt"; initializeStudy(*study); - TimeSeriesNumbers::Generate(*study); - TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); + Antares::Solver::TimeSeriesNumbers::Generate(*study); + Antares::Solver::TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); bool file_exists = fs::exists(bc_path); BOOST_CHECK_EQUAL(file_exists, true); @@ -88,8 +88,8 @@ BOOST_AUTO_TEST_CASE(BC_output_ts_numbers_file_for_each_group) study->parameters.storeTimeseriesNumbers = true; study->bindingConstraintsGroups.add("test1"); study->bindingConstraintsGroups.add("test2"); - study->bindingConstraintsGroups["test1"]->timeseriesNumbers.resize(1, 1); - study->bindingConstraintsGroups["test2"]->timeseriesNumbers.resize(1, 1); + study->bindingConstraintsGroups["test1"]->timeseriesNumbers.reset(1); + study->bindingConstraintsGroups["test2"]->timeseriesNumbers.reset(1); auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); @@ -100,9 +100,9 @@ BOOST_AUTO_TEST_CASE(BC_output_ts_numbers_file_for_each_group) durationCollector); initializeStudy(*study); - TimeSeriesNumbers::Generate(*study); + Antares::Solver::TimeSeriesNumbers::Generate(*study); - TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); + Antares::Solver::TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); fs::path test1_path = working_tmp_dir / "ts-numbers" / "bindingconstraints" / "test1.txt"; fs::path test2_path = working_tmp_dir / "ts-numbers" / "bindingconstraints" / "test2.txt"; @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(BC_timeseries_numbers_store_values) auto bc = std::make_shared(); bc->RHSTimeSeries().resize(10, 10); group->add(bc); - study->bindingConstraintsGroups["test1"]->timeseriesNumbers.resize(1, 1); + study->bindingConstraintsGroups["test1"]->timeseriesNumbers.reset(1); auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); @@ -129,22 +129,19 @@ BOOST_AUTO_TEST_CASE(BC_timeseries_numbers_store_values) durationCollector); initializeStudy(*study); - TimeSeriesNumbers::Generate(*study); - Matrix series(2, 2); - series[0][0] = 0; - series[0][1] = 1; - series[1][0] = 42; - series[1][1] = 3; - study->bindingConstraintsGroups["test1"]->timeseriesNumbers = series; + Antares::Solver::TimeSeriesNumbers::Generate(*study); - TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); + auto& tsNumbers = study->bindingConstraintsGroups["test1"]->timeseriesNumbers; + tsNumbers.reset(2); + tsNumbers[0] = 0; + tsNumbers[1] = 1; + + Antares::Solver::TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(*study, *resultWriter); fs::path test1_path = working_tmp_dir / "ts-numbers" / "bindingconstraints" / "test1.txt"; BOOST_CHECK_EQUAL(fs::exists(test1_path), true); Matrix out; out.loadFromCSVFile(test1_path.string()); - BOOST_CHECK_EQUAL(series[0][0] + 1, out[0][0]); - BOOST_CHECK_EQUAL(series[0][1] + 1, out[0][1]); - BOOST_CHECK_EQUAL(series[1][0] + 1, out[1][0]); - BOOST_CHECK_EQUAL(series[1][1] + 1, out[1][1]); + BOOST_CHECK_EQUAL(tsNumbers[0] + 1, out[0][0]); + BOOST_CHECK_EQUAL(tsNumbers[1] + 1, out[0][1]); } diff --git a/src/tests/src/solver/simulation/tests-ts-numbers.cpp b/src/tests/src/solver/simulation/tests-ts-numbers.cpp index d554c4e380..bd6de6403d 100644 --- a/src/tests/src/solver/simulation/tests-ts-numbers.cpp +++ b/src/tests/src/solver/simulation/tests-ts-numbers.cpp @@ -140,8 +140,8 @@ BOOST_AUTO_TEST_CASE(two_areas_with_5_ready_made_ts_on_load___check_intra_modal_ // intra-modal for load : drawn TS numbers in all areas must be equal uint year = 0; - BOOST_CHECK_EQUAL(area_1->load.series.timeseriesNumbers[0][year], - area_2->load.series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(area_1->load.series.timeseriesNumbers[year], + area_2->load.series.timeseriesNumbers[year]); } // ======================= @@ -206,10 +206,10 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][year], - thCluster_11->series.timeseriesNumbers[0][year]); - BOOST_CHECK_EQUAL(thCluster_21->series.timeseriesNumbers[0][year], - thCluster_11->series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[year], + thCluster_11->series.timeseriesNumbers[year]); + BOOST_CHECK_EQUAL(thCluster_21->series.timeseriesNumbers[year], + thCluster_11->series.timeseriesNumbers[year]); } BOOST_AUTO_TEST_CASE( @@ -238,8 +238,8 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - BOOST_CHECK_EQUAL(thCluster_21->series.timeseriesNumbers[0][year], - thCluster_11->series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(thCluster_21->series.timeseriesNumbers[year], + thCluster_11->series.timeseriesNumbers[year]); } BOOST_AUTO_TEST_CASE( @@ -298,10 +298,10 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - BOOST_CHECK_EQUAL(rnCluster_12->series.timeseriesNumbers[0][year], - rnCluster_11->series.timeseriesNumbers[0][year]); - BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[0][year], - rnCluster_11->series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(rnCluster_12->series.timeseriesNumbers[year], + rnCluster_11->series.timeseriesNumbers[year]); + BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[year], + rnCluster_11->series.timeseriesNumbers[year]); } BOOST_AUTO_TEST_CASE( @@ -330,8 +330,8 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[0][year], - rnCluster_11->series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(rnCluster_21->series.timeseriesNumbers[year], + rnCluster_11->series.timeseriesNumbers[year]); } BOOST_AUTO_TEST_CASE( @@ -383,13 +383,13 @@ BOOST_AUTO_TEST_CASE(check_intra_modal_on_hydro_max_power_time_series) study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); - BOOST_CHECK(TimeSeriesNumbers::Generate(*study)); + BOOST_CHECK(Antares::Solver::TimeSeriesNumbers::Generate(*study)); for (unsigned int year = 0; year < nbYears; year++) { - unsigned int ts_number_1 = area_1->hydro.series->timeseriesNumbersHydroMaxPower[0][year]; - unsigned int ts_number_2 = area_2->hydro.series->timeseriesNumbersHydroMaxPower[0][year]; - unsigned int ts_number_3 = area_3->hydro.series->timeseriesNumbersHydroMaxPower[0][year]; + unsigned int ts_number_1 = area_1->hydro.series->timeseriesNumbersHydroMaxPower[year]; + unsigned int ts_number_2 = area_2->hydro.series->timeseriesNumbersHydroMaxPower[year]; + unsigned int ts_number_3 = area_3->hydro.series->timeseriesNumbersHydroMaxPower[year]; BOOST_CHECK_EQUAL(ts_number_1, ts_number_2); BOOST_CHECK_EQUAL(ts_number_1, ts_number_3); @@ -430,10 +430,10 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - uint drawnTsNbForLoad = area->load.series.timeseriesNumbers[0][year]; - BOOST_CHECK_EQUAL(area->wind.series.timeseriesNumbers[0][year], drawnTsNbForLoad); - BOOST_CHECK_EQUAL(thCluster_1->series.timeseriesNumbers[0][year], drawnTsNbForLoad); - BOOST_CHECK_EQUAL(thCluster_2->series.timeseriesNumbers[0][year], drawnTsNbForLoad); + uint drawnTsNbForLoad = area->load.series.timeseriesNumbers[year]; + BOOST_CHECK_EQUAL(area->wind.series.timeseriesNumbers[year], drawnTsNbForLoad); + BOOST_CHECK_EQUAL(thCluster_1->series.timeseriesNumbers[year], drawnTsNbForLoad); + BOOST_CHECK_EQUAL(thCluster_2->series.timeseriesNumbers[year], drawnTsNbForLoad); } BOOST_AUTO_TEST_CASE( @@ -466,10 +466,10 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - uint drawnTsNbForLoad = area->load.series.timeseriesNumbers[0][year]; - BOOST_CHECK_EQUAL(area->wind.series.timeseriesNumbers[0][year], drawnTsNbForLoad); - BOOST_CHECK_EQUAL(thCluster_1->series.timeseriesNumbers[0][year], drawnTsNbForLoad); - BOOST_CHECK_EQUAL(thCluster_2->series.timeseriesNumbers[0][year], drawnTsNbForLoad); + uint drawnTsNbForLoad = area->load.series.timeseriesNumbers[year]; + BOOST_CHECK_EQUAL(area->wind.series.timeseriesNumbers[year], drawnTsNbForLoad); + BOOST_CHECK_EQUAL(thCluster_1->series.timeseriesNumbers[year], drawnTsNbForLoad); + BOOST_CHECK_EQUAL(thCluster_2->series.timeseriesNumbers[year], drawnTsNbForLoad); } BOOST_AUTO_TEST_CASE( @@ -526,8 +526,8 @@ BOOST_AUTO_TEST_CASE( // TS number checks uint year = 0; - BOOST_CHECK_EQUAL(rnCluster_1->series.timeseriesNumbers[0][year], - area->load.series.timeseriesNumbers[0][year]); + BOOST_CHECK_EQUAL(rnCluster_1->series.timeseriesNumbers[year], + area->load.series.timeseriesNumbers[year]); } BOOST_AUTO_TEST_CASE( @@ -624,12 +624,12 @@ BOOST_AUTO_TEST_CASE(load_wind_thermal_in_intra_and_inter_modal____check_all_ts_ // - inside an area // - for all areas uint year = 0; - uint referenceLoadTsNumber = area_1->load.series.timeseriesNumbers[0][year]; - BOOST_CHECK_EQUAL(area_2->load.series.timeseriesNumbers[0][year], referenceLoadTsNumber); - BOOST_CHECK_EQUAL(area_1->wind.series.timeseriesNumbers[0][year], referenceLoadTsNumber); - BOOST_CHECK_EQUAL(area_2->wind.series.timeseriesNumbers[0][year], referenceLoadTsNumber); - BOOST_CHECK_EQUAL(thCluster_area_1->series.timeseriesNumbers[0][year], referenceLoadTsNumber); - BOOST_CHECK_EQUAL(thCluster_area_2->series.timeseriesNumbers[0][year], referenceLoadTsNumber); + uint referenceLoadTsNumber = area_1->load.series.timeseriesNumbers[year]; + BOOST_CHECK_EQUAL(area_2->load.series.timeseriesNumbers[year], referenceLoadTsNumber); + BOOST_CHECK_EQUAL(area_1->wind.series.timeseriesNumbers[year], referenceLoadTsNumber); + BOOST_CHECK_EQUAL(area_2->wind.series.timeseriesNumbers[year], referenceLoadTsNumber); + BOOST_CHECK_EQUAL(thCluster_area_1->series.timeseriesNumbers[year], referenceLoadTsNumber); + BOOST_CHECK_EQUAL(thCluster_area_2->series.timeseriesNumbers[year], referenceLoadTsNumber); } BOOST_AUTO_TEST_CASE(check_all_drawn_ts_numbers_are_bounded_between_0_and_nb_of_ts) @@ -678,13 +678,13 @@ BOOST_AUTO_TEST_CASE(check_all_drawn_ts_numbers_are_bounded_between_0_and_nb_of_ // TS number checks : each energy drawn ts numbers are up-bounded with the number of TS of the // related energy uint year = 0; - uint loadTsNumber = area->load.series.timeseriesNumbers[0][year]; - uint windTsNumber = area->wind.series.timeseriesNumbers[0][year]; - uint solarTsNumber = area->solar.series.timeseriesNumbers[0][year]; - uint hydroTsNumber = area->hydro.series->timeseriesNumbers[0][year]; - uint thermalTsNumber = thCluster->series.timeseriesNumbers[0][year]; + uint loadTsNumber = area->load.series.timeseriesNumbers[year]; + uint windTsNumber = area->wind.series.timeseriesNumbers[year]; + uint solarTsNumber = area->solar.series.timeseriesNumbers[year]; + uint hydroTsNumber = area->hydro.series->timeseriesNumbers[year]; + uint thermalTsNumber = thCluster->series.timeseriesNumbers[year]; auto binding_constraints_TS_number = study->bindingConstraintsGroups["dummy"] - ->timeseriesNumbers[0][year]; + ->timeseriesNumbers[year]; BOOST_CHECK(loadTsNumber < loadNumberOfTs); BOOST_CHECK(windTsNumber < windNumberOfTs);