Antares Simulator
Power System Simulator
Loading...
Searching...
No Matches
reportbuilder.hxx
1/*
2** Copyright 2007-2024, 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#ifndef __SOLVER_VARIABLE_SURVEYRESULTS_REPORT_BUILDER_HXX__
22#define __SOLVER_VARIABLE_SURVEYRESULTS_REPORT_BUILDER_HXX__
23
24#include <limits>
25
26#include <yuni/yuni.h>
27#include <yuni/core/static/types.h>
28#include <yuni/core/string.h>
29#include <yuni/io/directory.h>
30
31#include <antares/logs/logs.h>
32#include <antares/study/filter.h>
33
34#include "../categories.h"
35#include "../endoflist.h"
36#include "../info.h"
37#include "../surveyresults.h"
38
39namespace Antares
40{
41namespace Solver
42{
43namespace Variable
44{
45namespace Container
46{
47namespace // anonymous
48{
49template<class NextT, int CDataLevel, int CFile = 1>
50struct VariablesStatsByDataLevel
51{
52 enum
53 {
54 nextFileLevel = (CFile * 2 > (int)Category::FileLevel::maxFileLevel) ? 1 : CFile * 2,
55 currentVariableCount = NextT::template Statistics < CDataLevel,
56 CFile > ::count,
57 nextVariableCount = VariablesStatsByDataLevel < NextT,
58 CDataLevel,
59 nextFileLevel > ::count,
60
62 count = (int)currentVariableCount + (int)nextVariableCount,
63 };
64};
65
66template<class NextT, int CDataLevel>
67struct VariablesStatsByDataLevel<NextT, CDataLevel, Category::FileLevel::maxFileLevel>
68{
69 enum
70 {
71 count = 0,
72 };
73};
74
75template<class NextT, int CDataLevel = 1, int CFile = 1>
76struct BrowseAllVariables
77{
78 enum
79 {
80 nextFileLevel = (CFile * 2 > (int)Category::FileLevel::maxFileLevel) ? 1 : CFile * 2,
81 nextDataLevel = (CDataLevel * 2 > (int)Category::DataLevel::maxDataLevel) ? 1
82 : CDataLevel * 2,
83 currentValue = NextT::template Statistics < CDataLevel,
84 CFile > ::count,
85 nextValue = BrowseAllVariables < NextT,
86 nextDataLevel,
87 nextFileLevel > ::maxValue,
88
89 maxValue = (currentValue > (int)nextValue) ? currentValue : (int)nextValue,
90 };
91
92 template<class L, class S>
93 static void buildSurveyResults(const L& list, S& results)
94 {
95 // Exporting data for the current state
96 list.template buildSurveyResults<S, CDataLevel, CFile>(results);
97 // Go to the next status
98 BrowseAllVariables<NextT, nextDataLevel, nextFileLevel>::template buildSurveyResults<L, S>(
99 list,
100 results);
101 }
102};
103
104template<class NextT>
105struct BrowseAllVariables<NextT,
106 Category::DataLevel::maxDataLevel,
107 Category::FileLevel::maxFileLevel>
108{
109 enum
110 {
111 maxValue = NextT::template Statistics < Category::DataLevel::maxDataLevel,
112 Category::FileLevel::maxFileLevel > ::count
113 };
114
115 template<class L, class S>
116 static void buildSurveyResults(const L& list, S& results)
117 {
118 // Exporting data for the current state
119 list.template buildSurveyResults<S,
120 Category::DataLevel::maxDataLevel,
121 Category::FileLevel::maxFileLevel>(results);
122 // This is the final available state
123 }
124};
125
126template<bool GlobalT, class NextT, int CDataLevel, int CFile = 1>
127class SurveyReportBuilderFile
128{
129public:
130 using ListType = NextT;
131
132 enum
133 {
135 globalResults = (GlobalT) ? 1 : 0,
137 nextFileLevel = CFile * 2,
138 };
139
140 static void Run(const ListType& list, SurveyResults& results, unsigned int numSpace)
141 {
142 if (globalResults)
143 {
144 RunGlobalResults(list, results);
145 }
146 else
147 {
148 RunAnnual(list, results, numSpace);
149 }
150
151 // The survey type
152 using SurveyRBFileType = SurveyReportBuilderFile<GlobalT, NextT, CDataLevel, nextFileLevel>;
153 // Go to the next data level
154 SurveyRBFileType::Run(list, results, numSpace);
155 }
156
157private:
158 static void RunGlobalResults(const ListType& list, SurveyResults& results)
159 {
160 // All hours
161 list.buildSurveyReport(results, CDataLevel, CFile, Category::hourly);
162 // All days
163 list.buildSurveyReport(results, CDataLevel, CFile, Category::daily);
164 // All weeks
165 list.buildSurveyReport(results, CDataLevel, CFile, Category::weekly);
166 // All months
167 list.buildSurveyReport(results, CDataLevel, CFile, Category::monthly);
168 // All years
169 list.buildSurveyReport(results, CDataLevel, CFile, Category::annual);
170 }
171
172 static void RunAnnual(const ListType& list, SurveyResults& results, unsigned int numSpace)
173 {
174 // All hours
175 list.buildAnnualSurveyReport(results, CDataLevel, CFile, Category::hourly, numSpace);
176 // All days
177 list.buildAnnualSurveyReport(results, CDataLevel, CFile, Category::daily, numSpace);
178 // All weeks
179 list.buildAnnualSurveyReport(results, CDataLevel, CFile, Category::weekly, numSpace);
180 // All months
181 list.buildAnnualSurveyReport(results, CDataLevel, CFile, Category::monthly, numSpace);
182 // All years
183 list.buildAnnualSurveyReport(results, CDataLevel, CFile, Category::annual, numSpace);
184 }
185
186}; // class SurveyReportBuilderFile
187
188// Specialization for the final state (dummy)
189template<bool GlobalT, class NextT, int N>
190class SurveyReportBuilderFile<GlobalT, NextT, N, 2 * Category::FileLevel::maxFileLevel>
191{
192public:
193 using ListType = NextT;
194
195 // dead end
196 static inline void Run(const ListType&, SurveyResults&, unsigned int)
197 {
198 }
199};
200
201template<bool GlobalT, class NextT, int CDataLevel = 1>
202class SurveyReportBuilder
203{
204public:
206 using ListType = NextT;
207
208 enum
209 {
210 nextDataLevel = CDataLevel * 2,
211 };
212
213 static void Run(const ListType& list, SurveyResults& results, unsigned int numSpace = 9999)
214 {
215 // Area - Thermal clusters - Links
216 if (CDataLevel & Category::DataLevel::area || CDataLevel & Category::DataLevel::link
217 || CDataLevel & Category::DataLevel::thermalAggregate)
218 {
219 RunForEachArea(list, results, numSpace);
220 }
221
222 // Set of Areas
223 if (CDataLevel & Category::DataLevel::setOfAreas)
224 {
225 RunForEachSetOfAreas(list, results, numSpace);
226 }
227
228 // Binding constraints level
229 if (CDataLevel & Category::DataLevel::bindingConstraint)
230 {
231 RunForEachBindingConstraint(list, results, numSpace);
232 }
233
234 // Go to the next data level
235 SurveyReportBuilder<GlobalT, NextT, nextDataLevel>::Run(list, results, numSpace);
236 }
237
238 static void RunDigest(const ListType& list, SurveyResults& results, IResultWriter& writer)
239 {
240 logs.info() << "Exporting digest...";
241 logs.debug() << " . Digest, truncating file";
242 // Digest: Summary for All years
243 logs.debug() << " . Digest, annual";
244
245 // Digest file : areas part
246 std::string digestBuffer;
247 list.buildDigest(results, Category::digestAllYears, Category::DataLevel::area);
248 results.exportDigestAllYears(digestBuffer);
249
250 // Degest file : districts part
251 list.buildDigest(results, Category::digestAllYears, Category::DataLevel::setOfAreas);
252 results.exportDigestAllYears(digestBuffer);
253
254 // Digest: Flow linear (only if selected by user)
255 if (results.data.study.parameters.variablesPrintInfo.isPrinted("FLOW LIN."))
256 {
257 logs.debug() << " . Digest, flow linear";
258 results.data.matrix.fill(std::numeric_limits<double>::quiet_NaN());
259 list.buildDigest(results, Category::digestFlowLinear, Category::DataLevel::area);
260 results.exportDigestMatrix("Links (FLOW LIN.)", digestBuffer);
261 }
262
263 // Digest: Flow Quad (only if selected by user)
264 if (results.data.study.parameters.variablesPrintInfo.isPrinted("FLOW QUAD."))
265 {
266 logs.debug() << " . Digest, flow quad";
267 results.data.matrix.fill(std::numeric_limits<double>::quiet_NaN());
268 list.buildDigest(results, Category::digestFlowQuad, Category::DataLevel::area);
269 results.exportDigestMatrix("Links (FLOW QUAD.)", digestBuffer);
270 }
271 // THIS FILE IS DEPRECATED !!!
272 YString digestFileName;
273 std::filesystem::path path = static_cast<std::string>(results.data.originalOutput);
274 path /= "grid";
275 path /= "digest.txt";
276 writer.addEntryFromBuffer(path, digestBuffer);
277 }
278
279private:
280 static void RunForEachArea(const ListType& list, SurveyResults& results, unsigned int numSpace)
281 {
282 using namespace Yuni;
283
284 // No need to do anything for any area here if no zonal variables were selected.
285 uint selectedZonalVarsCount = results.data.study.parameters.variablesPrintInfo
286 .getNbSelectedZonalVars();
287
288 // All values related to an area
289 // Note: A thermal cluster is attached to an area
290 auto end = results.data.study.areas.end();
291 for (auto i = results.data.study.areas.begin(); i != end; ++i)
292 {
293 auto& area = *(i->second);
294 // Alias to the current area
295 results.data.area = &area;
296 // No thermal cluster for now
297 results.data.thermalCluster = nullptr;
298 // No link for now
299 results.data.link = nullptr;
300
301 // Skipping the creation of a result directory if it is meant to be empty.
302 // ... Getting few indicators value before deciding if we skip the results directory
303 // creation.
304 bool printingSynthesis = GlobalT; // Are we printing synthesis or year-by-year results ?
305 bool filterAllYearByYear = !(area.filterYearByYear & Data::filterAll);
306 bool filterAllSynthesis = !(area.filterSynthesis & Data::filterAll);
307
308 // ... Do we skip the current area's result directory creation because no results were
309 // asked
310 // in the inspector for the current area ?
311 bool skipDirectory = (!printingSynthesis && filterAllYearByYear)
312 || (printingSynthesis && filterAllSynthesis);
313
314 // ... Or do we skip the current area's result directory creation because no zonal
315 // variables were selected ?
316 skipDirectory = skipDirectory || !selectedZonalVarsCount;
317
318 // Generating the report for each area
319 if (CDataLevel & Category::DataLevel::area && !skipDirectory)
320 {
321 logs.info() << "Exporting results : " << area.name;
322 // The new output
323 std::filesystem::path path = static_cast<std::string>(results.data.originalOutput);
324 path /= "areas";
325 path /= area.id.to<std::string>();
326
327 results.data.output = path.string();
328 SurveyReportBuilderFile<GlobalT, NextT, CDataLevel>::Run(list, results, numSpace);
329 }
330
331 // Thermal clusters for the current area
332 if (CDataLevel & Category::DataLevel::thermalAggregate)
333 {
334 RunForEachThermalCluster(list, results, numSpace);
335 }
336 // Links
337 if (CDataLevel & Category::DataLevel::link && !area.links.empty())
338 {
339 RunForEachLink(list, results, numSpace);
340 }
341 }
342 }
343
344 static void RunForEachThermalCluster(const ListType& list,
345 SurveyResults& results,
346 unsigned int numSpace)
347 {
348 // Only do something if there is at least one column to write somewhere
349 // See below: if (CDataLevel & Category::DataLevel::thermalAggregate)
350 if (VariablesStatsByDataLevel<NextT, Category::DataLevel::thermalAggregate>::count)
351 {
352 auto& area = *results.data.area;
353 for (auto& cluster: area.thermal.list.each_enabled_and_not_mustrun())
354 {
355 results.data.thermalCluster = cluster.get();
356
357 logs.info() << "Exporting results : " << area.name << " :: " << cluster->name();
358 // The new output
359 std::filesystem::path path = static_cast<std::string>(results.data.originalOutput);
360 path /= std::filesystem::path("areas") / area.id.to<std::string>() / "thermal"
361 / cluster->id();
362
363 results.data.output = path.string();
364
365 SurveyReportBuilderFile<GlobalT, NextT, CDataLevel>::Run(list, results, numSpace);
366 }
367 }
368 }
369
370 static void RunForEachLink(const ListType& list, SurveyResults& results, unsigned int numSpace)
371 {
372 using namespace Yuni;
373
374 // No need to do anything for any link here if no link variables were selected.
375 uint selectedLinkVarsCount = results.data.study.parameters.variablesPrintInfo
376 .getNbSelectedLinkVars();
377 if (!selectedLinkVarsCount)
378 {
379 return;
380 }
381
382 int count_int = VariablesStatsByDataLevel<NextT, Category::DataLevel::link>::count;
383 if (count_int)
384 {
385 auto& area = *results.data.area;
386 auto end = area.links.end();
387 for (auto i = area.links.begin(); i != end; ++i)
388 {
389 // The link
390 auto& link = *(i->second);
391 results.data.link = &link;
392
393 // Skipping the creation of a result directory if it is meant to be empty.
394 // ... Getting few indicators value before deciding if we skip the results directory
395 // creation.
396 bool printingSynthesis = GlobalT; // Are we printing synthesis or year-by-year
397 // results ?
398 bool filterAllYearByYear = !(link.filterYearByYear & Data::filterAll);
399 bool filterAllSynthesis = !(link.filterSynthesis & Data::filterAll);
400
401 // ... Do we skip the current link's result directory creation because no results
402 // were asked
403 // in the inspector for the current link ?
404 bool skipDirectory = (!printingSynthesis && filterAllYearByYear)
405 || (printingSynthesis && filterAllSynthesis);
406
407 if (!skipDirectory)
408 {
409 Antares::logs.info() << "Exporting results : " << area.name << " - "
410 << results.data.link->with->name;
411 // The new output
412 std::filesystem::path path = static_cast<std::string>(
413 results.data.originalOutput);
414 std::string areaId = static_cast<std::string>(area.id) + " - "
415 + results.data.link->with->id;
416 path /= std::filesystem::path("links") / areaId;
417
418 results.data.output = path.string();
419
420 SurveyReportBuilderFile<GlobalT, NextT, CDataLevel>::Run(list,
421 results,
422 numSpace);
423 }
424 }
425 }
426 }
427
428 static void RunForEachSetOfAreas(const ListType& list,
429 SurveyResults& results,
430 unsigned int numSpace)
431 {
432 using namespace ::Antares;
433 using namespace ::Yuni;
434
435 // No need to do anything for any district (set of areas) here if no zonal variables were
436 // selected.
437 uint selectedZonalVarsCount = results.data.study.parameters.variablesPrintInfo
438 .getNbSelectedZonalVars();
439 if (!selectedZonalVarsCount)
440 {
441 return;
442 }
443
444 results.data.area = nullptr;
445 results.data.thermalCluster = nullptr;
446 results.data.link = nullptr;
447
448 // alias to the set of sets of areas
449 const Data::Study::SetsOfAreas& sets = results.data.study.setsOfAreas;
450
451 unsigned int indx = 0;
452 for (unsigned int i = 0; i != sets.size(); ++i)
453 {
454 if (!sets.hasOutput(i) || !sets.resultSize(i))
455 {
456 continue;
457 }
458
459 logs.info() << "Exporting results : " << sets.caption(i);
460 // The new output
461 std::filesystem::path path = static_cast<std::string>(results.data.originalOutput);
462 std::string setId = "@ " + sets.nameByIndex(i);
463 path /= std::filesystem::path("areas") / setId;
464
465 results.data.output = path.string();
466 results.data.setOfAreasIndex = indx++;
467
468 SurveyReportBuilderFile<GlobalT, NextT, CDataLevel>::Run(list, results, numSpace);
469 }
470 }
471
472 static void RunForEachBindingConstraint(const ListType& list,
473 SurveyResults& results,
474 unsigned int numSpace)
475 {
476 using namespace Yuni;
477
478 // Generating the report for each binding constraint
479 if (CDataLevel & Category::DataLevel::bindingConstraint)
480 {
481 logs.info() << "Exporting results : binding constraints";
482 // The new output
483 std::filesystem::path path = static_cast<std::string>(results.data.originalOutput);
484 path /= "binding_constraints";
485
486 results.data.output = path.string();
487 SurveyReportBuilderFile<GlobalT, NextT, CDataLevel>::Run(list, results, numSpace);
488 }
489 }
490
491}; // class SurveyReportBuilder
492
493template<bool GlobalT, class NextT>
494class SurveyReportBuilder<GlobalT, NextT, 2 * Category::DataLevel::maxDataLevel>
495{
496public:
497 using ListType = NextT;
498
499 // Dead end
500 static void Run(const ListType&, SurveyResults&, unsigned int)
501 {
502 }
503};
504
505} // Anonymous namespace
506
507} // namespace Container
508} // namespace Variable
509} // namespace Solver
510} // namespace Antares
511
512#endif // __SOLVER_VARIABLE_SURVEYRESULTS_REPORT_BUILDER_HXX__
Definition sets.h:40
bool hasOutput(const Yuni::ShortString128 &s) const
Get if the results for a given group should be written to the output.
Definition sets.cpp:360
uint resultSize(const Yuni::ShortString128 &s) const
Get the size of a result set.
Definition sets.cpp:371
Definition variable.h:25