Antares Simulator
Power System Simulator
STSbyGroup.h
1 /*
2 ** Copyright 2007-2025, RTE (https://www.rte-france.com)
3 ** See AUTHORS.txt
4 ** SPDX-License-Identifier: MPL-2.0
5 ** This file is part of Antares-Simulator,
6 ** Adequacy and Performance assessment for interconnected energy networks.
7 **
8 ** Antares_Simulator is free software: you can redistribute it and/or modify
9 ** it under the terms of the Mozilla Public Licence 2.0 as published by
10 ** the Mozilla Foundation, either version 2 of the License, or
11 ** (at your option) any later version.
12 **
13 ** Antares_Simulator is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** Mozilla Public Licence 2.0 for more details.
17 **
18 ** You should have received a copy of the Mozilla Public Licence 2.0
19 ** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20 */
21 #pragma once
22 
23 #include <antares/utils/utils.h>
24 #include "antares/solver/variable/variable.h"
25 
26 namespace
27 {
28 inline std::vector<std::string> sortedUniqueGroups(
29  const std::vector<Antares::Data::ShortTermStorage::STStorageCluster>& storages)
30 {
31  std::set<std::string> names;
32  for (const auto& cluster: storages)
33  {
34  names.insert(cluster.properties.groupName);
35  }
36  return {names.begin(), names.end()};
37 }
38 } // namespace
39 
40 namespace Antares::Solver::Variable::Economy
41 {
43 {
45  static std::string Caption()
46  {
47  return "STS by group";
48  }
49 
51  static std::string Unit()
52  {
53  return "MWh";
54  }
55 
57  static std::string Description()
58  {
59  return "STS injections, withdrawals and levels";
60  }
61 
63  typedef Results<R::AllYears::Average< // The average values throughout all years
64  R::AllYears::StdDeviation< // The standard deviation values throughout all years
65  R::AllYears::Min< // The minimum values throughout all years
66  R::AllYears::Max< // The maximum values throughout all years
67  >>>>>
69 
72 
74  static constexpr uint8_t categoryDataLevel = Category::DataLevel::area;
76  static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile
77  & (Category::FileLevel::id
78  | Category::FileLevel::va);
80  static constexpr uint8_t precision = Category::all;
82  static constexpr uint8_t nodeDepthForGUI = +0;
84  static constexpr uint8_t decimal = 0;
85  // Nb of columns occupied by this variable in year-by-year results
86  static constexpr int columnCount = Category::dynamicColumns;
88  static constexpr uint8_t spatialAggregate = Category::spatialAggregateSum;
89  static constexpr uint8_t spatialAggregateMode = Category::spatialAggregateEachYear;
90  static constexpr uint8_t spatialAggregatePostProcessing = 0;
92  static constexpr uint8_t hasIntermediateValues = 1;
94  static constexpr uint8_t isPossiblyNonApplicable = 0;
95 
97  typedef std::vector<IntermediateValues> IntermediateValuesBaseType;
98  typedef std::vector<IntermediateValuesBaseType> IntermediateValuesType;
99 
100 }; // class VCard
101 
105 template<class NextT = Container::EndOfList>
106 class STSbyGroup: public Variable::IVariable<STSbyGroup<NextT>, NextT, VCardSTSbyGroup>
107 {
108 private:
109  enum VariableType
110  {
111  injection = 0,
112  withdrawal = 1,
113  level = 2
114  };
115 
116 public:
118  typedef NextT NextType;
123 
126 
128 
129  enum
130  {
132  count = 1 + NextT::count,
133  };
134 
135  template<int CDataLevel, int CFile>
136  struct Statistics
137  {
138  enum
139  {
140  count = ((VCardType::categoryDataLevel & CDataLevel
141  && VCardType::categoryFileLevel & CFile)
142  ? (NextType::template Statistics<CDataLevel, CFile>::count
143  + VCardType::columnCount * ResultsType::count)
144  : NextType::template Statistics<CDataLevel, CFile>::count),
145  };
146  };
147 
148 public:
149  void initializeFromArea(Data::Study* study, Data::Area* area)
150  {
151  // Get the number of years in parallel
152  pNbYearsParallel = study->maxNbYearsInParallel;
153  pValuesForTheCurrentYear.resize(pNbYearsParallel);
154 
155  // Building the vector of group names the clusters belong to.
156  groupNames_ = sortedUniqueGroups(area->shortTermStorage.storagesByIndex);
157  groupToNumbers_ = Utils::giveNumbersToStrings(groupNames_);
158 
159  nbColumns_ = groupNames_.size() * NB_COLS_PER_GROUP;
160 
161  if (nbColumns_)
162  {
163  AncestorType::pResults.resize(nbColumns_);
164 
165  for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
166  {
167  pValuesForTheCurrentYear[numSpace].resize(nbColumns_);
168  }
169 
170  for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
171  {
172  for (unsigned int i = 0; i != nbColumns_; ++i)
173  {
174  pValuesForTheCurrentYear[numSpace][i].initializeFromStudy(*study);
175  }
176  }
177 
178  for (unsigned int i = 0; i != nbColumns_; ++i)
179  {
180  AncestorType::pResults[i].initializeFromStudy(*study);
181  AncestorType::pResults[i].reset();
182  }
183  }
184  else
185  {
186  AncestorType::pResults.clear();
187  }
188  // Next
189  NextType::initializeFromArea(study, area);
190  }
191 
192  size_t getMaxNumberColumns() const
193  {
194  return nbColumns_ * ResultsType::count;
195  }
196 
197  void yearBegin(unsigned int year, unsigned int numSpace)
198  {
199  // Reset the values for the current year
200  for (unsigned int i = 0; i != nbColumns_; ++i)
201  {
202  pValuesForTheCurrentYear[numSpace][i].reset();
203  }
204  // Next variable
205  NextType::yearBegin(year, numSpace);
206  }
207 
208  void yearEnd(unsigned int year, unsigned int numSpace)
209  {
210  // Here we perform time-aggregations :
211  // ---------------------------------
212  // For a given MC year, from hourly results we compute daily, weekly, monthly and annual
213  // results by aggregation operations (averages or sums).
214  // Caution :
215  // - level results are stored in columns of which indices satisfy : col_index % 3 == 2.
216  // They are time-aggregated by means of averages
217  // - injection and withdrawal results are stored in columns of which indices
218  // satisfy : col_index % 3 != 2.
219  // They are time-aggregated by means of sums.
220 
221  for (unsigned int column = 0; column < nbColumns_; column++)
222  {
223  switch (column % NB_COLS_PER_GROUP)
224  {
225  case VariableType::level:
226  pValuesForTheCurrentYear[numSpace][column]
227  .computeAveragesForCurrentYearFromHourlyResults();
228  break;
229  case VariableType::injection:
230  case VariableType::withdrawal:
231  pValuesForTheCurrentYear[numSpace][column].computeStatisticsForTheCurrentYear();
232  break;
233  }
234  }
235  // Next variable
236  NextType::yearEnd(year, numSpace);
237  }
238 
239  void computeSummary(unsigned int year, unsigned int numSpace)
240  {
241  // Merge all those values with the global results
242  VariableAccessorType::ComputeSummary(pValuesForTheCurrentYear[numSpace],
244  year);
245 
246  // Next variable
247  NextType::computeSummary(year, numSpace);
248  }
249 
250  void hourBegin(unsigned int hourInTheYear)
251  {
252  NextType::hourBegin(hourInTheYear);
253  }
254 
255  void hourForEachArea(State& state, unsigned int numSpace)
256  {
257  using namespace Antares::Data::ShortTermStorage;
258  const auto& shortTermStorage = state.area->shortTermStorage;
259 
260  uint clusterIndex = 0;
261  for (const auto& sts: shortTermStorage.storagesByIndex)
262  {
263  unsigned int groupNumber = groupToNumbers_[sts.properties.groupName];
264  const auto& result = state.hourlyResults->ShortTermStorage[clusterIndex];
265  // Injection
266  pValuesForTheCurrentYear[numSpace][NB_COLS_PER_GROUP * groupNumber
267  + VariableType::injection][state.hourInTheYear]
268  += result.injection[state.hourInTheWeek];
269 
270  // Withdrawal
271  pValuesForTheCurrentYear[numSpace][NB_COLS_PER_GROUP * groupNumber
272  + VariableType::withdrawal][state.hourInTheYear]
273  += result.withdrawal[state.hourInTheWeek];
274 
275  // Levels
276  pValuesForTheCurrentYear[numSpace][NB_COLS_PER_GROUP * groupNumber
277  + VariableType::level][state.hourInTheYear]
278  += result.level[state.hourInTheWeek];
279 
280  clusterIndex++;
281  }
282 
283  // Next variable
284  NextType::hourForEachArea(state, numSpace);
285  }
286 
287  inline void buildDigest(SurveyResults& results, int digestLevel, int dataLevel) const
288  {
289  // Ask to build the digest to the next variable
290  NextType::buildDigest(results, digestLevel, dataLevel);
291  }
292 
293  Antares::Memory::Stored<double>::ConstReturnType retrieveRawHourlyValuesForCurrentYear(
294  unsigned int column,
295  unsigned int numSpace) const
296  {
297  return pValuesForTheCurrentYear[numSpace][column].hour;
298  }
299 
300  std::string caption(unsigned int column) const
301  {
302  static const std::vector<std::string> VAR_POSSIBLE_KINDS = {"INJECTION",
303  "WITHDRAWAL",
304  "LEVEL"};
305  const std::string& groupName = groupNames_[column / NB_COLS_PER_GROUP];
306  const std::string& variableKind = VAR_POSSIBLE_KINDS[column % NB_COLS_PER_GROUP];
307  return groupName + "_" + variableKind;
308  }
309 
310  std::string unit(unsigned int column) const
311  {
312  switch (column % NB_COLS_PER_GROUP)
313  {
314  case VariableType::level:
315  return "MWh";
316  case VariableType::injection:
317  case VariableType::withdrawal:
318  return "MW";
319  default:
320  return "error";
321  }
322  }
323 
324  void localBuildAnnualSurveyReport(SurveyResults& results,
325  int fileLevel,
326  int precision,
327  unsigned int numSpace) const
328  {
329  // Initializing external pointer on current variable non applicable status
330  results.isCurrentVarNA = AncestorType::isNonApplicable;
331 
332  if (!AncestorType::isPrinted[0])
333  {
334  return;
335  }
336 
337  for (unsigned int column = 0; column < nbColumns_; column++)
338  {
339  results.variableCaption = caption(column);
340  results.variableUnit = unit(column);
341  pValuesForTheCurrentYear[numSpace][column]
342  .template buildAnnualSurveyReport<VCardType>(results, fileLevel, precision);
343  }
344  }
345 
346  void buildSurveyReport(SurveyResults& results,
347  int dataLevel,
348  int fileLevel,
349  int precision) const
350  {
351  // Building synthesis results
352  // ------------------------------
353 
354  if (AncestorType::isPrinted[0])
355  {
356  // And only if we match the current data level _and_ precision level
357  if ((dataLevel & VCardType::categoryDataLevel)
358  && (fileLevel & VCardType::categoryFileLevel) && (precision & VCardType::precision))
359  {
360  results.isCurrentVarNA[0] = AncestorType::isNonApplicable[0];
361 
362  for (unsigned int column = 0; column < nbColumns_; column++)
363  {
364  results.variableCaption = caption(column);
365  results.variableUnit = unit(column);
366  AncestorType::pResults[column]
367  .template buildSurveyReport<ResultsType, VCardType>(
368  results,
369  AncestorType::pResults[column],
370  dataLevel,
371  fileLevel,
372  precision);
373  }
374  }
375  }
376  // Ask to the next item in the static list to export its results as well
377  NextType::buildSurveyReport(results, dataLevel, fileLevel, precision);
378  }
379 
380 private:
382  typename VCardType::IntermediateValuesType pValuesForTheCurrentYear;
383  size_t nbColumns_ = 0;
384  std::vector<std::string> groupNames_; // Names of group containing the clusters of the area
385  std::map<std::string, unsigned int> groupToNumbers_; // Gives to each group (of area) a number
386  const int NB_COLS_PER_GROUP = 3; // Injection + withdrawal + levels = 3 variables
387  unsigned int pNbYearsParallel;
388 
389 }; // class STSbyGroup
390 
391 } // End namespace Antares::Solver::Variable::Economy
Definition for a single area.
Definition: area.h:51
Definition: study.h:57
Variables related to short term storage groups.
Definition: STSbyGroup.h:107
VCardSTSbyGroup VCardType
VCard.
Definition: STSbyGroup.h:120
@ count
How many items have we got.
Definition: STSbyGroup.h:132
VCardType::ResultsType ResultsType
List of expected results.
Definition: STSbyGroup.h:125
Variable::IVariable< STSbyGroup< NextT >, NextT, VCardType > AncestorType
Ancestor.
Definition: STSbyGroup.h:122
NextT NextType
Type of the next static variable.
Definition: STSbyGroup.h:118
Interface for any variable.
Definition: variable.h:47
StoredResultType pResults
All the results about this variable.
Definition: variable.h:323
Temporary buffer for allocating results for a single year.
Definition: intermediate.h:42
Definition: results.h:44
@ count
The count if item in the list.
Definition: results.h:52
Definition: cbuilder.h:120
static constexpr uint8_t spatialAggregate
The Spatial aggregation.
Definition: STSbyGroup.h:88
static constexpr uint8_t decimal
Decimal precision.
Definition: STSbyGroup.h:84
static constexpr uint8_t nodeDepthForGUI
Indentation (GUI)
Definition: STSbyGroup.h:82
static constexpr uint8_t categoryFileLevel
File level (provided by the type of the results)
Definition: STSbyGroup.h:76
VCardSTSbyGroup VCardForSpatialAggregate
The VCard to look for for calculating spatial aggregates.
Definition: STSbyGroup.h:71
static constexpr uint8_t precision
Precision (views)
Definition: STSbyGroup.h:80
static constexpr uint8_t categoryDataLevel
Data Level.
Definition: STSbyGroup.h:74
static constexpr uint8_t hasIntermediateValues
Intermediate values.
Definition: STSbyGroup.h:92
Results< R::AllYears::Average< R::AllYears::StdDeviation< R::AllYears::Min< R::AllYears::Max< > > > > > ResultsType
The synhesis results.
Definition: STSbyGroup.h:68
static std::string Unit()
Unit.
Definition: STSbyGroup.h:51
static std::string Description()
The short description of the variable.
Definition: STSbyGroup.h:57
static std::string Caption()
Caption.
Definition: STSbyGroup.h:45
static constexpr uint8_t isPossiblyNonApplicable
Can this variable be non applicable (0 : no, 1 : yes)
Definition: STSbyGroup.h:94