diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 3a9bc71d65..e54c221cdb 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -85,11 +85,11 @@ jobs: ortools-url: ${{env.ORTOOLS_URL}} ortools-dir: ${{env.ORTOOLS_DIR}} - - name: Setup Python 3.11 + - name: Setup Python 3.12 uses: actions/setup-python@v4 with: architecture: 'x64' - python-version: '3.11' + python-version: '3.12' - name: Install pip dependencies if necessary run: pip install -r src/tests/examples/requirements.txt diff --git a/docs/reference-guide/03-commands.md b/docs/reference-guide/03-commands.md index 6765f0825a..a0842e2d84 100644 --- a/docs/reference-guide/03-commands.md +++ b/docs/reference-guide/03-commands.md @@ -178,7 +178,7 @@ this command allows to state, for each kind of time-series, whether it should be the available set (be it ready-made or Antares-generated) _**OR**_ should take a user-defined value (in the former case, the default "rand" value should be kept; in the latter, the value should be the reference number of the time-series to use). Multiple simulation profiles can be defined and archived. The default active profile gives the "rand" status for all time-series in all areas (full probabilistic simulation). - Regarding Hydro time-series, the scenario builder gives, in addition to the assignment of a specific number to use for the inflows time-series, the ability to define the initial reservoir level to use for each MC year, also hydro power credits scenario builder is available to support time-series for Maximum Generation and Maximum Pumping because the number of TS's for ROR, Hydro Storage and Minimum Generation can be different than the number of TS's for Maximum Generation and Maximum Pumping. + Regarding Hydro time-series, the scenario builder gives, in addition to the assignment of a specific number to use for the inflows time-series, the ability to define the initial reservoir level to use for each MC year, also hydro max power scenario builder is available to support time-series for Maximum Generation and Maximum Pumping because the number of TS's for ROR, Hydro Storage and Minimum Generation can be different than the number of TS's for Maximum Generation and Maximum Pumping. - **MC Scenario playlist** For each Monte-Carlo year of the simulation defined in the "Simulation" active window, this command allows to state whether a MC year prepared for the simulation should be actually simulated or not. diff --git a/docs/reference-guide/04-active_windows.md b/docs/reference-guide/04-active_windows.md index 2e6e2f66a8..32a2fdf2e1 100644 --- a/docs/reference-guide/04-active_windows.md +++ b/docs/reference-guide/04-active_windows.md @@ -97,10 +97,10 @@ These two parts are detailed hereafter. ### RIGHT PART: Time-series management -For the different kinds of time-series that Antares manages in a non-deterministic way (load, thermal generation, hydro power, hydro power credits, wind power, solar power or renewable depending on the option chosen): +For the different kinds of time-series that Antares manages in a non-deterministic way (load, thermal generation, hydro power, hydro max power, wind power, solar power or renewable depending on the option chosen): 1. **Choice of the kind of time-series to use** -Either « ready-made » or «stochastic » (i.e. Antares-generated), defined by setting the value to either "on" or "off". Exception is hydro power credits that can only be « ready-made ». Note that for Thermal time-series, the cluster-wise parameter may overrule this global parameter (see Thermal window description below). +Either « ready-made » or «stochastic » (i.e. Antares-generated), defined by setting the value to either "on" or "off". Exception is hydro max power that can only be « ready-made ». Note that for Thermal time-series, the cluster-wise parameter may overrule this global parameter (see Thermal window description below). 2. **For stochastic TS only**: - **Number** Number of TS to generate diff --git a/docs/reference-guide/13-file-format.md b/docs/reference-guide/13-file-format.md index 5be64dcd62..26c5cb3401 100644 --- a/docs/reference-guide/13-file-format.md +++ b/docs/reference-guide/13-file-format.md @@ -1,11 +1,11 @@ # Study format changes This is a list of all recent changes that came with new Antares Simulator features. The main goal of this document is to lower the costs of changing existing interfaces, both GUI and scripts. ## v8.8.0 -For each area, new files are added **input/hydro/series/<area>/maxgen.txt** and **input/hydro/series/<area>/maxpump.txt**. These files have one or more columns, and 8760 rows. The number of columns in these two files must be the same, if there is more than one column in each file, but if there is just one column for example in maxgen.txt file, maxpump.txt file can have more than one column and vice versa. For old studies, file **input/hydro/common/capacity/maxpower_<area>** will be deleted after upgrading the study and corresponding data from that file will be copied to already mentioned new files, even if study is upgraded or not. In that case maxgen.txt and maxpump.txt files will have just one column and 8760 rows. +For each area, new files are added **input/hydro/series/<area>/maxHourlyGenPower.txt** and **input/hydro/series/<area>/maxHourlyPumpPower.txt**. These files have one or more columns, and 8760 rows. The number of columns in these two files must be the same, if there is more than one column in each file, but if there is just one column for example in maxHourlyGenPower.txt file, maxHourlyPumpPower.txt file can have more than one column and vice versa. For old studies, file **input/hydro/common/capacity/maxpower_<area>** will be deleted after upgrading the study and corresponding data from that file will be copied to already mentioned new files, even if study is upgraded or not. In that case maxHourlyGenPower.txt and maxHourlyPumpPower.txt files will have just one column and 8760 rows. -Also for each area, new files are added **input/hydro/common/capacity/maxhoursGen_<area>** and **input/hydro/common/capacity/maxhoursPump_<area>**. These files have just one column and 365 rows. For old studies, file **input/hydro/common/capacity/maxpower_<area>** will be deleted after upgrading the study and corresponding data from that file will be copied to already mentioned new files, even if study is upgraded or not. +Also for each area, new files are added **input/hydro/common/capacity/maxDailyGenEnergy_<area>** and **input/hydro/common/capacity/maxDailyPumpEnergy_<area>**. These files have just one column and 365 rows. For old studies, file **input/hydro/common/capacity/maxpower_<area>** will be deleted after upgrading the study and corresponding data from that file will be copied to already mentioned new files, even if study is upgraded or not. ### Input -Under `Configure/MC Scenario Builder` new section added `Hydro-Power-Credits` +Under `Configure/MC Scenario Builder` new section added `Hydro Max Power` In the existing file **settings/scenariobuilder.dat**, under **<ruleset>** section following properties added: * **hgp,<area>,<year> = <hgp-value>** ## v8.7.0 diff --git a/src/libs/antares/constants.h b/src/libs/antares/constants.h index f82f0372de..61372b62bc 100644 --- a/src/libs/antares/constants.h +++ b/src/libs/antares/constants.h @@ -42,6 +42,8 @@ /*! Hours per year */ #define HOURS_PER_YEAR 8760 +#define HOURS_PER_DAY 24U + namespace Antares::Constants { extern const std::array daysPerMonth; diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index ba979fda64..be95d2762b 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -23,8 +23,8 @@ set(SRC_STUDY_SCENARIO_BUILDER scenario-builder/ThermalTSNumberData.h scenario-builder/HydroTSNumberData.h scenario-builder/HydroTSNumberData.cpp - scenario-builder/HydroPowerCreditsTSNumberData.h - scenario-builder/HydroPowerCreditsTSNumberData.cpp + scenario-builder/HydroMaxPowerTSNumberData.h + scenario-builder/HydroMaxPowerTSNumberData.cpp scenario-builder/SolarTSNumberData.cpp scenario-builder/solarTSNumberData.h scenario-builder/WindTSNumberData.h @@ -137,8 +137,10 @@ set(SRC_STUDY_PART_HYDRO parts/hydro/allocation.h parts/hydro/allocation.hxx parts/hydro/allocation.cpp - parts/hydro/datatransfer.h - parts/hydro/datatransfer.cpp + parts/hydro/hydromaxtimeseriesreader.h + parts/hydro/hydromaxtimeseriesreader.cpp + parts/hydro/pair-of-integers.h + parts/hydro/pair-of-integers.cpp ) source_group("study\\part\\hydro" FILES ${SRC_STUDY_PART_HYDRO}) diff --git a/src/libs/antares/study/area/area.cpp b/src/libs/antares/study/area/area.cpp index 9cc17127aa..fa96644f71 100644 --- a/src/libs/antares/study/area/area.cpp +++ b/src/libs/antares/study/area/area.cpp @@ -280,7 +280,7 @@ void Area::resizeAllTimeseriesNumbers(uint n) solar.series->timeseriesNumbers.clear(); wind.series->timeseriesNumbers.clear(); hydro.series->timeseriesNumbers.clear(); - hydro.series->timeseriesNumbersPowerCredits.clear(); + hydro.series->timeseriesNumbersHydroMaxPower.clear(); for (auto& namedLink : links) { AreaLink* link = namedLink.second; @@ -293,7 +293,7 @@ void Area::resizeAllTimeseriesNumbers(uint n) solar.series->timeseriesNumbers.resize(1, n); wind.series->timeseriesNumbers.resize(1, n); hydro.series->timeseriesNumbers.resize(1, n); - hydro.series->timeseriesNumbersPowerCredits.resize(1, n); + hydro.series->timeseriesNumbersHydroMaxPower.resize(1, n); for (auto& namedLink : links) { AreaLink* link = namedLink.second; diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index 378d1895ae..dd1519eea4 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -901,34 +901,47 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "prepro"; ret = area.hydro.prepro->loadFromFolder(study, area.id, buffer.c_str()) && ret; } - if (area.hydro.series && (!options.loadOnlyNeeded || !area.hydro.prepro)) // Series - { - buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "series"; - ret = area.hydro.series->loadFromFolder(study, area.id, buffer) && ret; - } - if (area.hydro.series && study.header.version < 870) + if (auto* hydroSeries = area.hydro.series; hydroSeries) { - std::shared_ptr datatransfer = std::make_shared(); - buffer.clear() << study.folderInput << SEP << "hydro"; + if (!options.loadOnlyNeeded || !area.hydro.prepro) // Series + { + buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "series"; + ret = hydroSeries->loadGenerationTS(area.id, buffer, study.header.version) && ret; - datatransfer->LoadFromFolder(study, buffer, area); - datatransfer->SupportForOldStudies(study, buffer, area); - } + hydroSeries->EqualizeGenerationTSsizes( + area, study.usedByTheSolver, study.gotFatalError); + } - if (area.hydro.series) - { - buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "series"; - ret = area.hydro.series->LoadHydroPowerCredits(study, area.id, buffer) && ret; + if (study.header.version < 870) + { + buffer.clear() << study.folderInput << SEP << "hydro"; + + HydroMaxTimeSeriesReader reader; + ret = reader(buffer, area, study.usedByTheSolver) && ret; + } + + if (study.header.version >= 870) + { + buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "series"; + ret = hydroSeries->LoadMaxPower(area.id, buffer) && ret; + + if (study.usedByTheSolver) + { + hydroSeries->EqualizeMaxPowerTSsizes(area, study.gotFatalError); + } + else + hydroSeries->setHydroModulability(area); + } + + hydroSeries->resizeTSinDeratedMode( + study.parameters.derated, study.header.version, study.usedByTheSolver); } buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "common" << SEP - << "capacity" << SEP << "maxpower_" << area.id << '.' - << study.inputExtension; - - bool exists = IO::File::Exists(buffer); + << "capacity" << SEP << "maxpower_" << area.id << ".txt"; - if (study.header.version >= 870 && exists) + if (bool exists = IO::File::Exists(buffer); study.header.version >= 870 && exists) { IO::File::Delete(buffer); } @@ -1636,13 +1649,7 @@ void AreaList::removeLoadTimeseries() void AreaList::removeHydroTimeseries() { each([&](Data::Area& area) { - area.hydro.series->ror.reset(1, HOURS_PER_YEAR); - area.hydro.series->storage.reset(1, DAYS_PER_YEAR); - area.hydro.series->mingen.reset(1, HOURS_PER_YEAR); - area.hydro.series->maxgen.reset(1, HOURS_PER_YEAR); - area.hydro.series->maxpump.reset(1, HOURS_PER_YEAR); - area.hydro.series->count = 1; - area.hydro.series->countpowercredits = 1; + area.hydro.series->reset(); }); } diff --git a/src/libs/antares/study/area/scratchpad.cpp b/src/libs/antares/study/area/scratchpad.cpp index ed8b7ffbce..4233293ad4 100644 --- a/src/libs/antares/study/area/scratchpad.cpp +++ b/src/libs/antares/study/area/scratchpad.cpp @@ -32,9 +32,7 @@ using namespace Yuni; -namespace Antares -{ -namespace Data +namespace Antares::Data { AreaScratchpad::TimeseriesData::TimeseriesData(Area& area) : load(area.load.series->timeSeries), solar(area.solar.series->timeSeries), wind(area.wind.series->timeSeries) @@ -56,7 +54,7 @@ AreaScratchpad::AreaScratchpad(const StudyRuntimeInfos& rinfos, Area& area) : ts originalMustrunSum[h] = std::numeric_limits::quiet_NaN(); } - // Fatal hors hydro + // Fatal hors hydro { double sum; uint w; @@ -77,6 +75,18 @@ AreaScratchpad::AreaScratchpad(const StudyRuntimeInfos& rinfos, Area& area) : ts } } + // Hourly maximum generation/pumping power matrices and their number of TS's (width of matrices) + auto const& maxHourlyGenPower = area.hydro.series->maxHourlyGenPower; + auto const& maxHourlyPumpPower = area.hydro.series->maxHourlyPumpPower; + uint nbOfMaxPowerTimeSeries = area.hydro.series->maxPowerTScount(); + + // Setting width and height of daily mean maximum generation/pumping power matrices + meanMaxDailyGenPower.reset(nbOfMaxPowerTimeSeries, DAYS_PER_YEAR); + meanMaxDailyPumpPower.reset(nbOfMaxPowerTimeSeries, DAYS_PER_YEAR); + + // Instantiate daily mean maximum generation/pumping power matrices + CalculateMeanDailyMaxPowerMatrices(maxHourlyGenPower, maxHourlyPumpPower, nbOfMaxPowerTimeSeries); + // =============== // hydroHasMod // =============== @@ -85,13 +95,12 @@ AreaScratchpad::AreaScratchpad(const StudyRuntimeInfos& rinfos, Area& area) : ts // Hydro generation permission // ------------------------------ // Useful whether we use a heuristic target or not - bool hydroGenerationPermission = false; + bool hydroGenerationPermission = false; - // ... Getting hydro max power - auto const& maxPower = area.hydro.series->maxgen; - auto const& maxGenHours = area.hydro.maxHoursGen[0]; + // ... Getting hydro max energy + auto const& maxDailyGenEnergy = area.hydro.maxDailyGenEnergy[0]; - hydroGenerationPermission = CheckForPositiveEnergy(maxPower, maxGenHours); + hydroGenerationPermission = CheckForPositiveEnergy(maxHourlyGenPower, maxDailyGenEnergy); // --------------------- // Hydro has inflows @@ -120,47 +129,64 @@ AreaScratchpad::AreaScratchpad(const StudyRuntimeInfos& rinfos, Area& area) : ts // -------------------------- hydroHasMod = hydroHasInflows || hydroGenerationPermission; - // =============== // Pumping // =============== - // ... Hydro max power - // ... Hydro max pumping power and energy - auto const& maxPumpingP = area.hydro.series->maxpump; - auto const& maxPumpHours = area.hydro.maxHoursPump[0]; + // Hydro max pumping energy + auto const& maxDailyPumpEnergy = area.hydro.maxDailyPumpEnergy[0]; - // If pumping energy is nil over the whole year, pumpHasMod is false, true otherwise. - pumpHasMod = CheckForPositiveEnergy(maxPumpingP, maxPumpHours); + // If pumping energy is nil over the whole year, pumpHasMod is false, true otherwise. + pumpHasMod = CheckForPositiveEnergy(maxHourlyPumpPower, maxDailyPumpEnergy); } AreaScratchpad::~AreaScratchpad() = default; -bool AreaScratchpad::CheckForPositiveEnergy(const Matrix& matrix, - const Matrix::ColumnType& hours) +void AreaScratchpad::CalculateMeanDailyMaxPowerMatrices(const Matrix& hourlyMaxGenMatrix, + const Matrix& hourlyMaxPumpMatrix, + uint nbOfMaxPowerTimeSeries) { - double value = 0.; + for (uint nbOfTimeSeries = 0; nbOfTimeSeries < nbOfMaxPowerTimeSeries; ++nbOfTimeSeries) + { + auto& hourlyMaxGenColumn = hourlyMaxGenMatrix[nbOfTimeSeries]; + auto& hourlyMaxPumpColumn = hourlyMaxPumpMatrix[nbOfTimeSeries]; + auto& MeanMaxDailyGenPowerColumn = meanMaxDailyGenPower[nbOfTimeSeries]; + auto& MeanMaxDailyPumpPowerColumn = meanMaxDailyPumpPower[nbOfTimeSeries]; + + CalculateDailyMeanPower(hourlyMaxGenColumn, MeanMaxDailyGenPowerColumn); + CalculateDailyMeanPower(hourlyMaxPumpColumn, MeanMaxDailyPumpPowerColumn); + } +} - for (uint width = 0; width < matrix.width; ++width) +bool CheckForPositiveEnergy(const Matrix& power, + const Matrix::ColumnType& energy) +{ + for (uint tsNumber = 0; tsNumber < power.width; ++tsNumber) { - for (uint d = 0; d < DAYS_PER_YEAR; ++d) + double yearlyMaxGenEnergy = 0; + + for (uint day = 0; day < DAYS_PER_YEAR; ++day) { - value += CalculateDailyMeanPower(d, matrix[width]) * hours[d]; + yearlyMaxGenEnergy += power[tsNumber][day] * energy[day]; - if (value > 0.) + if (yearlyMaxGenEnergy > 0.) return true; } - - value = 0.; } return false; } -double CalculateDailyMeanPower(uint dYear, const Matrix::ColumnType& maxPower) +void CalculateDailyMeanPower(const Matrix::ColumnType& hourlyColumn, + Matrix::ColumnType& dailyColumn) { - return std::accumulate(maxPower + dYear * 24, maxPower + dYear * 24 + 24, 0) / 24.; + for (uint day = 0; day < DAYS_PER_YEAR; ++day) + { + dailyColumn[day] = std::accumulate(hourlyColumn + day * HOURS_PER_DAY, + hourlyColumn + day * HOURS_PER_DAY + HOURS_PER_DAY, + 0) + / 24.; + } } -} // namespace Data -} // namespace Antares +} // namespace Antares::Data diff --git a/src/libs/antares/study/area/scratchpad.h b/src/libs/antares/study/area/scratchpad.h index 0fd3c946d8..f019ad7c75 100644 --- a/src/libs/antares/study/area/scratchpad.h +++ b/src/libs/antares/study/area/scratchpad.h @@ -36,9 +36,7 @@ #include #include -namespace Antares -{ -namespace Data +namespace Antares::Data { /*! ** \brief Scratchpad for temporary data performed by the solver @@ -99,14 +97,36 @@ class AreaScratchpad final */ double dispatchableGenerationMargin[168]; + /*! + ** \brief Daily mean maximum power matrices + ** + ** These matrices will be calculated based on maximum + ** hourly generation/pumping matrices + */ + Matrix meanMaxDailyGenPower; + Matrix meanMaxDailyPumpPower; + private: - bool CheckForPositiveEnergy(const Matrix& matrix, - const Matrix::ColumnType& hours); + /*! + ** \brief Caluclation of daily mean maximum power matrices + ** + ** Calculates daily mean maximum generation/pumping power + ** power matrices meanMaxDailyGenPower/meanMaxDailyPumpPower + */ + void CalculateMeanDailyMaxPowerMatrices(const Matrix& hourlyMaxGenMatrix, + const Matrix& hourlyMaxPumpMatrix, + uint nbOfMaxPowerTimeSeries); + }; // class AreaScratchpad -double CalculateDailyMeanPower(uint dYear, const Matrix::ColumnType& maxPower); +// Calculates daily mean maximum generation/pumping power for one column/time-serie +void CalculateDailyMeanPower(const Matrix::ColumnType& hourlyColumn, + Matrix::ColumnType& dailyColumn); + +// Return true if maximum generated energy just in one day and for every TS is grated than 0 +bool CheckForPositiveEnergy(const Matrix& power, + const Matrix::ColumnType& energy); -} // namespace Data -} // namespace Antares +} // namespace Antares::Data #endif // __ANTARES_LIBS_STUDY_AREA_SCRATCHPAD_H__ diff --git a/src/libs/antares/study/area/store-timeseries-numbers.cpp b/src/libs/antares/study/area/store-timeseries-numbers.cpp index 83cd1d3f9a..b453fb4fc2 100644 --- a/src/libs/antares/study/area/store-timeseries-numbers.cpp +++ b/src/libs/antares/study/area/store-timeseries-numbers.cpp @@ -48,7 +48,7 @@ struct TSNumbersPredicate }; } // anonymous namespace -static void genericStoreTimeseriesNumbers(Solver::IResultWriter::Ptr writer, +static void storeTSnumbers(Solver::IResultWriter::Ptr writer, const Matrix& timeseriesNumbers, const String& id, const String& directory) @@ -69,28 +69,28 @@ static void genericStoreTimeseriesNumbers(Solver::IResultWriter::Ptr writer, void storeTimeseriesNumbersForLoad(Solver::IResultWriter::Ptr writer, const Area& area) { - genericStoreTimeseriesNumbers(writer, area.load.series->timeseriesNumbers, area.id, "load"); + storeTSnumbers(writer, area.load.series->timeseriesNumbers, area.id, "load"); } void storeTimeseriesNumbersForSolar(Solver::IResultWriter::Ptr writer, const Area& area) { - genericStoreTimeseriesNumbers(writer, area.solar.series->timeseriesNumbers, area.id, "solar"); + storeTSnumbers(writer, area.solar.series->timeseriesNumbers, area.id, "solar"); } void storeTimeseriesNumbersForHydro(Solver::IResultWriter::Ptr writer, const Area& area) { - genericStoreTimeseriesNumbers(writer, area.hydro.series->timeseriesNumbers, area.id, "hydro"); + storeTSnumbers(writer, area.hydro.series->timeseriesNumbers, area.id, "hydro"); } -void storeTimeseriesNumbersForHydroPowerCredits(Solver::IResultWriter::Ptr writer, const Area& area) +void storeTimeseriesNumbersForHydroMaxPower(Solver::IResultWriter::Ptr writer, const Area& area) { - genericStoreTimeseriesNumbers(writer, area.hydro.series->timeseriesNumbersPowerCredits, area.id, "power-credits"); + storeTSnumbers(writer, area.hydro.series->timeseriesNumbersHydroMaxPower, area.id, "max-power"); } void storeTimeseriesNumbersForWind(Solver::IResultWriter::Ptr writer, const Area& area) { - genericStoreTimeseriesNumbers(writer, area.wind.series->timeseriesNumbers, area.id, "wind"); + storeTSnumbers(writer, area.wind.series->timeseriesNumbers, area.id, "wind"); } void storeTimeseriesNumbersForThermal(Solver::IResultWriter::Ptr writer, const Area& area) diff --git a/src/libs/antares/study/area/store-timeseries-numbers.h b/src/libs/antares/study/area/store-timeseries-numbers.h index baca1094c9..c5a0d2cb7e 100644 --- a/src/libs/antares/study/area/store-timeseries-numbers.h +++ b/src/libs/antares/study/area/store-timeseries-numbers.h @@ -46,7 +46,7 @@ namespace Antares::Data void storeTimeseriesNumbersForThermal(Solver::IResultWriter::Ptr writer, const Area& area); void storeTimeseriesNumbersForRenewable(Solver::IResultWriter::Ptr writer, const Area& area); void storeTimeseriesNumbersForTransmissionCapacities(Solver::IResultWriter::Ptr writer, const Area& area); - void storeTimeseriesNumbersForHydroPowerCredits(Solver::IResultWriter::Ptr writer, const Area& area); + void storeTimeseriesNumbersForHydroMaxPower(Solver::IResultWriter::Ptr writer, const Area& area); } //Antares::Data diff --git a/src/libs/antares/study/area/store-timeseries-numbers.hxx b/src/libs/antares/study/area/store-timeseries-numbers.hxx index 5bb4454a1f..ea183242f9 100644 --- a/src/libs/antares/study/area/store-timeseries-numbers.hxx +++ b/src/libs/antares/study/area/store-timeseries-numbers.hxx @@ -62,8 +62,8 @@ void singleAreaStoreTimeseriesNumbers(Solver::IResultWriter::Ptr writer, const A case timeSeriesTransmissionCapacities: storeTimeseriesNumbersForTransmissionCapacities(writer, area); break; - case timeSeriesHydroPowerCredits: - storeTimeseriesNumbersForHydroPowerCredits(writer, area); + case timeSeriesHydroMaxPower: + storeTimeseriesNumbersForHydroMaxPower(writer, area); break; case timeSeriesCount: default: diff --git a/src/libs/antares/study/cleaner/cleaner-v20.cpp b/src/libs/antares/study/cleaner/cleaner-v20.cpp index 6b7a5ffc85..240d38aba3 100644 --- a/src/libs/antares/study/cleaner/cleaner-v20.cpp +++ b/src/libs/antares/study/cleaner/cleaner-v20.cpp @@ -87,11 +87,9 @@ static void listOfFilesAnDirectoriesToKeepForArea(PathList& e, PathList& p, cons e.add(buffer); buffer.clear() << "input/hydro/common/capacity/inflowPattern_" << id << ".txt"; e.add(buffer); - buffer.clear() << "input/hydro/common/capacity/maxpower_" << id << ".txt"; + buffer.clear() << "input/hydro/common/capacity/maxDailyGenEnergy_" << id << ".txt"; e.add(buffer); - buffer.clear() << "input/hydro/common/capacity/maxhoursGen_" << id << ".txt"; - e.add(buffer); - buffer.clear() << "input/hydro/common/capacity/maxhoursPump_" << id << ".txt"; + buffer.clear() << "input/hydro/common/capacity/maxDailyPumpEnergy_" << id << ".txt"; e.add(buffer); buffer.clear() << "input/hydro/common/capacity/reservoir_" << id << ".txt"; e.add(buffer); @@ -103,9 +101,9 @@ static void listOfFilesAnDirectoriesToKeepForArea(PathList& e, PathList& p, cons e.add(buffer); buffer.clear() << "input/hydro/series/" << id << "/mingen.txt"; e.add(buffer); - buffer.clear() << "input/hydro/series/" << id << "/maxgen.txt"; + buffer.clear() << "input/hydro/series/" << id << "/maxHourlyGenPower.txt"; e.add(buffer); - buffer.clear() << "input/hydro/series/" << id << "/maxpump.txt"; + buffer.clear() << "input/hydro/series/" << id << "/maxHourlyPumpPower.txt"; e.add(buffer); buffer.clear() << "input/hydro/allocation/" << id << ".ini"; p.add(buffer); diff --git a/src/libs/antares/study/fwd.h b/src/libs/antares/study/fwd.h index 85a08863a1..9afca30e8a 100644 --- a/src/libs/antares/study/fwd.h +++ b/src/libs/antares/study/fwd.h @@ -221,8 +221,8 @@ enum TimeSeries : unsigned int timeSeriesRenewable = 32, //! TimeSeries : Renewable timeSeriesTransmissionCapacities = 64, - //! TimeSeries : Hydro Power Credits - timeSeriesHydroPowerCredits = 256, + //! TimeSeries : Hydro Max Power + timeSeriesHydroMaxPower = 256, //! The maximum number of time-series that we can encounter timeSeriesCount = 8, diff --git a/src/libs/antares/study/parameters.cpp b/src/libs/antares/study/parameters.cpp index 7f5994db78..c255129b3a 100644 --- a/src/libs/antares/study/parameters.cpp +++ b/src/libs/antares/study/parameters.cpp @@ -74,8 +74,8 @@ static bool ConvertCStrToListTimeSeries(const String& value, uint& v) v |= timeSeriesRenewable; else if (word == "ntc") v |= timeSeriesTransmissionCapacities; - else if (word == "power-credits") - v |= timeSeriesHydroPowerCredits; + else if (word == "max-power") + v |= timeSeriesHydroMaxPower; return true; }); return true; @@ -394,11 +394,11 @@ static void ParametersSaveTimeSeries(IniFile::Section* s, const char* name, uint v += ", "; v += "ntc"; } - if (value & timeSeriesHydroPowerCredits) + if (value & timeSeriesHydroMaxPower) { if (!v.empty()) v += ", "; - v += "power-credits"; + v += "max-power"; } s->add(name, v); } @@ -1081,7 +1081,7 @@ bool Parameters::loadFromINI(const IniFile& ini, uint version, const StudyLoadOp fixGenRefreshForNTC(); - fixGenRefreshForHydroPowerCredits(); + fixGenRefreshForHydroMaxPower(); // Specific action before launching a simulation if (options.usedByTheSolver) @@ -1141,18 +1141,18 @@ void Parameters::fixGenRefreshForNTC() } } -void Parameters::fixGenRefreshForHydroPowerCredits() +void Parameters::fixGenRefreshForHydroMaxPower() { - if ((timeSeriesHydroPowerCredits & timeSeriesToGenerate) != 0) + if ((timeSeriesHydroMaxPower & timeSeriesToGenerate) != 0) { - timeSeriesToGenerate &= ~timeSeriesHydroPowerCredits; - logs.error() << "Time-series generation is not available for hydro power credits. It " + timeSeriesToGenerate &= ~timeSeriesHydroMaxPower; + logs.error() << "Time-series generation is not available for hydro max power. It " "will be automatically disabled."; } - if ((timeSeriesHydroPowerCredits & timeSeriesToRefresh) != 0) + if ((timeSeriesHydroMaxPower & timeSeriesToRefresh) != 0) { - timeSeriesToRefresh &= ~timeSeriesHydroPowerCredits; - logs.error() << "Time-series refresh is not available for hydro power credits. It will " + timeSeriesToRefresh &= ~timeSeriesHydroMaxPower; + logs.error() << "Time-series refresh is not available for hydro max power. It will " "be automatically disabled."; } } @@ -1401,7 +1401,7 @@ void Parameters::prepareForSimulation(const StudyLoadOptions& options) if (interModal == timeSeriesLoad || interModal == timeSeriesSolar || interModal == timeSeriesWind || interModal == timeSeriesHydro - || interModal == timeSeriesThermal || interModal == timeSeriesRenewable || interModal == timeSeriesHydroPowerCredits) + || interModal == timeSeriesThermal || interModal == timeSeriesRenewable || interModal == timeSeriesHydroMaxPower) { // Only one timeseries in interModal correlation, which is the same than nothing interModal = 0; diff --git a/src/libs/antares/study/parameters.h b/src/libs/antares/study/parameters.h index 5dd10917a0..0042f224a0 100644 --- a/src/libs/antares/study/parameters.h +++ b/src/libs/antares/study/parameters.h @@ -161,9 +161,9 @@ class Parameters final /*! ** \brief Try to detect then fix TS generation/refresh parameters - * for Hydro Power Credits + * for Hydro Max Power */ - void fixGenRefreshForHydroPowerCredits(); + void fixGenRefreshForHydroMaxPower(); /*! ** \brief Get the amount of memory used by the general data diff --git a/src/libs/antares/study/parts/hydro/container.cpp b/src/libs/antares/study/parts/hydro/container.cpp index c7705b0ae0..7bb56dc9fa 100644 --- a/src/libs/antares/study/parts/hydro/container.cpp +++ b/src/libs/antares/study/parts/hydro/container.cpp @@ -28,7 +28,7 @@ #include "../../study.h" #include "container.h" #include -#include "datatransfer.h" +#include "hydromaxtimeseriesreader.h" using namespace Antares; using namespace Yuni; @@ -92,10 +92,10 @@ void PartHydro::reset() reservoirLevel.fillColumn(average, 0.5); reservoirLevel.fillColumn(maximum, 1.); waterValues.reset(101, DAYS_PER_YEAR, true); - maxHoursGen.reset(1, DAYS_PER_YEAR, true); - maxHoursGen.fillColumn(0, 24.); - maxHoursPump.reset(1, DAYS_PER_YEAR, true); - maxHoursPump.fillColumn(0, 24.); + maxDailyGenEnergy.reset(1, DAYS_PER_YEAR, true); + maxDailyGenEnergy.fillColumn(0, 24.); + maxDailyPumpEnergy.reset(1, DAYS_PER_YEAR, true); + maxDailyPumpEnergy.fillColumn(0, 24.); creditModulation.reset(101, 2, true); creditModulation.fill(1); // reset of the hydro allocation - however we don't have any information @@ -116,161 +116,121 @@ bool PartHydro::LoadFromFolder(Study& study, const AnyString& folder) bool ret = true; // Initialize all alpha values to 0 - study.areas.each([&](Data::Area& area) { - area.hydro.interDailyBreakdown = 1.; - area.hydro.intraDailyModulation = 24.; - area.hydro.intermonthlyBreakdown = 1.; - area.hydro.reservoirManagement = false; - area.hydro.followLoadModulations = true; - area.hydro.useWaterValue = false; - area.hydro.hardBoundsOnRuleCurves = false; - area.hydro.useHeuristicTarget = true; - area.hydro.useLeeway = false; - area.hydro.powerToLevel = false; - area.hydro.leewayLowerBound = 1.; - area.hydro.leewayUpperBound = 1.; - area.hydro.initializeReservoirLevelDate = 0; - area.hydro.reservoirCapacity = 0.; - area.hydro.pumpingEfficiency = 1.; - - if (study.header.version >= 870) - { - // GUI part patch : - // We need to know, when estimating the RAM required by the solver, if the current area - // is hydro modulable. Therefore, reading the area's daily max power at this stage is - // necessary. - - if (!study.usedByTheSolver) - { - bool enabledModeIsChanged = false; - if (JIT::enabled) - { - JIT::enabled = false; // Allowing to read the area's daily max power - enabledModeIsChanged = true; - } - - ret = area.hydro.LoadHours(study, area, folder); - - if (enabledModeIsChanged) - JIT::enabled = true; // Back to the previous loading mode. - } - else - { - ret = area.hydro.LoadHours(study, area, folder); - } - } - - if (study.header.version < 870) - { - std::shared_ptr datatransfer = std::make_shared(); - - ret = datatransfer->LoadFromFolder(study, folder, area); - ret = datatransfer->AutoTransferHours(study, folder, area); - } - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP - << "creditmodulations_" << area.id << '.' << study.inputExtension; - ret = area.hydro.creditModulation.loadFromCSVFile( - buffer, 101, 2, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "reservoir_" - << area.id << '.' << study.inputExtension; - ret = area.hydro.reservoirLevel.loadFromCSVFile( - buffer, 3, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP - << "waterValues_" << area.id << '.' << study.inputExtension; - ret = area.hydro.waterValues.loadFromCSVFile( - buffer, 101, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP - << "inflowPattern_" << area.id << '.' << study.inputExtension; - ret = area.hydro.inflowPattern.loadFromCSVFile( - buffer, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - if (study.usedByTheSolver) - { - auto& col = area.hydro.inflowPattern[0]; - bool errorInflow = false; - for (int day = 0; day < DAYS_PER_YEAR; day++) - { - if (col[day] < 0 && !errorInflow) - { - logs.error() << area.name << ": invalid inflow value"; - errorInflow = true; - ret = false; - } - } - bool errorLevels = false; - auto& colMin = area.hydro.reservoirLevel[minimum]; - auto& colAvg = area.hydro.reservoirLevel[average]; - auto& colMax = area.hydro.reservoirLevel[maximum]; - for (int day = 0; day < DAYS_PER_YEAR; day++) - { - if (!errorLevels - && (colMin[day] < 0 || colAvg[day] < 0 || colMin[day] > colMax[day] - || colAvg[day] > 100 || colMax[day] > 100)) - { - logs.error() << area.name << ": invalid reservoir level value"; - errorLevels = true; - ret = false; - } - } - - bool errorHours = false; - auto& colGen = area.hydro.maxHoursGen[0]; - auto& colPump = area.hydro.maxHoursPump[0]; - - for (int day = 0; day < DAYS_PER_YEAR; day++) - { - if (!errorHours && (colGen[day] < 0 || (colGen[day] > 24))) - { - logs.error() << area.name << ": invalid power or energy value"; - errorHours = true; - ret = false; - } - - if (!errorHours && (colPump[day] < 0 || (colPump[day] > 24))) - { - logs.error() << area.name << ": invalid power or energy value"; - errorHours = true; - ret = false; - } - } - - for (int i = 0; i < 101; i++) - { - if ((area.hydro.creditModulation[i][0] < 0) - || (area.hydro.creditModulation[i][1] < 0)) - { - logs.error() << area.name << ": invalid credit modulation value"; - ret = false; - } - } - } - else - { - /* - Maxgen matrix is not initialized at this moment, so this code will induce - Segmentation fault (core dumped) because maxgen matrix pointing to invalid memory - address. This code block is moved to series.cpp file for hydro. - - Is area hydro modulable ? - - auto& max = area.hydro.series->maxgen; - - if (MatrixTestForAtLeastOnePositiveValue(max)) - { - area.hydro.hydroModulable = true; - } - */ - } - }); + study.areas.each( + [&](Data::Area& area) + { + area.hydro.interDailyBreakdown = 1.; + area.hydro.intraDailyModulation = 24.; + area.hydro.intermonthlyBreakdown = 1.; + area.hydro.reservoirManagement = false; + area.hydro.followLoadModulations = true; + area.hydro.useWaterValue = false; + area.hydro.hardBoundsOnRuleCurves = false; + area.hydro.useHeuristicTarget = true; + area.hydro.useLeeway = false; + area.hydro.powerToLevel = false; + area.hydro.leewayLowerBound = 1.; + area.hydro.leewayUpperBound = 1.; + area.hydro.initializeReservoirLevelDate = 0; + area.hydro.reservoirCapacity = 0.; + area.hydro.pumpingEfficiency = 1.; + + if (study.header.version >= 870) + { + // GUI part patch : + // We need to know, when estimating the RAM required by the solver, if the current + // area is hydro modulable. Therefore, reading the area's daily max power at this + // stage is necessary. + + if (!study.usedByTheSolver) + { + bool enabledModeIsChanged = false; + if (JIT::enabled) + { + JIT::enabled = false; // Allowing to read the area's daily max power + enabledModeIsChanged = true; + } + + ret = area.hydro.LoadDailyMaxEnergy(folder, area.id) && ret; + + if (enabledModeIsChanged) + JIT::enabled = true; // Back to the previous loading mode. + } + else + { + ret = area.hydro.LoadDailyMaxEnergy(folder, area.id) && ret; + + // Check is moved here, because in case of old study + // maxDailyGenEnergy and maxDailyPumpEnergy are not yet initialized. + + ret = area.hydro.CheckDailyMaxEnergy(area.name) && ret; + } + } + + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP + << "creditmodulations_" << area.id << '.' << study.inputExtension; + ret = area.hydro.creditModulation.loadFromCSVFile( + buffer, 101, 2, Matrix<>::optFixedSize, &study.dataBuffer) + && ret; + + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "reservoir_" + << area.id << '.' << study.inputExtension; + ret = area.hydro.reservoirLevel.loadFromCSVFile( + buffer, 3, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) + && ret; + + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "waterValues_" + << area.id << '.' << study.inputExtension; + ret = area.hydro.waterValues.loadFromCSVFile( + buffer, 101, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) + && ret; + + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP + << "inflowPattern_" << area.id << '.' << study.inputExtension; + ret = area.hydro.inflowPattern.loadFromCSVFile( + buffer, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) + && ret; + + if (study.usedByTheSolver) + { + auto& col = area.hydro.inflowPattern[0]; + bool errorInflow = false; + for (int day = 0; day < DAYS_PER_YEAR; day++) + { + if (col[day] < 0 && !errorInflow) + { + logs.error() << area.name << ": invalid inflow value"; + errorInflow = true; + ret = false; + } + } + bool errorLevels = false; + auto& colMin = area.hydro.reservoirLevel[minimum]; + auto& colAvg = area.hydro.reservoirLevel[average]; + auto& colMax = area.hydro.reservoirLevel[maximum]; + for (int day = 0; day < DAYS_PER_YEAR; day++) + { + if (!errorLevels + && (colMin[day] < 0 || colAvg[day] < 0 || colMin[day] > colMax[day] + || colAvg[day] > 100 || colMax[day] > 100)) + { + logs.error() << area.name << ": invalid reservoir level value"; + errorLevels = true; + ret = false; + } + } + + for (int i = 0; i < 101; i++) + { + if ((area.hydro.creditModulation[i][0] < 0) + || (area.hydro.creditModulation[i][1] < 0)) + { + logs.error() << area.name << ": invalid credit modulation value"; + ret = false; + } + } + } + }); IniFile ini; if (not ini.open(buffer.clear() << folder << SEP << "hydro.ini")) @@ -707,13 +667,13 @@ bool PartHydro::SaveToFolder(const AreaList& areas, const AnyString& folder) sPowerToLevel->add(area.id, true); // max hours gen - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursGen_" + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxDailyGenEnergy_" << area.id << ".txt"; - ret = area.hydro.maxHoursGen.saveToCSVFile(buffer, /*decimal*/ 2) && ret; + ret = area.hydro.maxDailyGenEnergy.saveToCSVFile(buffer, /*decimal*/ 2) && ret; // max hours pump - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursPump_" + buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxDailyPumpEnergy_" << area.id << ".txt"; - ret = area.hydro.maxHoursPump.saveToCSVFile(buffer, /*decimal*/ 2) && ret; + ret = area.hydro.maxDailyPumpEnergy.saveToCSVFile(buffer, /*decimal*/ 2) && ret; // credit modulations buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "creditmodulations_" << area.id << ".txt"; @@ -743,8 +703,8 @@ bool PartHydro::forceReload(bool reload) const ret = inflowPattern.forceReload(reload) && ret; ret = reservoirLevel.forceReload(reload) && ret; ret = waterValues.forceReload(reload) && ret; - ret = maxHoursGen.forceReload(reload) && ret; - ret = maxHoursPump.forceReload(reload) && ret; + ret = maxDailyGenEnergy.forceReload(reload) && ret; + ret = maxDailyPumpEnergy.forceReload(reload) && ret; if (series) ret = series->forceReload(reload) && ret; @@ -760,8 +720,8 @@ void PartHydro::markAsModified() const reservoirLevel.markAsModified(); waterValues.markAsModified(); creditModulation.markAsModified(); - maxHoursGen.markAsModified(); - maxHoursPump.markAsModified(); + maxDailyGenEnergy.markAsModified(); + maxDailyPumpEnergy.markAsModified(); if (series) series->markAsModified(); @@ -814,43 +774,71 @@ void PartHydro::copyFrom(const PartHydro& rhs) pumpingEfficiency = rhs.pumpingEfficiency; } - // max hours gen + // max daily gen { - maxHoursGen = rhs.maxHoursGen; - maxHoursGen.unloadFromMemory(); - rhs.maxHoursGen.unloadFromMemory(); + maxDailyGenEnergy = rhs.maxDailyGenEnergy; + maxDailyGenEnergy.unloadFromMemory(); + rhs.maxDailyGenEnergy.unloadFromMemory(); } - // max hours pump + // max daily pump { - maxHoursPump = rhs.maxHoursPump; - maxHoursPump.unloadFromMemory(); - rhs.maxHoursPump.unloadFromMemory(); + maxDailyPumpEnergy = rhs.maxDailyPumpEnergy; + maxDailyPumpEnergy.unloadFromMemory(); + rhs.maxDailyPumpEnergy.unloadFromMemory(); } } -bool PartHydro::LoadHours(Study& study, Area& area, const AnyString& folder) +bool PartHydro::LoadDailyMaxEnergy(const AnyString& folder, const AnyString& areaid) { - auto& buffer = study.bufferLoadingTS; + YString filePath; + Matrix<>::BufferType fileContent; bool ret = true; - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursGen_" - << area.id << '.' << study.inputExtension; + filePath.clear() << folder << SEP << "common" << SEP << "capacity" << SEP + << "maxDailyGenEnergy_" << areaid << ".txt"; - ret = area.hydro.maxHoursGen.loadFromCSVFile( - buffer, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) + ret = maxDailyGenEnergy.loadFromCSVFile( + filePath, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &fileContent) && ret; - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursPump_" - << area.id << '.' << study.inputExtension; + filePath.clear() << folder << SEP << "common" << SEP << "capacity" << SEP + << "maxDailyPumpEnergy_" << areaid << ".txt"; - ret = area.hydro.maxHoursPump.loadFromCSVFile( - buffer, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) + ret = maxDailyPumpEnergy.loadFromCSVFile( + filePath, 1, DAYS_PER_YEAR, Matrix<>::optFixedSize, &fileContent) && ret; return ret; } +bool PartHydro::CheckDailyMaxEnergy(const AnyString& areaName) +{ + bool ret = true; + bool errorEnergy = false; + auto& colGen = maxDailyGenEnergy[0]; + auto& colPump = maxDailyPumpEnergy[0]; + + for (int day = 0; day < DAYS_PER_YEAR; day++) + { + if (!errorEnergy && (colGen[day] < 0 || (colGen[day] > 24))) + { + logs.error() << areaName << ": invalid maximum generation energy value"; + errorEnergy = true; + ret = false; + } + + if (!errorEnergy && (colPump[day] < 0 || (colPump[day] > 24))) + { + logs.error() << areaName << ": invalid maximum pumping energy value"; + errorEnergy = true; + ret = false; + } + } + + return ret; +} + void getWaterValue(const double& level /* format : in % of reservoir capacity */, const Matrix& waterValues, const uint day, diff --git a/src/libs/antares/study/parts/hydro/container.h b/src/libs/antares/study/parts/hydro/container.h index 9c193cea09..26171655e3 100644 --- a/src/libs/antares/study/parts/hydro/container.h +++ b/src/libs/antares/study/parts/hydro/container.h @@ -100,9 +100,11 @@ class PartHydro void markAsModified() const; /*! - ** \brief Load hours data + ** \brief Load daily max energy */ - bool LoadHours(Study& study, Area& area, const AnyString& folder); + bool LoadDailyMaxEnergy(const AnyString& folder, const AnyString& areaid); + + bool CheckDailyMaxEnergy(const AnyString& areaName); public: //! Inter-daily breakdown (previously called Smoothing Factor or alpha) @@ -162,8 +164,8 @@ class PartHydro //! Data for time-series DataSeriesHydro* series; - Matrix maxHoursGen; - Matrix maxHoursPump; + Matrix maxDailyGenEnergy; + Matrix maxDailyPumpEnergy; }; // class PartHydro diff --git a/src/libs/antares/study/parts/hydro/datatransfer.cpp b/src/libs/antares/study/parts/hydro/datatransfer.cpp deleted file mode 100644 index 9fac54de84..0000000000 --- a/src/libs/antares/study/parts/hydro/datatransfer.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -** 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 -*/ - -#include "../../study.h" -#include "datatransfer.h" -#include - -using namespace Yuni; - -#define SEP IO::Separator - -namespace Antares::Data -{ - -DataTransfer::DataTransfer() -{ - maxPower.reset(4, DAYS_PER_YEAR, true); -} - -bool DataTransfer::LoadFromFolder(Study& study, const AnyString& folder, Area& area) -{ - auto& buffer = study.bufferLoadingTS; - bool ret = true; - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxpower_" - << area.id << '.' << study.inputExtension; - - // GUI part patch : - // We need to know, when estimating the RAM required by the solver, if the current area - // is hydro modulable. Therefore, reading the area's daily max power at this stage is - // necessary. - - if (!study.usedByTheSolver) - { - bool enabledModeIsChanged = false; - if (JIT::enabled) - { - JIT::enabled = false; // Allowing to read the area's daily max power - enabledModeIsChanged = true; - } - - ret = maxPower.loadFromCSVFile( - buffer, 4, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - if (enabledModeIsChanged) - JIT::enabled = true; // Back to the previous loading mode. - } - else - { - ret = maxPower.loadFromCSVFile( - buffer, 4, DAYS_PER_YEAR, Matrix<>::optFixedSize, &study.dataBuffer) - && ret; - - bool errorPowers = false; - for (uint i = 0; i < 4; ++i) - { - auto& col = maxPower[i]; - for (uint day = 0; day < DAYS_PER_YEAR; ++day) - { - if (!errorPowers && (col[day] < 0 || (i % 2 /*column hours*/ && col[day] > 24))) - { - logs.error() << area.name << ": invalid power or energy value"; - errorPowers = true; - ret = false; - } - } - } - } - - return ret; -} - -bool DataTransfer::AutoTransferHours(Study& study, const AnyString& folder, Area& area) -{ - auto& buffer = study.bufferLoadingTS; - bool ret = true; - - auto& maxHoursGen = area.hydro.maxHoursGen; - auto& maxHoursPump = area.hydro.maxHoursPump; - - maxHoursGen.reset(1, DAYS_PER_YEAR, true); - maxHoursGen.fillColumn(0, 24.); - - maxHoursPump.reset(1, DAYS_PER_YEAR, true); - maxHoursPump.fillColumn(0, 24.); - - for (uint day = 0; day < DAYS_PER_YEAR; ++day) - { - maxHoursGen[0][day] = maxPower[genMaxE][day]; - maxHoursPump[0][day] = maxPower[pumpMaxE][day]; - } - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursGen_" - << area.id << ".txt"; - ret = maxHoursGen.saveToCSVFile(buffer, /*decimal*/ 2) && ret; - - buffer.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxhoursPump_" - << area.id << ".txt"; - ret = maxHoursPump.saveToCSVFile(buffer, /*decimal*/ 2) && ret; - - return ret; -} - -bool DataTransfer::SupportForOldStudies(Study& study, const AnyString& folder, Area& area) -{ - bool ret = true; - auto& buffer = study.bufferLoadingTS; - auto& maxgen = area.hydro.series->maxgen; - auto& maxpump = area.hydro.series->maxpump; - - auto& MaxPowerGen = maxPower[genMaxP]; - auto& MaxPowerPump = maxPower[pumpMaxP]; - - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); - - AutoTransferPower(maxgen, MaxPowerGen); - AutoTransferPower(maxpump, MaxPowerPump); - - buffer.clear() << folder << SEP << "series" << SEP << area.id << SEP << "maxgen." << study.inputExtension; - ret = maxgen.saveToCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; - - buffer.clear() << folder << SEP << "series" << SEP << area.id << SEP << "maxpump." << study.inputExtension; - ret = maxpump.saveToCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; - - return ret; -} - -void DataTransfer::AutoTransferPower(Matrix& matrix, - const Matrix::ColumnType& maxP) -{ - uint hours = 0; - uint days = 0; - - while (hours < HOURS_PER_YEAR && days < DAYS_PER_YEAR) - { - for (uint i = 0; i < 24; ++i) - { - matrix[0][hours] = maxP[days]; - ++hours; - } - ++days; - } -} - -} // namespace Antares::Data \ No newline at end of file diff --git a/src/libs/antares/study/parts/hydro/datatransfer.h b/src/libs/antares/study/parts/hydro/datatransfer.h deleted file mode 100644 index e2e2307305..0000000000 --- a/src/libs/antares/study/parts/hydro/datatransfer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -** 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 __ANTARES_LIBS_STUDY_PARTS_HYDRO_DATA_TRANSFER_H__ -#define __ANTARES_LIBS_STUDY_PARTS_HYDRO_DATA_TRANSFER_H__ - -#include "../../../array/antares//array/matrix.h" - -namespace Antares::Data -{ -/*! -** \brief Hydro for a single area -*/ -class DataTransfer -{ - -public: - - DataTransfer(); - - enum powerDailyE - { - //! Generated max power - genMaxP = 0, - //! Generated max energy - genMaxE, - //! Pumping max Power - pumpMaxP, - // Pumping max Energy - pumpMaxE, - }; - - Matrix maxPower; - - bool LoadFromFolder(Study& study, const AnyString& folder, Area& area); - bool AutoTransferHours(Study& study, const AnyString& folder, Area& area); - void AutoTransferPower(Matrix& matrix, - const Matrix::ColumnType& maxPower); - bool SupportForOldStudies(Study& study, const AnyString& folder, Area& area); - - -}; - -} // Antares::Data - -#endif /*__ANTARES_LIBS_STUDY_PARTS_HYDRO_DATA_TRANSFER_H__*/ \ No newline at end of file diff --git a/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp new file mode 100644 index 0000000000..ab2c60f6ae --- /dev/null +++ b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp @@ -0,0 +1,136 @@ +/* +** 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 +*/ + +#include "../../study.h" +#include "hydromaxtimeseriesreader.h" +#include + +using namespace Yuni; + +#define SEP IO::Separator + +namespace Antares::Data +{ + +HydroMaxTimeSeriesReader::HydroMaxTimeSeriesReader() +{ + dailyMaxPumpAndGen.reset(4U, DAYS_PER_YEAR, true); +} + +bool HydroMaxTimeSeriesReader::loadDailyMaxPowersAndEnergies(const AnyString& folder, + const Area& area, + bool usedBySolver) +{ + YString filePath; + Matrix<>::BufferType fileContent; + bool ret = true; + + filePath.clear() << folder << SEP << "common" << SEP << "capacity" << SEP << "maxpower_" + << area.id << ".txt"; + + // It is necessary to load maxpower_ txt file, whether loading is called from old GUI + // or from solver. + + if (!usedBySolver) + { + bool enabledModeIsChanged = false; + + if (JIT::enabled) + { + JIT::enabled = false; // Allowing to read the area's daily max power and energy + enabledModeIsChanged = true; + } + + ret = dailyMaxPumpAndGen.loadFromCSVFile( + filePath, 4U, DAYS_PER_YEAR, Matrix<>::optFixedSize, &fileContent) + && ret; + + if (enabledModeIsChanged) + JIT::enabled = true; // Back to the previous loading mode. + } + else + { + ret = dailyMaxPumpAndGen.loadFromCSVFile( + filePath, 4U, DAYS_PER_YEAR, Matrix<>::optFixedSize, &fileContent) + && ret; + + bool errorPowers = false; + for (uint i = 0; i < 4U; ++i) + { + auto& col = dailyMaxPumpAndGen[i]; + for (uint day = 0; day < DAYS_PER_YEAR; ++day) + { + if (!errorPowers && (col[day] < 0. || (i % 2U /*column hours*/ && col[day] > 24.))) + { + logs.error() << area.name << ": invalid power or energy value"; + errorPowers = true; + ret = false; + } + } + } + } + return ret; +} + +void HydroMaxTimeSeriesReader::copyDailyMaxEnergy(Area& area) const +{ + copyDailyMaxGenerationEnergy(area); + copyDailyMaxPumpingEnergy(area); +} + +void HydroMaxTimeSeriesReader::copyDailyMaxGenerationEnergy(Area& area) const +{ + auto& maxDailyGenEnergy = area.hydro.maxDailyGenEnergy; + const auto& dailyMaxGenE = dailyMaxPumpAndGen[genMaxE]; + + maxDailyGenEnergy.reset(1U, DAYS_PER_YEAR, true); + + maxDailyGenEnergy.pasteToColumn(0, dailyMaxGenE); +} + +void HydroMaxTimeSeriesReader::copyDailyMaxPumpingEnergy(Area& area) const +{ + auto& maxDailyPumpEnergy = area.hydro.maxDailyPumpEnergy; + const auto& dailyMaxPumpE = dailyMaxPumpAndGen[pumpMaxE]; + + maxDailyPumpEnergy.reset(1U, DAYS_PER_YEAR, true); + + maxDailyPumpEnergy.pasteToColumn(0, dailyMaxPumpE); +} + +bool HydroMaxTimeSeriesReader::operator()(const AnyString& folder, Area& area, bool usedBySolver) +{ + bool ret = true; + + ret = loadDailyMaxPowersAndEnergies(folder, area, usedBySolver) && ret; + copyDailyMaxEnergy(area); + area.hydro.series->buildMaxPowerFromDailyTS(dailyMaxPumpAndGen[genMaxP], dailyMaxPumpAndGen[pumpMaxP]); + + return ret; +} + +} // namespace Antares::Data \ No newline at end of file diff --git a/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.h b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.h new file mode 100644 index 0000000000..fefb4ef239 --- /dev/null +++ b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.h @@ -0,0 +1,83 @@ +/* +** 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 __ANTARES_LIBS_STUDY_PARTS_HYDRO_MAX_TIME_SERIES_READER_H__ +#define __ANTARES_LIBS_STUDY_PARTS_HYDRO_MAX_TIME_SERIES_READER_H__ + +#include "../../../array/antares//array/matrix.h" + +namespace Antares::Data +{ +/*! +** This class provides support for old studies, reading from deprecated files, +** fils matrix dailyMaxPumpAndGen and transfers data to the corresponding data +** class members of class PartHydro. Just versions below 8.7 will use instance +** of this class to be compatible with current implementation. +*/ +class HydroMaxTimeSeriesReader +{ +public: + HydroMaxTimeSeriesReader(); + + bool operator()(const AnyString& folder, Area& area, bool usedBySolver); + + Matrix dailyMaxPumpAndGen; + + enum powerDailyE + { + //! Generated max power + genMaxP = 0, + //! Generated max energy + genMaxE, + //! Pumping max Power + pumpMaxP, + // Pumping max Energy + pumpMaxE, + }; + +private: + /** + * \brief Loading deprecated files + * This function provides reading from deprecated files which + * contains daily maximum generation/pumping power and energy data. + */ + bool loadDailyMaxPowersAndEnergies(const AnyString& folder, + const Area& area, + bool usedBySolver); + + /** + * \brief Copy energy functions + * These functions provides coping of energy data loaded + * from deprecated file. + */ + void copyDailyMaxEnergy(Area& area) const; + void copyDailyMaxGenerationEnergy(Area& area) const; + void copyDailyMaxPumpingEnergy(Area& area) const; +}; +} // namespace Antares::Data + +#endif /*__ANTARES_LIBS_STUDY_PARTS_HYDRO_MAX_TIME_SERIES_READER_H__*/ \ No newline at end of file diff --git a/src/libs/antares/study/parts/hydro/pair-of-integers.cpp b/src/libs/antares/study/parts/hydro/pair-of-integers.cpp new file mode 100644 index 0000000000..1332469837 --- /dev/null +++ b/src/libs/antares/study/parts/hydro/pair-of-integers.cpp @@ -0,0 +1,25 @@ +#include "pair-of-integers.h" +#include + + +PairOfIntegers::PairOfIntegers(unsigned int numberOfTS_1, unsigned int numberOfTS_2) + : numberOfTS_1_(numberOfTS_1), numberOfTS_2_(numberOfTS_2) +{ + numberOfTSsup_ = std::max(numberOfTS_1_, numberOfTS_2_); + numberOfTSinf_ = std::min(numberOfTS_1_, numberOfTS_2_); +} + +bool PairOfIntegers::bothZero() const +{ + return numberOfTSsup_ == 0; +} + +bool PairOfIntegers::same() const +{ + return (numberOfTS_1_ == numberOfTS_2_) ? true : false; +} + +bool PairOfIntegers::bothGreaterThanOne() const +{ + return (numberOfTSinf_ > 1); +} \ No newline at end of file diff --git a/src/libs/antares/study/parts/hydro/pair-of-integers.h b/src/libs/antares/study/parts/hydro/pair-of-integers.h new file mode 100644 index 0000000000..3c3ca0e839 --- /dev/null +++ b/src/libs/antares/study/parts/hydro/pair-of-integers.h @@ -0,0 +1,18 @@ +#pragma once + +class PairOfIntegers +{ +public: + PairOfIntegers(unsigned int numberOfTS_1, unsigned int numberOfTS_2); + + bool bothZero() const; + bool same() const; + bool bothGreaterThanOne() const; + unsigned int sup() const { return numberOfTSsup_; } + +private: + unsigned int numberOfTS_1_; + unsigned int numberOfTS_2_; + unsigned int numberOfTSsup_{ 0 }; + unsigned int numberOfTSinf_{ 0 }; +}; diff --git a/src/libs/antares/study/parts/hydro/series.cpp b/src/libs/antares/study/parts/hydro/series.cpp index 219af54df2..c94957f91d 100644 --- a/src/libs/antares/study/parts/hydro/series.cpp +++ b/src/libs/antares/study/parts/hydro/series.cpp @@ -32,6 +32,8 @@ #include #include #include "../../study.h" +#include "pair-of-integers.h" +#include using namespace Yuni; @@ -41,15 +43,78 @@ namespace Antares { namespace Data { -DataSeriesHydro::DataSeriesHydro() : count(0) +DataSeriesHydro::DataSeriesHydro() { // Pmin was introduced in v8.6 // The previous behavior was Pmin=0 - // For compatibility reasons with existing studies, mingen, maxgen and maxpump are set to one + // For compatibility reasons with existing studies, mingen, maxHourlyGenPower and maxHourlyPumpPower are set to one // column of zeros by default mingen.reset(1, HOURS_PER_YEAR); - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); + maxHourlyGenPower.reset(1, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); +} + +unsigned int EqualizeTSsize(Matrix& TScollection1, + Matrix& TScollection2, + bool& fatalError, + const std::string& fatalErrorMsg, + Area& area, + unsigned int height1 = HOURS_PER_YEAR, + unsigned int height2 = HOURS_PER_YEAR) +{ + PairOfIntegers pairOfTSsizes(TScollection1.width, TScollection2.width); + + if (pairOfTSsizes.bothZero()) + { + TScollection1.reset(1, height1); + TScollection2.reset(1, height2); + return 1; + } + + if (pairOfTSsizes.same()) + return pairOfTSsizes.sup(); + + if (pairOfTSsizes.bothGreaterThanOne()) + { + logs.fatal() << fatalErrorMsg; + fatalError = true; + return 0; + } + + // At this point, one TS collection size is > 1 and the other is of size 1. + + // This following instruction to force reloading all area's TS when saving the study (GUI) + area.invalidateJIT = true; + + if (TScollection1.width == 1) + resizeMatrixNoDataLoss(TScollection1, pairOfTSsizes.sup()); + if (TScollection2.width == 1) + resizeMatrixNoDataLoss(TScollection2, pairOfTSsizes.sup()); + + return pairOfTSsizes.sup(); +} + +void DataSeriesHydro::copyGenerationTS(const DataSeriesHydro& source) +{ + ror = source.ror; + storage = source.storage; + mingen = source.mingen; + + generationTScount_ = source.generationTScount_; + + source.ror.unloadFromMemory(); + source.storage.unloadFromMemory(); + source.mingen.unloadFromMemory(); +} +void DataSeriesHydro::copyMaxPowerTS(const DataSeriesHydro& source) +{ + maxHourlyGenPower = source.maxHourlyGenPower; + maxHourlyPumpPower = source.maxHourlyPumpPower; + + maxPowerTScount_ = source.maxPowerTScount_; + + source.maxHourlyGenPower.unloadFromMemory(); + source.maxHourlyPumpPower.unloadFromMemory(); } bool DataSeriesHydro::saveToFolder(const AreaName& areaID, const AnyString& folder) const @@ -68,229 +133,107 @@ bool DataSeriesHydro::saveToFolder(const AreaName& areaID, const AnyString& fold ret = storage.saveToCSVFile(buffer, 0) && ret; buffer.clear() << folder << SEP << areaID << SEP << "mingen.txt"; ret = mingen.saveToCSVFile(buffer, 0) && ret; - buffer.clear() << folder << SEP << areaID << SEP << "maxgen.txt"; - ret = maxgen.saveToCSVFile(buffer, 0) && ret; - buffer.clear() << folder << SEP << areaID << SEP << "maxpump.txt"; - ret = maxpump.saveToCSVFile(buffer, 0) && ret; + buffer.clear() << folder << SEP << areaID << SEP << "maxHourlyGenPower.txt"; + ret = maxHourlyGenPower.saveToCSVFile(buffer, 0) && ret; + buffer.clear() << folder << SEP << areaID << SEP << "maxHourlyPumpPower.txt"; + ret = maxHourlyPumpPower.saveToCSVFile(buffer, 0) && ret; return ret; } return false; } -bool DataSeriesHydro::loadFromFolder(Study& study, const AreaName& areaID, const AnyString& folder) -{ - bool ret = true; - auto& buffer = study.bufferLoadingTS; - - buffer.clear() << folder << SEP << areaID << SEP << "ror." << study.inputExtension; - ret = ror.loadFromCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; +bool loadTSfromFile(Matrix& ts, + const AreaName& areaID, + const AnyString& folder, + const std::string& filename, + unsigned int height) +{ + YString filePath; + Matrix<>::BufferType fileContent; + filePath.clear() << folder << SEP << areaID << SEP << filename; + return ts.loadFromCSVFile(filePath, 1, height, &fileContent); +} - buffer.clear() << folder << SEP << areaID << SEP << "mod." << study.inputExtension; - ret = storage.loadFromCSVFile(buffer, 1, DAYS_PER_YEAR, &study.dataBuffer) && ret; +bool DataSeriesHydro::loadGenerationTS(const AreaName& areaID, const AnyString& folder, unsigned int studyVersion) +{ + timeseriesNumbers.clear(); - // The number of time-series - count = storage.width; + bool ret = loadTSfromFile(ror, areaID, folder, "ror.txt", HOURS_PER_YEAR); + ret = loadTSfromFile(storage, areaID, folder, "mod.txt", DAYS_PER_YEAR) && ret; + if (studyVersion >= 860) + ret = loadTSfromFile(mingen, areaID, folder, "mingen.txt", HOURS_PER_YEAR) && ret; + return ret; +} - if (ror.width > count) - count = ror.width; +void DataSeriesHydro::EqualizeGenerationTSsizes(Area& area, bool usedByTheSolver, bool& fatalError) +{ + if (!usedByTheSolver) // From GUI, no need to equalize TS collections sizes + return; - if (study.header.version >= 860) - { - buffer.clear() << folder << SEP << areaID << SEP << "mingen." << study.inputExtension; - ret = mingen.loadFromCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; - } + // 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."; - if (study.usedByTheSolver) - { - if (0 == count) - { - logs.error() << "Hydro: `" << areaID - << "`: empty matrix detected. Fixing it with default values"; - ror.reset(1, HOURS_PER_YEAR); - storage.reset(1, DAYS_PER_YEAR); - mingen.reset(1, HOURS_PER_YEAR); - } - else - { - if (count > 1 && storage.width != ror.width) - { - if (ror.width != 1 && storage.width != 1) - { - logs.fatal() << "Hydro: `" << areaID - << "`: The matrices ROR (run-of-the-river) and hydro-storage must " - "have the same number of time-series."; - study.gotFatalError = true; - } - else - { - if (ror.width == 1) - { - ror.resizeWithoutDataLost(count, ror.height); - for (uint x = 1; x < count; ++x) - ror.pasteToColumn(x, ror[0]); - } - else - { - if (storage.width == 1) - { - storage.resizeWithoutDataLost(count, storage.height); - for (uint x = 1; x < count; ++x) - storage.pasteToColumn(x, storage[0]); - } - } - Area* areaToInvalidate = study.areas.find(areaID); - if (areaToInvalidate) - { - areaToInvalidate->invalidateJIT = true; - logs.info() - << " '" << areaID << "': The hydro data have been normalized to " - << count << " timeseries"; - } - else - logs.error() - << "Impossible to find the area `" << areaID << "` to invalidate it"; - } - } - checkMinGenTsNumber(study, areaID); - } + generationTScount_ = EqualizeTSsize(ror, storage, fatalError, fatalErrorMsg, area, HOURS_PER_YEAR, DAYS_PER_YEAR); - if (study.parameters.derated) - { - ror.averageTimeseries(); - storage.averageTimeseries(); - mingen.averageTimeseries(); - count = 1; - } - } + logs.info() << " '" << area.id << "': ROR and INFLOWS time series were both set to : " << generationTScount_; - timeseriesNumbers.clear(); + // 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."; - return ret; -} + generationTScount_ = EqualizeTSsize(ror, mingen, fatalError, fatalErrorMsg, area); -void DataSeriesHydro::checkMinGenTsNumber(Study& study, const AreaName& areaID) -{ - if (mingen.width != storage.width) - { - if (mingen.width > 1) - { - logs.fatal() << "Hydro: `" << areaID - << "`: The matrices Minimum Generation must " - "has the same number of time-series as ROR and hydro-storage."; - study.gotFatalError = true; - } - else - { - mingen.resizeWithoutDataLost(count, mingen.height); - for (uint x = 1; x < count; ++x) - mingen.pasteToColumn(x, mingen[0]); - Area* areaToInvalidate = study.areas.find(areaID); - if (areaToInvalidate) - { - areaToInvalidate->invalidateJIT = true; - logs.info() << " '" << areaID - << "': The hydro minimum generation data have been normalized to " - << count << " timeseries"; - } - else - logs.error() << "Impossible to find the area `" << areaID << "` to invalidate it"; - } - } + logs.info() << " '" << area.id << "': ROR and MINGEN time series were both set to : " << generationTScount_; } -bool DataSeriesHydro::LoadHydroPowerCredits(Study& study, const AreaName& areaID, const AnyString& folder) +bool DataSeriesHydro::LoadMaxPower(const AreaName& areaID, const AnyString& folder) { bool ret = true; - auto& buffer = study.bufferLoadingTS; + YString filepath; + Matrix<>::BufferType fileContent; - if (study.header.version >= 870) - { - buffer.clear() << folder << SEP << areaID << SEP << "maxgen." << study.inputExtension; - ret = maxgen.loadFromCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; - buffer.clear() << folder << SEP << areaID << SEP << "maxpump." << study.inputExtension; - ret = maxpump.loadFromCSVFile(buffer, 1, HOURS_PER_YEAR, &study.dataBuffer) && ret; - } + filepath.clear() << folder << SEP << areaID << SEP << "maxHourlyGenPower.txt"; + ret = maxHourlyGenPower.loadFromCSVFile(filepath, 1, HOURS_PER_YEAR, &fileContent) && ret; - countpowercredits = maxgen.width; + filepath.clear() << folder << SEP << areaID << SEP << "maxHourlyPumpPower.txt"; + ret = maxHourlyPumpPower.loadFromCSVFile(filepath, 1, HOURS_PER_YEAR, &fileContent) && ret; - if (maxpump.width > countpowercredits) - countpowercredits = maxpump.width; + timeseriesNumbersHydroMaxPower.clear(); - if (study.usedByTheSolver) - { - if (countpowercredits == 0) - { - logs.error() << "Hydro Power Credits: `" << areaID - << "`: empty matrix detected. Fixing it with default values"; + return ret; +} - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); - } - else - { - if (countpowercredits > 1 && maxgen.width != maxpump.width) - { - if (maxpump.width != 1 && maxgen.width != 1) - { - logs.fatal() << "Hydro Power Credits: `" << areaID - << "`: The matrices Maximum Generation and Maximum Pumping must " - "have the same number of time-series."; - study.gotFatalError = true; - } - else - { - if (maxpump.width == 1) - { - maxpump.resizeWithoutDataLost(countpowercredits, maxpump.height); - for (uint x = 1; x < countpowercredits; ++x) - maxpump.pasteToColumn(x, maxpump[0]); - } - else - { - if (maxgen.width == 1) - { - maxgen.resizeWithoutDataLost(countpowercredits, maxgen.height); - for (uint x = 1; x < countpowercredits; ++x) - maxgen.pasteToColumn(x, maxgen[0]); - } - } - Area* areaToInvalidate = study.areas.find(areaID); - if (areaToInvalidate) - { - areaToInvalidate->invalidateJIT = true; - logs.info() << " '" << areaID - << "': The hydro power credits data have been normalized to " - << countpowercredits << " timeseries"; - } - else - logs.error() - << "Impossible to find the area `" << areaID << "` to invalidate it"; - } - } - } +void ConvertDailyTSintoHourlyTS(const Matrix::ColumnType& dailyColumn, + Matrix::ColumnType& hourlyColumn) +{ + uint hour = 0; + uint day = 0; - if (study.parameters.derated) - { - maxgen.averageTimeseries(); - maxpump.averageTimeseries(); - countpowercredits = 1; - } - } - else + while (hour < HOURS_PER_YEAR && day < DAYS_PER_YEAR) { - // Is area hydro modulable ? - Area* area = study.areas.find(areaID); - - if (MatrixTestForAtLeastOnePositiveValue(maxgen)) + for (uint i = 0; i < HOURS_PER_DAY; ++i) { - area->hydro.hydroModulable = true; + hourlyColumn[hour] = dailyColumn[day]; + ++hour; } + ++day; } +} - timeseriesNumbersPowerCredits.clear(); +void DataSeriesHydro::buildMaxPowerFromDailyTS(const Matrix::ColumnType& DailyMaxGenPower, + const Matrix::ColumnType& DailyMaxPumpPower) +{ + maxPowerTScount_ = 1; - return ret; + maxHourlyGenPower.reset(maxPowerTScount_, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(maxPowerTScount_, HOURS_PER_YEAR); + + ConvertDailyTSintoHourlyTS(DailyMaxGenPower, maxHourlyGenPower[0]); + ConvertDailyTSintoHourlyTS(DailyMaxPumpPower, maxHourlyPumpPower[0]); } bool DataSeriesHydro::forceReload(bool reload) const @@ -299,8 +242,8 @@ bool DataSeriesHydro::forceReload(bool reload) const ret = ror.forceReload(reload) && ret; ret = storage.forceReload(reload) && ret; ret = mingen.forceReload(reload) && ret; - ret = maxgen.forceReload(reload) && ret; - ret = maxpump.forceReload(reload) && ret; + ret = maxHourlyGenPower.forceReload(reload) && ret; + ret = maxHourlyPumpPower.forceReload(reload) && ret; return ret; } @@ -309,8 +252,8 @@ void DataSeriesHydro::markAsModified() const ror.markAsModified(); storage.markAsModified(); mingen.markAsModified(); - maxgen.markAsModified(); - maxpump.markAsModified(); + maxHourlyGenPower.markAsModified(); + maxHourlyPumpPower.markAsModified(); } void DataSeriesHydro::reset() @@ -318,16 +261,99 @@ void DataSeriesHydro::reset() ror.reset(1, HOURS_PER_YEAR); storage.reset(1, DAYS_PER_YEAR); mingen.reset(1, HOURS_PER_YEAR); - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); - count = 1; - countpowercredits = 1; + generationTScount_ = 1; + + maxHourlyGenPower.reset(1, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); + maxPowerTScount_ = 1; +} + +void DataSeriesHydro::resizeRORandSTORAGE(unsigned int width) +{ + ror.resize(width, HOURS_PER_YEAR); + storage.resize(width, DAYS_PER_YEAR); + generationTScount_ = width; +} + +void DataSeriesHydro::resizeGenerationTS(unsigned int w, unsigned int h) +{ + ror.resize(w, h); + storage.resize(w, std::min((unsigned int)DAYS_PER_YEAR, h)); + mingen.resize(w, h); + generationTScount_ = w; +} + +void DataSeriesHydro::resizeMaxPowerTS(unsigned int w, unsigned int h) +{ + maxHourlyGenPower.reset(w, h); + maxHourlyPumpPower.reset(w, h); + maxPowerTScount_ = w; } uint64_t DataSeriesHydro::memoryUsage() const { return sizeof(double) + ror.memoryUsage() + storage.memoryUsage() + mingen.memoryUsage() - + maxgen.memoryUsage() + maxpump.memoryUsage(); + + maxHourlyGenPower.memoryUsage() + maxHourlyPumpPower.memoryUsage(); } + +void DataSeriesHydro::EqualizeMaxPowerTSsizes(Area& area, bool& fatalError) +{ + std::string fatalErrorMsg = "Hydro Max Power: " + area.id.to() + " : "; + fatalErrorMsg += "generation and pumping must have the same number of TS."; + + maxPowerTScount_ = EqualizeTSsize(maxHourlyGenPower, maxHourlyPumpPower, fatalError, fatalErrorMsg, area); + + logs.info() << " '" << area.id << "': The number of hydro max power (generation and pumping) " + << "TS were both set to : " << maxPowerTScount_; +} + +void DataSeriesHydro::setHydroModulability(Area& area) const +{ + if (MatrixTestForAtLeastOnePositiveValue(maxHourlyGenPower)) + { + area.hydro.hydroModulable = true; + } +} + +uint DataSeriesHydro::TScount() const +{ + return generationTScount_; +} + +uint DataSeriesHydro::maxPowerTScount() const +{ + return maxPowerTScount_; +} + +void DataSeriesHydro::resizeTSinDeratedMode(bool derated, + unsigned int studyVersion, + bool usedBySolver) +{ + if (!(derated && usedBySolver)) + return; + + ror.averageTimeseries(); + storage.averageTimeseries(); + if (studyVersion >= 860) + mingen.averageTimeseries(); + generationTScount_ = 1; + + if (studyVersion >= 870) + { + maxHourlyGenPower.averageTimeseries(); + maxHourlyPumpPower.averageTimeseries(); + maxPowerTScount_ = 1; + } +} + +// TODO : this function should not be here, as it applies to +// any time series, not just hydro TS. +void resizeMatrixNoDataLoss(Matrix& matrixToResize, uint width) +{ + matrixToResize.resizeWithoutDataLost(width, matrixToResize.height); + for (uint x = 1; x < width; ++x) + matrixToResize.pasteToColumn(x, matrixToResize[0]); +} + } // namespace Data } // namespace Antares diff --git a/src/libs/antares/study/parts/hydro/series.h b/src/libs/antares/study/parts/hydro/series.h index 499ad64c82..04ffa79550 100644 --- a/src/libs/antares/study/parts/hydro/series.h +++ b/src/libs/antares/study/parts/hydro/series.h @@ -29,11 +29,14 @@ #include #include "../../fwd.h" +#include + namespace Antares { namespace Data { + /*! ** \brief Data series (Hydro) */ @@ -48,6 +51,9 @@ class DataSeriesHydro DataSeriesHydro(); //@} + void copyGenerationTS(const DataSeriesHydro& source); + void copyMaxPowerTS(const DataSeriesHydro& source); + //! \name Data //@{ /*! @@ -55,6 +61,10 @@ class DataSeriesHydro */ void reset(); + void resizeRORandSTORAGE(unsigned int width); + void resizeGenerationTS(unsigned int w, unsigned int h); + void resizeMaxPowerTS(unsigned int w, unsigned int h); + /*! ** \brief Load all data not already loaded ** @@ -65,16 +75,17 @@ class DataSeriesHydro void markAsModified() const; //@} - //! \name Save / Load - //@{ - /*! - ** \brief Load data series for hydro from a folder - ** - ** \param d The data series for hydro - ** \param folder The source folder - ** \return A non-zero value if the operation succeeded, 0 otherwise - */ - bool loadFromFolder(Study& s, const AreaName& areaID, const AnyString& folder); + void EqualizeGenerationTSsizes(Area& area, bool usedByTheSolver, bool& fatalError); + + // Loading hydro time series collection + // Returned boolean : reading from file failed + bool loadGenerationTS(const AreaName& areaID, const AnyString& folder, unsigned int studyVersion); + + // Loading hydro max generation and mqx pumping TS's + bool LoadMaxPower(const AreaName& areaID, const AnyString& folder); + + void buildMaxPowerFromDailyTS(const Matrix::ColumnType& DailyMaxGenPower, + const Matrix::ColumnType& DailyMaxPumpPower); /*! ** \brief Save data series for hydro into a folder (`input/hydro/series`) @@ -100,12 +111,6 @@ class DataSeriesHydro //@} - /*! - ** \brief Check TS number for Minimum Generation and logs error if necessary - */ - void checkMinGenTsNumber(Study& s, const AreaName& areaID); - -public: /*! ** \brief Run-of-the-river - ROR (MW) ** @@ -134,44 +139,48 @@ class DataSeriesHydro ** ** Merely a matrix of TimeSeriesCount * HOURS_PER_YEAR values */ - Matrix maxgen; + Matrix maxHourlyGenPower; /*! ** \brief Maximum Pumping (MW) ** ** Merely a matrix of TimeSeriesCount * HOURS_PER_YEAR values */ - Matrix maxpump; + Matrix maxHourlyPumpPower; - /*! - ** \brief The number of time-series - ** - ** This value must be the same as the width of the matrices `mod` and `fatal`. - ** It is only provided for convenience to avoid same strange and ambiguous code - ** (for example using `fatal.width` and `mod.width` in the same routine, it might - ** indicate that the two values are not strictly equal) - */ - uint count; + // TS's number matrices for Generation and Maximum Power + Matrix timeseriesNumbers; + Matrix timeseriesNumbersHydroMaxPower; - /*! - ** \brief The number of time-series for maxgen and maxpump matrices - ** - ** This value must be the same as the width of the matrices `maxgen` and `maxpump`. - ** It is only provided for convenience to avoid same strange and ambiguous code - ** (for example using `maxgen.width` and `maxpump.width` in the same routine, it might - ** indicate that the two values are not strictly equal) - */ - uint countpowercredits = 0; + // Equalizing max generation and max pumping numbers of TS's + void EqualizeMaxPowerTSsizes(Area& area, bool& fatalError); - /*! - ** \brief Monte-Carlo - */ - Matrix timeseriesNumbers; - Matrix timeseriesNumbersPowerCredits; - bool LoadHydroPowerCredits(Study& study, const AreaName& areaID, const AnyString& folder); + void setHydroModulability(Area& area) const; + + // Getters for generation (ror, storage and mingen) and + // max power (generation and pumping) number of TS + uint TScount() const; + uint maxPowerTScount() const; + + // Setting TS's when derated mode is on + void resizeTSinDeratedMode(bool derated, unsigned int studyVersion, bool useBySolver); + +private: + + // The number of time-series about generation (ror, inflows (=storage), mingen) + // They all should have the same number of columns (width), as they each year receives a common + // TS number for all three. + uint generationTScount_ = 0; + + // The number of time-series about max power (maxHourlyGenPower and maxHourlyPumpPower) + // They both should have the same number of columns (width), as they each year receives a common + // TS number for all three. + uint maxPowerTScount_ = 0; }; // class DataSeriesHydro +void resizeMatrixNoDataLoss(Matrix& matrixToResize, uint width); + } // namespace Data } // namespace Antares diff --git a/src/libs/antares/study/parts/parts.h b/src/libs/antares/study/parts/parts.h index 1dcbdbc39d..01d654821f 100644 --- a/src/libs/antares/study/parts/parts.h +++ b/src/libs/antares/study/parts/parts.h @@ -40,7 +40,7 @@ #include "hydro/prepro.h" #include "hydro/series.h" #include "hydro/container.h" -#include "hydro/datatransfer.h" +#include "hydro/hydromaxtimeseriesreader.h" // Wind #include "wind/prepro.h" diff --git a/src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.cpp b/src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.cpp similarity index 62% rename from src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.cpp rename to src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.cpp index 36d9a452f7..3bfb7e50d5 100644 --- a/src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.cpp +++ b/src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.cpp @@ -1,21 +1,21 @@ -#include "HydroPowerCreditsTSNumberData.h" +#include "HydroMaxPowerTSNumberData.h" #include "applyToMatrix.hxx" // ================================ -// Hydro Energy Credits... +// Hydro Max Power... // ================================ namespace Antares::Data::ScenarioBuilder { -uint hydroPowerCreditsTSNumberData::get_tsGenCount(const Study& study) const +uint hydroMaxPowerTSNumberData::get_tsGenCount(const Study& study) const { //This function must be overriden because it is inherited from abstract class return 0; } -bool hydroPowerCreditsTSNumberData::apply(Study& study) +bool hydroMaxPowerTSNumberData::apply(Study& study) { bool ret = true; CString<512, false> logprefix; @@ -25,7 +25,7 @@ bool hydroPowerCreditsTSNumberData::apply(Study& study) // The total number of areas; const uint areaCount = study.areas.size(); - const uint tsGenCountHydroPowerCredits = get_tsGenCount(study); + const uint tsGenCountHydroMaxPower = get_tsGenCount(study); for (uint areaIndex = 0; areaIndex != areaCount; ++areaIndex) { @@ -35,8 +35,8 @@ bool hydroPowerCreditsTSNumberData::apply(Study& study) assert(areaIndex < pTSNumberRules.width); const MatrixType::ColumnType& col = pTSNumberRules[areaIndex]; - logprefix.clear() << "Hydro Power Credits: Area '" << area.name << "': "; - ret = ApplyToMatrixPowerCredits(errors, logprefix, *area.hydro.series, col, tsGenCountHydroPowerCredits) && ret; + logprefix.clear() << "Hydro Max Power: Area '" << area.name << "': "; + ret = ApplyToMatrixMaxPower(errors, logprefix, *area.hydro.series, col, tsGenCountHydroMaxPower) && ret; } return ret; } diff --git a/src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.h b/src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.h similarity index 60% rename from src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.h rename to src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.h index ac30d2b036..0cdc741693 100644 --- a/src/libs/antares/study/scenario-builder/HydroPowerCreditsTSNumberData.h +++ b/src/libs/antares/study/scenario-builder/HydroMaxPowerTSNumberData.h @@ -3,22 +3,22 @@ #include "TSnumberData.h" // ===================== -// Hydro Power Credits... +// Hydro Max Power... // ===================== namespace Antares::Data::ScenarioBuilder { -class hydroPowerCreditsTSNumberData : public TSNumberData +class hydroMaxPowerTSNumberData : public TSNumberData { public: bool apply(Study& study) override; CString<512, false> get_prefix() const override; uint get_tsGenCount(const Study& study) const override; - virtual ~hydroPowerCreditsTSNumberData() = default; + virtual ~hydroMaxPowerTSNumberData() = default; }; -inline CString<512, false> hydroPowerCreditsTSNumberData::get_prefix() const +inline CString<512, false> hydroMaxPowerTSNumberData::get_prefix() const { return "hgp,"; } diff --git a/src/libs/antares/study/scenario-builder/applyToMatrix.hxx b/src/libs/antares/study/scenario-builder/applyToMatrix.hxx index e4fa56a602..ac79bd9716 100644 --- a/src/libs/antares/study/scenario-builder/applyToMatrix.hxx +++ b/src/libs/antares/study/scenario-builder/applyToMatrix.hxx @@ -25,7 +25,7 @@ inline bool CheckValidity(uint value, uint tsGenMax) { // When the TS-Generators are not used - return (!tsGenMax) ? (value < data.count) : (value < tsGenMax); + return (!tsGenMax) ? (value < data.TScount()) : (value < tsGenMax); } template<> @@ -46,10 +46,10 @@ inline bool CheckValidity(uint value, const BindingConst } template -static inline bool CheckValidityHydroPowerCredits(uint value, const D& data, uint tsGenMax) +static inline bool CheckValidityHydroMaxPower(uint value, const D& data, uint tsGenMax) { // TS Generator never used - return (!tsGenMax) ? (value < data.countpowercredits) : (value < tsGenMax); + return (!tsGenMax) ? (value < data.maxPowerTScount()) : (value < tsGenMax); } template @@ -98,7 +98,7 @@ bool ApplyToMatrix(uint& errors, } template -bool ApplyToMatrixPowerCredits(uint& errors, +bool ApplyToMatrixMaxPower(uint& errors, StringT& logprefix, D& data, const TSNumberData::MatrixType::ColumnType& years, uint tsGenMax) @@ -106,10 +106,10 @@ bool ApplyToMatrixPowerCredits(uint& errors, bool ret = true; // In this case, m.height represents the total number of years - const uint nbYears = data.timeseriesNumbersPowerCredits.height; + const uint nbYears = data.timeseriesNumbersHydroMaxPower.height; // The matrix m has only one column - assert(data.timeseriesNumbersPowerCredits.width == 1); - typename Matrix::ColumnType& target = data.timeseriesNumbersPowerCredits[0]; + assert(data.timeseriesNumbersHydroMaxPower.width == 1); + typename Matrix::ColumnType& target = data.timeseriesNumbersHydroMaxPower[0]; for (uint y = 0; y != nbYears; ++y) { @@ -119,7 +119,7 @@ bool ApplyToMatrixPowerCredits(uint& errors, uint tsNum = years[y] - 1; // When the TS-Generators are not used - if (!CheckValidityHydroPowerCredits(tsNum, data, tsGenMax)) + if (!CheckValidityHydroMaxPower(tsNum, data, tsGenMax)) { if (errors <= maxErrors) { diff --git a/src/libs/antares/study/scenario-builder/rules.cpp b/src/libs/antares/study/scenario-builder/rules.cpp index 38a4b4fe95..191e92016b 100644 --- a/src/libs/antares/study/scenario-builder/rules.cpp +++ b/src/libs/antares/study/scenario-builder/rules.cpp @@ -55,8 +55,8 @@ void Rules::saveToINIFile(Yuni::IO::File::Stream& file) const solar.saveToINIFile(study_, file); // hydro hydro.saveToINIFile(study_, file); - // hydroPowerCredits - hydroPowerCredits.saveToINIFile(study_, file); + // hydroMaxPower + hydroMaxPower.saveToINIFile(study_, file); // wind wind.saveToINIFile(study_, file); // Thermal clusters, renewable clusters, links NTS : each area @@ -81,7 +81,7 @@ bool Rules::reset() load.reset(study_); solar.reset(study_); hydro.reset(study_); - hydroPowerCredits.reset(study_); + hydroMaxPower.reset(study_); wind.reset(study_); // Thermal @@ -246,7 +246,7 @@ bool Rules::readHydro(const AreaName::Vector& splitKey, String value, bool updat return true; } -bool Rules::readHydroPowerCredits(const AreaName::Vector& splitKey, String value, bool updaterMode) +bool Rules::readHydroMaxPower(const AreaName::Vector& splitKey, String value, bool updaterMode) { const uint year = splitKey[2].to(); const AreaName& areaname = splitKey[1]; @@ -256,7 +256,7 @@ bool Rules::readHydroPowerCredits(const AreaName::Vector& splitKey, String value return false; uint val = fromStringToTSnumber(value); - hydroPowerCredits.setTSnumber(area->index, year, val); + hydroMaxPower.setTSnumber(area->index, year, val); return true; } @@ -369,7 +369,7 @@ bool Rules::readLine(const AreaName::Vector& splitKey, String value, bool update else if (kind_of_scenario == "h") return readHydro(splitKey, value, updaterMode); else if (kind_of_scenario == "hgp") - return readHydroPowerCredits(splitKey, value, updaterMode); + return readHydroMaxPower(splitKey, value, updaterMode); else if (kind_of_scenario == "s") return readSolar(splitKey, value, updaterMode); else if (kind_of_scenario == "hl") @@ -389,7 +389,7 @@ bool Rules::apply() returned_status = load.apply(study_) && returned_status; returned_status = solar.apply(study_) && returned_status; returned_status = hydro.apply(study_) && returned_status; - returned_status = hydroPowerCredits.apply(study_) && returned_status; + returned_status = hydroMaxPower.apply(study_) && returned_status; returned_status = wind.apply(study_) && returned_status; for (uint i = 0; i != pAreaCount; ++i) { diff --git a/src/libs/antares/study/scenario-builder/rules.h b/src/libs/antares/study/scenario-builder/rules.h index 2e2565802b..ebfe5e534f 100644 --- a/src/libs/antares/study/scenario-builder/rules.h +++ b/src/libs/antares/study/scenario-builder/rules.h @@ -40,7 +40,7 @@ #include "HydroTSNumberData.h" #include "WindTSNumberData.h" #include "LoadTSNumberData.h" -#include "HydroPowerCreditsTSNumberData.h" +#include "HydroMaxPowerTSNumberData.h" #include #include @@ -116,8 +116,8 @@ class Rules final : private Yuni::NonCopyable solarTSNumberData solar; //! Hydro hydroTSNumberData hydro; - //! Hydro Power Credits - hydroPowerCreditsTSNumberData hydroPowerCredits; + //! Hydro Max Power + hydroMaxPowerTSNumberData hydroMaxPower; //! Wind windTSNumberData wind; @@ -141,7 +141,7 @@ class Rules final : private Yuni::NonCopyable bool readLoad(const AreaName::Vector& instrs, String value, bool updaterMode); bool readWind(const AreaName::Vector& instrs, String value, bool updaterMode); bool readHydro(const AreaName::Vector& instrs, String value, bool updaterMode); - bool readHydroPowerCredits(const AreaName::Vector& splitKey, String value, bool updaterMode); + bool readHydroMaxPower(const AreaName::Vector& splitKey, String value, bool updaterMode); bool readSolar(const AreaName::Vector& instrs, String value, bool updaterMode); bool readHydroLevels(const AreaName::Vector& instrs, String value, bool updaterMode); bool readLink(const AreaName::Vector& instrs, String value, bool updaterMode); diff --git a/src/solver/aleatoire/alea_tirage_au_sort_chroniques.cpp b/src/solver/aleatoire/alea_tirage_au_sort_chroniques.cpp index e003d4109c..287631518e 100644 --- a/src/solver/aleatoire/alea_tirage_au_sort_chroniques.cpp +++ b/src/solver/aleatoire/alea_tirage_au_sort_chroniques.cpp @@ -59,17 +59,21 @@ void ApplyRandomTSnumbers(const Study& study, ptchro.Solar = (data.timeSeries.width != 1) ? (long)data.timeseriesNumbers[0][year] : 0; // zero-based } - // Hydro and Hydro Power Credits + // Hydro { const Data::DataSeriesHydro& data = *area.hydro.series; assert(year < data.timeseriesNumbers.height); - assert(year < data.timeseriesNumbersPowerCredits.height); + ptchro.Hydraulique - = (data.count != 1) ? (long)data.timeseriesNumbers[0][year] : 0; // zero-based - ptchro.HydrauliquePowerCredits - = (data.countpowercredits != 1) - ? static_cast(data.timeseriesNumbersPowerCredits[0][year]) - : 0; + = (data.TScount() != 1) ? (long)data.timeseriesNumbers[0][year] : 0; // zero-based + } + // Hydro Max Power + { + const Data::DataSeriesHydro& data = *area.hydro.series; + assert(year < data.timeseriesNumbersHydroMaxPower.height); + ptchro.HydroMaxPower = (data.maxPowerTScount() != 1) + ? (data.timeseriesNumbersHydroMaxPower[0][year]) + : 0; // zero-based } // Wind { diff --git a/src/solver/hydro/management/daily.cpp b/src/solver/hydro/management/daily.cpp index 3c7bae0cd0..8f5969169f 100644 --- a/src/solver/hydro/management/daily.cpp +++ b/src/solver/hydro/management/daily.cpp @@ -193,7 +193,7 @@ struct DebugData double niveauDeb = ventilationResults.NiveauxReservoirsDebutJours[day]; double niveauFin = ventilationResults.NiveauxReservoirsFinJours[day]; double apports = srcinflows[day] / reservoirCapacity; - double turbMax = Antares::Data::CalculateDailyMeanPower(day, maxP) * maxE[day] / reservoirCapacity; + double turbMax = maxP[day] * maxE[day] / reservoirCapacity; double turbCible = dailyTargetGen[day] / reservoirCapacity; double turbCibleUpdated = dailyTargetGen[day] / reservoirCapacity + previousMonthWaste[realmonth] / daysPerMonth; @@ -240,6 +240,10 @@ inline void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::St auto& data = tmpDataByArea_[numSpace][z]; + auto& scratchpad = area.scratchpad[numSpace]; + + auto& meanMaxDailyGenPower = scratchpad.meanMaxDailyGenPower; + int initReservoirLvlMonth = area.hydro.initializeReservoirLevelDate; double reservoirCapacity = area.hydro.reservoirCapacity; @@ -250,14 +254,12 @@ inline void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::St uint dayYear = 0; - auto const& maxPowerHours = area.hydro.maxHoursGen; - auto const& maxPower = area.hydro.series->maxgen; + auto const& maxDailyGenEnergy = area.hydro.maxDailyGenEnergy; - uint tsIndexPowerCredits - = (NumeroChroniquesTireesParPays[numSpace][z]).HydrauliquePowerCredits; + uint tsIndexMaxPower = (NumeroChroniquesTireesParPays[numSpace][z]).HydroMaxPower; - auto const& maxP = maxPower[tsIndexPowerCredits < maxPower.width ? tsIndexPowerCredits : 0]; - auto const& maxE = maxPowerHours[0]; + auto const& maxP = meanMaxDailyGenPower[tsIndexMaxPower]; + auto const& maxE = maxDailyGenEnergy[0]; auto& ventilationResults = ventilationResults_[numSpace][z]; @@ -281,17 +283,16 @@ inline void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::St auto daysPerMonth = calendar_.months[month].days; assert(daysPerMonth <= maxOPP); assert(daysPerMonth <= maxDailyTargetGen); - assert(daysPerMonth + dayYear - 1 < maxPower.height); + assert(daysPerMonth + dayYear - 1 < meanMaxDailyGenPower.height); for (uint day = 0; day != daysPerMonth; ++day) { auto dYear = day + dayYear; assert(day < 32); assert(dYear < 366); - auto meanPower = Antares::Data::CalculateDailyMeanPower(dYear, maxP); if (debugData) - debugData->OPP[dYear] = meanPower * maxE[dYear]; + debugData->OPP[dYear] = maxP[dYear] * maxE[dYear]; } dayYear += daysPerMonth; @@ -400,8 +401,7 @@ inline void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::St uint dayMonth = 0; for (uint day = firstDay; day != endDay; ++day) { - auto meanPower = Antares::Data::CalculateDailyMeanPower(day, maxP); - problem.TurbineMax[dayMonth] = meanPower * maxE[day]; + problem.TurbineMax[dayMonth] = maxP[day] * maxE[day]; problem.TurbineMin[dayMonth] = data.dailyMinGen[day]; problem.TurbineCible[dayMonth] = dailyTargetGen[day]; dayMonth++; @@ -478,8 +478,7 @@ inline void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::St uint dayMonth = 0; for (uint day = firstDay; day != endDay; ++day) { - auto meanPower = Antares::Data::CalculateDailyMeanPower(day, maxP); - problem.TurbineMax[dayMonth] = meanPower * maxE[day] / reservoirCapacity; + problem.TurbineMax[dayMonth] = maxP[day] * maxE[day] / reservoirCapacity; problem.TurbineMin[dayMonth] = data.dailyMinGen[day] / reservoirCapacity; problem.TurbineCible[dayMonth] diff --git a/src/solver/hydro/management/management.cpp b/src/solver/hydro/management/management.cpp index cfe510b239..b2a69f12b8 100644 --- a/src/solver/hydro/management/management.cpp +++ b/src/solver/hydro/management/management.cpp @@ -306,34 +306,38 @@ bool HydroManagement::checkWeeklyMinGeneration(uint tsIndex, Data::Area& area) c return true; } -bool HydroManagement::checkHourlyMinMaxGeneration(uint tsIndex, - uint tsIndexPowerCredits, - Data::Area& area) const +bool HydroManagement::checkGenerationPowerConsistency(uint numSpace) const { - // Hourly minimum generation <= hourly inflows for each hour - auto& mingenmatrix = area.hydro.series->mingen; - auto const& srcmingen = mingenmatrix[tsIndex < mingenmatrix.width ? tsIndex : 0]; - auto& maxgenmatrix = area.hydro.series->maxgen; - auto const& srcmaxgen - = maxgenmatrix[tsIndexPowerCredits < maxgenmatrix.width ? tsIndexPowerCredits : 0]; + bool ret = true; - for (uint h = 0; h < HOURS_PER_YEAR; ++h) - { - const auto& max = srcmaxgen[h]; - const auto& min = srcmingen[h]; + areas_.each( + [&numSpace, &ret](const Data::Area& area) + { + uint z = area.index; + auto tsIndex = (uint)NumeroChroniquesTireesParPays[numSpace][z].Hydraulique; + auto tsIndexMaxPower = NumeroChroniquesTireesParPays[numSpace][z].HydroMaxPower; - if (max < min) - { - logs.error() << "In area: " << area.name << " [hourly] minimum generation of " << min - << " MW in timestep " << h + 1 << " of TS-" << tsIndex + 1 - << " is incompatible with the maximum generation of " << max - << " MW in timestep " << h + 1 << " of TS-" << tsIndexPowerCredits + 1 - << " MW."; - return false; - } - } + auto const& srcmingen = area.hydro.series->mingen; + auto const& srcmaxgen = area.hydro.series->maxHourlyGenPower; - return true; + for (uint h = 0; h < HOURS_PER_YEAR; ++h) + { + const auto& min = srcmingen[tsIndex < srcmingen.width ? tsIndex : 0][h]; + const auto& max = srcmaxgen[tsIndexMaxPower < srcmaxgen.width ? tsIndexMaxPower : 0][h]; + + if (max < min) + { + logs.error() << "In area: " << area.name << " [hourly] minimum generation of " + << min << " MW in timestep " << h + 1 << " of TS-" << tsIndex + 1 + << " is incompatible with the maximum generation of " << max + << " MW in timestep " << h + 1 << " of TS-" << tsIndexMaxPower + 1 << " MW."; + ret = false; + return; + } + } + }); + + return ret; } bool HydroManagement::checkMinGeneration(uint numSpace) @@ -344,15 +348,11 @@ bool HydroManagement::checkMinGeneration(uint numSpace) uint z = area.index; const auto& ptchro = NumeroChroniquesTireesParPays[numSpace][z]; auto tsIndex = (uint)ptchro.Hydraulique; - auto tsIndexPowerCredits = ptchro.HydrauliquePowerCredits; bool useHeuristicTarget = area.hydro.useHeuristicTarget; bool followLoadModulations = area.hydro.followLoadModulations; bool reservoirManagement = area.hydro.reservoirManagement; - if (!reservoirManagement) - ret = checkHourlyMinMaxGeneration(tsIndex, tsIndexPowerCredits, area) && ret; - if (!useHeuristicTarget) return; @@ -513,6 +513,12 @@ double HydroManagement::randomReservoirLevel(double min, double avg, double max) return x * max + (1. - x) * min; } +bool HydroManagement::checksOnGenerationPowerBounds(uint numSpace) +{ + return (checkMinGeneration(numSpace) && checkGenerationPowerConsistency(numSpace)) ? true + : false; +} + void HydroManagement::makeVentilation(double* randomReservoirLevel, Solver::Variable::State& state, uint y, @@ -522,7 +528,7 @@ void HydroManagement::makeVentilation(double* randomReservoirLevel, prepareInflowsScaling(numSpace); minGenerationScaling(numSpace); - if (!checkMinGeneration(numSpace)) + if (!checksOnGenerationPowerBounds(numSpace)) { throw FatalError("hydro management: invalid minimum generation"); } diff --git a/src/solver/hydro/management/management.h b/src/solver/hydro/management/management.h index 7f44b35570..2ff0b75fdb 100644 --- a/src/solver/hydro/management/management.h +++ b/src/solver/hydro/management/management.h @@ -88,7 +88,7 @@ struct TmpDataByArea typedef struct { std::vector HydrauliqueModulableQuotidien; /* indice par jour */ - std::vector NiveauxReservoirsDebutJours; //Niveaux (quotidiens) du reservoir de début + std::vector NiveauxReservoirsDebutJours; //Niveaux (quotidiens) du reservoir de début //de jour (en cas de gestion des reservoirs). std::vector NiveauxReservoirsFinJours; //Niveaux (quotidiens) du reservoir de fin //de jour (en cas de gestion des reservoirs). @@ -131,9 +131,11 @@ class HydroManagement final //! check Weekly minimum generation is lower than available inflows bool checkWeeklyMinGeneration(uint tsIndex, Data::Area& area) const; //! check Hourly minimum generation is lower than available inflows - bool checkHourlyMinMaxGeneration(uint tsIndex, uint tsIndexPowerCredits, Data::Area& area) const; + bool checkGenerationPowerConsistency(uint numSpace) const; //! check minimum generation is lower than available inflows bool checkMinGeneration(uint numSpace); + //! return false if checkGenerationPowerConsistency or checkMinGeneration returns false + bool checksOnGenerationPowerBounds(uint numSpace); //! Prepare the net demand for each area template void prepareNetDemand(uint numSpace); diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index bc81cbcf53..beb1696131 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -559,26 +559,26 @@ void SIM_RenseignementProblemeHebdo(const Study& study, ntc.ValeurDeLoopFlowOrigineVersExtremite[k] = lnk.parameters[fhlLoopFlow][hourInYear]; } } - preparerBindingConstraint(problem, numSpace, PasDeTempsDebut, study.bindingConstraints, weekFirstDay, hourInWeek); + preparerBindingConstraint( + problem, numSpace, PasDeTempsDebut, study.bindingConstraints, weekFirstDay, hourInWeek); for (uint k = 0; k < nbPays; ++k) { auto& tsIndex = NumeroChroniquesTireesParPays[numSpace][k]; - uint tsIndexPowerCredits = tsIndex.HydrauliquePowerCredits; + uint tsIndexMaxPower = tsIndex.HydroMaxPower; auto& area = *(study.areas.byIndex[k]); auto& scratchpad = area.scratchpad[numSpace]; auto& ror = area.hydro.series->ror; - auto& maxgenmatrix = area.hydro.series->maxgen; - auto const& srcmaxgen - = maxgenmatrix[tsIndexPowerCredits < maxgenmatrix.width ? tsIndexPowerCredits : 0]; - auto const& ContrainteDePmaxHydrauliqueHoraire = srcmaxgen[PasDeTempsDebut + hourInWeek]; + auto& maxHourlyGenPowerMatrix = area.hydro.series->maxHourlyGenPower; + auto const& maxHourlyGenPowerTS + = maxHourlyGenPowerMatrix[tsIndexMaxPower]; + auto const& ContrainteDePmaxHydrauliqueHoraire = maxHourlyGenPowerTS[PasDeTempsDebut + hourInWeek]; - auto& maxpumpmatrix = area.hydro.series->maxpump; - auto const& srcmaxpump - = maxpumpmatrix[tsIndexPowerCredits < maxpumpmatrix.width ? tsIndexPowerCredits - : 0]; - auto const& ContrainteDePmaxPompageHoraire = srcmaxpump[PasDeTempsDebut + hourInWeek]; + auto& maxHourlyPumpPowerMatrix = area.hydro.series->maxHourlyPumpPower; + auto const& maxHourlyPumpPowerTS + = maxHourlyPumpPowerMatrix[tsIndexMaxPower]; + auto const& ContrainteDePmaxPompageHoraire = maxHourlyPumpPowerTS[PasDeTempsDebut + hourInWeek]; assert(&scratchpad); assert((uint)hourInYear < scratchpad.ts.load.height); @@ -624,10 +624,8 @@ void SIM_RenseignementProblemeHebdo(const Study& study, if (problem.CaracteristiquesHydrauliques[k].PresenceDHydrauliqueModulable > 0) { - problem.CaracteristiquesHydrauliques[k] - .ContrainteDePmaxHydrauliqueHoraire[hourInWeek] + problem.CaracteristiquesHydrauliques[k].ContrainteDePmaxHydrauliqueHoraire[hourInWeek] = ContrainteDePmaxHydrauliqueHoraire - * problem.CaracteristiquesHydrauliques[k].WeeklyGeneratingModulation; } @@ -652,11 +650,10 @@ void SIM_RenseignementProblemeHebdo(const Study& study, uint tsIndex = (NumeroChroniquesTireesParPays[numSpace][k]).Hydraulique; auto& inflowsmatrix = area.hydro.series->storage; auto const& srcinflows = inflowsmatrix[tsIndex < inflowsmatrix.width ? tsIndex : 0]; - uint tsIndexPowerCredits = (NumeroChroniquesTireesParPays[numSpace][k]).HydrauliquePowerCredits; - auto& maxgenmatrix = area.hydro.series->maxgen; - auto const& srcmaxgen = maxgenmatrix[tsIndexPowerCredits < maxgenmatrix.width ? tsIndexPowerCredits : 0]; - auto& maxpumpmatrix = area.hydro.series->maxpump; - auto const& srcmaxpump = maxpumpmatrix[tsIndexPowerCredits < maxpumpmatrix.width ? tsIndexPowerCredits : 0]; + uint tsIndexMaxPower = (NumeroChroniquesTireesParPays[numSpace][k]).HydroMaxPower; + auto& scratchpad = area.scratchpad[numSpace]; + auto& dailyMeanMaxGenPower = scratchpad.meanMaxDailyGenPower[tsIndexMaxPower]; + auto& dailyMeanMaxPumpPower = scratchpad.meanMaxDailyPumpPower[tsIndexMaxPower]; auto& mingenmatrix = area.hydro.series->mingen; auto const& srcmingen = mingenmatrix[tsIndex < mingenmatrix.width ? tsIndex : 0]; for (uint j = 0; j < problem.NombreDePasDeTemps; ++j) @@ -674,14 +671,13 @@ void SIM_RenseignementProblemeHebdo(const Study& study, for (uint j = 0; j < 7; ++j) { uint day = study.calendar.hours[PasDeTempsDebut + j * 24].dayYear; - auto meanPower = CalculateDailyMeanPower(day, srcmaxgen); problem.CaracteristiquesHydrauliques[k] .MinEnergieHydrauParIntervalleOptimise[j] = 0.; problem.CaracteristiquesHydrauliques[k] .MaxEnergieHydrauParIntervalleOptimise[j] - = meanPower * area.hydro.maxHoursGen[0][day] + = dailyMeanMaxGenPower[day] * area.hydro.maxDailyGenEnergy[0][day] * problem.CaracteristiquesHydrauliques[k] .WeeklyGeneratingModulation; } @@ -730,9 +726,9 @@ void SIM_RenseignementProblemeHebdo(const Study& study, for (uint j = 0; j < 7; ++j) { uint day = study.calendar.hours[PasDeTempsDebut + j * 24].dayYear; - auto meanPower = CalculateDailyMeanPower(day, srcmaxgen); - double DGC = meanPower * area.hydro.maxHoursGen[0][day]; + double DGC + = dailyMeanMaxGenPower[day] * area.hydro.maxDailyGenEnergy[0][day]; DGU_tmp[j] = DNT[day] * LUB; DGL_tmp[j] = DNT[day] * LLB; @@ -837,11 +833,11 @@ void SIM_RenseignementProblemeHebdo(const Study& study, for (uint j = 0; j < 7; ++j) { uint day = study.calendar.hours[PasDeTempsDebut + j * 24].dayYear; - auto meanPump = CalculateDailyMeanPower(day, srcmaxpump); problem.CaracteristiquesHydrauliques[k] .MaxEnergiePompageParIntervalleOptimise[j] - = meanPump * area.hydro.maxHoursPump[0][day] + = dailyMeanMaxPumpPower[day] + * area.hydro.maxDailyPumpEnergy[0][day] * problem.CaracteristiquesHydrauliques[k] .WeeklyPumpingModulation; } @@ -872,10 +868,9 @@ void SIM_RenseignementProblemeHebdo(const Study& study, for (uint j = 0; j < 7; ++j) { uint day = study.calendar.hours[PasDeTempsDebut + j * 24].dayYear; - auto meanPump = CalculateDailyMeanPower(day, srcmaxpump); - double DPC - = meanPump * area.hydro.maxHoursPump[0][day]; + double DPC = dailyMeanMaxPumpPower[day] + * area.hydro.maxDailyPumpEnergy[0][day]; WPU += DPC; } @@ -885,9 +880,9 @@ void SIM_RenseignementProblemeHebdo(const Study& study, for (uint j = 0; j < 7; ++j) { uint day = study.calendar.hours[PasDeTempsDebut + j * 24].dayYear; - auto meanPump = CalculateDailyMeanPower(day, srcmaxpump); - double DPC - = meanPump * area.hydro.maxHoursPump[0][day]; + + double DPC = dailyMeanMaxPumpPower[day] + * area.hydro.maxDailyPumpEnergy[0][day]; double rc = area.hydro.reservoirCapacity; if (not area.hydro.hardBoundsOnRuleCurves) diff --git a/src/solver/simulation/sim_structure_donnees.h b/src/solver/simulation/sim_structure_donnees.h index a45fcffdf1..725890b24a 100644 --- a/src/solver/simulation/sim_structure_donnees.h +++ b/src/solver/simulation/sim_structure_donnees.h @@ -34,7 +34,7 @@ typedef struct std::vector ThermiqueParPalier; std::vector RenouvelableParPalier; int Hydraulique; - unsigned int HydrauliquePowerCredits; + unsigned int HydroMaxPower; int Eolien; int Consommation; int Solar; diff --git a/src/solver/simulation/timeseries-numbers.cpp b/src/solver/simulation/timeseries-numbers.cpp index a2e78889f4..17cf9055e5 100644 --- a/src/solver/simulation/timeseries-numbers.cpp +++ b/src/solver/simulation/timeseries-numbers.cpp @@ -50,7 +50,7 @@ const map ts_to_tsIndex = {{timeSeriesLoad, 0}, {timeSeriesSolar, 4}, {timeSeriesRenewable, 5}, {timeSeriesTransmissionCapacities, 6}, - {timeSeriesHydroPowerCredits, 7}}; + {timeSeriesHydroMaxPower, 7}}; const map ts_to_tsTitle = {{timeSeriesLoad, "load"}, @@ -60,7 +60,7 @@ const map ts_to_tsTitle {timeSeriesSolar, "solar"}, {timeSeriesRenewable, "renewable clusters"}, {timeSeriesTransmissionCapacities, "transmission capacities"}, - {timeSeriesHydroPowerCredits, "power-credits"}}; + {timeSeriesHydroMaxPower, "max-power"}}; void addInterModalTimeSeriesToMessage(const array& isTSintermodal, std::string& interModalTsMsg) @@ -95,7 +95,7 @@ static bool GenerateDeratedMode(Study& study) area.solar.series->timeseriesNumbers.zero(); area.wind.series->timeseriesNumbers.zero(); area.hydro.series->timeseriesNumbers.zero(); - area.hydro.series->timeseriesNumbersPowerCredits.zero(); + area.hydro.series->timeseriesNumbersHydroMaxPower.zero(); for (uint i = 0; i != area.thermal.clusterCount(); ++i) { @@ -151,7 +151,7 @@ class hydroAreaNumberOfTSretriever : public areaNumberOfTSretriever } std::vector getAreaTimeSeriesNumber(const Area& area) { - std::vector to_return = {area.hydro.series->count}; + std::vector to_return = {area.hydro.series->TScount()}; return to_return; } uint getGeneratedTimeSeriesNumber() @@ -160,15 +160,15 @@ class hydroAreaNumberOfTSretriever : public areaNumberOfTSretriever } }; -class hydroPowerCreditsAreaNumberOfTSretriever : public areaNumberOfTSretriever +class hydroMaxPowerAreaNumberOfTSretriever : public areaNumberOfTSretriever { public: - explicit hydroPowerCreditsAreaNumberOfTSretriever(Study& study) : areaNumberOfTSretriever(study) + explicit hydroMaxPowerAreaNumberOfTSretriever(Study& study) : areaNumberOfTSretriever(study) { } std::vector getAreaTimeSeriesNumber(const Area& area) override { - std::vector to_return = {area.hydro.series->countpowercredits}; + std::vector to_return = {area.hydro.series->maxPowerTScount()}; return to_return; } uint getGeneratedTimeSeriesNumber() override @@ -176,7 +176,7 @@ class hydroPowerCreditsAreaNumberOfTSretriever : public areaNumberOfTSretriever return 1; } - virtual ~hydroPowerCreditsAreaNumberOfTSretriever() = default; + virtual ~hydroMaxPowerAreaNumberOfTSretriever() = default; }; class windAreaNumberOfTSretriever : public areaNumberOfTSretriever @@ -378,8 +378,8 @@ bool checkIntraModalConsistency(array& nbTimeseriesByMode = make_shared(study); ts_to_numberOfTSretrievers[timeSeriesTransmissionCapacities] = make_shared(study); - ts_to_numberOfTSretrievers[timeSeriesHydroPowerCredits] - = make_shared(study); + ts_to_numberOfTSretrievers[timeSeriesHydroMaxPower] + = make_shared(study); // Loop over TS kind and check intra-modal consistency mapTStoRetriever::iterator it = ts_to_numberOfTSretrievers.begin(); @@ -444,15 +444,15 @@ bool checkInterModalConsistencyForArea(Area& area, if (isTSintermodal[indexTS]) { uint nbTimeSeries - = isTSgenerated[indexTS] ? parameters.nbTimeSeriesHydro : area.hydro.series->count; + = isTSgenerated[indexTS] ? parameters.nbTimeSeriesHydro : area.hydro.series->TScount(); listNumberTsOverArea.push_back(nbTimeSeries); } - // Hydro Power Credits : Add hydro's power credits number of TS in area ... - indexTS = ts_to_tsIndex.at(timeSeriesHydroPowerCredits); + // Hydro Max Power : Add hydro's max power number of TS in area ... + indexTS = ts_to_tsIndex.at(timeSeriesHydroMaxPower); if (isTSintermodal[indexTS]) { - uint nbTimeSeries = area.hydro.series->countpowercredits; + uint nbTimeSeries = area.hydro.series->maxPowerTScount(); listNumberTsOverArea.push_back(nbTimeSeries); } @@ -566,13 +566,13 @@ void storeTSnumbersForIntraModal(const array& intramo area.hydro.series->timeseriesNumbers[0][year] = intramodal_draws[indexTS]; // ------------- - // Hydro Power Credits ... + // Hydro Max Power ... // ------------- - assert(year < area.hydro.series->timeseriesNumbersPowerCredits.height); - indexTS = ts_to_tsIndex.at(timeSeriesHydroPowerCredits); + assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height); + indexTS = ts_to_tsIndex.at(timeSeriesHydroMaxPower); if (isTSintramodal[indexTS]) - area.hydro.series->timeseriesNumbersPowerCredits[0][year] = intramodal_draws[indexTS]; + area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = intramodal_draws[indexTS]; // ------------- // Thermal ... @@ -682,16 +682,16 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i } // ------------- - // Hydro Power Credits... + // Hydro Max Power... // ------------- - indexTS = ts_to_tsIndex.at(timeSeriesHydroPowerCredits); + indexTS = ts_to_tsIndex.at(timeSeriesHydroMaxPower); if (!isTSintramodal[indexTS]) { - uint nbTimeSeries = area.hydro.series->maxgen.width; + uint nbTimeSeries = area.hydro.series->maxPowerTScount(); if (nbTimeSeries != 1) { - area.hydro.series->timeseriesNumbersPowerCredits[0][year] = static_cast( + area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = static_cast( (floor(study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries))); } } @@ -805,8 +805,8 @@ Matrix* getFirstTSnumberInterModalMatrixFoundInArea( else if (isTSintermodal[ts_to_tsIndex.at(timeSeriesRenewable)] && area.renewable.clusterCount() > 0) tsNumbersMtx = &(area.renewable.clusters[0]->series->timeseriesNumbers); - else if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydroPowerCredits)]) - tsNumbersMtx = &(area.hydro.series->timeseriesNumbersPowerCredits); + else if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydroMaxPower)]) + tsNumbersMtx = &(area.hydro.series->timeseriesNumbersHydroMaxPower); } assert(tsNumbersMtx); @@ -839,9 +839,9 @@ void applyMatrixDrawsToInterModalModesInArea(Matrix* tsNumbersMtx, if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydro)]) area.hydro.series->timeseriesNumbers[0][year] = draw; - assert(year < area.hydro.series->timeseriesNumbersPowerCredits.height); - if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydroPowerCredits)]) - area.hydro.series->timeseriesNumbersPowerCredits[0][year] = draw; + assert(year < area.hydro.series->timeseriesNumbersHydroMaxPower.height); + if (isTSintermodal[ts_to_tsIndex.at(timeSeriesHydroMaxPower)]) + area.hydro.series->timeseriesNumbersHydroMaxPower[0][year] = draw; if (isTSintermodal[ts_to_tsIndex.at(timeSeriesThermal)]) { @@ -894,10 +894,10 @@ static void fixTSNumbersWhenWidthIsOne(Study& study) area.wind.series->timeseriesNumbers, area.wind.series->timeSeries.width, years); // Hydro fixTSNumbersSingleAreaSingleMode( - area.hydro.series->timeseriesNumbers, area.hydro.series->count, years); - // Hydro Power Credits + area.hydro.series->timeseriesNumbers, area.hydro.series->TScount(), years); + // Hydro Max Power fixTSNumbersSingleAreaSingleMode( - area.hydro.series->timeseriesNumbersPowerCredits, area.hydro.series->countpowercredits, years); + area.hydro.series->timeseriesNumbersHydroMaxPower, area.hydro.series->maxPowerTScount(), years); // Thermal std::for_each(area.thermal.clusters.cbegin(), @@ -965,7 +965,7 @@ bool TimeSeriesNumbers::Generate(Study& study) (bool)(timeSeriesRenewable & parameters.intraModal) && parameters.renewableGeneration.isClusters(), (bool)(timeSeriesTransmissionCapacities & parameters.intraModal), - static_cast(timeSeriesHydroPowerCredits & parameters.intraModal)}; + static_cast(timeSeriesHydroMaxPower & parameters.intraModal)}; array nbTimeseriesByMode; @@ -980,7 +980,7 @@ bool TimeSeriesNumbers::Generate(Study& study) (bool)(timeSeriesSolar & parameters.timeSeriesToRefresh), false, // TS generation is always disabled for renewables false, // TS generation is always disabled for links transmission capacities - false}; // TS generation is always disabled for hydro power credits + false}; // TS generation is always disabled for hydro max power if (not checkIntraModalConsistency(nbTimeseriesByMode, isTSintramodal, isTSgenerated, study)) return false; @@ -1012,7 +1012,7 @@ bool TimeSeriesNumbers::Generate(Study& study) (bool)(timeSeriesRenewable & parameters.interModal) && parameters.renewableGeneration.isClusters(), false, // links transmission capacities time series cannot be inter-modal - static_cast(timeSeriesHydroPowerCredits & parameters.interModal)}; + static_cast(timeSeriesHydroMaxPower & parameters.interModal)}; if (std::any_of(std::begin(isTSintermodal), std::end(isTSintermodal), [](bool x) { return x; })) { @@ -1051,7 +1051,7 @@ void TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(Data::Study& study) study.storeTimeSeriesNumbers(); study.storeTimeSeriesNumbers(); study.storeTimeSeriesNumbers(); - study.storeTimeSeriesNumbers(); + study.storeTimeSeriesNumbers(); Simulation::BindingConstraintsTimeSeriesNumbersWriter ts_writer(study.resultWriter); ts_writer.write(study.bindingConstraintsGroups); diff --git a/src/solver/ts-generator/hydro.cpp b/src/solver/ts-generator/hydro.cpp index cb458bb4ad..1dfea0dfdc 100644 --- a/src/solver/ts-generator/hydro.cpp +++ b/src/solver/ts-generator/hydro.cpp @@ -50,11 +50,7 @@ namespace TSGenerator static void PreproHydroInitMatrices(Data::Study& study, uint tsCount) { study.areas.each([&](Data::Area& area) { - auto& hydroseries = *(area.hydro.series); - - hydroseries.ror.resize(tsCount, HOURS_PER_YEAR); - hydroseries.storage.resize(tsCount, DAYS_PER_YEAR); - hydroseries.count = tsCount; + area.hydro.series->resizeRORandSTORAGE(tsCount); }); } diff --git a/src/solver/variable/economy/max-mrg.cpp b/src/solver/variable/economy/max-mrg.cpp index de0754c887..f522e52259 100644 --- a/src/solver/variable/economy/max-mrg.cpp +++ b/src/solver/variable/economy/max-mrg.cpp @@ -133,9 +133,9 @@ inline void PrepareMaxMRGFor(const State& state, double* opmrg, uint numSpace) uint loop = 100; // arbitrary - maximum number of iterations // Pmax - uint tsIndex = (NumeroChroniquesTireesParPays[numSpace][index]).HydrauliquePowerCredits; - auto& maxgenmatrix = area.hydro.series->maxgen; - const auto& P = maxgenmatrix[tsIndex < maxgenmatrix.width ? tsIndex : 0]; + uint tsIndex = (NumeroChroniquesTireesParPays[numSpace][index]).HydroMaxPower; + auto& maxHourlyGenPowerMatrix = area.hydro.series->maxHourlyGenPower; + const auto& P = maxHourlyGenPowerMatrix[tsIndex]; do { diff --git a/src/tests/run-study-tests/test_unfeasible_problem.py b/src/tests/run-study-tests/test_unfeasible_problem.py index 7ef0212061..4047907b21 100644 --- a/src/tests/run-study-tests/test_unfeasible_problem.py +++ b/src/tests/run-study-tests/test_unfeasible_problem.py @@ -65,4 +65,3 @@ def test_unfeasible_problem_01__warning_dry(study_path, check_runner): checks_on_weeks=warnings_on_weeks, simulation=check_runner.get_simulation())) check_runner.run(checks) - diff --git a/src/tests/src/libs/antares/study/constraint/test_constraint.cpp b/src/tests/src/libs/antares/study/constraint/test_constraint.cpp index a671d7857c..91aedabf1b 100644 --- a/src/tests/src/libs/antares/study/constraint/test_constraint.cpp +++ b/src/tests/src/libs/antares/study/constraint/test_constraint.cpp @@ -13,7 +13,7 @@ #include "antares/study/area/area.h" #include #include -#include "utils.h" +#include using namespace Antares::Data; namespace fs = std::filesystem; diff --git a/src/tests/src/libs/antares/study/constraint/test_group.cpp b/src/tests/src/libs/antares/study/constraint/test_group.cpp index c53f3c855d..c7f4faef7d 100644 --- a/src/tests/src/libs/antares/study/constraint/test_group.cpp +++ b/src/tests/src/libs/antares/study/constraint/test_group.cpp @@ -9,7 +9,7 @@ #include #include #include "antares/study/study.h" -#include "utils.h" +#include using namespace Antares::Data; namespace fs = std::filesystem; diff --git a/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt b/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt index 41f54f9059..d113d66e8b 100644 --- a/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt @@ -1,66 +1,59 @@ # Useful variables definitions set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") set(src_libs_antares "${CMAKE_SOURCE_DIR}/libs/antares") +set(src_test_utils "${CMAKE_SOURCE_DIR}/tests/src/utils") -# Hydro data transfer -set(SRC_DATA_TRANSFER - test-datatransfer-class.cpp - help-functions.h - help-functions.cpp) -add_executable(test-hydro-data-transfer ${SRC_DATA_TRANSFER}) +# Hydro data reader +set(SRC_HYDRO_READER + test-hydroreader-class.cpp) -target_include_directories(test-hydro-data-transfer +add_executable(test-hydro-reader ${SRC_HYDRO_READER}) + +target_include_directories(test-hydro-reader PRIVATE "${src_libs_antares_study}" - "${src_libs_antares_study}/parts/hydro" "${src_libs_antares}/array/antares/array" + "${src_test_utils}" ) -target_link_libraries(test-hydro-data-transfer +target_link_libraries(test-hydro-reader PRIVATE Boost::unit_test_framework - antares-core - model_antares - antares-solver-hydro - yuni-static-core + Antares::study + test_utils_unit ) # Linux if(UNIX AND NOT APPLE) - target_link_libraries(test-hydro-data-transfer PRIVATE stdc++fs) + target_link_libraries(test-hydro-reader PRIVATE stdc++fs) endif() -set_target_properties(test-hydro-data-transfer PROPERTIES FOLDER Unit-tests) -add_test(NAME test-hydro-data-transfer COMMAND test-hydro-data-transfer) -set_property(TEST test-hydro-data-transfer PROPERTY LABELS unit) +set_target_properties(test-hydro-reader PROPERTIES FOLDER Unit-tests/hydro) +add_test(NAME hydro-reader COMMAND test-hydro-reader) +set_property(TEST hydro-reader PROPERTY LABELS unit) -# Useful variables definitions -set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") -set(src_libs_antares "${CMAKE_SOURCE_DIR}/libs/antares") # Hydro series set(SRC_HYDRO_SERIES - test-hydro-series.cpp - help-functions.h - help-functions.cpp) + test-hydro-series.cpp) add_executable(test-hydro-series ${SRC_HYDRO_SERIES}) target_include_directories(test-hydro-series PRIVATE "${src_libs_antares_study}" - "${src_libs_antares_study}/parts/hydro" "${src_libs_antares}/array/antares/array" + "${src_libs_antares}/exception/antares/exception" + "${src_test_utils}" ) target_link_libraries(test-hydro-series PRIVATE Boost::unit_test_framework - antares-core - model_antares - antares-solver-hydro - yuni-static-core + Antares::study + Antares::exception + test_utils_unit ) # Linux @@ -68,6 +61,6 @@ if(UNIX AND NOT APPLE) target_link_libraries(test-hydro-series PRIVATE stdc++fs) endif() -set_target_properties(test-hydro-series PROPERTIES FOLDER Unit-tests) -add_test(NAME test-hydro-series COMMAND test-hydro-series) -set_property(TEST test-hydro-series PROPERTY LABELS unit) \ No newline at end of file +set_target_properties(test-hydro-series PROPERTIES FOLDER Unit-tests/hydro) +add_test(NAME hydro-series COMMAND test-hydro-series) +set_property(TEST hydro-series PROPERTY LABELS unit) \ No newline at end of file diff --git a/src/tests/src/libs/antares/study/parts/hydro/help-functions.cpp b/src/tests/src/libs/antares/study/parts/hydro/help-functions.cpp deleted file mode 100644 index 5d96198a85..0000000000 --- a/src/tests/src/libs/antares/study/parts/hydro/help-functions.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "help-functions.h" - -void createFolder(const my_string& path, const my_string& folder_name) -{ - fs::path folder_path = fs::path(path.c_str()) / folder_name.c_str(); - fs::create_directory(folder_path); -} - -bool createFile(const my_string& folder_path, const my_string& file_name) -{ - // Construct the full path to the file - fs::path path = fs::path(folder_path.c_str()) / file_name.c_str(); - - // Create an output file stream - std::ofstream outputFile(path); - - if (outputFile.is_open()) - { - // File was successfully created and is open - outputFile << "This is a sample content." << std::endl; - outputFile.close(); - return true; - } - else - { - // Failed to create or open the file - return false; - } -} - -void InstantiateMatrix(Matrix& matrix, double seed, uint type) -{ - for (uint i = 0; i < matrix.width; i++) - { - for (uint hours = 0; hours < type; hours++) - { - if (hours != 0 && hours != type - 1) - matrix[i][hours] = seed; - else if (hours == 0) - matrix[i][hours] = seed + 1; - else if (hours == type - 1) - matrix[i][hours] = seed + 2; - } - } -} - -void InstantiateColumn(Matrix::ColumnType& col, double seed, uint type) -{ - for (uint days = 0; days < type; days++) - { - if (days != 0 && days != type - 1) - col[days] = seed; - else if (days == 0) - col[days] = seed + 1; - else if (days == type - 1) - col[days] = seed + 2; - } -} - -void removeFolder(my_string& path, my_string& folder_name) -{ - fs::path folder_path = fs::path(path.c_str()) / folder_name.c_str(); - if (fs::exists(folder_path)) - { - try - { - fs::remove_all(folder_path); - std::cout << "Folder '" << folder_name << "' at '" << folder_path - << "' deleted.\n"; - } - catch (const fs::filesystem_error& e) - { - std::cerr << "Exception deleting folder '" << folder_name << "': " << e.what() - << "\n"; - } - } -} \ No newline at end of file diff --git a/src/tests/src/libs/antares/study/parts/hydro/help-functions.h b/src/tests/src/libs/antares/study/parts/hydro/help-functions.h deleted file mode 100644 index 6e0e579d49..0000000000 --- a/src/tests/src/libs/antares/study/parts/hydro/help-functions.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#define SEP Yuni::IO::Separator - -using namespace Antares::Data; -using my_string = Yuni::CString<256, false>; -using namespace std; -namespace fs = std::filesystem; - -void createFolder(const my_string& path, const my_string& folder_name); -bool createFile(const my_string& folder_path, const my_string& file_name); -void InstantiateMatrix(Matrix& matrix, double seed, uint type); -void InstantiateColumn(Matrix::ColumnType& col, double seed, uint type); -void removeFolder(my_string& path, my_string& folder_name); \ No newline at end of file diff --git a/src/tests/src/libs/antares/study/parts/hydro/test-datatransfer-class.cpp b/src/tests/src/libs/antares/study/parts/hydro/test-datatransfer-class.cpp deleted file mode 100644 index 95f3e75c7e..0000000000 --- a/src/tests/src/libs/antares/study/parts/hydro/test-datatransfer-class.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#define BOOST_TEST_MODULE test data transfer - -#define WIN32_LEAN_AND_MEAN - -#include -#include "help-functions.h" -#include - -struct Fixture -{ - Fixture() - { - study = make_shared(true); - datatransfer = make_shared(); - study->inputExtension = "txt"; - // Add areas - area_1 = study->areaAdd("Area1"); - area_2 = study->areaAdd("Area2"); - study->areas.rebuildIndexes(); - - // Create necessary folders and files for these two areas - createFoldersAndFiles(); - - auto& gen = datatransfer->maxPower[DataTransfer::genMaxP]; - InstantiateColumn(gen, 300., DAYS_PER_YEAR); - - auto& pump = datatransfer->maxPower[DataTransfer::pumpMaxP]; - InstantiateColumn(pump, 200., DAYS_PER_YEAR); - - auto& hoursGen = datatransfer->maxPower[DataTransfer::genMaxE]; - InstantiateColumn(hoursGen, 20., DAYS_PER_YEAR); - - auto& hoursPump = datatransfer->maxPower[DataTransfer::pumpMaxE]; - InstantiateColumn(hoursPump, 14., DAYS_PER_YEAR); - - my_string buffer; - my_string file_name = "maxpower_" + area_2->id + ".txt"; - buffer.clear() << base_folder << SEP << hydro_folder << SEP << common_folder << SEP - << capacity_folder << SEP << file_name; - datatransfer->maxPower.saveToCSVFile(buffer, 2); - } - - void createFoldersAndFiles() - { - my_string buffer; - - // hydro folder - createFolder(base_folder, hydro_folder); - - // series folder - buffer.clear() << base_folder << SEP << hydro_folder; - createFolder(buffer, series_folder); - - // area1 folder - my_string area1_folder = area_1->id; - buffer.clear() << base_folder << SEP << hydro_folder << SEP << series_folder; - createFolder(buffer, area1_folder); - buffer.clear() << base_folder << SEP << hydro_folder << SEP << series_folder << SEP - << area1_folder; - // maxgen and maxpump files - createFile(buffer, maxgentxt); - createFile(buffer, maxpumptxt); - - // common and capacity folders - buffer.clear() << base_folder << SEP << hydro_folder; - createFolder(buffer, common_folder); - buffer.clear() << base_folder << SEP << hydro_folder << SEP << common_folder; - createFolder(buffer, capacity_folder); - - // maxhours files - buffer.clear() << base_folder << SEP << hydro_folder << SEP << common_folder << SEP - << capacity_folder; - my_string file1_name = maxhoursGen << SEP << area_2->id << SEP << ".txt"; - my_string file2_name = maxhoursPump << SEP << area_2->id << SEP << ".txt"; - my_string file3_name = maxpower << SEP << area_2->id << SEP << ".txt"; - - createFile(buffer, file1_name); - createFile(buffer, file2_name); - createFile(buffer, file3_name); - } - - shared_ptr study; - shared_ptr datatransfer; - Area* area_1; - Area* area_2; - my_string base_folder = fs::current_path().string(); - my_string hydro_folder = "hydro"; - my_string series_folder = "series"; - my_string common_folder = "common"; - my_string capacity_folder = "capacity"; - my_string maxhoursGen = "maxhoursGen_"; - my_string maxhoursPump = "maxhoursPump_"; - my_string maxpower = "maxpower_"; - my_string maxgentxt = "maxgen.txt"; - my_string maxpumptxt = "maxpump.txt"; - - ~Fixture() - { - removeFolder(base_folder, hydro_folder); - } -}; - -BOOST_AUTO_TEST_SUITE(s) - -BOOST_FIXTURE_TEST_CASE(Testing_support_for_old_studies, Fixture) -{ - my_string buffer; - bool ret = false; - - buffer.clear() << base_folder << SEP << hydro_folder; - ret = datatransfer->SupportForOldStudies(*study, buffer, *area_1); - BOOST_CHECK(ret); -} - -BOOST_FIXTURE_TEST_CASE(Testing_auto_transfer_hours, Fixture) -{ - my_string buffer; - bool ret = false; - - buffer.clear() << base_folder << SEP << hydro_folder; - ret = datatransfer->AutoTransferHours(*study, buffer, *area_2); - BOOST_CHECK(ret); -} - -BOOST_FIXTURE_TEST_CASE(Testing_load_from_folder_when_retuns_true, Fixture) -{ - my_string buffer; - bool ret = false; - datatransfer->maxPower.reset(4, DAYS_PER_YEAR, true); - - buffer.clear() << base_folder << SEP << hydro_folder; - ret = datatransfer->LoadFromFolder(*study, buffer, *area_2); - BOOST_CHECK(ret); -} - -BOOST_FIXTURE_TEST_CASE(Testing_load_from_folder_when_retuns_false, Fixture) -{ - my_string buffer; - bool ret = false; - - auto& hoursGen = datatransfer->maxPower[DataTransfer::genMaxE]; - InstantiateColumn(hoursGen, 25., DAYS_PER_YEAR); - - my_string file_name = "maxpower_" + area_2->id + ".txt"; - buffer.clear() << base_folder << SEP << hydro_folder << SEP << common_folder << SEP - << capacity_folder << SEP << file_name; - datatransfer->maxPower.saveToCSVFile(buffer, 2); - datatransfer->maxPower.reset(4, DAYS_PER_YEAR, true); - - buffer.clear() << base_folder << SEP << hydro_folder; - ret = datatransfer->LoadFromFolder(*study, buffer, *area_2); - BOOST_CHECK(!ret); -} - -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/tests/src/libs/antares/study/parts/hydro/test-hydro-series.cpp b/src/tests/src/libs/antares/study/parts/hydro/test-hydro-series.cpp index 2f2772bb1c..750cdf707d 100644 --- a/src/tests/src/libs/antares/study/parts/hydro/test-hydro-series.cpp +++ b/src/tests/src/libs/antares/study/parts/hydro/test-hydro-series.cpp @@ -3,24 +3,35 @@ #define WIN32_LEAN_AND_MEAN #include -#include "help-functions.h" #include +#include +#include +#include + +#define SEP "/" + +using namespace Antares::Data; +namespace fs = std::filesystem; + +void fillTimeSeriesWithSpecialEnds(Matrix& timeSeries, double value) +{ + for (uint ts = 0; ts < timeSeries.width; ts++) + { + timeSeries[ts][0] = value + 1; + timeSeries[ts][timeSeries.height - 1] = value + 2; + } +} struct Fixture { Fixture() { // Create studies - study = make_shared(true); - study->inputExtension = "txt"; - studyNoSolver = make_shared(); - studyNoSolver->inputExtension = "txt"; + study = std::make_shared(true); // Add areas to studies area_1 = study->areaAdd("Area1"); study->areas.rebuildIndexes(); - area_No_Solver = studyNoSolver->areaAdd("AreaNoSolver"); - studyNoSolver->areas.rebuildIndexes(); // Create necessary folders and files for these two areas createFoldersAndFiles(); @@ -29,42 +40,47 @@ struct Fixture study->header.version = 870; study->parameters.derated = false; - studyNoSolver->header.version = 870; - studyNoSolver->parameters.derated = false; + // Setting necessary paths + pathToMaxHourlyGenPower_file.clear(); + pathToMaxHourlyGenPower_file = base_folder + SEP + series_folder + SEP + area_1->id.c_str() + + SEP + maxHourlyGenPower_file; + + pathToMaxHourlyPumpPower_file.clear(); + pathToMaxHourlyPumpPower_file = base_folder + SEP + series_folder + SEP + area_1->id.c_str() + + SEP + maxHourlyPumpPower_file; + + pathToSeriesFolder.clear(); + pathToSeriesFolder = base_folder + SEP + series_folder; } void createFoldersAndFiles() { // series folder - my_string buffer; + stringT buffer; createFolder(base_folder, series_folder); - // areas folder - my_string area1_folder = area_1->id; - my_string area_No_Solver_folder = area_No_Solver->id; - buffer.clear() << base_folder << SEP << series_folder; + // area folder + stringT area1_folder = area_1->id.c_str(); + buffer.clear(); + buffer = base_folder + SEP + series_folder; createFolder(buffer, area1_folder); - createFolder(buffer, area_No_Solver_folder); - - // maxgen and maxpump files - buffer.clear() << base_folder << SEP << series_folder << SEP << area1_folder; - createFile(buffer, maxgentxt); - createFile(buffer, maxpumptxt); - // maxgen and maxpump files - buffer.clear() << base_folder << SEP << series_folder << SEP << area_No_Solver_folder; - createFile(buffer, maxgentxt); - createFile(buffer, maxpumptxt); + // maxHourlyGenPower and maxHourlyPumpPower files + buffer.clear(); + buffer = base_folder + SEP + series_folder + SEP + area1_folder; + createFile(buffer, maxHourlyGenPower_file); + createFile(buffer, maxHourlyPumpPower_file); } - shared_ptr study; - shared_ptr studyNoSolver; + std::shared_ptr study; Area* area_1; - Area* area_No_Solver; - my_string base_folder = fs::current_path().string(); - my_string series_folder = "series"; - my_string maxgentxt = "maxgen.txt"; - my_string maxpumptxt = "maxpump.txt"; + stringT base_folder = fs::temp_directory_path().string(); + stringT series_folder = "series"; + stringT maxHourlyGenPower_file = "maxHourlyGenPower.txt"; + stringT maxHourlyPumpPower_file = "maxHourlyPumpPower.txt"; + stringT pathToMaxHourlyGenPower_file; + stringT pathToMaxHourlyPumpPower_file; + stringT pathToSeriesFolder; ~Fixture() { @@ -74,110 +90,177 @@ struct Fixture BOOST_AUTO_TEST_SUITE(s) -BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_both_matrix_equal_width, Fixture) +BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_matrices_equal_width, Fixture) { - bool ret = false; - auto& maxgen = area_1->hydro.series->maxgen; - auto& maxpump = area_1->hydro.series->maxpump; - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - InstantiateMatrix(maxgen, 400., HOURS_PER_YEAR); - InstantiateMatrix(maxpump, 200., HOURS_PER_YEAR); - - my_string buffer; - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxgentxt; - maxgen.saveToCSVFile(buffer, 0); - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxpumptxt; - maxpump.saveToCSVFile(buffer, 0); - - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - buffer.clear() << base_folder << SEP << series_folder; - ret = area_1->hydro.series->LoadHydroPowerCredits(*study, area_1->id, buffer); + bool ret = true; + bool fatalError = false; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; BOOST_CHECK(ret); + + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + + BOOST_CHECK(!fatalError); + BOOST_CHECK_EQUAL(maxHourlyGenPower.width, 3); } -BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_matrices_different_width_case_1, Fixture) +BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_both_matrix_equal_width_and_derated, Fixture) { - bool ret = false; - auto& maxgen = area_1->hydro.series->maxgen; - auto& maxpump = area_1->hydro.series->maxpump; - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - InstantiateMatrix(maxgen, 400., HOURS_PER_YEAR); - InstantiateMatrix(maxpump, 200., HOURS_PER_YEAR); - - my_string buffer; - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxgentxt; - maxgen.saveToCSVFile(buffer, 0); - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxpumptxt; - maxpump.saveToCSVFile(buffer, 0); - - maxgen.reset(1, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - buffer.clear() << base_folder << SEP << series_folder; - ret = area_1->hydro.series->LoadHydroPowerCredits(*study, area_1->id, buffer); + bool ret = true; + bool fatalError = false; + study->parameters.derated = true; + unsigned int studyVersion = 870; + bool usedBySolver = true; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; BOOST_CHECK(ret); - BOOST_CHECK_EQUAL(maxgen.width, 3); + + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + area_1->hydro.series->resizeTSinDeratedMode(study->parameters.derated, studyVersion, usedBySolver); + + BOOST_CHECK_EQUAL(maxHourlyGenPower.width, 1); + BOOST_CHECK_EQUAL(maxHourlyPumpPower.width, 1); + BOOST_CHECK(!fatalError); } BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_matrices_different_width_case_2, Fixture) { - bool ret = false; - auto& maxgen = area_1->hydro.series->maxgen; - auto& maxpump = area_1->hydro.series->maxpump; - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); - - InstantiateMatrix(maxgen, 400., HOURS_PER_YEAR); - InstantiateMatrix(maxpump, 200., HOURS_PER_YEAR); - - my_string buffer; - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxgentxt; - maxgen.saveToCSVFile(buffer, 0); - buffer.clear() << base_folder << SEP << series_folder << SEP << area_1->id << SEP << maxpumptxt; - maxpump.saveToCSVFile(buffer, 0); - - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(1, HOURS_PER_YEAR); - - buffer.clear() << base_folder << SEP << series_folder; - ret = area_1->hydro.series->LoadHydroPowerCredits(*study, area_1->id, buffer); + bool ret = true; + bool fatalError = false; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(2, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(3, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(2, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; BOOST_CHECK(ret); - BOOST_CHECK_EQUAL(maxpump.width, 3); + + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + BOOST_CHECK(fatalError); } -BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_no_solver, Fixture) +BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_different_width_case_1, Fixture) { - bool ret = false; - auto& maxgen = area_No_Solver->hydro.series->maxgen; - auto& maxpump = area_No_Solver->hydro.series->maxpump; - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - InstantiateMatrix(maxgen, 400., HOURS_PER_YEAR); - InstantiateMatrix(maxpump, 200., HOURS_PER_YEAR); - - my_string buffer; - buffer.clear() << base_folder << SEP << series_folder << SEP << area_No_Solver->id << SEP - << maxgentxt; - maxgen.saveToCSVFile(buffer, 0); - buffer.clear() << base_folder << SEP << series_folder << SEP << area_No_Solver->id << SEP - << maxpumptxt; - maxpump.saveToCSVFile(buffer, 0); - - maxgen.reset(3, HOURS_PER_YEAR); - maxpump.reset(3, HOURS_PER_YEAR); - - buffer.clear() << base_folder << SEP << series_folder; - ret = area_No_Solver->hydro.series->LoadHydroPowerCredits( - *studyNoSolver, area_No_Solver->id, buffer); + bool ret = true; + bool fatalError = false; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(1, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(1, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(3, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; BOOST_CHECK(ret); - BOOST_CHECK(area_No_Solver->hydro.hydroModulable); + + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + + BOOST_CHECK(!fatalError); + BOOST_CHECK_EQUAL(maxHourlyGenPower.width, maxHourlyPumpPower.width); +} + +BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_different_width_case_2, Fixture) +{ + bool ret = true; + bool fatalError = false; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(4, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(4, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; + BOOST_CHECK(ret); + + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + + BOOST_CHECK(!fatalError); + BOOST_CHECK_EQUAL(maxHourlyGenPower.width, maxHourlyPumpPower.width); +} + +BOOST_FIXTURE_TEST_CASE(Testing_load_power_credits_both_zeros, Fixture) +{ + bool ret = true; + bool fatalError = false; + + auto& maxHourlyGenPower = area_1->hydro.series->maxHourlyGenPower; + auto& maxHourlyPumpPower = area_1->hydro.series->maxHourlyPumpPower; + maxHourlyGenPower.reset(4, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); + + fillTimeSeriesWithSpecialEnds(maxHourlyGenPower, 400.); + fillTimeSeriesWithSpecialEnds(maxHourlyPumpPower, 200.); + + ret = maxHourlyGenPower.saveToCSVFile(pathToMaxHourlyGenPower_file, 0) && ret; + ret = maxHourlyPumpPower.saveToCSVFile(pathToMaxHourlyPumpPower_file, 0) && ret; + + maxHourlyGenPower.reset(4, HOURS_PER_YEAR); + maxHourlyPumpPower.reset(1, HOURS_PER_YEAR); + + ret = area_1->hydro.series->LoadMaxPower(area_1->id, pathToSeriesFolder) && ret; + BOOST_CHECK(ret); + + maxHourlyGenPower.width = 0; + maxHourlyPumpPower.width = 0; + area_1->hydro.series->EqualizeMaxPowerTSsizes(*area_1, fatalError); + + BOOST_CHECK(!fatalError); + BOOST_CHECK_EQUAL(maxHourlyGenPower.width, maxHourlyPumpPower.width); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/tests/src/libs/antares/study/parts/hydro/test-hydroreader-class.cpp b/src/tests/src/libs/antares/study/parts/hydro/test-hydroreader-class.cpp new file mode 100644 index 0000000000..c581528e8b --- /dev/null +++ b/src/tests/src/libs/antares/study/parts/hydro/test-hydroreader-class.cpp @@ -0,0 +1,184 @@ +#define BOOST_TEST_MODULE test data transfer + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include + +#define SEP "/" + +using namespace Antares::Data; +namespace fs = std::filesystem; + +bool equalDailyMaxPowerAsHourlyTs(const Matrix::ColumnType& hourlyColumn, + const Matrix::ColumnType& dailyColumn) +{ + uint hour = 0; + uint day = 0; + + while (hour < HOURS_PER_YEAR && day < DAYS_PER_YEAR) + { + for (uint i = 0; i < HOURS_PER_DAY; ++i) + { + if (hourlyColumn[hour] != dailyColumn[day]) + return false; + ++hour; + } + ++day; + } + + return true; +} + +bool equalDailyMaxEnergyTs(const Matrix::ColumnType& col1, const Matrix::ColumnType& col2) +{ + for (uint h = 0; h < DAYS_PER_YEAR; ++h) + { + if (col1[h] != col2[h]) + return false; + } + + return true; +} + +void fillColumnWithSpecialEnds(Matrix::ColumnType& col, double value, uint heigth) +{ + col[0] = value + 1; + col[heigth - 1] = value + 2; +} + +struct Fixture +{ + Fixture() + { + study = std::make_shared(true); + reader = std::make_shared(); + // Add areas + area_1 = study->areaAdd("Area1"); + study->areas.rebuildIndexes(); + + // Create necessary folders and files for these two areas + createFoldersAndFiles(); + + auto& gen = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::genMaxP]; + fillColumnWithSpecialEnds(gen, 300., DAYS_PER_YEAR); + + auto& pump = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::pumpMaxP]; + fillColumnWithSpecialEnds(pump, 200., DAYS_PER_YEAR); + + auto& hoursGen = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::genMaxE]; + fillColumnWithSpecialEnds(hoursGen, 20., DAYS_PER_YEAR); + + auto& hoursPump = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::pumpMaxE]; + fillColumnWithSpecialEnds(hoursPump, 14., DAYS_PER_YEAR); + + stringT buffer; + buffer.clear(); + buffer = base_folder + SEP + hydro_folder + SEP + common_folder + SEP + capacity_folder + + SEP + maxpower + area_1->id.c_str() + ".txt"; + reader->dailyMaxPumpAndGen.saveToCSVFile(buffer, 2); + + // Reset columns + reader->dailyMaxPumpAndGen.fillColumn(HydroMaxTimeSeriesReader::genMaxP, 0.); + reader->dailyMaxPumpAndGen.fillColumn(HydroMaxTimeSeriesReader::pumpMaxP, 0.); + reader->dailyMaxPumpAndGen.fillColumn(HydroMaxTimeSeriesReader::genMaxE, 24.); + reader->dailyMaxPumpAndGen.fillColumn(HydroMaxTimeSeriesReader::pumpMaxE, 24.); + } + + void createFoldersAndFiles() + { + stringT buffer; + stringT area1_ID = area_1->id.c_str(); + stringT maxpowerArea1 = maxpower + area1_ID + ".txt"; + stringT maxDailyGenEnergy_Area1 = maxDailyGenEnergy_ + area1_ID + ".txt"; + stringT maxDailyPumpEnergy_Area1 = maxDailyPumpEnergy_ + area1_ID + ".txt"; + + buffer.clear(); + + // hydro folder + createFolder(base_folder, hydro_folder); + + // series folder + buffer = base_folder + SEP + hydro_folder; + createFolder(buffer, series_folder); + + // area1 folder + buffer.clear(); + buffer = base_folder + SEP + hydro_folder + SEP + series_folder; + createFolder(buffer, area1_ID); + buffer.clear(); + buffer = base_folder + SEP + hydro_folder + SEP + series_folder + SEP + area1_ID; + + // maxHourlyGenPower and maxHourlyPumpPower files + createFile(buffer, maxHourlyGenPower); + createFile(buffer, maxHourlyPumpPower); + + // common and capacity folders + buffer.clear(); + buffer = base_folder + SEP + hydro_folder; + createFolder(buffer, common_folder); + buffer.clear(); + buffer = base_folder + SEP + hydro_folder + SEP + common_folder; + createFolder(buffer, capacity_folder); + + // max daily energy and power file + buffer.clear(); + buffer = base_folder + SEP + hydro_folder + SEP + common_folder + SEP + capacity_folder; + createFile(buffer, maxpowerArea1); + + // max daily energy files + createFile(buffer, maxDailyGenEnergy_Area1); + createFile(buffer, maxDailyPumpEnergy_Area1); + } + + std::shared_ptr study; + std::shared_ptr reader; + Area* area_1; + stringT base_folder = fs::temp_directory_path().string(); + stringT hydro_folder = "hydro"; + stringT series_folder = "series"; + stringT common_folder = "common"; + stringT capacity_folder = "capacity"; + stringT maxDailyGenEnergy_ = "maxDailyGenEnergy_"; + stringT maxDailyPumpEnergy_ = "maxDailyPumpEnergy_"; + stringT maxpower = "maxpower_"; + stringT maxHourlyGenPower = "maxHourlyGenPower.txt"; + stringT maxHourlyPumpPower = "maxHourlyPumpPower.txt"; + + ~Fixture() + { + removeFolder(base_folder, hydro_folder); + } +}; + +BOOST_AUTO_TEST_SUITE(s) + +BOOST_FIXTURE_TEST_CASE(Testing_support_for_old_studies, Fixture) +{ + stringT buffer; + bool ret = true; + + auto& genP = area_1->hydro.series->maxHourlyGenPower[0]; + auto& pumpP = area_1->hydro.series->maxHourlyPumpPower[0]; + auto& genE = area_1->hydro.maxDailyGenEnergy[0]; + auto& pumpE = area_1->hydro.maxDailyPumpEnergy[0]; + + auto& genPReader = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::genMaxP]; + auto& pumpPReader = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::pumpMaxP]; + auto& genEReader = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::genMaxE]; + auto& pumpEReader = reader->dailyMaxPumpAndGen[HydroMaxTimeSeriesReader::pumpMaxE]; + + buffer.clear(); + buffer = base_folder + SEP + hydro_folder; + ret = (*reader)(buffer, *area_1, study->usedByTheSolver) && ret; + + BOOST_CHECK(ret); + BOOST_CHECK(equalDailyMaxPowerAsHourlyTs(genP, genPReader)); + BOOST_CHECK(equalDailyMaxPowerAsHourlyTs(pumpP, pumpPReader)); + BOOST_CHECK(equalDailyMaxEnergyTs(genE, genEReader)); + BOOST_CHECK(equalDailyMaxEnergyTs(pumpE, pumpEReader)); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file 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 f5457ea6c5..d098cf3ca0 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 @@ -83,15 +83,15 @@ struct Fixture // Hydro : set the nb of ready made TS nbReadyMadeTS = 12; - area_1->hydro.series->count = nbReadyMadeTS; - area_2->hydro.series->count = nbReadyMadeTS; - area_3->hydro.series->count = nbReadyMadeTS; + area_1->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); + area_2->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); + area_3->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); - // Hydro Power Credits: set the nb of ready made TS + // Hydro Max Power: set the nb of ready made TS nbReadyMadeTS = 15; - area_1->hydro.series->countpowercredits = nbReadyMadeTS; - area_2->hydro.series->countpowercredits = nbReadyMadeTS; - area_3->hydro.series->countpowercredits = nbReadyMadeTS; + area_1->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); + area_2->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); + area_3->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); // Links link_12 = AreaAddLinkBetweenAreas(area_1, area_2, false); @@ -239,7 +239,7 @@ BOOST_FIXTURE_TEST_CASE(on_area2_and_on_year_15__solar_TS_number_3_is_chosen__re } // ================= -// Tests on Hydro Power Credits +// 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) { @@ -248,10 +248,10 @@ BOOST_FIXTURE_TEST_CASE(on_area3_and_on_year_10__hydro_power_credits_TS_number_6 AreaName::Vector splitKey = { "hgp", "area 3", yearNumber }; BOOST_CHECK(my_rule.readLine(splitKey, tsNumber, false)); - BOOST_CHECK_EQUAL(my_rule.hydroPowerCredits.get_value(yearNumber.to(), area_3->index), tsNumber.to()); + 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->timeseriesNumbersPowerCredits[0][yearNumber.to()], tsNumber.to() - 1); + BOOST_CHECK_EQUAL(area_3->hydro.series->timeseriesNumbersHydroMaxPower[0][yearNumber.to()], tsNumber.to() - 1); } diff --git a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp index 6cc7154ed8..b2e26dd653 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp +++ b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp @@ -96,8 +96,7 @@ struct commonFixture study = std::make_shared(); // Set study parameters study->parameters.nbYears = 20; - study->parameters.timeSeriesToGenerate - = 0; // No generated time-series, only ready made time-series + study->parameters.timeSeriesToGenerate = 0; // No generated time-series, only ready made time-series // Add areas area_1 = study->areaAdd("Area 1"); @@ -125,15 +124,15 @@ struct commonFixture // Hydro : set the nb of ready made TS nbReadyMadeTS = 12; - area_1->hydro.series->count = nbReadyMadeTS; - area_2->hydro.series->count = nbReadyMadeTS; - area_3->hydro.series->count = nbReadyMadeTS; + area_1->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); + area_2->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); + area_3->hydro.series->resizeGenerationTS(nbReadyMadeTS, 1); - // Hydro Power Credits : set the nb of ready made TS + // Hydro Max Power : set the nb of ready made TS nbReadyMadeTS = 15; - area_1->hydro.series->countpowercredits = nbReadyMadeTS; - area_2->hydro.series->countpowercredits = nbReadyMadeTS; - area_3->hydro.series->countpowercredits = nbReadyMadeTS; + area_1->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); + area_2->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); + area_3->hydro.series->resizeMaxPowerTS(nbReadyMadeTS, 1); // Links link_12 = AreaAddLinkBetweenAreas(area_1, area_2, false); @@ -357,14 +356,14 @@ BOOST_FIXTURE_TEST_CASE( } // ================= -// Tests on Hydro Power Credits +// Tests on Hydro Max Power // ================= BOOST_FIXTURE_TEST_CASE( HYDRO_POWER_CREDITS__TS_number_for_many_areas_and_years__generated_and_ref_sc_buider_files_are_identical, saveFixture) { - my_rule->hydroPowerCredits.setTSnumber(area_2->index, 10, 7); - my_rule->hydroPowerCredits.setTSnumber(area_3->index, 4, 11); - my_rule->hydroPowerCredits.setTSnumber(area_1->index, 11, 3); + my_rule->hydroMaxPower.setTSnumber(area_2->index, 10, 7); + my_rule->hydroMaxPower.setTSnumber(area_3->index, 4, 11); + my_rule->hydroMaxPower.setTSnumber(area_1->index, 11, 3); saveScenarioBuilder(); 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 940a8b28fa..889f390b47 100644 --- a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp +++ b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp @@ -11,7 +11,7 @@ #include #include "timeseries-numbers.h" #include "BindingConstraintsTimeSeriesNumbersWriter.h" -#include "utils.h" +#include #include #include #include diff --git a/src/tests/src/solver/simulation/test-time_series.cpp b/src/tests/src/solver/simulation/test-time_series.cpp index 00357c5299..897ab37ee1 100644 --- a/src/tests/src/solver/simulation/test-time_series.cpp +++ b/src/tests/src/solver/simulation/test-time_series.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "utils.h" +#include using namespace Antares::Solver; using namespace Antares::Data; diff --git a/src/tests/src/utils/CMakeLists.txt b/src/tests/src/utils/CMakeLists.txt index bc7f9bc1d7..5e4781ad96 100644 --- a/src/tests/src/utils/CMakeLists.txt +++ b/src/tests/src/utils/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(test_utils_unit - utils.cpp - utils.h + files-system.cpp + files-system.h ) target_include_directories( diff --git a/src/tests/src/utils/files-system.cpp b/src/tests/src/utils/files-system.cpp new file mode 100644 index 0000000000..32eebb9dcb --- /dev/null +++ b/src/tests/src/utils/files-system.cpp @@ -0,0 +1,73 @@ +#include "files-system.h" + +namespace fs = std::filesystem; + +fs::path generateAndCreateDirName(const std::string& dirName) +{ + fs::path working_dir = fs::temp_directory_path() / dirName; + fs::remove_all(working_dir); + fs::create_directories(working_dir); + return working_dir; +} + +void createFolder(const stringT& path, const stringT& folder_name) +{ + fs::path folder_path = fs::path(path.c_str()) / folder_name.c_str(); + + try + { + fs::create_directory(folder_path); + } + catch (const fs::filesystem_error& e) + { + std::cerr << "Exception creating folder '" + folder_name + "': " + e.what() + "\n"; + } +} + +void createFile(const stringT& folder_path, const stringT& file_name) +{ + // Construct the full path to the file + fs::path path = fs::path(folder_path.c_str()) / file_name.c_str(); + + // Create an output file stream + std::ofstream outputFile(path); + + try + { + if (outputFile.is_open()) + { + // File was successfully created and is open + outputFile << "This is a sample content." << std::endl; + outputFile.close(); + std::cout << "File " + file_name + " is created in " + folder_path + "\n"; + } + else + { + // Failed to create or open the file + std::error_code ec = std::make_error_code(std::errc::io_error); + throw fs::filesystem_error("Failed to create the file.", ec); + } + } + catch (const fs::filesystem_error& e) + { + std::cerr << "Error creating file: " << file_name << "/" << e.what() << "\n"; + } +} + +void removeFolder(stringT& path, stringT& folder_name) +{ + fs::path folder_path = fs::path(path.c_str()) / folder_name.c_str(); + if (fs::exists(folder_path)) + { + try + { + fs::remove_all(folder_path); + std::cout << "Folder " + folder_name + " at " + folder_path.string() + + " deleted.\n"; + } + catch (const fs::filesystem_error& e) + { + std::cerr << "Exception deleting folder '" + folder_name + "': " + e.what() + "\n"; + } + } +} \ No newline at end of file diff --git a/src/tests/src/utils/utils.h b/src/tests/src/utils/files-system.h similarity index 52% rename from src/tests/src/utils/utils.h rename to src/tests/src/utils/files-system.h index 9c7e70367f..ccc5289c62 100644 --- a/src/tests/src/utils/utils.h +++ b/src/tests/src/utils/files-system.h @@ -1,8 +1,17 @@ #pragma once #include +#include +#include +#include + +using stringT = std::string; // The following macro is used due to linking issues with #define CREATE_TMP_DIR_BASED_ON_TEST_NAME() generateAndCreateDirName(boost::unit_test::framework::current_test_case().p_name); std::filesystem::path generateAndCreateDirName(const std::string&); + +void createFolder(const stringT& path, const stringT& folder_name); +void createFile(const stringT& folder_path, const stringT& file_name); +void removeFolder(stringT& path, stringT& folder_name); diff --git a/src/tests/src/utils/utils.cpp b/src/tests/src/utils/utils.cpp deleted file mode 100644 index 4fd0fe735e..0000000000 --- a/src/tests/src/utils/utils.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "utils.h" - -namespace fs = std::filesystem; - -fs::path generateAndCreateDirName(const std::string& dirName) -{ - fs::path working_dir = fs::temp_directory_path() / dirName; - fs::remove_all(working_dir); - fs::create_directories(working_dir); - return working_dir; -} diff --git a/src/ui/action/handler/antares-study/area/create.cpp b/src/ui/action/handler/antares-study/area/create.cpp index 381f69dba2..781b3435e0 100644 --- a/src/ui/action/handler/antares-study/area/create.cpp +++ b/src/ui/action/handler/antares-study/area/create.cpp @@ -285,8 +285,8 @@ void Create::createActionsForAStandardAreaCopy(Context& ctx, bool copyPosition) *tsNode += prepro; *tsNode += new Action::AntaresStudy::Area::AllocationHydro(pOriginalAreaName); - //Hydro Power Credits - *tsNode += new DataTimeseries(Data::timeSeriesHydroPowerCredits, pOriginalAreaName); + //Hydro Max Power + *tsNode += new DataTimeseries(Data::timeSeriesHydroMaxPower, pOriginalAreaName); // Thermal auto* area = ctx.extStudy->areas.findFromName(pOriginalAreaName); diff --git a/src/ui/action/handler/antares-study/area/timeseries.cpp b/src/ui/action/handler/antares-study/area/timeseries.cpp index 632dfb8733..a43bdc9577 100644 --- a/src/ui/action/handler/antares-study/area/timeseries.cpp +++ b/src/ui/action/handler/antares-study/area/timeseries.cpp @@ -57,8 +57,8 @@ DataTimeseries::DataTimeseries(Data::TimeSeries ts, const AnyString& areaname) : case Data::timeSeriesThermal: pInfos.caption << "Thermal : Timeseries"; break; - case Data::timeSeriesHydroPowerCredits: - pInfos.caption << "Power-Credits : Timeseries"; + case Data::timeSeriesHydroMaxPower: + pInfos.caption << "Max-Power : Timeseries"; break; default: break; @@ -106,8 +106,8 @@ void DataTimeseries::registerViewsWL(Context& ctx) case Data::timeSeriesThermal: ctx.view["6:Thermal"]["1:TS"] = this; break; - case Data::timeSeriesHydroPowerCredits: - ctx.view["7:Power-Credits"]["1:TS"] = this; + case Data::timeSeriesHydroMaxPower: + ctx.view["7:Max-Power"]["1:TS"] = this; break; default: break; @@ -161,27 +161,13 @@ bool DataTimeseries::performWL(Context& ctx) } case Data::timeSeriesHydro: { - ctx.area->hydro.series->ror = source->hydro.series->ror; - ctx.area->hydro.series->storage = source->hydro.series->storage; - ctx.area->hydro.series->mingen = source->hydro.series->mingen; - - ctx.area->hydro.series->count = source->hydro.series->count; - - source->hydro.series->ror.unloadFromMemory(); - source->hydro.series->storage.unloadFromMemory(); - source->hydro.series->mingen.unloadFromMemory(); - + ctx.area->hydro.series->copyGenerationTS(*source->hydro.series); break; } - case Data::timeSeriesHydroPowerCredits: + case Data::timeSeriesHydroMaxPower: { - ctx.area->hydro.series->maxgen = source->hydro.series->maxgen; - ctx.area->hydro.series->maxpump = source->hydro.series->maxpump; - - ctx.area->hydro.series->countpowercredits = source->hydro.series->countpowercredits; - - source->hydro.series->maxgen.unloadFromMemory(); - source->hydro.series->maxpump.unloadFromMemory(); + ctx.area->hydro.series->copyMaxPowerTS(*source->hydro.series); + break; } case Data::timeSeriesThermal: { diff --git a/src/ui/simulator/application/main/build/scenario-builder.cpp b/src/ui/simulator/application/main/build/scenario-builder.cpp index 268c21d4f0..0618c51187 100644 --- a/src/ui/simulator/application/main/build/scenario-builder.cpp +++ b/src/ui/simulator/application/main/build/scenario-builder.cpp @@ -176,18 +176,18 @@ class hydroScBuilderPageMaker final : public simpleScBuilderPageMaker } }; -// Hydro Power Credits ... -class hydroPowerCreditsScBuilderPageMaker final : public simpleScBuilderPageMaker +// Hydro Max Power ... +class hydroMaxPowerScBuilderPageMaker final : public simpleScBuilderPageMaker { using simpleScBuilderPageMaker::simpleScBuilderPageMaker; Renderer::ScBuilderRendererBase* getRenderer() override { - return new_check_allocation(); + return new_check_allocation(); } Notebook::Page* addPageToNotebook() override { - return notebook()->add(grid(), wxT("power-credits"), wxT("Hydro-Power-Credits")); + return notebook()->add(grid(), wxT("hydro-max-power"), wxT("Hydro-Max-Power")); } }; @@ -372,9 +372,9 @@ void ApplWnd::createNBScenarioBuilder() hydroScBuilderPageMaker hydroSBpageMaker(scenarioBuilderPanel, pScenarioBuilderNotebook); pageScBuilderHydro = hydroSBpageMaker.createPage(); - hydroPowerCreditsScBuilderPageMaker hydroPowerCreditsSBpageMaker(scenarioBuilderPanel, + hydroMaxPowerScBuilderPageMaker hydroMaxPowerSBpageMaker(scenarioBuilderPanel, pScenarioBuilderNotebook); - pageScBuilderHydroPowerCredits = hydroPowerCreditsSBpageMaker.createPage(); + pageScBuilderHydroMaxPower = hydroMaxPowerSBpageMaker.createPage(); windScBuilderPageMaker windSBpageMaker(scenarioBuilderPanel, pScenarioBuilderNotebook); pageScBuilderWind = windSBpageMaker.createPage(); diff --git a/src/ui/simulator/application/main/main.h b/src/ui/simulator/application/main/main.h index 3541566589..4d7caa3918 100644 --- a/src/ui/simulator/application/main/main.h +++ b/src/ui/simulator/application/main/main.h @@ -699,7 +699,7 @@ class ApplWnd final : public Component::Frame::WxLocalFrame, public Yuni::IEvent Component::Notebook::Page* pageScBuilderLoad; Component::Notebook::Page* pageScBuilderThermal; Component::Notebook::Page* pageScBuilderHydro; - Component::Notebook::Page* pageScBuilderHydroPowerCredits; + Component::Notebook::Page* pageScBuilderHydroMaxPower; Component::Notebook::Page* pageScBuilderWind; Component::Notebook::Page* pageScBuilderSolar; Component::Notebook::Page* pageScBuilderNTC; diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/area/hydromonthlypower.cpp b/src/ui/simulator/toolbox/components/datagrid/renderer/area/hydromonthlypower.cpp index fcfa7a9389..39aa340833 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/area/hydromonthlypower.cpp +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/area/hydromonthlypower.cpp @@ -102,9 +102,9 @@ void HydroMonthlyHours::internalAreaChanged(Antares::Data::Area* area) Data::PartHydro* pHydro = (area) ? &(area->hydro) : nullptr; Renderer::ARendererArea::internalAreaChanged(area); if (pHydro && hoursType == HoursType::Generation) - MatrixAncestorType::matrix(&pHydro->maxHoursGen); + MatrixAncestorType::matrix(&pHydro->maxDailyGenEnergy); else if (pHydro && hoursType == HoursType::Pumping) - MatrixAncestorType::matrix(&pHydro->maxHoursPump); + MatrixAncestorType::matrix(&pHydro->maxDailyPumpEnergy); else MatrixAncestorType::matrix(nullptr); } diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/area/timeseries.h b/src/ui/simulator/toolbox/components/datagrid/renderer/area/timeseries.h index 95e85b051f..60b83477c0 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/area/timeseries.h +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/area/timeseries.h @@ -332,16 +332,16 @@ class TimeSeriesHydroMinGen final : public ATimeSeries } }; -class TimeSeriesHydroMaxGen final : public ATimeSeries +class TimeSeriesHydroMaxHourlyGenPower final : public ATimeSeries { public: using AncestorType = Renderer::Matrix; - TimeSeriesHydroMaxGen(wxWindow* control, Toolbox::InputSelector::Area* notifier) : + TimeSeriesHydroMaxHourlyGenPower(wxWindow* control, Toolbox::InputSelector::Area* notifier) : ATimeSeries(control, notifier) { } - ~TimeSeriesHydroMaxGen() override + ~TimeSeriesHydroMaxHourlyGenPower() override { destroyBoundEvents(); } @@ -359,21 +359,21 @@ class TimeSeriesHydroMaxGen final : public ATimeSeries private: void internalAreaChanged(Antares::Data::Area* area) override { - matrix((area && CurrentStudyIsValid()) ? &(area->hydro.series->maxgen) : NULL); + matrix((area && CurrentStudyIsValid()) ? &(area->hydro.series->maxHourlyGenPower) : NULL); Renderer::ARendererArea::internalAreaChanged(area); } }; -class TimeSeriesHydroMaxPump final : public ATimeSeries +class TimeSeriesHydroMaxHourlyPumpPower final : public ATimeSeries { public: using AncestorType = Renderer::Matrix; - TimeSeriesHydroMaxPump(wxWindow* control, Toolbox::InputSelector::Area* notifier) : + TimeSeriesHydroMaxHourlyPumpPower(wxWindow* control, Toolbox::InputSelector::Area* notifier) : ATimeSeries(control, notifier) { } - ~TimeSeriesHydroMaxPump() override + ~TimeSeriesHydroMaxHourlyPumpPower() override { destroyBoundEvents(); } @@ -391,7 +391,7 @@ class TimeSeriesHydroMaxPump final : public ATimeSeries private: void internalAreaChanged(Antares::Data::Area* area) override { - matrix((area && CurrentStudyIsValid()) ? &(area->hydro.series->maxpump) : NULL); + matrix((area && CurrentStudyIsValid()) ? &(area->hydro.series->maxHourlyPumpPower) : NULL); Renderer::ARendererArea::internalAreaChanged(area); } }; diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/column.cpp b/src/ui/simulator/toolbox/components/datagrid/renderer/column.cpp index 7c2565be7e..1363e9b39b 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/column.cpp +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/column.cpp @@ -164,9 +164,9 @@ ColumnNTC::ColumnNTC() : Column(timeSeriesTransmissionCapacities, " Links NTC } // ------------------------------- -// Column Hydro Power Credits +// Column Hydro Max Power // ------------------------------- -ColumnHydroPowerCredits::ColumnHydroPowerCredits() : Column(timeSeriesHydroPowerCredits, " Hydro-Power-Credits ") +ColumnHydroMaxPower::ColumnHydroMaxPower() : Column(timeSeriesHydroMaxPower, " Hydro-Max-Power ") { cells_ = {new_check_allocation(), new_check_allocation(wxT("On")), diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/column.h b/src/ui/simulator/toolbox/components/datagrid/renderer/column.h index 1401862d1d..71b31aa0ec 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/column.h +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/column.h @@ -99,13 +99,13 @@ class ColumnNTC final : public Column }; // ------------------------------- -// Column for Hydro Power Credits +// Column for Hydro Max Power // ------------------------------- -class ColumnHydroPowerCredits final : public Column +class ColumnHydroMaxPower final : public Column { public: - ColumnHydroPowerCredits(); - ~ColumnHydroPowerCredits() override = default; + ColumnHydroMaxPower(); + ~ColumnHydroMaxPower() override = default; }; } // namespace Renderer diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.cpp b/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.cpp index d2718e81fa..752ef14eec 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.cpp +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.cpp @@ -69,31 +69,31 @@ double hydroScBuilderRenderer::cellNumericValue(int x, int y) const return 0.; } -bool hydroPowerCreditsScBuilderRenderer::cellValue(int x, int y, const Yuni::String& value) +bool hydroMaxPowerScBuilderRenderer::cellValue(int x, int y, const Yuni::String& value) { if (!(!study) && !(!pRules) && (uint)x < study->parameters.nbYears) { if ((uint)y < study->areas.size()) { - assert((uint)y < pRules->hydroPowerCredits.width()); - assert((uint)x < pRules->hydroPowerCredits.height()); + assert((uint)y < pRules->hydroMaxPower.width()); + assert((uint)x < pRules->hydroMaxPower.height()); uint val = fromStringToTSnumber(value); - pRules->hydroPowerCredits.set_value(x, y, val); + pRules->hydroMaxPower.set_value(x, y, val); return true; } } return false; } -double hydroPowerCreditsScBuilderRenderer::cellNumericValue(int x, int y) const +double hydroMaxPowerScBuilderRenderer::cellNumericValue(int x, int y) const { if (!(!study) && !(!pRules) && (uint)x < study->parameters.nbYears) { if ((uint)y < study->areas.size()) { - assert((uint)y < pRules->hydroPowerCredits.width()); - assert((uint)x < pRules->hydroPowerCredits.height()); - return pRules->hydroPowerCredits.get_value(x, y); + assert((uint)y < pRules->hydroMaxPower.width()); + assert((uint)x < pRules->hydroMaxPower.height()); + return pRules->hydroMaxPower.get_value(x, y); } } return 0.; diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.h b/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.h index 44e35a4be8..80ba31ebe6 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.h +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/scenario-builder-hydro-renderer.h @@ -46,14 +46,14 @@ class hydroScBuilderRenderer : public ScBuilderRendererAreasAsRows double cellNumericValue(int x, int y) const; }; // class hydroScBuilderRenderer -class hydroPowerCreditsScBuilderRenderer : public ScBuilderRendererAreasAsRows +class hydroMaxPowerScBuilderRenderer : public ScBuilderRendererAreasAsRows { public: - hydroPowerCreditsScBuilderRenderer() = default; + hydroMaxPowerScBuilderRenderer() = default; bool cellValue(int x, int y, const Yuni::String& value); double cellNumericValue(int x, int y) const; -}; // class hydroPowerCreditsScBuilderRenderer +}; // class hydroMaxPowerScBuilderRenderer } // namespace Renderer } // namespace Datagrid diff --git a/src/ui/simulator/toolbox/components/datagrid/renderer/ts-management.cpp b/src/ui/simulator/toolbox/components/datagrid/renderer/ts-management.cpp index 81bccb8082..69e212256b 100644 --- a/src/ui/simulator/toolbox/components/datagrid/renderer/ts-management.cpp +++ b/src/ui/simulator/toolbox/components/datagrid/renderer/ts-management.cpp @@ -46,7 +46,7 @@ TSmanagement::TSmanagement() : pControl(nullptr) columns_.push_back(new classicColumn(timeSeriesLoad, " Load ")); columns_.push_back(new thermalColumn()); columns_.push_back(new classicColumn(timeSeriesHydro, " Hydro ")); - columns_.push_back(new ColumnHydroPowerCredits()); + columns_.push_back(new ColumnHydroMaxPower()); } void TSmanagement::checkLineNumberInColumns() diff --git a/src/ui/simulator/windows/hydro/series.cpp b/src/ui/simulator/windows/hydro/series.cpp index 1112db0c9a..310fc98d9a 100644 --- a/src/ui/simulator/windows/hydro/series.cpp +++ b/src/ui/simulator/windows/hydro/series.cpp @@ -58,11 +58,11 @@ Series::Series(wxWindow* parent, Toolbox::InputSelector::Area* notifier) : pPageFatal = notebook->add(com, wxT("Minimum Generation")); com = new Component::Datagrid::Component(notebook); - com->renderer(new Component::Datagrid::Renderer::TimeSeriesHydroMaxGen(com, notifier)); + com->renderer(new Component::Datagrid::Renderer::TimeSeriesHydroMaxHourlyGenPower(com, notifier)); pPageFatal = notebook->add(com, wxT("Maximum Generation")); com = new Component::Datagrid::Component(notebook); - com->renderer(new Component::Datagrid::Renderer::TimeSeriesHydroMaxPump(com, notifier)); + com->renderer(new Component::Datagrid::Renderer::TimeSeriesHydroMaxHourlyPumpPower(com, notifier)); pPageFatal = notebook->add(com, wxT("Maximum Pumping")); // Connection to the notifier