Skip to content

Commit

Permalink
Rationalize consistency checks on the number of columns (#2073)
Browse files Browse the repository at this point in the history
# Context
This is a preliminary work to place `maxHydroPumping` & `maxHydroGen`
under sc-builder prefix "h", and remove prefix "hgp" introduced in CR23
(see #2068).

This should also fix #2069.

# Description
- Add homogeneity in the checks performed on the number of columns for
   - Links (direct & indirect) (prefix "ntc)
   - Hydro (ror, storage & mingen) (prefix "h")
- Thermal (prefix "t", not useful for now, but we may use this mechanism
for fuelCost & co2Cost, to replace the custom
`checkFuelCostColumnNumber` and `checkCO2CostColumnNumber` functions)
- Declare TSNumbers before series. Otherwise we get a segfault since
data members are initialized in the order where they appear in the class
declaration.
- Remove `EqualizeGenerationTSsizes` mechanism for `{ror, storage}` and
`{ror, mingen}`. If only one column is present, use it, which is more or
less equivalent to the column duplication made by
`EqualizeGenerationTSsizes`.

# TODO
- [x] Add unit tests, especially to check that errors are emitted when
they should.

# Related work
[Improve
logs](#2080)
  • Loading branch information
flomnes authored May 14, 2024
1 parent befae83 commit d0c90b5
Show file tree
Hide file tree
Showing 33 changed files with 497 additions and 346 deletions.
35 changes: 32 additions & 3 deletions src/libs/antares/series/include/antares/series/series.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#ifndef __ANTARES_LIBS_STUDY_PARTS_COMMON_TIMESERIES_H__
#define __ANTARES_LIBS_STUDY_PARTS_COMMON_TIMESERIES_H__

#include <map>
#include <optional>
#include <string>

#include <antares/array/matrix.h>

namespace Antares::Data
Expand All @@ -32,13 +36,37 @@ namespace Antares::Data
** The goal is to handle indexing with the time series numbers: getCoefficient()
** and also providing a wrapper for all the Matrix<> functions such as resize()
*/
class TimeSeries;

class TimeSeriesNumbers
{
public:
void registerSeries(const TimeSeries* s, std::string label);
// Return a description of the error in case of inconsistent number of columns, std::nullopt
// otherwis
std::optional<std::string> checkSeriesNumberOfColumnsConsistency() const;

uint32_t operator[](uint y) const;
uint32_t& operator[](uint y);

void clear();
void reset(uint h);

uint height() const;

void saveToBuffer(std::string& data) const;

private:
Matrix<uint32_t> tsNumbers;
std::map<std::string, const TimeSeries*> series;
};

class TimeSeries
{
public:
using numbers = Matrix<uint32_t>;
using TS = Matrix<double>;

explicit TimeSeries(numbers& tsNumbers);
explicit TimeSeries(TimeSeriesNumbers& tsNumbers);
/*!
** \brief Load series from a file
**
Expand Down Expand Up @@ -71,6 +99,7 @@ class TimeSeries

void reset();
void reset(uint32_t width, uint32_t height);
uint32_t numberOfColumns() const;
void unloadFromMemory() const;
void roundAllEntries();
void resize(uint32_t timeSeriesCount, uint32_t timestepCount);
Expand All @@ -82,7 +111,7 @@ class TimeSeries
uint64_t memoryUsage() const;

TS timeSeries;
numbers& timeseriesNumbers;
TimeSeriesNumbers& timeseriesNumbers;

static const std::vector<double> emptyColumn; ///< used in getColumn if timeSeries empty
};
Expand Down
91 changes: 89 additions & 2 deletions src/libs/antares/series/series.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

#include "antares/series/series.h"

#include <algorithm>
#include <sstream>
#include <vector>

#include <yuni/yuni.h>
#include <yuni/io/directory.h>
#include <yuni/io/file.h>
Expand All @@ -31,8 +35,80 @@ using namespace Yuni;

namespace Antares::Data
{
void TimeSeriesNumbers::registerSeries(const TimeSeries* s, std::string label)
{
series[std::move(label)] = s;
}

// TODO[FOM] Code duplication
static bool checkAllElementsIdenticalOrOne(std::vector<uint> w)
{
auto first_one = std::remove(w.begin(), w.end(), 1); // Reject all 1 to the end
return std::adjacent_find(w.begin(), first_one, std::not_equal_to<uint>()) == first_one;
}

static std::string errorMessage(const std::map<std::string, const TimeSeries*>& series)
{
std::ostringstream msg;
auto isLast = [&series](std::size_t& idx)
{
idx++;
return idx == series.size();
};
for (std::size_t idx = 0; const auto& [label, s]: series)
{
msg << label << ": " << s->numberOfColumns() << (isLast(idx) ? "" : ", ");
}
return msg.str();
}

uint TimeSeriesNumbers::height() const
{
return tsNumbers.height;
}

uint32_t TimeSeriesNumbers::operator[](uint y) const
{
return tsNumbers[0][y];
}

uint32_t& TimeSeriesNumbers::operator[](uint y)
{
return tsNumbers[0][y];
}

void TimeSeriesNumbers::reset(uint h)
{
tsNumbers.reset(1, h);
}

void TimeSeriesNumbers::clear()
{
tsNumbers.clear();
}

void TimeSeriesNumbers::saveToBuffer(std::string& data) const
{
const auto add1 = [](uint32_t x) { return x + 1; };
tsNumbers.saveToBuffer(data, 0, true, add1, true);
}

std::optional<std::string> TimeSeriesNumbers::checkSeriesNumberOfColumnsConsistency() const
{
std::vector<uint> width;
for (const auto& [_, s]: series)
{
width.push_back(s->numberOfColumns());
}

if (!checkAllElementsIdenticalOrOne(width))
{
return errorMessage(series);
}
return std::nullopt;
}

TimeSeries::TimeSeries(numbers& tsNumbers):
TimeSeries::TimeSeries(TimeSeriesNumbers& tsNumbers):
timeseriesNumbers(tsNumbers)
{
}
Expand Down Expand Up @@ -79,7 +155,13 @@ const double* TimeSeries::getColumn(uint32_t year) const

uint32_t TimeSeries::getSeriesIndex(uint32_t year) const
{
return timeseriesNumbers[0][year];
// If the timeSeries only has one column, we have no choice but to use it.
if (numberOfColumns() == 1)
{
return 0;
}

return timeseriesNumbers[year];
}

double* TimeSeries::operator[](uint32_t index)
Expand All @@ -101,6 +183,11 @@ void TimeSeries::reset(uint32_t width, uint32_t height)
timeSeries.reset(width, height);
}

uint32_t TimeSeries::numberOfColumns() const
{
return timeSeries.width;
}

void TimeSeries::resize(uint32_t timeSeriesCount, uint32_t timestepCount)
{
timeSeries.resize(timeSeriesCount, timestepCount);
Expand Down
12 changes: 6 additions & 6 deletions src/libs/antares/study/area/area.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,15 @@ void Area::resizeAllTimeseriesNumbers(uint nbYears)
{
assert(hydro.series and "series must not be nullptr !");

load.series.timeseriesNumbers.reset(1, nbYears);
solar.series.timeseriesNumbers.reset(1, nbYears);
wind.series.timeseriesNumbers.reset(1, nbYears);
hydro.series->timeseriesNumbers.reset(1, nbYears);
hydro.series->timeseriesNumbersHydroMaxPower.reset(1, nbYears);
load.series.timeseriesNumbers.reset(nbYears);
solar.series.timeseriesNumbers.reset(nbYears);
wind.series.timeseriesNumbers.reset(nbYears);
hydro.series->timeseriesNumbers.reset(nbYears);
hydro.series->timeseriesNumbersHydroMaxPower.reset(nbYears);
for (auto& namedLink: links)
{
AreaLink* link = namedLink.second;
link->timeseriesNumbers.reset(1, nbYears);
link->timeseriesNumbers.reset(nbYears);
}
thermal.resizeAllTimeseriesNumbers(nbYears);
renewable.resizeAllTimeseriesNumbers(nbYears);
Expand Down
18 changes: 4 additions & 14 deletions src/libs/antares/study/area/links.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@
using namespace Yuni;
using namespace Antares;

namespace // anonymous
{
struct TSNumbersPredicate
{
uint32_t operator()(uint32_t value) const
{
return value + 1;
}
};
} // namespace

#define SEP (IO::Separator)

namespace
Expand Down Expand Up @@ -76,6 +65,9 @@ AreaLink::AreaLink():
style(stPlain),
linkWidth(1)
{
timeseriesNumbers.registerSeries(&directCapacities, "direct-capacity");
timeseriesNumbers.registerSeries(&indirectCapacities, "indirect-capacity");

directCapacities.reset();
indirectCapacities.reset();
}
Expand Down Expand Up @@ -194,13 +186,12 @@ bool AreaLink::loadTimeSeries(const StudyVersion& version, const AnyString& fold
void AreaLink::storeTimeseriesNumbers(Solver::IResultWriter& writer) const
{
Clob path;
TSNumbersPredicate predicate;
std::string buffer;

path << "ts-numbers" << SEP << DIRECTORY_NAME_FOR_TRANSMISSION_CAPACITIES << SEP << from->id
<< SEP << with->id << ".txt";

timeseriesNumbers.saveToBuffer(buffer, 0, true, predicate, true);
timeseriesNumbers.saveToBuffer(buffer);
writer.addEntryFromBuffer(path.c_str(), buffer);
}

Expand Down Expand Up @@ -532,7 +523,6 @@ bool AreaLinksLoadFromFolder(Study& study, AreaList* l, Area* area, const AnyStr
// Checks on loaded link's data
if (study.usedByTheSolver)
{
// Short names for link's properties
const uint nbDirectTS = link.directCapacities.timeSeries.width;
const uint nbIndirectTS = link.indirectCapacities.timeSeries.width;
if (nbDirectTS != nbIndirectTS)
Expand Down
Loading

0 comments on commit d0c90b5

Please sign in to comment.