From 57f1ae028b28e4fe06aa242fe4eb85ea6ff01855 Mon Sep 17 00:00:00 2001
From: payetvin <113102157+payetvin@users.noreply.github.com>
Date: Fri, 22 Sep 2023 14:18:50 +0200
Subject: [PATCH] New "cash-flow" variable for ST storage (#1633)
* [DEV] Create STStorageCashFlowByCluster.h
---
src/solver/variable/CMakeLists.txt | 1 +
.../economy/STStorageCashFlowByCluster.h | 301 ++++++++++++++++++
src/solver/variable/economy/all.h | 4 +-
3 files changed, 305 insertions(+), 1 deletion(-)
create mode 100644 src/solver/variable/economy/STStorageCashFlowByCluster.h
diff --git a/src/solver/variable/CMakeLists.txt b/src/solver/variable/CMakeLists.txt
index 350e58b3c5..df21955781 100644
--- a/src/solver/variable/CMakeLists.txt
+++ b/src/solver/variable/CMakeLists.txt
@@ -107,6 +107,7 @@ set(SRC_VARIABLE_ECONOMY
economy/STStorageInjectionByCluster.h
economy/STStorageWithdrawalByCluster.h
economy/STStorageLevelsByCluster.h
+ economy/STStorageCashFlowByCluster.h
economy/unsupliedEnergy.h
economy/domesticUnsuppliedEnergy.h
economy/localMatchingRuleViolations.h
diff --git a/src/solver/variable/economy/STStorageCashFlowByCluster.h b/src/solver/variable/economy/STStorageCashFlowByCluster.h
new file mode 100644
index 0000000000..6ea3456132
--- /dev/null
+++ b/src/solver/variable/economy/STStorageCashFlowByCluster.h
@@ -0,0 +1,301 @@
+/*
+** 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
+*/
+#pragma once
+
+#include "../variable.h"
+
+namespace Antares::Solver::Variable::Economy
+{
+struct VCardSTstorageCashFlowByCluster
+{
+ //! Caption
+ static std::string Caption()
+ {
+ return "STS Cashflow By Cluster";
+ }
+ //! Unit
+ static std::string Unit()
+ {
+ return "CashFlow - Euro";
+ }
+
+ //! The short description of the variable
+ static std::string Description()
+ {
+ return "Cash Flow by short term storage";
+ }
+
+ //! The expecte results
+ typedef Results>
+ ResultsType;
+
+ //! The VCard to look for for calculating spatial aggregates
+ typedef VCardSTstorageCashFlowByCluster VCardForSpatialAggregate;
+
+ enum
+ {
+ //! Data Level
+ categoryDataLevel = Category::area,
+ //! File level (provided by the type of the results)
+ categoryFileLevel = ResultsType::categoryFile & Category::de_sts,
+ //! Precision (views)
+ precision = Category::all,
+ //! Indentation (GUI)
+ nodeDepthForGUI = +0,
+ //! Decimal precision
+ decimal = 0,
+ //! Number of columns used by the variable
+ columnCount = Category::dynamicColumns,
+ //! The Spatial aggregation
+ spatialAggregate = Category::spatialAggregateSum,
+ spatialAggregateMode = Category::spatialAggregateEachYear,
+ spatialAggregatePostProcessing = 0,
+ //! Intermediate values
+ hasIntermediateValues = 1,
+ //! Can this variable be non applicable (0 : no, 1 : yes)
+ isPossiblyNonApplicable = 0,
+ };
+
+ typedef IntermediateValues IntermediateValuesDeepType;
+ typedef IntermediateValues* IntermediateValuesBaseType;
+ typedef IntermediateValuesBaseType* IntermediateValuesType;
+
+}; // class VCard
+
+/*!
+** \brief Energy generated by short term storage clusters
+*/
+template
+class STstorageCashFlowByCluster : public Variable::IVariable,
+ NextT,
+ VCardSTstorageCashFlowByCluster>
+{
+public:
+ //! Type of the next static variable
+ typedef NextT NextType;
+ //! VCard
+ typedef VCardSTstorageCashFlowByCluster VCardType;
+ //! Ancestor
+ typedef Variable::IVariable, NextT, VCardType> AncestorType;
+
+ //! List of expected results
+ typedef typename VCardType::ResultsType ResultsType;
+
+ typedef VariableAccessor VariableAccessorType;
+
+ static constexpr int count = 1 + NextT::count;
+
+ template
+ struct Statistics
+ {
+ enum
+ {
+ count
+ = ((VCardType::categoryDataLevel & CDataLevel && VCardType::categoryFileLevel & CFile)
+ ? (NextType::template Statistics::count
+ + VCardType::columnCount * ResultsType::count)
+ : NextType::template Statistics::count),
+ };
+ };
+
+public:
+ STstorageCashFlowByCluster() = default;
+
+ ~STstorageCashFlowByCluster()
+ {
+ for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
+ delete[] pValuesForTheCurrentYear[numSpace];
+ delete[] pValuesForTheCurrentYear;
+ }
+
+ void initializeFromArea(Data::Study* study, Data::Area* area)
+ {
+ // Get the number of years in parallel
+ pNbYearsParallel = study->maxNbYearsInParallel;
+ pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel];
+
+ // Get the area
+ nbClusters_ = area->shortTermStorage.count();
+ if (nbClusters_)
+ {
+ AncestorType::pResults.resize(nbClusters_);
+
+ for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
+ pValuesForTheCurrentYear[numSpace]
+ = new VCardType::IntermediateValuesDeepType[nbClusters_];
+
+ for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
+ for (unsigned int i = 0; i != nbClusters_; ++i)
+ pValuesForTheCurrentYear[numSpace][i].initializeFromStudy(*study);
+
+ for (unsigned int i = 0; i != nbClusters_; ++i)
+ {
+ AncestorType::pResults[i].initializeFromStudy(*study);
+ AncestorType::pResults[i].reset();
+ }
+ }
+ else
+ {
+ for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++)
+ {
+ pValuesForTheCurrentYear[numSpace] = nullptr;
+ }
+
+ AncestorType::pResults.clear();
+ }
+ // Next
+ NextType::initializeFromArea(study, area);
+ }
+
+ size_t getMaxNumberColumns() const
+ {
+ return nbClusters_ * ResultsType::count;
+ }
+
+ void yearBegin(unsigned int year, unsigned int numSpace)
+ {
+ // Reset the values for the current year
+ for (unsigned int clusterIndex = 0; clusterIndex != nbClusters_; ++clusterIndex)
+ {
+ pValuesForTheCurrentYear[numSpace][clusterIndex].reset();
+ }
+ // Next variable
+ NextType::yearBegin(year, numSpace);
+ }
+
+ void yearEnd(unsigned int year, unsigned int numSpace)
+ {
+ for (unsigned int clusterIndex = 0; clusterIndex < nbClusters_; ++clusterIndex)
+ {
+ // Compute all statistics from hourly results for the current year (daily, weekly, monthly, ...)
+ pValuesForTheCurrentYear[numSpace][clusterIndex].computeStatisticsForTheCurrentYear();
+ }
+ // Next variable
+ NextType::yearEnd(year, numSpace);
+ }
+
+ void computeSummary(std::map& numSpaceToYear,
+ unsigned int nbYearsForCurrentSummary)
+ {
+ for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace)
+ {
+ for (unsigned int clusterIndex = 0; clusterIndex < nbClusters_; ++clusterIndex)
+ {
+ // Merge all those values with the global results
+ AncestorType::pResults[clusterIndex].merge(numSpaceToYear[numSpace],
+ pValuesForTheCurrentYear[numSpace][clusterIndex]);
+ }
+ }
+
+ // Next variable
+ NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary);
+ }
+
+ void hourBegin(unsigned int hourInTheYear)
+ {
+ // Next variable
+ NextType::hourBegin(hourInTheYear);
+ }
+
+ void hourForEachArea(State& state, unsigned int numSpace)
+ {
+ unsigned int hourInYear = state.hourInTheYear;
+ for (uint clusterIndex = 0; clusterIndex != state.area->shortTermStorage.count();
+ ++clusterIndex)
+ {
+ const auto& stsHourlyResults = state.hourlyResults->ShortTermStorage[state.hourInTheWeek];
+ // ST storage injection for the current cluster and this hour
+ // CashFlow[h] = (withdrawal - injection) * MRG. PRICE
+ pValuesForTheCurrentYear[numSpace][clusterIndex].hour[hourInYear]
+ = (stsHourlyResults.withdrawal[clusterIndex]
+ - stsHourlyResults.injection[clusterIndex])
+ * (-state.hourlyResults->CoutsMarginauxHoraires[state.hourInTheWeek]);
+ // Note: The marginal price provided by the solver is negative (naming convention).
+ }
+
+ // Next variable
+ NextType::hourForEachArea(state, numSpace);
+ }
+
+ inline void buildDigest(SurveyResults& results, int digestLevel, int dataLevel) const
+ {
+ // Ask to build the digest to the next variable
+ NextType::buildDigest(results, digestLevel, dataLevel);
+ }
+
+ Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear(
+ unsigned int column,
+ unsigned int numSpace) const
+ {
+ return pValuesForTheCurrentYear[numSpace][column].hour;
+ }
+
+ inline uint64_t memoryUsage() const
+ {
+ uint64_t r = (sizeof(IntermediateValues) * nbClusters_ + IntermediateValues::MemoryUsage())
+ * pNbYearsParallel;
+ r += sizeof(double) * nbClusters_ * maxHoursInAYear * pNbYearsParallel;
+ r += AncestorType::memoryUsage();
+ return r;
+ }
+
+ void localBuildAnnualSurveyReport(SurveyResults& results,
+ int fileLevel,
+ int precision,
+ unsigned int numSpace) const
+ {
+ // Initializing external pointer on current variable non applicable status
+ results.isCurrentVarNA = AncestorType::isNonApplicable;
+
+ if (AncestorType::isPrinted[0])
+ {
+ assert(NULL != results.data.area);
+ const auto& shortTermStorage = results.data.area->shortTermStorage;
+
+ // Write the data for the current year
+ for (uint clusterIndex = 0; clusterIndex < nbClusters_; ++clusterIndex)
+ {
+ // Write the data for the current year
+ const auto* cluster = shortTermStorage.storagesByIndex[clusterIndex];
+ results.variableCaption = cluster->properties.name;
+ results.variableUnit = VCardType::Unit();
+ pValuesForTheCurrentYear[numSpace][clusterIndex]
+ .template buildAnnualSurveyReport(results, fileLevel, precision);
+ }
+ }
+ }
+
+private:
+ //! Intermediate values for each year
+ typename VCardType::IntermediateValuesType pValuesForTheCurrentYear = nullptr;
+ size_t nbClusters_ = 0;
+ unsigned int pNbYearsParallel = 0;
+
+}; // class STstorageCashFlowByCluster
+
+} // End namespace Antares::Solver::Variable::Economy
diff --git a/src/solver/variable/economy/all.h b/src/solver/variable/economy/all.h
index 04e4c1f72d..b961c8dbf7 100644
--- a/src/solver/variable/economy/all.h
+++ b/src/solver/variable/economy/all.h
@@ -87,6 +87,7 @@
#include "STStorageInjectionByCluster.h"
#include "STStorageWithdrawalByCluster.h"
#include "STStorageLevelsByCluster.h"
+#include "STStorageCashFlowByCluster.h"
// Output variables associated to links
#include "links/flowLinear.h"
@@ -155,6 +156,7 @@ typedef // Prices
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
VariablesPerArea;
/*!