Antares Simulator
Power System Simulator
bindingConstraintsMarginalCost.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/study/binding_constraint/BindingConstraint.h"
24 
25 #include "../../variable.h"
26 
27 namespace Antares::Solver::Variable::Economy
28 {
30 {
32  static std::string Caption()
33  {
34  return "BC. MARG. COST";
35  }
36 
38  static std::string Unit()
39  {
40  return "Euro";
41  }
42 
44  static std::string Description()
45  {
46  return "Marginal cost for binding constraints";
47  }
48 
50  typedef Results<R::AllYears::Average< // The average values thoughout all years
51  R::AllYears::StdDeviation< // The standard deviation values throughout all years
52  R::AllYears::Min< // The minimum values thoughout all years
53  R::AllYears::Max< // The maximum values thoughout all years
54  >>>>>
56 
58  static constexpr uint8_t categoryDataLevel = Category::DataLevel::bindingConstraint;
60  static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile
61  & (Category::FileLevel::bc);
63  static constexpr uint8_t precision = Category::all;
65  static constexpr uint8_t nodeDepthForGUI = +0;
67  static constexpr uint8_t decimal = 2;
69  static constexpr int columnCount = 1;
71  static constexpr uint8_t hasIntermediateValues = 1;
73  static constexpr uint8_t isPossiblyNonApplicable = 1;
74 
76  typedef std::vector<IntermediateValues> IntermediateValuesType;
77 
78 }; // class VCard
79 
80 /*
81  Marginal cost associated to binding constraints :
82  Suppose that the BC is hourly,
83  - if binding constraint is not saturated (rhs is not reached) for a given hour, the value is 0;
84  - if binding constraint is saturated (rhs is reached), the value is the total benefit (�/MW) for
85  the system that would result in increasing the BC's rhs of 1 MW.
86 */
87 template<class NextT = Container::EndOfList>
89  : public Variable::IVariable<BindingConstMarginCost<NextT>, NextT, VCardBindingConstMarginCost>
90 {
91 public:
93  typedef NextT NextType;
98 
101 
103 
104  enum
105  {
107  count = 1 + NextT::count,
108  };
109 
110  template<int CDataLevel, int CFile>
111  struct Statistics
112  {
113  enum
114  {
115  count = ((VCardType::categoryDataLevel & CDataLevel
116  && VCardType::categoryFileLevel & CFile)
117  ? (NextType::template Statistics<CDataLevel, CFile>::count
119  : NextType::template Statistics<CDataLevel, CFile>::count),
120  };
121  };
122 
123 public:
124  BindingConstMarginCost() = default;
125 
126  void simulationBegin()
127  {
128  NextType::simulationBegin();
129  }
130 
131  void simulationEnd()
132  {
133  NextType::simulationEnd();
134  }
135 
136  void initializeFromStudy(Data::Study& study)
137  {
138  pNbYearsParallel = study.maxNbYearsInParallel;
139 
140  // Statistics thoughout all years
141  InitializeResultsFromStudy(AncestorType::pResults, study);
142 
143  // Intermediate values
144  pValuesForTheCurrentYear.resize(pNbYearsParallel);
145  for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
146  {
147  pValuesForTheCurrentYear[numSpace].initializeFromStudy(study);
148  }
149 
150  NextType::initializeFromStudy(study);
151  }
152 
153  template<class R>
154  static void InitializeResultsFromStudy(R& results, Data::Study& study)
155  {
156  VariableAccessorType::InitializeAndReset(results, study);
157  }
158 
159  void setAssociatedBindConstraint(std::shared_ptr<Data::BindingConstraint> bc_ptr)
160  {
161  associatedBC_ = bc_ptr;
162  }
163 
164  void setBindConstraintsCount(uint bcCount)
165  {
166  nbCount_ = bcCount;
167  }
168 
169  size_t getMaxNumberColumns() const
170  {
171  return nbCount_ * ResultsType::count;
172  }
173 
174  void yearBegin(unsigned int year, unsigned int numSpace)
175  {
176  // Reset the values for the current year
177  pValuesForTheCurrentYear[numSpace].reset();
178 
179  // Next variable
180  NextType::yearBegin(year, numSpace);
181  }
182 
183  void yearEnd(unsigned int year, unsigned int numSpace)
184  {
185  if (isInitialized())
186  {
187  // Compute statistics for the current year depending on
188  // the BC type (hourly, daily, weekly)
189  using namespace Data;
190  switch (associatedBC_->type())
191  {
192  case BindingConstraint::typeHourly:
193  pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromHourlyResults();
194  break;
195  case BindingConstraint::typeDaily:
196  pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromDailyResults();
197  break;
198  case BindingConstraint::typeWeekly:
199  pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromWeeklyResults();
200  break;
201  case BindingConstraint::typeUnknown:
202  case BindingConstraint::typeMax:
203  break;
204  }
205  }
206 
207  // Next variable
208  NextType::yearEnd(year, numSpace);
209  }
210 
211  void computeSummary(unsigned int year, unsigned int numSpace)
212  {
213  // Merge all those values with the global results
214  AncestorType::pResults.merge(year, pValuesForTheCurrentYear[numSpace]);
215 
216  // Next variable
217  NextType::computeSummary(year, numSpace);
218  }
219 
220  void weekBegin(State& state)
221  {
222  if (isInitialized())
223  {
224  auto numSpace = state.numSpace;
225  // For daily binding constraints, getting daily marginal price
226  using namespace Data;
227  switch (associatedBC_->type())
228  {
229  case BindingConstraint::typeHourly:
230  case BindingConstraint::typeUnknown:
231  case BindingConstraint::typeMax:
232  break;
233 
234  case BindingConstraint::typeDaily:
235  {
236  int dayInTheYear = state.weekInTheYear * 7;
237  for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++)
238  {
239  pValuesForTheCurrentYear[numSpace].day[dayInTheYear]
240  -= state.problemeHebdo
241  ->ResultatsContraintesCouplantes[associatedBC_][dayInTheWeek];
242 
243  dayInTheYear++;
244  }
245  break;
246  }
247 
248  // For weekly binding constraints, getting weekly marginal price
249  case BindingConstraint::typeWeekly:
250  {
251  uint weekInTheYear = state.weekInTheYear;
252  double weeklyValue = -state.problemeHebdo
253  ->ResultatsContraintesCouplantes[associatedBC_][0];
254 
255  pValuesForTheCurrentYear[numSpace].week[weekInTheYear] = weeklyValue;
256 
257  int dayInTheYear = state.weekInTheYear * 7;
258  for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++)
259  {
260  pValuesForTheCurrentYear[numSpace].day[dayInTheYear] = weeklyValue;
261  dayInTheYear++;
262  }
263  break;
264  }
265  }
266  }
267  NextType::weekBegin(state);
268  }
269 
270  void hourBegin(unsigned int hourInTheYear)
271  {
272  // Next variable
273  NextType::hourBegin(hourInTheYear);
274  }
275 
276  void hourForEachArea(State& state, unsigned int numSpace)
277  {
278  NextType::hourForEachArea(state, numSpace);
279  }
280 
281  void weekForEachArea(State& state, unsigned int numSpace)
282  {
283  NextType::weekForEachArea(state, numSpace);
284  }
285 
286  template<class VCardToFindT>
287  static void retrieveResultsForArea(typename Storage<VCardToFindT>::ResultsType** result,
288  const Data::Area* area)
289  {
290  // Next variable
291  NextType::template retrieveResultsForArea<VCardToFindT>(result, area);
292  }
293 
294  void buildDigest(SurveyResults& results, int digestLevel, int dataLevel) const
295  {
296  NextType::buildDigest(results, digestLevel, dataLevel);
297  }
298 
299  template<class V>
300  static void simulationEndSpatialAggregates(V& allVars)
301  {
302  NextType::template simulationEndSpatialAggregates<V>(allVars);
303  }
304 
305  template<class V>
306  static void computeSpatialAggregatesSummary(V& allVars,
307  unsigned int year,
308  unsigned int numSpace)
309  {
310  NextType::template computeSpatialAggregatesSummary<V>(allVars, year, numSpace);
311  }
312 
313  void beforeYearByYearExport(uint year, uint numSpace)
314  {
315  NextType::beforeYearByYearExport(year, numSpace);
316  }
317 
318  template<class SearchVCardT, class O>
319  static void computeSpatialAggregateWith(O& out, const Data::Area* area, uint numSpace)
320  {
321  NextType::template computeSpatialAggregateWith<SearchVCardT, O>(out, area, numSpace);
322  }
323 
324  template<class VCardToFindT>
325  static void retrieveResultsForLink(typename Storage<VCardToFindT>::ResultsType** result,
326  const Data::AreaLink* link)
327  {
328  NextType::template retrieveResultsForLink<VCardToFindT>(result, link);
329  }
330 
331  template<class VCardToFindT>
332  static void retrieveResultsForThermalCluster(
333  typename Storage<VCardToFindT>::ResultsType** result,
334  const Data::ThermalCluster* cluster)
335  {
336  NextType::template retrieveResultsForThermalCluster<VCardToFindT>(result, cluster);
337  }
338 
339  void hourEnd(State& state, unsigned int hourInTheYear)
340  {
341  if (isInitialized())
342  {
343  auto numSpace = state.numSpace;
344  if (associatedBC_->type() == Data::BindingConstraint::typeHourly)
345  {
346  pValuesForTheCurrentYear[numSpace][hourInTheYear]
347  -= state.problemeHebdo
348  ->ResultatsContraintesCouplantes[associatedBC_][state.hourInTheWeek];
349  }
350  }
351 
352  NextType::hourEnd(state, hourInTheYear);
353  }
354 
355  Antares::Memory::Stored<double>::ConstReturnType retrieveRawHourlyValuesForCurrentYear(
356  unsigned int,
357  unsigned int numSpace) const
358  {
359  return pValuesForTheCurrentYear[numSpace].hour;
360  }
361 
362  void localBuildAnnualSurveyReport(
363  SurveyResults& results,
364  int fileLevel,
365  int precision /* printed results : hourly, daily, weekly, ...*/,
366  unsigned int numSpace) const
367  {
368  if (!(precision & associatedBC_->yearByYearFilter()))
369  {
370  return;
371  }
372 
373  results.isCurrentVarNA = AncestorType::isNonApplicable;
374  // Initializing external pointer on current variable non applicable status
375  results.isCurrentVarNA[0] = isCurrentOutputNonApplicable(precision);
376 
377  if (AncestorType::isPrinted[0])
378  {
379  // Write the data for the current year
380  results.variableCaption = getBindConstraintCaption();
381  results.variableUnit = VCardType::Unit();
382  pValuesForTheCurrentYear[numSpace]
383  .template buildAnnualSurveyReport<VCardType>(results, fileLevel, precision);
384  }
385  }
386 
387  void buildSurveyReport(SurveyResults& results,
388  int dataLevel,
389  int fileLevel,
390  int precision) const
391  {
392  // Building syntheses results
393  // ------------------------------
394  if (precision & associatedBC_->yearByYearFilter())
395  {
396  // And only if we match the current data level _and_ precision level
397  if ((dataLevel & VCardType::categoryDataLevel)
398  && (fileLevel & VCardType::categoryFileLevel) && (precision & VCardType::precision))
399  {
400  results.isPrinted = AncestorType::isPrinted;
401  results.isCurrentVarNA = AncestorType::isNonApplicable;
402  results.isCurrentVarNA[0] = isCurrentOutputNonApplicable(precision);
403  results.variableCaption = getBindConstraintCaption();
404 
405  VariableAccessorType::template BuildSurveyReport<VCardType>(results,
407  dataLevel,
408  fileLevel,
409  precision,
410  false);
411  }
412  }
413  NextType::buildSurveyReport(results, dataLevel, fileLevel, precision);
414  }
415 
416 private:
417  // Private methods
418  // ---------------
419  std::string getBindConstraintCaption() const
420  {
421  std::string mathOperator(
422  Antares::Data::BindingConstraint::MathOperatorToCString(associatedBC_->operatorType()));
423  return std::string() + associatedBC_->name().c_str() + " (" + mathOperator + ")";
424  }
425 
426  bool isInitialized()
427  {
428  return associatedBC_ != nullptr;
429  }
430 
431  bool isCurrentOutputNonApplicable(int precision) const
432  {
433  using namespace Antares::Data;
434  // The current marginal prices to print becomes non applicable if they have a precision
435  // (hour, day, week, ...) smaller than the associated binding constraint granularity.
436  // Ex : if the BC is daily and we try to print hourly associated marginal prices,
437  // then these prices are set to N/A
438  switch (associatedBC_->type())
439  {
440  case BindingConstraint::typeUnknown:
441  case BindingConstraint::typeMax:
442  return true;
443  default:
444  const auto precision_bc = 1 << (associatedBC_->type() - 1);
445  return precision < precision_bc;
446  }
447  }
448 
449  // Private data mambers
450  // ----------------------
452  typename VCardType::IntermediateValuesType pValuesForTheCurrentYear;
453  unsigned int pNbYearsParallel = 0;
454  std::shared_ptr<Data::BindingConstraint> associatedBC_ = nullptr;
455  uint nbCount_ = 0; // Number of inequality BCs
456 
457 }; // class BindingConstMarginCost
458 
459 } // namespace Antares::Solver::Variable::Economy
Definition for a single area.
Definition: area.h:51
static const char * MathOperatorToCString(Operator o)
Convert a binding constraint operator into a short C-String (symbol)
Definition: BindingConstraint.cpp:133
@ typeHourly
The binding constraint has hourly values.
Definition: BindingConstraint.h:59
Definition: study.h:57
A single thermal cluster.
Definition: cluster.h:76
Definition: bindingConstraintsMarginalCost.h:90
NextT NextType
Type of the next static variable.
Definition: bindingConstraintsMarginalCost.h:93
@ count
How many items have we got.
Definition: bindingConstraintsMarginalCost.h:107
VCardBindingConstMarginCost VCardType
VCard.
Definition: bindingConstraintsMarginalCost.h:95
Variable::IVariable< BindingConstMarginCost< NextT >, NextT, VCardType > AncestorType
Ancestor.
Definition: bindingConstraintsMarginalCost.h:97
VCardType::ResultsType ResultsType
List of expected results.
Definition: bindingConstraintsMarginalCost.h:100
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
Definition: bindingConstraintsMarginalCost.h:112
Definition: bindingConstraintsMarginalCost.h:30
static constexpr uint8_t categoryFileLevel
File level (provided by the type of the results)
Definition: bindingConstraintsMarginalCost.h:60
static std::string Unit()
Unit.
Definition: bindingConstraintsMarginalCost.h:38
static constexpr uint8_t hasIntermediateValues
Intermediate values.
Definition: bindingConstraintsMarginalCost.h:71
static constexpr uint8_t categoryDataLevel
Data Level.
Definition: bindingConstraintsMarginalCost.h:58
static constexpr uint8_t nodeDepthForGUI
Indentation (GUI)
Definition: bindingConstraintsMarginalCost.h:65
static constexpr uint8_t decimal
Decimal precision.
Definition: bindingConstraintsMarginalCost.h:67
static constexpr int columnCount
Number of columns used by the variable.
Definition: bindingConstraintsMarginalCost.h:69
static constexpr uint8_t precision
Precision (views)
Definition: bindingConstraintsMarginalCost.h:63
Results< R::AllYears::Average< R::AllYears::StdDeviation< R::AllYears::Min< R::AllYears::Max< > > > > > ResultsType
The expecte results.
Definition: bindingConstraintsMarginalCost.h:55
static constexpr uint8_t isPossiblyNonApplicable
Can this variable be non applicable (0 : no, 1 : yes)
Definition: bindingConstraintsMarginalCost.h:73
static std::string Description()
The short description of the variable.
Definition: bindingConstraintsMarginalCost.h:44
static std::string Caption()
Caption.
Definition: bindingConstraintsMarginalCost.h:32
VariableAccessor< typename VCardT::ResultsType, VCardT::columnCount >::Type ResultsType
The true type used for the results.
Definition: info.h:760